summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-01-29 04:31:40 -0300
committerGravatar ReinUsesLisp2019-02-07 00:46:13 -0300
commitd62b0a9e2941eb9d43e84ee40fe1531c2dc92eea (patch)
tree0d8d248f88357b72c20a349af1eba6076d9ba9c0 /src
parentMerge pull request #2083 from ReinUsesLisp/shader-ir-cbuf-tracking (diff)
downloadyuzu-d62b0a9e2941eb9d43e84ee40fe1531c2dc92eea.tar.gz
yuzu-d62b0a9e2941eb9d43e84ee40fe1531c2dc92eea.tar.xz
yuzu-d62b0a9e2941eb9d43e84ee40fe1531c2dc92eea.zip
shader_ir: Clean texture management code
Previous code relied on GLSL parameter order (something that's always ill-formed on an IR design). This approach passes spatial coordiantes through operation nodes and array and depth compare values in the the texture metadata. It still contains an "extra" vector containing generic nodes for bias and component index (for example) which is still a bit ill-formed but it should be better than the previous approach.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp73
-rw-r--r--src/video_core/shader/decode/memory.cpp154
-rw-r--r--src/video_core/shader/shader_ir.h10
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
537Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, 535Node4 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
629Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, 617Node4 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
671Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare, 653Node4 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
706Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { 680Node4 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
289struct MetaTexture { 289struct 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
296constexpr MetaArithmetic PRECISE = {true}; 297constexpr 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);