summaryrefslogtreecommitdiff
path: root/src/video_core/debug_utils
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/debug_utils
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/debug_utils')
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp255
-rw-r--r--src/video_core/debug_utils/debug_utils.h15
2 files changed, 184 insertions, 86 deletions
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 1a20f19ec..328386b7e 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -14,6 +14,8 @@
14#include <png.h> 14#include <png.h>
15#endif 15#endif
16 16
17#include <nihstro/shader_binary.h>
18
17#include "common/log.h" 19#include "common/log.h"
18#include "common/file_util.h" 20#include "common/file_util.h"
19 21
@@ -22,6 +24,10 @@
22 24
23#include "debug_utils.h" 25#include "debug_utils.h"
24 26
27using nihstro::DVLBHeader;
28using nihstro::DVLEHeader;
29using nihstro::DVLPHeader;
30
25namespace Pica { 31namespace Pica {
26 32
27void DebugContext::OnEvent(Event event, void* data) { 33void DebugContext::OnEvent(Event event, void* data) {
@@ -98,65 +104,6 @@ void GeometryDumper::Dump() {
98 } 104 }
99} 105}
100 106
101#pragma pack(1)
102struct DVLBHeader {
103 enum : u32 {
104 MAGIC_WORD = 0x424C5644, // "DVLB"
105 };
106
107 u32 magic_word;
108 u32 num_programs;
109// u32 dvle_offset_table[];
110};
111static_assert(sizeof(DVLBHeader) == 0x8, "Incorrect structure size");
112
113struct DVLPHeader {
114 enum : u32 {
115 MAGIC_WORD = 0x504C5644, // "DVLP"
116 };
117
118 u32 magic_word;
119 u32 version;
120 u32 binary_offset; // relative to DVLP start
121 u32 binary_size_words;
122 u32 swizzle_patterns_offset;
123 u32 swizzle_patterns_num_entries;
124 u32 unk2;
125};
126static_assert(sizeof(DVLPHeader) == 0x1C, "Incorrect structure size");
127
128struct DVLEHeader {
129 enum : u32 {
130 MAGIC_WORD = 0x454c5644, // "DVLE"
131 };
132
133 enum class ShaderType : u8 {
134 VERTEX = 0,
135 GEOMETRY = 1,
136 };
137
138 u32 magic_word;
139 u16 pad1;
140 ShaderType type;
141 u8 pad2;
142 u32 main_offset_words; // offset within binary blob
143 u32 endmain_offset_words;
144 u32 pad3;
145 u32 pad4;
146 u32 constant_table_offset;
147 u32 constant_table_size; // number of entries
148 u32 label_table_offset;
149 u32 label_table_size;
150 u32 output_register_table_offset;
151 u32 output_register_table_size;
152 u32 uniform_table_offset;
153 u32 uniform_table_size;
154 u32 symbol_table_offset;
155 u32 symbol_table_size;
156
157};
158static_assert(sizeof(DVLEHeader) == 0x40, "Incorrect structure size");
159#pragma pack()
160 107
161void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, 108void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size,
162 u32 main_offset, const Regs::VSOutputAttributes* output_attributes) 109 u32 main_offset, const Regs::VSOutputAttributes* output_attributes)
@@ -276,8 +223,8 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data
276 dvlp.binary_size_words = binary_size; 223 dvlp.binary_size_words = binary_size;
277 QueueForWriting((u8*)binary_data, binary_size * sizeof(u32)); 224 QueueForWriting((u8*)binary_data, binary_size * sizeof(u32));
278 225
279 dvlp.swizzle_patterns_offset = write_offset - dvlp_offset; 226 dvlp.swizzle_info_offset = write_offset - dvlp_offset;
280 dvlp.swizzle_patterns_num_entries = swizzle_size; 227 dvlp.swizzle_info_num_entries = swizzle_size;
281 u32 dummy = 0; 228 u32 dummy = 0;
282 for (unsigned int i = 0; i < swizzle_size; ++i) { 229 for (unsigned int i = 0; i < swizzle_size; ++i) {
283 QueueForWriting((u8*)&swizzle_data[i], sizeof(swizzle_data[i])); 230 QueueForWriting((u8*)&swizzle_data[i], sizeof(swizzle_data[i]));
@@ -356,10 +303,29 @@ std::unique_ptr<PicaTrace> FinishPicaTracing()
356 return std::move(ret); 303 return std::move(ret);
357} 304}
358 305
359const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info) { 306const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info, bool disable_alpha) {
360 _dbg_assert_(Debug_GPU, info.format == Pica::Regs::TextureFormat::RGB8); 307
361 308 // Images are split into 8x8 tiles. Each tile is composed of four 4x4 subtiles each
362 // Cf. rasterizer code for an explanation of this algorithm. 309 // of which is composed of four 2x2 subtiles each of which is composed of four texels.
310 // Each structure is embedded into the next-bigger one in a diagonal pattern, e.g.
311 // texels are laid out in a 2x2 subtile like this:
312 // 2 3
313 // 0 1
314 //
315 // The full 8x8 tile has the texels arranged like this:
316 //
317 // 42 43 46 47 58 59 62 63
318 // 40 41 44 45 56 57 60 61
319 // 34 35 38 39 50 51 54 55
320 // 32 33 36 37 48 49 52 53
321 // 10 11 14 15 26 27 30 31
322 // 08 09 12 13 24 25 28 29
323 // 02 03 06 07 18 19 22 23
324 // 00 01 04 05 16 17 20 21
325
326 // TODO(neobrain): Not sure if this swizzling pattern is used for all textures.
327 // To be flexible in case different but similar patterns are used, we keep this
328 // somewhat inefficient code around for now.
363 int texel_index_within_tile = 0; 329 int texel_index_within_tile = 0;
364 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) { 330 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) {
365 int sub_tile_width = 1 << block_size_index; 331 int sub_tile_width = 1 << block_size_index;
@@ -376,19 +342,134 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
376 int coarse_x = (x / block_width) * block_width; 342 int coarse_x = (x / block_width) * block_width;
377 int coarse_y = (y / block_height) * block_height; 343 int coarse_y = (y / block_height) * block_height;
378 344
379 const u8* source_ptr = source + coarse_x * block_height * 3 + coarse_y * info.stride + texel_index_within_tile * 3; 345 switch (info.format) {
380 return { source_ptr[2], source_ptr[1], source_ptr[0], 255 }; 346 case Regs::TextureFormat::RGBA8:
347 {
348 const u8* source_ptr = source + coarse_x * block_height * 4 + coarse_y * info.stride + texel_index_within_tile * 4;
349 return { source_ptr[3], source_ptr[2], source_ptr[1], disable_alpha ? (u8)255 : source_ptr[0] };
350 }
351
352 case Regs::TextureFormat::RGB8:
353 {
354 const u8* source_ptr = source + coarse_x * block_height * 3 + coarse_y * info.stride + texel_index_within_tile * 3;
355 return { source_ptr[2], source_ptr[1], source_ptr[0], 255 };
356 }
357
358 case Regs::TextureFormat::RGBA5551:
359 {
360 const u16 source_ptr = *(const u16*)(source + coarse_x * block_height * 2 + coarse_y * info.stride + texel_index_within_tile * 2);
361 u8 r = (source_ptr >> 11) & 0x1F;
362 u8 g = ((source_ptr) >> 6) & 0x1F;
363 u8 b = (source_ptr >> 1) & 0x1F;
364 u8 a = source_ptr & 1;
365 return Math::MakeVec<u8>((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), disable_alpha ? 255 : (a * 255));
366 }
367
368 case Regs::TextureFormat::RGB565:
369 {
370 const u16 source_ptr = *(const u16*)(source + coarse_x * block_height * 2 + coarse_y * info.stride + texel_index_within_tile * 2);
371 u8 r = (source_ptr >> 11) & 0x1F;
372 u8 g = ((source_ptr) >> 5) & 0x3F;
373 u8 b = (source_ptr) & 0x1F;
374 return Math::MakeVec<u8>((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2), 255);
375 }
376
377 case Regs::TextureFormat::RGBA4:
378 {
379 const u8* source_ptr = source + coarse_x * block_height * 2 + coarse_y * info.stride + texel_index_within_tile * 2;
380 u8 r = source_ptr[1] >> 4;
381 u8 g = source_ptr[1] & 0xFF;
382 u8 b = source_ptr[0] >> 4;
383 u8 a = source_ptr[0] & 0xFF;
384 r = (r << 4) | r;
385 g = (g << 4) | g;
386 b = (b << 4) | b;
387 a = (a << 4) | a;
388 return { r, g, b, disable_alpha ? (u8)255 : a };
389 }
390
391 case Regs::TextureFormat::IA8:
392 {
393 const u8* source_ptr = source + coarse_x * block_height * 2 + coarse_y * info.stride + texel_index_within_tile * 2;
394
395 // TODO: component order not verified
396
397 if (disable_alpha) {
398 // Show intensity as red, alpha as green
399 return { source_ptr[0], source_ptr[1], 0, 255 };
400 } else {
401 return { source_ptr[0], source_ptr[0], source_ptr[0], source_ptr[1]};
402 }
403 }
404
405 case Regs::TextureFormat::I8:
406 {
407 const u8* source_ptr = source + coarse_x * block_height + coarse_y * info.stride + texel_index_within_tile;
408 return { *source_ptr, *source_ptr, *source_ptr, 255 };
409 }
410
411 case Regs::TextureFormat::A8:
412 {
413 const u8* source_ptr = source + coarse_x * block_height + coarse_y * info.stride + texel_index_within_tile;
414
415 if (disable_alpha) {
416 return { *source_ptr, *source_ptr, *source_ptr, 255 };
417 } else {
418 return { 0, 0, 0, *source_ptr };
419 }
420 }
421
422 case Regs::TextureFormat::IA4:
423 {
424 const u8* source_ptr = source + coarse_x * block_height / 2 + coarse_y * info.stride + texel_index_within_tile / 2;
425
426 // TODO: component order not verified
427
428 u8 i = (*source_ptr) & 0xF;
429 u8 a = ((*source_ptr) & 0xF0) >> 4;
430 a |= a << 4;
431 i |= i << 4;
432
433 if (disable_alpha) {
434 // Show intensity as red, alpha as green
435 return { i, a, 0, 255 };
436 } else {
437 return { i, i, i, a };
438 }
439 }
440
441 case Regs::TextureFormat::A4:
442 {
443 const u8* source_ptr = source + coarse_x * block_height / 2 + coarse_y * info.stride + texel_index_within_tile / 2;
444
445 // TODO: component order not verified
446
447 u8 a = (coarse_x % 2) ? ((*source_ptr)&0xF) : (((*source_ptr) & 0xF0) >> 4);
448 a |= a << 4;
449
450 if (disable_alpha) {
451 return { *source_ptr, *source_ptr, *source_ptr, 255 };
452 } else {
453 return { 0, 0, 0, *source_ptr };
454 }
455 }
456
457 default:
458 LOG_ERROR(HW_GPU, "Unknown texture format: %x", (u32)info.format);
459 _dbg_assert_(HW_GPU, 0);
460 return {};
461 }
381} 462}
382 463
383TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config, 464TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config,
384 const Regs::TextureFormat& format) 465 const Regs::TextureFormat& format)
385{ 466{
386 TextureInfo info; 467 TextureInfo info;
387 info.address = config.GetPhysicalAddress(); 468 info.physical_address = config.GetPhysicalAddress();
388 info.width = config.width; 469 info.width = config.width;
389 info.height = config.height; 470 info.height = config.height;
390 info.format = format; 471 info.format = format;
391 info.stride = Pica::Regs::BytesPerPixel(info.format) * info.width; 472 info.stride = Pica::Regs::NibblesPerPixel(info.format) * info.width / 2;
392 return info; 473 return info;
393} 474}
394 475
@@ -499,26 +580,32 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
499 for (size_t index = 0; index < stages.size(); ++index) { 580 for (size_t index = 0; index < stages.size(); ++index) {
500 const auto& tev_stage = stages[index]; 581 const auto& tev_stage = stages[index];
501 582
502 const std::map<Source, std::string> source_map = { 583 static const std::map<Source, std::string> source_map = {
503 { Source::PrimaryColor, "PrimaryColor" }, 584 { Source::PrimaryColor, "PrimaryColor" },
504 { Source::Texture0, "Texture0" }, 585 { Source::Texture0, "Texture0" },
586 { Source::Texture1, "Texture1" },
587 { Source::Texture2, "Texture2" },
505 { Source::Constant, "Constant" }, 588 { Source::Constant, "Constant" },
506 { Source::Previous, "Previous" }, 589 { Source::Previous, "Previous" },
507 }; 590 };
508 591
509 const std::map<ColorModifier, std::string> color_modifier_map = { 592 static const std::map<ColorModifier, std::string> color_modifier_map = {
510 { ColorModifier::SourceColor, { "%source.rgb" } } 593 { ColorModifier::SourceColor, { "%source.rgb" } },
594 { ColorModifier::SourceAlpha, { "%source.aaa" } },
511 }; 595 };
512 const std::map<AlphaModifier, std::string> alpha_modifier_map = { 596 static const std::map<AlphaModifier, std::string> alpha_modifier_map = {
513 { AlphaModifier::SourceAlpha, "%source.a" } 597 { AlphaModifier::SourceAlpha, "%source.a" },
598 { AlphaModifier::OneMinusSourceAlpha, "(255 - %source.a)" },
514 }; 599 };
515 600
516 std::map<Operation, std::string> combiner_map = { 601 static const std::map<Operation, std::string> combiner_map = {
517 { Operation::Replace, "%source1" }, 602 { Operation::Replace, "%source1" },
518 { Operation::Modulate, "(%source1 * %source2) / 255" }, 603 { Operation::Modulate, "(%source1 * %source2) / 255" },
604 { Operation::Add, "(%source1 + %source2)" },
605 { Operation::Lerp, "lerp(%source1, %source2, %source3)" },
519 }; 606 };
520 607
521 auto ReplacePattern = 608 static auto ReplacePattern =
522 [](const std::string& input, const std::string& pattern, const std::string& replacement) -> std::string { 609 [](const std::string& input, const std::string& pattern, const std::string& replacement) -> std::string {
523 size_t start = input.find(pattern); 610 size_t start = input.find(pattern);
524 if (start == std::string::npos) 611 if (start == std::string::npos)
@@ -528,8 +615,8 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
528 ret.replace(start, pattern.length(), replacement); 615 ret.replace(start, pattern.length(), replacement);
529 return ret; 616 return ret;
530 }; 617 };
531 auto GetColorSourceStr = 618 static auto GetColorSourceStr =
532 [&source_map,&color_modifier_map,&ReplacePattern](const Source& src, const ColorModifier& modifier) { 619 [](const Source& src, const ColorModifier& modifier) {
533 auto src_it = source_map.find(src); 620 auto src_it = source_map.find(src);
534 std::string src_str = "Unknown"; 621 std::string src_str = "Unknown";
535 if (src_it != source_map.end()) 622 if (src_it != source_map.end())
@@ -542,8 +629,8 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
542 629
543 return ReplacePattern(modifier_str, "%source", src_str); 630 return ReplacePattern(modifier_str, "%source", src_str);
544 }; 631 };
545 auto GetColorCombinerStr = 632 static auto GetColorCombinerStr =
546 [&](const Regs::TevStageConfig& tev_stage) { 633 [](const Regs::TevStageConfig& tev_stage) {
547 auto op_it = combiner_map.find(tev_stage.color_op); 634 auto op_it = combiner_map.find(tev_stage.color_op);
548 std::string op_str = "Unknown op (%source1, %source2, %source3)"; 635 std::string op_str = "Unknown op (%source1, %source2, %source3)";
549 if (op_it != combiner_map.end()) 636 if (op_it != combiner_map.end())
@@ -553,8 +640,8 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
553 op_str = ReplacePattern(op_str, "%source2", GetColorSourceStr(tev_stage.color_source2, tev_stage.color_modifier2)); 640 op_str = ReplacePattern(op_str, "%source2", GetColorSourceStr(tev_stage.color_source2, tev_stage.color_modifier2));
554 return ReplacePattern(op_str, "%source3", GetColorSourceStr(tev_stage.color_source3, tev_stage.color_modifier3)); 641 return ReplacePattern(op_str, "%source3", GetColorSourceStr(tev_stage.color_source3, tev_stage.color_modifier3));
555 }; 642 };
556 auto GetAlphaSourceStr = 643 static auto GetAlphaSourceStr =
557 [&source_map,&alpha_modifier_map,&ReplacePattern](const Source& src, const AlphaModifier& modifier) { 644 [](const Source& src, const AlphaModifier& modifier) {
558 auto src_it = source_map.find(src); 645 auto src_it = source_map.find(src);
559 std::string src_str = "Unknown"; 646 std::string src_str = "Unknown";
560 if (src_it != source_map.end()) 647 if (src_it != source_map.end())
@@ -567,8 +654,8 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
567 654
568 return ReplacePattern(modifier_str, "%source", src_str); 655 return ReplacePattern(modifier_str, "%source", src_str);
569 }; 656 };
570 auto GetAlphaCombinerStr = 657 static auto GetAlphaCombinerStr =
571 [&](const Regs::TevStageConfig& tev_stage) { 658 [](const Regs::TevStageConfig& tev_stage) {
572 auto op_it = combiner_map.find(tev_stage.alpha_op); 659 auto op_it = combiner_map.find(tev_stage.alpha_op);
573 std::string op_str = "Unknown op (%source1, %source2, %source3)"; 660 std::string op_str = "Unknown op (%source1, %source2, %source3)";
574 if (op_it != combiner_map.end()) 661 if (op_it != combiner_map.end())
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
index 51f14f12f..f361a5385 100644
--- a/src/video_core/debug_utils/debug_utils.h
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -26,6 +26,7 @@ public:
26 CommandProcessed, 26 CommandProcessed,
27 IncomingPrimitiveBatch, 27 IncomingPrimitiveBatch,
28 FinishedPrimitiveBatch, 28 FinishedPrimitiveBatch,
29 VertexLoaded,
29 30
30 NumEvents 31 NumEvents
31 }; 32 };
@@ -192,7 +193,7 @@ void OnPicaRegWrite(u32 id, u32 value);
192std::unique_ptr<PicaTrace> FinishPicaTracing(); 193std::unique_ptr<PicaTrace> FinishPicaTracing();
193 194
194struct TextureInfo { 195struct TextureInfo {
195 unsigned int address; 196 PAddr physical_address;
196 int width; 197 int width;
197 int height; 198 int height;
198 int stride; 199 int stride;
@@ -202,7 +203,17 @@ struct TextureInfo {
202 const Pica::Regs::TextureFormat& format); 203 const Pica::Regs::TextureFormat& format);
203}; 204};
204 205
205const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info); 206/**
207 * Lookup texel located at the given coordinates and return an RGBA vector of its color.
208 * @param source Source pointer to read data from
209 * @param s,t Texture coordinates to read from
210 * @param info TextureInfo object describing the texture setup
211 * @param disable_alpha This is used for debug widgets which use this method to display textures without providing a good way to visualize alpha by themselves. If true, this will return 255 for the alpha component, and either drop the information entirely or store it in an "unused" color channel.
212 * @todo Eventually we should get rid of the disable_alpha parameter.
213 */
214const Math::Vec4<u8> LookupTexture(const u8* source, int s, int t, const TextureInfo& info,
215 bool disable_alpha = false);
216
206void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data); 217void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data);
207 218
208void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages); 219void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages);