diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 73 | ||||
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 154 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 10 |
3 files changed, 104 insertions, 133 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 70e124dc4..aecd4758a 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -719,45 +719,51 @@ private: | |||
| 719 | constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"}; | 719 | constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"}; |
| 720 | 720 | ||
| 721 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); | 721 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
| 722 | const auto count = static_cast<u32>(operation.GetOperandsCount()); | ||
| 723 | ASSERT(meta); | 722 | ASSERT(meta); |
| 724 | 723 | ||
| 724 | const auto count = static_cast<u32>(operation.GetOperandsCount()); | ||
| 725 | const bool has_array = meta->sampler.IsArray(); | ||
| 726 | const bool has_shadow = meta->sampler.IsShadow(); | ||
| 727 | |||
| 725 | std::string expr = func; | 728 | std::string expr = func; |
| 726 | expr += '('; | 729 | expr += '('; |
| 727 | expr += GetSampler(meta->sampler); | 730 | expr += GetSampler(meta->sampler); |
| 728 | expr += ", "; | 731 | expr += ", "; |
| 729 | 732 | ||
| 730 | expr += coord_constructors[meta->coords_count - 1]; | 733 | expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow ? 1 : 0) - 1); |
| 731 | expr += '('; | 734 | expr += '('; |
| 732 | for (u32 i = 0; i < count; ++i) { | 735 | for (u32 i = 0; i < count; ++i) { |
| 733 | const bool is_extra = i >= meta->coords_count; | 736 | expr += Visit(operation[i]); |
| 734 | const bool is_array = i == meta->array_index; | ||
| 735 | |||
| 736 | std::string operand = [&]() { | ||
| 737 | if (is_extra && is_extra_int) { | ||
| 738 | if (const auto immediate = std::get_if<ImmediateNode>(operation[i])) { | ||
| 739 | return std::to_string(static_cast<s32>(immediate->GetValue())); | ||
| 740 | } else { | ||
| 741 | return "ftoi(" + Visit(operation[i]) + ')'; | ||
| 742 | } | ||
| 743 | } else { | ||
| 744 | return Visit(operation[i]); | ||
| 745 | } | ||
| 746 | }(); | ||
| 747 | if (is_array) { | ||
| 748 | ASSERT(!is_extra); | ||
| 749 | operand = "float(ftoi(" + operand + "))"; | ||
| 750 | } | ||
| 751 | |||
| 752 | expr += operand; | ||
| 753 | 737 | ||
| 754 | if (i + 1 == meta->coords_count) { | 738 | const u32 next = i + 1; |
| 755 | expr += ')'; | 739 | if (next < count || has_array || has_shadow) |
| 756 | } | 740 | expr += ", "; |
| 757 | if (i + 1 < count) { | 741 | } |
| 742 | if (has_array) { | ||
| 743 | expr += "float(ftoi(" + Visit(meta->array) + "))"; | ||
| 744 | } | ||
| 745 | if (has_shadow) { | ||
| 746 | if (has_array) | ||
| 758 | expr += ", "; | 747 | expr += ", "; |
| 748 | expr += Visit(meta->depth_compare); | ||
| 749 | } | ||
| 750 | expr += ')'; | ||
| 751 | |||
| 752 | for (const Node extra : meta->extras) { | ||
| 753 | expr += ", "; | ||
| 754 | if (is_extra_int) { | ||
| 755 | if (const auto immediate = std::get_if<ImmediateNode>(extra)) { | ||
| 756 | // Inline the string as an immediate integer in GLSL (some extra arguments are | ||
| 757 | // required to be constant) | ||
| 758 | expr += std::to_string(static_cast<s32>(immediate->GetValue())); | ||
| 759 | } else { | ||
| 760 | expr += "ftoi(" + Visit(extra) + ')'; | ||
| 761 | } | ||
| 762 | } else { | ||
| 763 | expr += Visit(extra); | ||
| 759 | } | 764 | } |
| 760 | } | 765 | } |
| 766 | |||
| 761 | expr += ')'; | 767 | expr += ')'; |
| 762 | return expr; | 768 | return expr; |
| 763 | } | 769 | } |
| @@ -1198,26 +1204,29 @@ private: | |||
| 1198 | std::string F4TexelFetch(Operation operation) { | 1204 | std::string F4TexelFetch(Operation operation) { |
| 1199 | constexpr std::array<const char*, 4> constructors = {"int", "ivec2", "ivec3", "ivec4"}; | 1205 | constexpr std::array<const char*, 4> constructors = {"int", "ivec2", "ivec3", "ivec4"}; |
| 1200 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); | 1206 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
| 1201 | const auto count = static_cast<u32>(operation.GetOperandsCount()); | ||
| 1202 | ASSERT(meta); | 1207 | ASSERT(meta); |
| 1208 | UNIMPLEMENTED_IF(meta->sampler.IsArray()); | ||
| 1209 | UNIMPLEMENTED_IF(!meta->extras.empty()); | ||
| 1210 | |||
| 1211 | const auto count = static_cast<u32>(operation.GetOperandsCount()); | ||
| 1203 | 1212 | ||
| 1204 | std::string expr = "texelFetch("; | 1213 | std::string expr = "texelFetch("; |
| 1205 | expr += GetSampler(meta->sampler); | 1214 | expr += GetSampler(meta->sampler); |
| 1206 | expr += ", "; | 1215 | expr += ", "; |
| 1207 | 1216 | ||
| 1208 | expr += constructors[meta->coords_count - 1]; | 1217 | expr += constructors.at(count - 1); |
| 1209 | expr += '('; | 1218 | expr += '('; |
| 1210 | for (u32 i = 0; i < count; ++i) { | 1219 | for (u32 i = 0; i < count; ++i) { |
| 1211 | expr += VisitOperand(operation, i, Type::Int); | 1220 | expr += VisitOperand(operation, i, Type::Int); |
| 1212 | 1221 | ||
| 1213 | if (i + 1 == meta->coords_count) { | 1222 | const u32 next = i + 1; |
| 1223 | if (next == count) | ||
| 1214 | expr += ')'; | 1224 | expr += ')'; |
| 1215 | } | 1225 | if (next < count) |
| 1216 | if (i + 1 < count) { | ||
| 1217 | expr += ", "; | 1226 | expr += ", "; |
| 1218 | } | ||
| 1219 | } | 1227 | } |
| 1220 | expr += ')'; | 1228 | expr += ')'; |
| 1229 | |||
| 1221 | return expr + GetSwizzle(meta->element); | 1230 | return expr + GetSwizzle(meta->element); |
| 1222 | } | 1231 | } |
| 1223 | 1232 | ||
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index e006f8138..be6ca044b 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -306,7 +306,6 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 306 | case OpCode::Id::TLD4S: { | 306 | case OpCode::Id::TLD4S: { |
| 307 | UNIMPLEMENTED_IF_MSG(instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI), | 307 | UNIMPLEMENTED_IF_MSG(instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI), |
| 308 | "AOFFI is not implemented"); | 308 | "AOFFI is not implemented"); |
| 309 | |||
| 310 | if (instr.tld4s.UsesMiscMode(TextureMiscMode::NODEP)) { | 309 | if (instr.tld4s.UsesMiscMode(TextureMiscMode::NODEP)) { |
| 311 | LOG_WARNING(HW_GPU, "TLD4S.NODEP implementation is incomplete"); | 310 | LOG_WARNING(HW_GPU, "TLD4S.NODEP implementation is incomplete"); |
| 312 | } | 311 | } |
| @@ -315,9 +314,8 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 315 | const Node op_a = GetRegister(instr.gpr8); | 314 | const Node op_a = GetRegister(instr.gpr8); |
| 316 | const Node op_b = GetRegister(instr.gpr20); | 315 | const Node op_b = GetRegister(instr.gpr20); |
| 317 | 316 | ||
| 318 | std::vector<Node> coords; | ||
| 319 | |||
| 320 | // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. | 317 | // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. |
| 318 | std::vector<Node> coords; | ||
| 321 | if (depth_compare) { | 319 | if (depth_compare) { |
| 322 | // Note: TLD4S coordinate encoding works just like TEXS's | 320 | // Note: TLD4S coordinate encoding works just like TEXS's |
| 323 | const Node op_y = GetRegister(instr.gpr8.Value() + 1); | 321 | const Node op_y = GetRegister(instr.gpr8.Value() + 1); |
| @@ -328,18 +326,18 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 328 | coords.push_back(op_a); | 326 | coords.push_back(op_a); |
| 329 | coords.push_back(op_b); | 327 | coords.push_back(op_b); |
| 330 | } | 328 | } |
| 331 | const auto num_coords = static_cast<u32>(coords.size()); | 329 | std::vector<Node> extras; |
| 332 | coords.push_back(Immediate(static_cast<u32>(instr.tld4s.component))); | 330 | extras.push_back(Immediate(static_cast<u32>(instr.tld4s.component))); |
| 333 | 331 | ||
| 334 | const auto& sampler = | 332 | const auto& sampler = |
| 335 | GetSampler(instr.sampler, TextureType::Texture2D, false, depth_compare); | 333 | GetSampler(instr.sampler, TextureType::Texture2D, false, depth_compare); |
| 336 | 334 | ||
| 337 | Node4 values; | 335 | Node4 values; |
| 338 | for (u32 element = 0; element < values.size(); ++element) { | 336 | for (u32 element = 0; element < values.size(); ++element) { |
| 339 | auto params = coords; | 337 | auto coords_copy = coords; |
| 340 | MetaTexture meta{sampler, element, num_coords}; | 338 | MetaTexture meta{sampler, {}, {}, extras, element}; |
| 341 | values[element] = | 339 | values[element] = |
| 342 | Operation(OperationCode::F4TextureGather, std::move(meta), std::move(params)); | 340 | Operation(OperationCode::F4TextureGather, meta, std::move(coords_copy)); |
| 343 | } | 341 | } |
| 344 | 342 | ||
| 345 | WriteTexsInstructionFloat(bb, instr, values); | 343 | WriteTexsInstructionFloat(bb, instr, values); |
| @@ -360,12 +358,13 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 360 | switch (instr.txq.query_type) { | 358 | switch (instr.txq.query_type) { |
| 361 | case Tegra::Shader::TextureQueryType::Dimension: { | 359 | case Tegra::Shader::TextureQueryType::Dimension: { |
| 362 | for (u32 element = 0; element < 4; ++element) { | 360 | for (u32 element = 0; element < 4; ++element) { |
| 363 | if (instr.txq.IsComponentEnabled(element)) { | 361 | if (!instr.txq.IsComponentEnabled(element)) { |
| 364 | MetaTexture meta{sampler, element}; | 362 | continue; |
| 365 | const Node value = Operation(OperationCode::F4TextureQueryDimensions, | ||
| 366 | std::move(meta), GetRegister(instr.gpr8)); | ||
| 367 | SetTemporal(bb, indexer++, value); | ||
| 368 | } | 363 | } |
| 364 | MetaTexture meta{sampler, {}, {}, {}, element}; | ||
| 365 | const Node value = Operation(OperationCode::F4TextureQueryDimensions, meta, | ||
| 366 | GetRegister(instr.gpr8)); | ||
| 367 | SetTemporal(bb, indexer++, value); | ||
| 369 | } | 368 | } |
| 370 | for (u32 i = 0; i < indexer; ++i) { | 369 | for (u32 i = 0; i < indexer; ++i) { |
| 371 | SetRegister(bb, instr.gpr0.Value() + i, GetTemporal(i)); | 370 | SetRegister(bb, instr.gpr0.Value() + i, GetTemporal(i)); |
| @@ -412,9 +411,8 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 412 | 411 | ||
| 413 | for (u32 element = 0; element < 2; ++element) { | 412 | for (u32 element = 0; element < 2; ++element) { |
| 414 | auto params = coords; | 413 | auto params = coords; |
| 415 | MetaTexture meta_texture{sampler, element, static_cast<u32>(coords.size())}; | 414 | MetaTexture meta{sampler, {}, {}, {}, element}; |
| 416 | const Node value = | 415 | const Node value = Operation(OperationCode::F4TextureQueryLod, meta, std::move(params)); |
| 417 | Operation(OperationCode::F4TextureQueryLod, meta_texture, std::move(params)); | ||
| 418 | SetTemporal(bb, element, value); | 416 | SetTemporal(bb, element, value); |
| 419 | } | 417 | } |
| 420 | for (u32 element = 0; element < 2; ++element) { | 418 | for (u32 element = 0; element < 2; ++element) { |
| @@ -535,15 +533,16 @@ void ShaderIR::WriteTexsInstructionHalfFloat(NodeBlock& bb, Instruction instr, | |||
| 535 | } | 533 | } |
| 536 | 534 | ||
| 537 | Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | 535 | Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, |
| 538 | TextureProcessMode process_mode, bool depth_compare, bool is_array, | 536 | TextureProcessMode process_mode, std::vector<Node> coords, |
| 539 | std::size_t array_offset, std::size_t bias_offset, | 537 | Node array, Node depth_compare, u32 bias_offset) { |
| 540 | std::vector<Node>&& coords) { | 538 | const bool is_array = array; |
| 541 | UNIMPLEMENTED_IF_MSG( | 539 | const bool is_shadow = depth_compare; |
| 542 | (texture_type == TextureType::Texture3D && (is_array || depth_compare)) || | ||
| 543 | (texture_type == TextureType::TextureCube && is_array && depth_compare), | ||
| 544 | "This method is not supported."); | ||
| 545 | 540 | ||
| 546 | const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, depth_compare); | 541 | UNIMPLEMENTED_IF_MSG((texture_type == TextureType::Texture3D && (is_array || is_shadow)) || |
| 542 | (texture_type == TextureType::TextureCube && is_array && is_shadow), | ||
| 543 | "This method is not supported."); | ||
| 544 | |||
| 545 | const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, is_shadow); | ||
| 547 | 546 | ||
| 548 | const bool lod_needed = process_mode == TextureProcessMode::LZ || | 547 | const bool lod_needed = process_mode == TextureProcessMode::LZ || |
| 549 | process_mode == TextureProcessMode::LL || | 548 | process_mode == TextureProcessMode::LL || |
| @@ -552,35 +551,30 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 552 | // LOD selection (either via bias or explicit textureLod) not supported in GL for | 551 | // LOD selection (either via bias or explicit textureLod) not supported in GL for |
| 553 | // sampler2DArrayShadow and samplerCubeArrayShadow. | 552 | // sampler2DArrayShadow and samplerCubeArrayShadow. |
| 554 | const bool gl_lod_supported = | 553 | const bool gl_lod_supported = |
| 555 | !((texture_type == Tegra::Shader::TextureType::Texture2D && is_array && depth_compare) || | 554 | !((texture_type == Tegra::Shader::TextureType::Texture2D && is_array && is_shadow) || |
| 556 | (texture_type == Tegra::Shader::TextureType::TextureCube && is_array && depth_compare)); | 555 | (texture_type == Tegra::Shader::TextureType::TextureCube && is_array && is_shadow)); |
| 557 | 556 | ||
| 558 | const OperationCode read_method = | 557 | const OperationCode read_method = |
| 559 | lod_needed && gl_lod_supported ? OperationCode::F4TextureLod : OperationCode::F4Texture; | 558 | lod_needed && gl_lod_supported ? OperationCode::F4TextureLod : OperationCode::F4Texture; |
| 560 | 559 | ||
| 561 | UNIMPLEMENTED_IF(process_mode != TextureProcessMode::None && !gl_lod_supported); | 560 | UNIMPLEMENTED_IF(process_mode != TextureProcessMode::None && !gl_lod_supported); |
| 562 | 561 | ||
| 563 | std::optional<u32> array_offset_value; | 562 | std::vector<Node> extras; |
| 564 | if (is_array) | ||
| 565 | array_offset_value = static_cast<u32>(array_offset); | ||
| 566 | |||
| 567 | const auto coords_count = static_cast<u32>(coords.size()); | ||
| 568 | |||
| 569 | if (process_mode != TextureProcessMode::None && gl_lod_supported) { | 563 | if (process_mode != TextureProcessMode::None && gl_lod_supported) { |
| 570 | if (process_mode == TextureProcessMode::LZ) { | 564 | if (process_mode == TextureProcessMode::LZ) { |
| 571 | coords.push_back(Immediate(0.0f)); | 565 | extras.push_back(Immediate(0.0f)); |
| 572 | } else { | 566 | } else { |
| 573 | // If present, lod or bias are always stored in the register indexed by the gpr20 | 567 | // If present, lod or bias are always stored in the register indexed by the gpr20 |
| 574 | // field with an offset depending on the usage of the other registers | 568 | // field with an offset depending on the usage of the other registers |
| 575 | coords.push_back(GetRegister(instr.gpr20.Value() + bias_offset)); | 569 | extras.push_back(GetRegister(instr.gpr20.Value() + bias_offset)); |
| 576 | } | 570 | } |
| 577 | } | 571 | } |
| 578 | 572 | ||
| 579 | Node4 values; | 573 | Node4 values; |
| 580 | for (u32 element = 0; element < values.size(); ++element) { | 574 | for (u32 element = 0; element < values.size(); ++element) { |
| 581 | auto params = coords; | 575 | auto copy_coords = coords; |
| 582 | MetaTexture meta{sampler, element, coords_count, array_offset_value}; | 576 | MetaTexture meta{sampler, array, depth_compare, extras, element}; |
| 583 | values[element] = Operation(read_method, std::move(meta), std::move(params)); | 577 | values[element] = Operation(read_method, meta, std::move(copy_coords)); |
| 584 | } | 578 | } |
| 585 | 579 | ||
| 586 | return values; | 580 | return values; |
| @@ -602,28 +596,22 @@ Node4 ShaderIR::GetTexCode(Instruction instr, TextureType texture_type, | |||
| 602 | for (std::size_t i = 0; i < coord_count; ++i) { | 596 | for (std::size_t i = 0; i < coord_count; ++i) { |
| 603 | coords.push_back(GetRegister(coord_register + i)); | 597 | coords.push_back(GetRegister(coord_register + i)); |
| 604 | } | 598 | } |
| 605 | // 1D.DC in opengl the 2nd component is ignored. | 599 | // 1D.DC in OpenGL the 2nd component is ignored. |
| 606 | if (depth_compare && !is_array && texture_type == TextureType::Texture1D) { | 600 | if (depth_compare && !is_array && texture_type == TextureType::Texture1D) { |
| 607 | coords.push_back(Immediate(0.0f)); | 601 | coords.push_back(Immediate(0.0f)); |
| 608 | } | 602 | } |
| 609 | std::size_t array_offset{}; | 603 | |
| 610 | if (is_array) { | 604 | const Node array = is_array ? GetRegister(array_register) : nullptr; |
| 611 | array_offset = coords.size(); | 605 | |
| 612 | coords.push_back(GetRegister(array_register)); | 606 | Node dc{}; |
| 613 | } | ||
| 614 | if (depth_compare) { | 607 | if (depth_compare) { |
| 615 | // Depth is always stored in the register signaled by gpr20 | 608 | // Depth is always stored in the register signaled by gpr20 or in the next register if lod |
| 616 | // or in the next register if lod or bias are used | 609 | // or bias are used |
| 617 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); | 610 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); |
| 618 | coords.push_back(GetRegister(depth_register)); | 611 | dc = GetRegister(depth_register); |
| 619 | } | ||
| 620 | // Fill ignored coordinates | ||
| 621 | while (coords.size() < total_coord_count) { | ||
| 622 | coords.push_back(Immediate(0)); | ||
| 623 | } | 612 | } |
| 624 | 613 | ||
| 625 | return GetTextureCode(instr, texture_type, process_mode, depth_compare, is_array, array_offset, | 614 | return GetTextureCode(instr, texture_type, process_mode, coords, array, dc, 0); |
| 626 | 0, std::move(coords)); | ||
| 627 | } | 615 | } |
| 628 | 616 | ||
| 629 | Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, | 617 | Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, |
| @@ -641,6 +629,7 @@ Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, | |||
| 641 | (is_array || !(lod_bias_enabled || depth_compare) || (coord_count > 2)) | 629 | (is_array || !(lod_bias_enabled || depth_compare) || (coord_count > 2)) |
| 642 | ? static_cast<u64>(instr.gpr20.Value()) | 630 | ? static_cast<u64>(instr.gpr20.Value()) |
| 643 | : coord_register + 1; | 631 | : coord_register + 1; |
| 632 | const u32 bias_offset = coord_count > 2 ? 1 : 0; | ||
| 644 | 633 | ||
| 645 | std::vector<Node> coords; | 634 | std::vector<Node> coords; |
| 646 | for (std::size_t i = 0; i < coord_count; ++i) { | 635 | for (std::size_t i = 0; i < coord_count; ++i) { |
| @@ -648,24 +637,17 @@ Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, | |||
| 648 | coords.push_back(GetRegister(last ? last_coord_register : coord_register + i)); | 637 | coords.push_back(GetRegister(last ? last_coord_register : coord_register + i)); |
| 649 | } | 638 | } |
| 650 | 639 | ||
| 651 | std::size_t array_offset{}; | 640 | const Node array = is_array ? GetRegister(array_register) : nullptr; |
| 652 | if (is_array) { | 641 | |
| 653 | array_offset = coords.size(); | 642 | Node dc{}; |
| 654 | coords.push_back(GetRegister(array_register)); | ||
| 655 | } | ||
| 656 | if (depth_compare) { | 643 | if (depth_compare) { |
| 657 | // Depth is always stored in the register signaled by gpr20 | 644 | // Depth is always stored in the register signaled by gpr20 or in the next register if lod |
| 658 | // or in the next register if lod or bias are used | 645 | // or bias are used |
| 659 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); | 646 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); |
| 660 | coords.push_back(GetRegister(depth_register)); | 647 | dc = GetRegister(depth_register); |
| 661 | } | ||
| 662 | // Fill ignored coordinates | ||
| 663 | while (coords.size() < total_coord_count) { | ||
| 664 | coords.push_back(Immediate(0)); | ||
| 665 | } | 648 | } |
| 666 | 649 | ||
| 667 | return GetTextureCode(instr, texture_type, process_mode, depth_compare, is_array, array_offset, | 650 | return GetTextureCode(instr, texture_type, process_mode, coords, array, dc, bias_offset); |
| 668 | (coord_count > 2 ? 1 : 0), std::move(coords)); | ||
| 669 | } | 651 | } |
| 670 | 652 | ||
| 671 | Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare, | 653 | Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare, |
| @@ -680,24 +662,16 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 680 | const u64 coord_register = array_register + (is_array ? 1 : 0); | 662 | const u64 coord_register = array_register + (is_array ? 1 : 0); |
| 681 | 663 | ||
| 682 | std::vector<Node> coords; | 664 | std::vector<Node> coords; |
| 683 | 665 | for (size_t i = 0; i < coord_count; ++i) | |
| 684 | for (size_t i = 0; i < coord_count; ++i) { | ||
| 685 | coords.push_back(GetRegister(coord_register + i)); | 666 | coords.push_back(GetRegister(coord_register + i)); |
| 686 | } | ||
| 687 | std::optional<u32> array_offset; | ||
| 688 | if (is_array) { | ||
| 689 | array_offset = static_cast<u32>(coords.size()); | ||
| 690 | coords.push_back(GetRegister(array_register)); | ||
| 691 | } | ||
| 692 | 667 | ||
| 693 | const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, depth_compare); | 668 | const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, depth_compare); |
| 694 | 669 | ||
| 695 | Node4 values; | 670 | Node4 values; |
| 696 | for (u32 element = 0; element < values.size(); ++element) { | 671 | for (u32 element = 0; element < values.size(); ++element) { |
| 697 | auto params = coords; | 672 | auto coords_copy = coords; |
| 698 | MetaTexture meta{sampler, element, static_cast<u32>(coords.size()), array_offset}; | 673 | MetaTexture meta{sampler, GetRegister(array_register), {}, {}, element}; |
| 699 | values[element] = | 674 | values[element] = Operation(OperationCode::F4TextureGather, meta, std::move(coords_copy)); |
| 700 | Operation(OperationCode::F4TextureGather, std::move(meta), std::move(params)); | ||
| 701 | } | 675 | } |
| 702 | 676 | ||
| 703 | return values; | 677 | return values; |
| @@ -705,7 +679,6 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 705 | 679 | ||
| 706 | Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { | 680 | Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { |
| 707 | const std::size_t type_coord_count = GetCoordCount(texture_type); | 681 | const std::size_t type_coord_count = GetCoordCount(texture_type); |
| 708 | const std::size_t total_coord_count = type_coord_count + (is_array ? 1 : 0); | ||
| 709 | const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; | 682 | const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; |
| 710 | 683 | ||
| 711 | // If enabled arrays index is always stored in the gpr8 field | 684 | // If enabled arrays index is always stored in the gpr8 field |
| @@ -719,33 +692,22 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is | |||
| 719 | : coord_register + 1; | 692 | : coord_register + 1; |
| 720 | 693 | ||
| 721 | std::vector<Node> coords; | 694 | std::vector<Node> coords; |
| 722 | |||
| 723 | for (std::size_t i = 0; i < type_coord_count; ++i) { | 695 | for (std::size_t i = 0; i < type_coord_count; ++i) { |
| 724 | const bool last = (i == (type_coord_count - 1)) && (type_coord_count > 1); | 696 | const bool last = (i == (type_coord_count - 1)) && (type_coord_count > 1); |
| 725 | coords.push_back(GetRegister(last ? last_coord_register : coord_register + i)); | 697 | coords.push_back(GetRegister(last ? last_coord_register : coord_register + i)); |
| 726 | } | 698 | } |
| 727 | std::optional<u32> array_offset; | ||
| 728 | if (is_array) { | ||
| 729 | array_offset = static_cast<u32>(coords.size()); | ||
| 730 | coords.push_back(GetRegister(array_register)); | ||
| 731 | } | ||
| 732 | const auto coords_count = static_cast<u32>(coords.size()); | ||
| 733 | 699 | ||
| 734 | if (lod_enabled) { | 700 | const Node array = is_array ? GetRegister(array_register) : nullptr; |
| 735 | // When lod is used always is in grp20 | 701 | // When lod is used always is in gpr20 |
| 736 | coords.push_back(GetRegister(instr.gpr20)); | 702 | const Node lod = lod_enabled ? GetRegister(instr.gpr20) : Immediate(0); |
| 737 | } else { | ||
| 738 | coords.push_back(Immediate(0)); | ||
| 739 | } | ||
| 740 | 703 | ||
| 741 | const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, false); | 704 | const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, false); |
| 742 | 705 | ||
| 743 | Node4 values; | 706 | Node4 values; |
| 744 | for (u32 element = 0; element < values.size(); ++element) { | 707 | for (u32 element = 0; element < values.size(); ++element) { |
| 745 | auto params = coords; | 708 | auto coords_copy = coords; |
| 746 | MetaTexture meta{sampler, element, coords_count, array_offset}; | 709 | MetaTexture meta{sampler, array, {}, {lod}, element}; |
| 747 | values[element] = | 710 | values[element] = Operation(OperationCode::F4TexelFetch, meta, std::move(coords_copy)); |
| 748 | Operation(OperationCode::F4TexelFetch, std::move(meta), std::move(params)); | ||
| 749 | } | 711 | } |
| 750 | return values; | 712 | return values; |
| 751 | } | 713 | } |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 1d4fbef53..0c3d9c61e 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -288,9 +288,10 @@ struct MetaHalfArithmetic { | |||
| 288 | 288 | ||
| 289 | struct MetaTexture { | 289 | struct MetaTexture { |
| 290 | const Sampler& sampler; | 290 | const Sampler& sampler; |
| 291 | Node array{}; | ||
| 292 | Node depth_compare{}; | ||
| 293 | std::vector<Node> extras; | ||
| 291 | u32 element{}; | 294 | u32 element{}; |
| 292 | u32 coords_count{}; | ||
| 293 | std::optional<u32> array_index; | ||
| 294 | }; | 295 | }; |
| 295 | 296 | ||
| 296 | constexpr MetaArithmetic PRECISE = {true}; | 297 | constexpr MetaArithmetic PRECISE = {true}; |
| @@ -754,9 +755,8 @@ private: | |||
| 754 | bool lod_bias_enabled, std::size_t max_coords, std::size_t max_inputs); | 755 | bool lod_bias_enabled, std::size_t max_coords, std::size_t max_inputs); |
| 755 | 756 | ||
| 756 | Node4 GetTextureCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, | 757 | Node4 GetTextureCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, |
| 757 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, | 758 | Tegra::Shader::TextureProcessMode process_mode, std::vector<Node> coords, |
| 758 | bool is_array, std::size_t array_offset, std::size_t bias_offset, | 759 | Node array, Node depth_compare, u32 bias_offset); |
| 759 | std::vector<Node>&& coords); | ||
| 760 | 760 | ||
| 761 | Node GetVideoOperand(Node op, bool is_chunk, bool is_signed, Tegra::Shader::VideoType type, | 761 | Node GetVideoOperand(Node op, bool is_chunk, bool is_signed, Tegra::Shader::VideoType type, |
| 762 | u64 byte_height); | 762 | u64 byte_height); |