summaryrefslogtreecommitdiff
path: root/src/video_core/rasterizer.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2014-12-20 12:40:06 -0500
committerGravatar bunnei2014-12-20 12:40:06 -0500
commitacabd7be82b4174a3adab0771df6320bdbc5a85b (patch)
treec47c2f68f50005bfb5c4003831f3977aec0be3ca /src/video_core/rasterizer.cpp
parentMerge pull request #315 from chinhodado/master (diff)
parentPica/VertexShader: Promote a log message to critical status. (diff)
downloadyuzu-acabd7be82b4174a3adab0771df6320bdbc5a85b.tar.gz
yuzu-acabd7be82b4174a3adab0771df6320bdbc5a85b.tar.xz
yuzu-acabd7be82b4174a3adab0771df6320bdbc5a85b.zip
Merge pull request #284 from neobrain/pica_progress
Pica progress: Texturing, shaders, cleanups & more
Diffstat (limited to 'src/video_core/rasterizer.cpp')
-rw-r--r--src/video_core/rasterizer.cpp164
1 files changed, 98 insertions, 66 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index b7e04a560..bf9c36661 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -18,7 +18,7 @@ namespace Pica {
18namespace Rasterizer { 18namespace Rasterizer {
19 19
20static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { 20static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
21 u32* color_buffer = (u32*)Memory::GetPointer(registers.framebuffer.GetColorBufferAddress()); 21 u32* color_buffer = reinterpret_cast<u32*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetColorBufferPhysicalAddress())));
22 u32 value = (color.a() << 24) | (color.r() << 16) | (color.g() << 8) | color.b(); 22 u32 value = (color.a() << 24) | (color.r() << 16) | (color.g() << 8) | color.b();
23 23
24 // Assuming RGBA8 format until actual framebuffer format handling is implemented 24 // Assuming RGBA8 format until actual framebuffer format handling is implemented
@@ -26,14 +26,14 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
26} 26}
27 27
28static u32 GetDepth(int x, int y) { 28static u32 GetDepth(int x, int y) {
29 u16* depth_buffer = (u16*)Memory::GetPointer(registers.framebuffer.GetDepthBufferAddress()); 29 u16* depth_buffer = reinterpret_cast<u16*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetDepthBufferPhysicalAddress())));
30 30
31 // Assuming 16-bit depth buffer format until actual format handling is implemented 31 // Assuming 16-bit depth buffer format until actual format handling is implemented
32 return *(depth_buffer + x + y * registers.framebuffer.GetWidth()); 32 return *(depth_buffer + x + y * registers.framebuffer.GetWidth());
33} 33}
34 34
35static void SetDepth(int x, int y, u16 value) { 35static void SetDepth(int x, int y, u16 value) {
36 u16* depth_buffer = (u16*)Memory::GetPointer(registers.framebuffer.GetDepthBufferAddress()); 36 u16* depth_buffer = reinterpret_cast<u16*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetDepthBufferPhysicalAddress())));
37 37
38 // Assuming 16-bit depth buffer format until actual format handling is implemented 38 // Assuming 16-bit depth buffer format until actual format handling is implemented
39 *(depth_buffer + x + y * registers.framebuffer.GetWidth()) = value; 39 *(depth_buffer + x + y * registers.framebuffer.GetWidth()) = value;
@@ -167,60 +167,48 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
167 (u8)(GetInterpolatedAttribute(v0.color.a(), v1.color.a(), v2.color.a()).ToFloat32() * 255) 167 (u8)(GetInterpolatedAttribute(v0.color.a(), v1.color.a(), v2.color.a()).ToFloat32() * 255)
168 }; 168 };
169 169
170 Math::Vec4<u8> texture_color{}; 170 Math::Vec2<float24> uv[3];
171 float24 u = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u()); 171 uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u());
172 float24 v = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v()); 172 uv[0].v() = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v());
173 if (registers.texturing_enable) { 173 uv[1].u() = GetInterpolatedAttribute(v0.tc1.u(), v1.tc1.u(), v2.tc1.u());
174 // Images are split into 8x8 tiles. Each tile is composed of four 4x4 subtiles each 174 uv[1].v() = GetInterpolatedAttribute(v0.tc1.v(), v1.tc1.v(), v2.tc1.v());
175 // of which is composed of four 2x2 subtiles each of which is composed of four texels. 175 uv[2].u() = GetInterpolatedAttribute(v0.tc2.u(), v1.tc2.u(), v2.tc2.u());
176 // Each structure is embedded into the next-bigger one in a diagonal pattern, e.g. 176 uv[2].v() = GetInterpolatedAttribute(v0.tc2.v(), v1.tc2.v(), v2.tc2.v());
177 // texels are laid out in a 2x2 subtile like this: 177
178 // 2 3 178 Math::Vec4<u8> texture_color[3]{};
179 // 0 1 179 for (int i = 0; i < 3; ++i) {
180 // 180 auto texture = registers.GetTextures()[i];
181 // The full 8x8 tile has the texels arranged like this: 181 if (!texture.enabled)
182 // 182 continue;
183 // 42 43 46 47 58 59 62 63 183
184 // 40 41 44 45 56 57 60 61 184 _dbg_assert_(HW_GPU, 0 != texture.config.address);
185 // 34 35 38 39 50 51 54 55 185
186 // 32 33 36 37 48 49 52 53 186 int s = (int)(uv[i].u() * float24::FromFloat32(static_cast<float>(texture.config.width))).ToFloat32();
187 // 10 11 14 15 26 27 30 31 187 int t = (int)(uv[i].v() * float24::FromFloat32(static_cast<float>(texture.config.height))).ToFloat32();
188 // 08 09 12 13 24 25 28 29 188 auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val, unsigned size) {
189 // 02 03 06 07 18 19 22 23 189 switch (mode) {
190 // 00 01 04 05 16 17 20 21 190 case Regs::TextureConfig::ClampToEdge:
191 191 val = std::max(val, 0);
192 // TODO: This is currently hardcoded for RGB8 192 val = std::min(val, (int)size - 1);
193 u32* texture_data = (u32*)Memory::GetPointer(registers.texture0.GetPhysicalAddress()); 193 return val;
194 194
195 // TODO(neobrain): Not sure if this swizzling pattern is used for all textures. 195 case Regs::TextureConfig::Repeat:
196 // To be flexible in case different but similar patterns are used, we keep this 196 return (int)(((unsigned)val) % size);
197 // somewhat inefficient code around for now. 197
198 int s = (int)(u * float24::FromFloat32(static_cast<float>(registers.texture0.width))).ToFloat32(); 198 default:
199 int t = (int)(v * float24::FromFloat32(static_cast<float>(registers.texture0.height))).ToFloat32(); 199 LOG_ERROR(HW_GPU, "Unknown texture coordinate wrapping mode %x\n", (int)mode);
200 int texel_index_within_tile = 0; 200 _dbg_assert_(HW_GPU, 0);
201 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) { 201 return 0;
202 int sub_tile_width = 1 << block_size_index; 202 }
203 int sub_tile_height = 1 << block_size_index; 203 };
204 204 s = GetWrappedTexCoord(registers.texture0.wrap_s, s, registers.texture0.width);
205 int sub_tile_index = (s & sub_tile_width) << block_size_index; 205 t = GetWrappedTexCoord(registers.texture0.wrap_t, t, registers.texture0.height);
206 sub_tile_index += 2 * ((t & sub_tile_height) << block_size_index); 206
207 texel_index_within_tile += sub_tile_index; 207 u8* texture_data = Memory::GetPointer(PAddrToVAddr(texture.config.GetPhysicalAddress()));
208 } 208 auto info = DebugUtils::TextureInfo::FromPicaRegister(texture.config, texture.format);
209 209
210 const int block_width = 8; 210 texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info);
211 const int block_height = 8; 211 DebugUtils::DumpTexture(texture.config, texture_data);
212
213 int coarse_s = (s / block_width) * block_width;
214 int coarse_t = (t / block_height) * block_height;
215
216 const int row_stride = registers.texture0.width * 3;
217 u8* source_ptr = (u8*)texture_data + coarse_s * block_height * 3 + coarse_t * row_stride + texel_index_within_tile * 3;
218 texture_color.r() = source_ptr[2];
219 texture_color.g() = source_ptr[1];
220 texture_color.b() = source_ptr[0];
221 texture_color.a() = 0xFF;
222
223 DebugUtils::DumpTexture(registers.texture0, (u8*)texture_data);
224 } 212 }
225 213
226 // Texture environment - consists of 6 stages of color and alpha combining. 214 // Texture environment - consists of 6 stages of color and alpha combining.
@@ -237,22 +225,29 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
237 using AlphaModifier = Regs::TevStageConfig::AlphaModifier; 225 using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
238 using Operation = Regs::TevStageConfig::Operation; 226 using Operation = Regs::TevStageConfig::Operation;
239 227
240 auto GetColorSource = [&](Source source) -> Math::Vec3<u8> { 228 auto GetColorSource = [&](Source source) -> Math::Vec4<u8> {
241 switch (source) { 229 switch (source) {
242 case Source::PrimaryColor: 230 case Source::PrimaryColor:
243 return primary_color.rgb(); 231 return primary_color;
244 232
245 case Source::Texture0: 233 case Source::Texture0:
246 return texture_color.rgb(); 234 return texture_color[0];
235
236 case Source::Texture1:
237 return texture_color[1];
238
239 case Source::Texture2:
240 return texture_color[2];
247 241
248 case Source::Constant: 242 case Source::Constant:
249 return {tev_stage.const_r, tev_stage.const_g, tev_stage.const_b}; 243 return {tev_stage.const_r, tev_stage.const_g, tev_stage.const_b, tev_stage.const_a};
250 244
251 case Source::Previous: 245 case Source::Previous:
252 return combiner_output.rgb(); 246 return combiner_output;
253 247
254 default: 248 default:
255 LOG_ERROR(HW_GPU, "Unknown color combiner source %d\n", (int)source); 249 LOG_ERROR(HW_GPU, "Unknown color combiner source %d\n", (int)source);
250 _dbg_assert_(HW_GPU, 0);
256 return {}; 251 return {};
257 } 252 }
258 }; 253 };
@@ -263,7 +258,13 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
263 return primary_color.a(); 258 return primary_color.a();
264 259
265 case Source::Texture0: 260 case Source::Texture0:
266 return texture_color.a(); 261 return texture_color[0].a();
262
263 case Source::Texture1:
264 return texture_color[1].a();
265
266 case Source::Texture2:
267 return texture_color[2].a();
267 268
268 case Source::Constant: 269 case Source::Constant:
269 return tev_stage.const_a; 270 return tev_stage.const_a;
@@ -273,17 +274,23 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
273 274
274 default: 275 default:
275 LOG_ERROR(HW_GPU, "Unknown alpha combiner source %d\n", (int)source); 276 LOG_ERROR(HW_GPU, "Unknown alpha combiner source %d\n", (int)source);
277 _dbg_assert_(HW_GPU, 0);
276 return 0; 278 return 0;
277 } 279 }
278 }; 280 };
279 281
280 auto GetColorModifier = [](ColorModifier factor, const Math::Vec3<u8>& values) -> Math::Vec3<u8> { 282 auto GetColorModifier = [](ColorModifier factor, const Math::Vec4<u8>& values) -> Math::Vec3<u8> {
281 switch (factor) 283 switch (factor)
282 { 284 {
283 case ColorModifier::SourceColor: 285 case ColorModifier::SourceColor:
284 return values; 286 return values.rgb();
287
288 case ColorModifier::SourceAlpha:
289 return { values.a(), values.a(), values.a() };
290
285 default: 291 default:
286 LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor); 292 LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor);
293 _dbg_assert_(HW_GPU, 0);
287 return {}; 294 return {};
288 } 295 }
289 }; 296 };
@@ -292,8 +299,13 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
292 switch (factor) { 299 switch (factor) {
293 case AlphaModifier::SourceAlpha: 300 case AlphaModifier::SourceAlpha:
294 return value; 301 return value;
302
303 case AlphaModifier::OneMinusSourceAlpha:
304 return 255 - value;
305
295 default: 306 default:
296 LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor); 307 LOG_ERROR(HW_GPU, "Unknown alpha factor %d\n", (int)factor);
308 _dbg_assert_(HW_GPU, 0);
297 return 0; 309 return 0;
298 } 310 }
299 }; 311 };
@@ -306,8 +318,21 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
306 case Operation::Modulate: 318 case Operation::Modulate:
307 return ((input[0] * input[1]) / 255).Cast<u8>(); 319 return ((input[0] * input[1]) / 255).Cast<u8>();
308 320
321 case Operation::Add:
322 {
323 auto result = input[0] + input[1];
324 result.r() = std::min(255, result.r());
325 result.g() = std::min(255, result.g());
326 result.b() = std::min(255, result.b());
327 return result.Cast<u8>();
328 }
329
330 case Operation::Lerp:
331 return ((input[0] * input[2] + input[1] * (Math::MakeVec<u8>(255, 255, 255) - input[2]).Cast<u8>()) / 255).Cast<u8>();
332
309 default: 333 default:
310 LOG_ERROR(HW_GPU, "Unknown color combiner operation %d\n", (int)op); 334 LOG_ERROR(HW_GPU, "Unknown color combiner operation %d\n", (int)op);
335 _dbg_assert_(HW_GPU, 0);
311 return {}; 336 return {};
312 } 337 }
313 }; 338 };
@@ -320,8 +345,15 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
320 case Operation::Modulate: 345 case Operation::Modulate:
321 return input[0] * input[1] / 255; 346 return input[0] * input[1] / 255;
322 347
348 case Operation::Add:
349 return std::min(255, input[0] + input[1]);
350
351 case Operation::Lerp:
352 return (input[0] * input[2] + input[1] * (255 - input[2])) / 255;
353
323 default: 354 default:
324 LOG_ERROR(HW_GPU, "Unknown alpha combiner operation %d\n", (int)op); 355 LOG_ERROR(HW_GPU, "Unknown alpha combiner operation %d\n", (int)op);
356 _dbg_assert_(HW_GPU, 0);
325 return 0; 357 return 0;
326 } 358 }
327 }; 359 };