diff options
| author | 2018-12-22 01:20:57 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:52 -0300 | |
| commit | 03e088a4f44af1212da0c7c23f95293a6e129a35 (patch) | |
| tree | 4c5b87cabf709f6ca3a839b7dff7c75b7ced2a4c /src | |
| parent | shader_decode: Fixup FSET (diff) | |
| download | yuzu-03e088a4f44af1212da0c7c23f95293a6e129a35.tar.gz yuzu-03e088a4f44af1212da0c7c23f95293a6e129a35.tar.xz yuzu-03e088a4f44af1212da0c7c23f95293a6e129a35.zip | |
shader_ir: Fixup TEX and TEXS and partially fix TLD4 decompiling
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 99 | ||||
| -rw-r--r-- | src/video_core/shader/glsl_decompiler.cpp | 29 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 4 |
3 files changed, 72 insertions, 60 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index c70e2ff02..500a32af5 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -183,28 +183,24 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { | |||
| 183 | 183 | ||
| 184 | const Node texture = GetTexCode(instr, texture_type, process_mode, depth_compare, is_array); | 184 | const Node texture = GetTexCode(instr, texture_type, process_mode, depth_compare, is_array); |
| 185 | 185 | ||
| 186 | if (depth_compare) { | 186 | MetaComponents meta; |
| 187 | SetRegister(bb, instr.gpr0, texture); | 187 | std::array<Node, 4> dest; |
| 188 | } else { | 188 | |
| 189 | MetaComponents meta; | 189 | std::size_t dest_elem = 0; |
| 190 | std::array<Node, 4> dest; | 190 | for (std::size_t elem = 0; elem < 4; ++elem) { |
| 191 | 191 | if (!instr.tex.IsComponentEnabled(elem)) { | |
| 192 | std::size_t dest_elem = 0; | 192 | // Skip disabled components |
| 193 | for (std::size_t elem = 0; elem < 4; ++elem) { | 193 | continue; |
| 194 | if (!instr.tex.IsComponentEnabled(elem)) { | ||
| 195 | // Skip disabled components | ||
| 196 | continue; | ||
| 197 | } | ||
| 198 | meta.components_map[dest_elem] = static_cast<u32>(elem); | ||
| 199 | dest[dest_elem] = GetRegister(instr.gpr0.Value() + dest_elem); | ||
| 200 | |||
| 201 | ++dest_elem; | ||
| 202 | } | 194 | } |
| 203 | std::generate(dest.begin() + dest_elem, dest.end(), [&]() { return GetRegister(RZ); }); | 195 | meta.components_map[dest_elem] = static_cast<u32>(elem); |
| 196 | dest[dest_elem] = GetRegister(instr.gpr0.Value() + dest_elem); | ||
| 204 | 197 | ||
| 205 | bb.push_back(Operation(OperationCode::AssignComposite, std::move(meta), texture, | 198 | ++dest_elem; |
| 206 | dest[0], dest[1], dest[2], dest[3])); | ||
| 207 | } | 199 | } |
| 200 | std::generate(dest.begin() + dest_elem, dest.end(), [&]() { return GetRegister(RZ); }); | ||
| 201 | |||
| 202 | bb.push_back(Operation(OperationCode::AssignComposite, std::move(meta), texture, dest[0], | ||
| 203 | dest[1], dest[2], dest[3])); | ||
| 208 | break; | 204 | break; |
| 209 | } | 205 | } |
| 210 | case OpCode::Id::TEXS: { | 206 | case OpCode::Id::TEXS: { |
| @@ -272,7 +268,7 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { | |||
| 272 | params.push_back(Immediate(static_cast<u32>(instr.tld4.component))); | 268 | params.push_back(Immediate(static_cast<u32>(instr.tld4.component))); |
| 273 | 269 | ||
| 274 | const auto& sampler = GetSampler(instr.sampler, texture_type, false, depth_compare); | 270 | const auto& sampler = GetSampler(instr.sampler, texture_type, false, depth_compare); |
| 275 | const MetaTexture meta{sampler, num_coordinates}; | 271 | MetaTexture meta{sampler, num_coordinates}; |
| 276 | 272 | ||
| 277 | const Node texture = | 273 | const Node texture = |
| 278 | Operation(OperationCode::F4TextureGather, std::move(meta), std::move(params)); | 274 | Operation(OperationCode::F4TextureGather, std::move(meta), std::move(params)); |
| @@ -331,7 +327,7 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { | |||
| 331 | 327 | ||
| 332 | const auto& sampler = | 328 | const auto& sampler = |
| 333 | GetSampler(instr.sampler, TextureType::Texture2D, false, depth_compare); | 329 | GetSampler(instr.sampler, TextureType::Texture2D, false, depth_compare); |
| 334 | const MetaTexture meta{sampler, num_coords}; | 330 | MetaTexture meta{sampler, num_coords}; |
| 335 | 331 | ||
| 336 | WriteTexsInstructionFloat( | 332 | WriteTexsInstructionFloat( |
| 337 | bb, instr, Operation(OperationCode::F4TextureGather, meta, std::move(params))); | 333 | bb, instr, Operation(OperationCode::F4TextureGather, meta, std::move(params))); |
| @@ -350,7 +346,7 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { | |||
| 350 | 346 | ||
| 351 | switch (instr.txq.query_type) { | 347 | switch (instr.txq.query_type) { |
| 352 | case Tegra::Shader::TextureQueryType::Dimension: { | 348 | case Tegra::Shader::TextureQueryType::Dimension: { |
| 353 | const MetaTexture meta_texture{sampler}; | 349 | MetaTexture meta_texture{sampler}; |
| 354 | const MetaComponents meta_components{{0, 1, 2, 3}}; | 350 | const MetaComponents meta_components{{0, 1, 2, 3}}; |
| 355 | 351 | ||
| 356 | const Node texture = Operation(OperationCode::F4TextureQueryDimensions, meta_texture, | 352 | const Node texture = Operation(OperationCode::F4TextureQueryDimensions, meta_texture, |
| @@ -402,7 +398,7 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { | |||
| 402 | texture_type = TextureType::Texture2D; | 398 | texture_type = TextureType::Texture2D; |
| 403 | } | 399 | } |
| 404 | 400 | ||
| 405 | const MetaTexture meta_texture{sampler, static_cast<u32>(coords.size())}; | 401 | MetaTexture meta_texture{sampler, static_cast<u32>(coords.size())}; |
| 406 | const Node texture = | 402 | const Node texture = |
| 407 | Operation(OperationCode::F4TextureQueryLod, meta_texture, std::move(coords)); | 403 | Operation(OperationCode::F4TextureQueryLod, meta_texture, std::move(coords)); |
| 408 | 404 | ||
| @@ -474,7 +470,8 @@ void ShaderIR::WriteTexsInstructionFloat(BasicBlock& bb, Tegra::Shader::Instruct | |||
| 474 | 470 | ||
| 475 | Node ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | 471 | Node ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, |
| 476 | TextureProcessMode process_mode, bool depth_compare, bool is_array, | 472 | TextureProcessMode process_mode, bool depth_compare, bool is_array, |
| 477 | std::size_t bias_offset, std::vector<Node>&& coords) { | 473 | std::size_t array_offset, std::size_t bias_offset, |
| 474 | std::vector<Node>&& coords) { | ||
| 478 | UNIMPLEMENTED_IF_MSG( | 475 | UNIMPLEMENTED_IF_MSG( |
| 479 | (texture_type == TextureType::Texture3D && (is_array || depth_compare)) || | 476 | (texture_type == TextureType::Texture3D && (is_array || depth_compare)) || |
| 480 | (texture_type == TextureType::TextureCube && is_array && depth_compare), | 477 | (texture_type == TextureType::TextureCube && is_array && depth_compare), |
| @@ -486,26 +483,26 @@ Node ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 486 | process_mode == TextureProcessMode::LL || | 483 | process_mode == TextureProcessMode::LL || |
| 487 | process_mode == TextureProcessMode::LLA; | 484 | process_mode == TextureProcessMode::LLA; |
| 488 | 485 | ||
| 486 | // LOD selection (either via bias or explicit textureLod) not supported in GL for | ||
| 487 | // sampler2DArrayShadow and samplerCubeArrayShadow. | ||
| 489 | const bool gl_lod_supported = | 488 | const bool gl_lod_supported = |
| 490 | !((texture_type == TextureType::Texture2D && is_array && depth_compare) || | 489 | !((texture_type == Tegra::Shader::TextureType::Texture2D && is_array && depth_compare) || |
| 491 | (texture_type == TextureType::TextureCube && !is_array && depth_compare)); | 490 | (texture_type == Tegra::Shader::TextureType::TextureCube && is_array && depth_compare)); |
| 492 | 491 | ||
| 493 | const OperationCode read_method = | 492 | const OperationCode read_method = |
| 494 | lod_needed && gl_lod_supported ? OperationCode::F4TextureLod : OperationCode::F4Texture; | 493 | lod_needed && gl_lod_supported ? OperationCode::F4TextureLod : OperationCode::F4Texture; |
| 495 | 494 | ||
| 496 | const MetaTexture meta{sampler, static_cast<u32>(coords.size())}; | 495 | UNIMPLEMENTED_IF(process_mode != TextureProcessMode::None && !gl_lod_supported); |
| 497 | 496 | ||
| 497 | std::optional<u32> array_offset_value; | ||
| 498 | if (is_array) | ||
| 499 | array_offset_value = static_cast<u32>(array_offset); | ||
| 500 | MetaTexture meta{sampler, static_cast<u32>(coords.size()), array_offset_value}; | ||
| 498 | std::vector<Node> params = std::move(coords); | 501 | std::vector<Node> params = std::move(coords); |
| 499 | 502 | ||
| 500 | if (process_mode != TextureProcessMode::None) { | 503 | if (process_mode != TextureProcessMode::None && gl_lod_supported) { |
| 501 | if (process_mode == TextureProcessMode::LZ) { | 504 | if (process_mode == TextureProcessMode::LZ) { |
| 502 | if (gl_lod_supported) { | 505 | params.push_back(Immediate(0.0f)); |
| 503 | params.push_back(Immediate(0)); | ||
| 504 | } else { | ||
| 505 | // Lod 0 is emulated by a big negative bias in scenarios that are not supported by | ||
| 506 | // GLSL | ||
| 507 | params.push_back(Immediate(-1000)); | ||
| 508 | } | ||
| 509 | } else { | 506 | } else { |
| 510 | // If present, lod or bias are always stored in the register indexed by the gpr20 field | 507 | // If present, lod or bias are always stored in the register indexed by the gpr20 field |
| 511 | // with an offset depending on the usage of the other registers | 508 | // with an offset depending on the usage of the other registers |
| @@ -518,8 +515,8 @@ Node ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 518 | 515 | ||
| 519 | Node ShaderIR::GetTexCode(Instruction instr, TextureType texture_type, | 516 | Node ShaderIR::GetTexCode(Instruction instr, TextureType texture_type, |
| 520 | TextureProcessMode process_mode, bool depth_compare, bool is_array) { | 517 | TextureProcessMode process_mode, bool depth_compare, bool is_array) { |
| 521 | const bool lod_bias_enabled = (process_mode != Tegra::Shader::TextureProcessMode::None && | 518 | const bool lod_bias_enabled = |
| 522 | process_mode != Tegra::Shader::TextureProcessMode::LZ); | 519 | (process_mode != TextureProcessMode::None && process_mode != TextureProcessMode::LZ); |
| 523 | 520 | ||
| 524 | const auto [coord_count, total_coord_count] = ValidateAndGetCoordinateElement( | 521 | const auto [coord_count, total_coord_count] = ValidateAndGetCoordinateElement( |
| 525 | texture_type, depth_compare, is_array, lod_bias_enabled, 4, 5); | 522 | texture_type, depth_compare, is_array, lod_bias_enabled, 4, 5); |
| @@ -536,29 +533,30 @@ Node ShaderIR::GetTexCode(Instruction instr, TextureType texture_type, | |||
| 536 | if (depth_compare && !is_array && texture_type == TextureType::Texture1D) { | 533 | if (depth_compare && !is_array && texture_type == TextureType::Texture1D) { |
| 537 | coords.push_back(Immediate(0.0f)); | 534 | coords.push_back(Immediate(0.0f)); |
| 538 | } | 535 | } |
| 536 | std::size_t array_offset{}; | ||
| 537 | if (is_array) { | ||
| 538 | array_offset = coords.size(); | ||
| 539 | coords.push_back(GetRegister(array_register)); | ||
| 540 | } | ||
| 539 | if (depth_compare) { | 541 | if (depth_compare) { |
| 540 | // Depth is always stored in the register signaled by gpr20 | 542 | // Depth is always stored in the register signaled by gpr20 |
| 541 | // or in the next register if lod or bias are used | 543 | // or in the next register if lod or bias are used |
| 542 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); | 544 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); |
| 543 | coords.push_back(GetRegister(depth_register)); | 545 | coords.push_back(GetRegister(depth_register)); |
| 544 | } | 546 | } |
| 545 | if (is_array) { | ||
| 546 | coords.push_back(GetRegister(array_register)); | ||
| 547 | } | ||
| 548 | // Fill ignored coordinates | 547 | // Fill ignored coordinates |
| 549 | while (coords.size() < total_coord_count) { | 548 | while (coords.size() < total_coord_count) { |
| 550 | coords.push_back(Immediate(0)); | 549 | coords.push_back(Immediate(0)); |
| 551 | } | 550 | } |
| 552 | 551 | ||
| 553 | return GetTextureCode(instr, texture_type, process_mode, depth_compare, is_array, 0, | 552 | return GetTextureCode(instr, texture_type, process_mode, depth_compare, is_array, array_offset, |
| 554 | std::move(coords)); | 553 | 0, std::move(coords)); |
| 555 | } | 554 | } |
| 556 | 555 | ||
| 557 | Node ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, | 556 | Node ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, |
| 558 | TextureProcessMode process_mode, bool depth_compare, bool is_array) { | 557 | TextureProcessMode process_mode, bool depth_compare, bool is_array) { |
| 559 | 558 | const bool lod_bias_enabled = | |
| 560 | const bool lod_bias_enabled = (process_mode != Tegra::Shader::TextureProcessMode::None && | 559 | (process_mode != TextureProcessMode::None && process_mode != TextureProcessMode::LZ); |
| 561 | process_mode != Tegra::Shader::TextureProcessMode::LZ); | ||
| 562 | 560 | ||
| 563 | const auto [coord_count, total_coord_count] = ValidateAndGetCoordinateElement( | 561 | const auto [coord_count, total_coord_count] = ValidateAndGetCoordinateElement( |
| 564 | texture_type, depth_compare, is_array, lod_bias_enabled, 4, 4); | 562 | texture_type, depth_compare, is_array, lod_bias_enabled, 4, 4); |
| @@ -577,22 +575,23 @@ Node ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, | |||
| 577 | coords.push_back(GetRegister(last ? last_coord_register : coord_register + i)); | 575 | coords.push_back(GetRegister(last ? last_coord_register : coord_register + i)); |
| 578 | } | 576 | } |
| 579 | 577 | ||
| 578 | std::size_t array_offset{}; | ||
| 579 | if (is_array) { | ||
| 580 | array_offset = coords.size(); | ||
| 581 | coords.push_back(GetRegister(array_register)); | ||
| 582 | } | ||
| 580 | if (depth_compare) { | 583 | if (depth_compare) { |
| 581 | // Depth is always stored in the register signaled by gpr20 | 584 | // Depth is always stored in the register signaled by gpr20 |
| 582 | // or in the next register if lod or bias are used | 585 | // or in the next register if lod or bias are used |
| 583 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); | 586 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); |
| 584 | coords.push_back(GetRegister(depth_register)); | 587 | coords.push_back(GetRegister(depth_register)); |
| 585 | } | 588 | } |
| 586 | if (is_array) { | ||
| 587 | coords.push_back( | ||
| 588 | Operation(OperationCode::ICastFloat, NO_PRECISE, GetRegister(array_register))); | ||
| 589 | } | ||
| 590 | // Fill ignored coordinates | 589 | // Fill ignored coordinates |
| 591 | while (coords.size() < total_coord_count) { | 590 | while (coords.size() < total_coord_count) { |
| 592 | coords.push_back(Immediate(0)); | 591 | coords.push_back(Immediate(0)); |
| 593 | } | 592 | } |
| 594 | 593 | ||
| 595 | return GetTextureCode(instr, texture_type, process_mode, depth_compare, is_array, | 594 | return GetTextureCode(instr, texture_type, process_mode, depth_compare, is_array, array_offset, |
| 596 | (coord_count > 2 ? 1 : 0), std::move(coords)); | 595 | (coord_count > 2 ? 1 : 0), std::move(coords)); |
| 597 | } | 596 | } |
| 598 | 597 | ||
diff --git a/src/video_core/shader/glsl_decompiler.cpp b/src/video_core/shader/glsl_decompiler.cpp index 3ca3fae6d..a513c0c4b 100644 --- a/src/video_core/shader/glsl_decompiler.cpp +++ b/src/video_core/shader/glsl_decompiler.cpp | |||
| @@ -635,8 +635,10 @@ private: | |||
| 635 | result_type)); | 635 | result_type)); |
| 636 | } | 636 | } |
| 637 | 637 | ||
| 638 | #pragma optimize("", off) | ||
| 639 | |||
| 638 | std::string GenerateTexture(Operation operation, const std::string& func, | 640 | std::string GenerateTexture(Operation operation, const std::string& func, |
| 639 | const std::string& extra_cast = "") { | 641 | std::string extra_cast(std::string) = nullptr) { |
| 640 | constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"}; | 642 | constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"}; |
| 641 | 643 | ||
| 642 | const auto& meta = std::get<MetaTexture>(operation.GetMeta()); | 644 | const auto& meta = std::get<MetaTexture>(operation.GetMeta()); |
| @@ -651,15 +653,17 @@ private: | |||
| 651 | expr += '('; | 653 | expr += '('; |
| 652 | for (u32 i = 0; i < count; ++i) { | 654 | for (u32 i = 0; i < count; ++i) { |
| 653 | const bool is_extra = i >= meta.coords_count; | 655 | const bool is_extra = i >= meta.coords_count; |
| 654 | const bool do_cast = is_extra && !extra_cast.empty(); | 656 | const bool is_array = i == meta.array_index; |
| 655 | if (do_cast) { | 657 | |
| 656 | expr += extra_cast; | 658 | std::string operand = Visit(operation[i]); |
| 657 | expr += '('; | 659 | if (is_extra && extra_cast != nullptr) { |
| 660 | operand = extra_cast(operand); | ||
| 658 | } | 661 | } |
| 659 | expr += Visit(operation[i]); | 662 | if (is_array) { |
| 660 | if (do_cast) { | 663 | ASSERT(!is_extra); |
| 661 | expr += ')'; | 664 | operand = "float(ftoi(" + operand + "))"; |
| 662 | } | 665 | } |
| 666 | expr += operand; | ||
| 663 | if (i + 1 == meta.coords_count) { | 667 | if (i + 1 == meta.coords_count) { |
| 664 | expr += ')'; | 668 | expr += ')'; |
| 665 | } | 669 | } |
| @@ -1065,7 +1069,14 @@ private: | |||
| 1065 | } | 1069 | } |
| 1066 | 1070 | ||
| 1067 | std::string F4TextureGather(Operation operation) { | 1071 | std::string F4TextureGather(Operation operation) { |
| 1068 | return GenerateTexture(operation, "textureGather", "int"); | 1072 | const bool is_shadow = std::get<MetaTexture>(operation.GetMeta()).sampler.IsShadow(); |
| 1073 | if (is_shadow) { | ||
| 1074 | return GenerateTexture(operation, "textureGather", | ||
| 1075 | [](std::string ref_z) { return ref_z; }); | ||
| 1076 | } else { | ||
| 1077 | return GenerateTexture(operation, "textureGather", | ||
| 1078 | [](std::string comp) { return "ftoi(" + comp + ')'; }); | ||
| 1079 | } | ||
| 1069 | } | 1080 | } |
| 1070 | 1081 | ||
| 1071 | std::string F4TextureQueryDimensions(Operation operation) { | 1082 | std::string F4TextureQueryDimensions(Operation operation) { |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index b1083c4a0..5939318c1 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -265,6 +265,7 @@ struct MetaHalfArithmetic { | |||
| 265 | struct MetaTexture { | 265 | struct MetaTexture { |
| 266 | const Sampler& sampler; | 266 | const Sampler& sampler; |
| 267 | u32 coords_count{}; | 267 | u32 coords_count{}; |
| 268 | std::optional<u32> array_index; | ||
| 268 | }; | 269 | }; |
| 269 | 270 | ||
| 270 | struct MetaComponents { | 271 | struct MetaComponents { |
| @@ -696,7 +697,8 @@ private: | |||
| 696 | 697 | ||
| 697 | Node GetTextureCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, | 698 | Node GetTextureCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, |
| 698 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, | 699 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, |
| 699 | bool is_array, std::size_t bias_offset, std::vector<Node>&& coords); | 700 | bool is_array, std::size_t array_offset, std::size_t bias_offset, |
| 701 | std::vector<Node>&& coords); | ||
| 700 | 702 | ||
| 701 | void WriteLogicOperation(BasicBlock& bb, Tegra::Shader::Register dest, | 703 | void WriteLogicOperation(BasicBlock& bb, Tegra::Shader::Register dest, |
| 702 | Tegra::Shader::LogicOperation logic_op, Node op_a, Node op_b, | 704 | Tegra::Shader::LogicOperation logic_op, Node op_a, Node op_b, |