summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-11-25 22:36:25 -0500
committerGravatar GitHub2018-11-25 22:36:25 -0500
commit03948134019e75c2e090db42a470d8cded96de4d (patch)
tree3e89cac69fc21a847b735282466d55e01f32e2da /src
parentMerge pull request #1783 from ReinUsesLisp/clip-distances (diff)
parentFix Texture Overlapping (diff)
downloadyuzu-03948134019e75c2e090db42a470d8cded96de4d.tar.gz
yuzu-03948134019e75c2e090db42a470d8cded96de4d.tar.xz
yuzu-03948134019e75c2e090db42a470d8cded96de4d.zip
Merge pull request #1782 from FernandoS27/dc
Fixed Coordinate Encodings in TEX and TEXS instructions
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp304
1 files changed, 188 insertions, 116 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 3b7841715..9dbaf26d4 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1292,7 +1292,15 @@ private:
1292 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1); 1292 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1);
1293 } 1293 }
1294 1294
1295 void WriteTexsInstruction(const Instruction& instr, const std::string& texture) { 1295 void WriteTexsInstruction(const Instruction& instr, const std::string& coord,
1296 const std::string& texture) {
1297 // Add an extra scope and declare the texture coords inside to prevent
1298 // overwriting them in case they are used as outputs of the texs instruction.
1299 shader.AddLine('{');
1300 ++shader.scope;
1301 shader.AddLine(coord);
1302 shader.AddLine("vec4 texture_tmp = " + texture + ';');
1303
1296 // TEXS has two destination registers and a swizzle. The first two elements in the swizzle 1304 // TEXS has two destination registers and a swizzle. The first two elements in the swizzle
1297 // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1 1305 // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1
1298 1306
@@ -1304,17 +1312,19 @@ private:
1304 1312
1305 if (written_components < 2) { 1313 if (written_components < 2) {
1306 // Write the first two swizzle components to gpr0 and gpr0+1 1314 // Write the first two swizzle components to gpr0 and gpr0+1
1307 regs.SetRegisterToFloat(instr.gpr0, component, texture, 1, 4, false, 1315 regs.SetRegisterToFloat(instr.gpr0, component, "texture_tmp", 1, 4, false,
1308 written_components % 2); 1316 written_components % 2);
1309 } else { 1317 } else {
1310 ASSERT(instr.texs.HasTwoDestinations()); 1318 ASSERT(instr.texs.HasTwoDestinations());
1311 // Write the rest of the swizzle components to gpr28 and gpr28+1 1319 // Write the rest of the swizzle components to gpr28 and gpr28+1
1312 regs.SetRegisterToFloat(instr.gpr28, component, texture, 1, 4, false, 1320 regs.SetRegisterToFloat(instr.gpr28, component, "texture_tmp", 1, 4, false,
1313 written_components % 2); 1321 written_components % 2);
1314 } 1322 }
1315 1323
1316 ++written_components; 1324 ++written_components;
1317 } 1325 }
1326 --shader.scope;
1327 shader.AddLine('}');
1318 } 1328 }
1319 1329
1320 static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) { 1330 static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) {
@@ -2536,61 +2546,83 @@ private:
2536 const bool depth_compare = 2546 const bool depth_compare =
2537 instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); 2547 instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
2538 u32 num_coordinates = TextureCoordinates(texture_type); 2548 u32 num_coordinates = TextureCoordinates(texture_type);
2539 if (depth_compare) 2549 u32 start_index = 0;
2540 num_coordinates += 1; 2550 std::string array_elem;
2551 if (is_array) {
2552 array_elem = regs.GetRegisterAsInteger(instr.gpr8);
2553 start_index = 1;
2554 }
2555 const auto process_mode = instr.tex.GetTextureProcessMode();
2556 u32 start_index_b = 0;
2557 std::string lod_value;
2558 if (process_mode != Tegra::Shader::TextureProcessMode::LZ &&
2559 process_mode != Tegra::Shader::TextureProcessMode::None) {
2560 start_index_b = 1;
2561 lod_value = regs.GetRegisterAsFloat(instr.gpr20);
2562 }
2563
2564 std::string depth_value;
2565 if (depth_compare) {
2566 depth_value = regs.GetRegisterAsFloat(instr.gpr20.Value() + start_index_b);
2567 }
2568
2569 bool depth_compare_extra = false;
2541 2570
2542 switch (num_coordinates) { 2571 switch (num_coordinates) {
2543 case 1: { 2572 case 1: {
2573 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index);
2544 if (is_array) { 2574 if (is_array) {
2545 const std::string index = regs.GetRegisterAsInteger(instr.gpr8); 2575 if (depth_compare) {
2546 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2576 coord = "vec3 coords = vec3(" + x + ", " + depth_value + ", " +
2547 coord = "vec2 coords = vec2(" + x + ", " + index + ");"; 2577 array_elem + ");";
2578 } else {
2579 coord = "vec2 coords = vec2(" + x + ", " + array_elem + ");";
2580 }
2548 } else { 2581 } else {
2549 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2582 if (depth_compare) {
2550 coord = "float coords = " + x + ';'; 2583 coord = "vec2 coords = vec2(" + x + ", " + depth_value + ");";
2584 } else {
2585 coord = "float coords = " + x + ';';
2586 }
2551 } 2587 }
2552 break; 2588 break;
2553 } 2589 }
2554 case 2: { 2590 case 2: {
2591 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index);
2592 const std::string y =
2593 regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 1);
2555 if (is_array) { 2594 if (is_array) {
2556 const std::string index = regs.GetRegisterAsInteger(instr.gpr8); 2595 if (depth_compare) {
2557 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2596 coord = "vec4 coords = vec4(" + x + ", " + y + ", " + depth_value +
2558 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2); 2597 ", " + array_elem + ");";
2559 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; 2598 } else {
2599 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + array_elem + ");";
2600 }
2560 } else { 2601 } else {
2561 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2602 if (depth_compare) {
2562 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2603 coord =
2563 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 2604 "vec3 coords = vec3(" + x + ", " + y + ", " + depth_value + ");";
2605 } else {
2606 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2607 }
2564 } 2608 }
2565 break; 2609 break;
2566 } 2610 }
2567 case 3: { 2611 case 3: {
2568 if (depth_compare) { 2612 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index);
2569 if (is_array) { 2613 const std::string y =
2570 const std::string index = regs.GetRegisterAsInteger(instr.gpr8); 2614 regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 1);
2571 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2615 const std::string z =
2572 const std::string y = regs.GetRegisterAsFloat(instr.gpr20); 2616 regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 2);
2573 const std::string z = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); 2617 if (is_array) {
2574 coord = "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " + index + 2618 depth_compare_extra = depth_compare;
2575 ");"; 2619 coord = "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " +
2576 } else { 2620 array_elem + ");";
2577 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2578 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2579 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
2580 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");";
2581 }
2582 } else { 2621 } else {
2583 if (is_array) { 2622 if (depth_compare) {
2584 const std::string index = regs.GetRegisterAsInteger(instr.gpr8); 2623 coord = "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " +
2585 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2624 depth_value + ");";
2586 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2);
2587 const std::string z = regs.GetRegisterAsFloat(instr.gpr8.Value() + 3);
2588 coord = "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " + index +
2589 ");";
2590 } else { 2625 } else {
2591 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2592 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2593 const std::string z = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2);
2594 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; 2626 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");";
2595 } 2627 }
2596 } 2628 }
@@ -2606,82 +2638,85 @@ private:
2606 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 2638 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2607 texture_type = Tegra::Shader::TextureType::Texture2D; 2639 texture_type = Tegra::Shader::TextureType::Texture2D;
2608 } 2640 }
2609 // TODO: make sure coordinates are always indexed to gpr8 and gpr20 is always bias
2610 // or lod.
2611 2641
2612 const std::string sampler = 2642 const std::string sampler =
2613 GetSampler(instr.sampler, texture_type, is_array, depth_compare); 2643 GetSampler(instr.sampler, texture_type, is_array, depth_compare);
2614 // Add an extra scope and declare the texture coords inside to prevent 2644 // Add an extra scope and declare the texture coords inside to prevent
2615 // overwriting them in case they are used as outputs of the texs instruction. 2645 // overwriting them in case they are used as outputs of the texs instruction.
2616 2646
2617 shader.AddLine("{"); 2647 shader.AddLine('{');
2618 ++shader.scope; 2648 ++shader.scope;
2619 shader.AddLine(coord); 2649 shader.AddLine(coord);
2620 std::string texture; 2650 std::string texture;
2621 2651
2622 switch (instr.tex.GetTextureProcessMode()) { 2652 switch (instr.tex.GetTextureProcessMode()) {
2623 case Tegra::Shader::TextureProcessMode::None: { 2653 case Tegra::Shader::TextureProcessMode::None: {
2624 texture = "texture(" + sampler + ", coords)"; 2654 if (!depth_compare_extra) {
2655 texture = "texture(" + sampler + ", coords)";
2656 } else {
2657 texture = "texture(" + sampler + ", coords, " + depth_value + ')';
2658 }
2625 break; 2659 break;
2626 } 2660 }
2627 case Tegra::Shader::TextureProcessMode::LZ: { 2661 case Tegra::Shader::TextureProcessMode::LZ: {
2628 texture = "textureLod(" + sampler + ", coords, 0.0)"; 2662 if (!depth_compare_extra) {
2663 texture = "textureLod(" + sampler + ", coords, 0.0)";
2664 } else {
2665 texture = "texture(" + sampler + ", coords, " + depth_value + ')';
2666 }
2629 break; 2667 break;
2630 } 2668 }
2631 case Tegra::Shader::TextureProcessMode::LB: 2669 case Tegra::Shader::TextureProcessMode::LB:
2632 case Tegra::Shader::TextureProcessMode::LBA: { 2670 case Tegra::Shader::TextureProcessMode::LBA: {
2633 const std::string bias = [&]() {
2634 if (depth_compare) {
2635 if (is_array)
2636 return regs.GetRegisterAsFloat(instr.gpr20.Value() + 2);
2637 else
2638 return regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
2639 } else {
2640 return regs.GetRegisterAsFloat(instr.gpr20);
2641 }
2642 }();
2643 shader.AddLine("float bias = " + bias + ';');
2644
2645 // TODO: Figure if A suffix changes the equation at all. 2671 // TODO: Figure if A suffix changes the equation at all.
2646 texture = "texture(" + sampler + ", coords, bias)"; 2672 if (!depth_compare_extra) {
2673 texture = "texture(" + sampler + ", coords, " + lod_value + ')';
2674 } else {
2675 texture = "texture(" + sampler + ", coords, " + depth_value + ')';
2676 LOG_WARNING(HW_GPU,
2677 "OpenGL Limitation: can't set bias value along depth compare");
2678 }
2647 break; 2679 break;
2648 } 2680 }
2649 case Tegra::Shader::TextureProcessMode::LL: 2681 case Tegra::Shader::TextureProcessMode::LL:
2650 case Tegra::Shader::TextureProcessMode::LLA: { 2682 case Tegra::Shader::TextureProcessMode::LLA: {
2651 const std::string lod = [&]() {
2652 if (num_coordinates <= 2) {
2653 return regs.GetRegisterAsFloat(instr.gpr20);
2654 } else {
2655 return regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
2656 }
2657 }();
2658 shader.AddLine("float lod = " + lod + ';');
2659
2660 // TODO: Figure if A suffix changes the equation at all. 2683 // TODO: Figure if A suffix changes the equation at all.
2661 texture = "textureLod(" + sampler + ", coords, lod)"; 2684 if (!depth_compare_extra) {
2685 texture = "textureLod(" + sampler + ", coords, " + lod_value + ')';
2686 } else {
2687 texture = "texture(" + sampler + ", coords, " + depth_value + ')';
2688 LOG_WARNING(HW_GPU,
2689 "OpenGL Limitation: can't set lod value along depth compare");
2690 }
2662 break; 2691 break;
2663 } 2692 }
2664 default: { 2693 default: {
2665 texture = "texture(" + sampler + ", coords)"; 2694 if (!depth_compare_extra) {
2695 texture = "texture(" + sampler + ", coords)";
2696 } else {
2697 texture = "texture(" + sampler + ", coords, " + depth_value + ')';
2698 }
2666 UNIMPLEMENTED_MSG("Unhandled texture process mode {}", 2699 UNIMPLEMENTED_MSG("Unhandled texture process mode {}",
2667 static_cast<u32>(instr.tex.GetTextureProcessMode())); 2700 static_cast<u32>(instr.tex.GetTextureProcessMode()));
2668 } 2701 }
2669 } 2702 }
2670 if (!depth_compare) { 2703 if (!depth_compare) {
2704 shader.AddLine("vec4 texture_tmp = " + texture + ';');
2671 std::size_t dest_elem{}; 2705 std::size_t dest_elem{};
2672 for (std::size_t elem = 0; elem < 4; ++elem) { 2706 for (std::size_t elem = 0; elem < 4; ++elem) {
2673 if (!instr.tex.IsComponentEnabled(elem)) { 2707 if (!instr.tex.IsComponentEnabled(elem)) {
2674 // Skip disabled components 2708 // Skip disabled components
2675 continue; 2709 continue;
2676 } 2710 }
2677 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); 2711 regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false,
2712 dest_elem);
2678 ++dest_elem; 2713 ++dest_elem;
2679 } 2714 }
2680 } else { 2715 } else {
2681 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); 2716 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false);
2682 } 2717 }
2683 --shader.scope; 2718 --shader.scope;
2684 shader.AddLine("}"); 2719 shader.AddLine('}');
2685 break; 2720 break;
2686 } 2721 }
2687 case OpCode::Id::TEXS: { 2722 case OpCode::Id::TEXS: {
@@ -2694,41 +2729,76 @@ private:
2694 const bool depth_compare = 2729 const bool depth_compare =
2695 instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); 2730 instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
2696 u32 num_coordinates = TextureCoordinates(texture_type); 2731 u32 num_coordinates = TextureCoordinates(texture_type);
2697 if (depth_compare) 2732 const auto process_mode = instr.texs.GetTextureProcessMode();
2698 num_coordinates += 1; 2733 std::string lod_value;
2699 2734 std::string coord;
2700 // Scope to avoid variable name overlaps. 2735 u32 lod_offset = 0;
2701 shader.AddLine('{'); 2736 if (process_mode == Tegra::Shader::TextureProcessMode::LL) {
2702 ++shader.scope; 2737 if (num_coordinates > 2) {
2738 lod_value = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
2739 lod_offset = 2;
2740 } else {
2741 lod_value = regs.GetRegisterAsFloat(instr.gpr20);
2742 lod_offset = 1;
2743 }
2744 }
2703 2745
2704 switch (num_coordinates) { 2746 switch (num_coordinates) {
2747 case 1: {
2748 coord = "float coords = " + regs.GetRegisterAsFloat(instr.gpr8) + ';';
2749 break;
2750 }
2705 case 2: { 2751 case 2: {
2706 if (is_array) { 2752 if (is_array) {
2707 const std::string index = regs.GetRegisterAsInteger(instr.gpr8); 2753 if (depth_compare) {
2708 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2754 const std::string index = regs.GetRegisterAsInteger(instr.gpr8);
2709 const std::string y = regs.GetRegisterAsFloat(instr.gpr20); 2755 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2710 shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"); 2756 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
2757 const std::string z = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
2758 coord = "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " + index +
2759 ");";
2760 } else {
2761 const std::string index = regs.GetRegisterAsInteger(instr.gpr8);
2762 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2763 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
2764 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");";
2765 }
2711 } else { 2766 } else {
2712 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2767 if (lod_offset != 0) {
2713 const std::string y = regs.GetRegisterAsFloat(instr.gpr20); 2768 if (depth_compare) {
2714 shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");"); 2769 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2770 const std::string y =
2771 regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2772 const std::string z =
2773 regs.GetRegisterAsFloat(instr.gpr20.Value() + lod_offset);
2774 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");";
2775 } else {
2776 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2777 const std::string y =
2778 regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2779 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2780 }
2781 } else {
2782 if (depth_compare) {
2783 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2784 const std::string y =
2785 regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2786 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
2787 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");";
2788 } else {
2789 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2790 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
2791 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2792 }
2793 }
2715 } 2794 }
2716 break; 2795 break;
2717 } 2796 }
2718 case 3: { 2797 case 3: {
2719 if (is_array) { 2798 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2720 const std::string index = regs.GetRegisterAsInteger(instr.gpr8); 2799 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2721 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2800 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
2722 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2); 2801 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");";
2723 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
2724 shader.AddLine("vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " +
2725 index + ");");
2726 } else {
2727 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2728 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2729 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
2730 shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + z + ");");
2731 }
2732 break; 2802 break;
2733 } 2803 }
2734 default: 2804 default:
@@ -2738,14 +2808,14 @@ private:
2738 // Fallback to interpreting as a 2D texture for now 2808 // Fallback to interpreting as a 2D texture for now
2739 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2809 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2740 const std::string y = regs.GetRegisterAsFloat(instr.gpr20); 2810 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
2741 shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");"); 2811 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2742 texture_type = Tegra::Shader::TextureType::Texture2D; 2812 texture_type = Tegra::Shader::TextureType::Texture2D;
2743 is_array = false; 2813 is_array = false;
2744 } 2814 }
2745 const std::string sampler = 2815 const std::string sampler =
2746 GetSampler(instr.sampler, texture_type, is_array, depth_compare); 2816 GetSampler(instr.sampler, texture_type, is_array, depth_compare);
2747 std::string texture; 2817 std::string texture;
2748 switch (instr.texs.GetTextureProcessMode()) { 2818 switch (process_mode) {
2749 case Tegra::Shader::TextureProcessMode::None: { 2819 case Tegra::Shader::TextureProcessMode::None: {
2750 texture = "texture(" + sampler + ", coords)"; 2820 texture = "texture(" + sampler + ", coords)";
2751 break; 2821 break;
@@ -2759,8 +2829,7 @@ private:
2759 break; 2829 break;
2760 } 2830 }
2761 case Tegra::Shader::TextureProcessMode::LL: { 2831 case Tegra::Shader::TextureProcessMode::LL: {
2762 const std::string op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); 2832 texture = "textureLod(" + sampler + ", coords, " + lod_value + ')';
2763 texture = "textureLod(" + sampler + ", coords, " + op_c + ')';
2764 break; 2833 break;
2765 } 2834 }
2766 default: { 2835 default: {
@@ -2770,13 +2839,11 @@ private:
2770 } 2839 }
2771 } 2840 }
2772 if (!depth_compare) { 2841 if (!depth_compare) {
2773 WriteTexsInstruction(instr, texture); 2842 WriteTexsInstruction(instr, coord, texture);
2774 } else { 2843 } else {
2775 WriteTexsInstruction(instr, "vec4(" + texture + ')'); 2844 WriteTexsInstruction(instr, coord, "vec4(" + texture + ')');
2776 } 2845 }
2777 2846
2778 shader.AddLine('}');
2779 --shader.scope;
2780 break; 2847 break;
2781 } 2848 }
2782 case OpCode::Id::TLDS: { 2849 case OpCode::Id::TLDS: {
@@ -2798,11 +2865,12 @@ private:
2798 // Scope to avoid variable name overlaps. 2865 // Scope to avoid variable name overlaps.
2799 shader.AddLine('{'); 2866 shader.AddLine('{');
2800 ++shader.scope; 2867 ++shader.scope;
2868 std::string coords;
2801 2869
2802 switch (texture_type) { 2870 switch (texture_type) {
2803 case Tegra::Shader::TextureType::Texture1D: { 2871 case Tegra::Shader::TextureType::Texture1D: {
2804 const std::string x = regs.GetRegisterAsInteger(instr.gpr8); 2872 const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
2805 shader.AddLine("int coords = " + x + ';'); 2873 coords = "float coords = " + x + ';';
2806 break; 2874 break;
2807 } 2875 }
2808 case Tegra::Shader::TextureType::Texture2D: { 2876 case Tegra::Shader::TextureType::Texture2D: {
@@ -2810,7 +2878,8 @@ private:
2810 2878
2811 const std::string x = regs.GetRegisterAsInteger(instr.gpr8); 2879 const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
2812 const std::string y = regs.GetRegisterAsInteger(instr.gpr20); 2880 const std::string y = regs.GetRegisterAsInteger(instr.gpr20);
2813 shader.AddLine("ivec2 coords = ivec2(" + x + ", " + y + ");"); 2881 // shader.AddLine("ivec2 coords = ivec2(" + x + ", " + y + ");");
2882 coords = "ivec2 coords = ivec2(" + x + ", " + y + ");";
2814 extra_op_offset = 1; 2883 extra_op_offset = 1;
2815 break; 2884 break;
2816 } 2885 }
@@ -2838,7 +2907,7 @@ private:
2838 static_cast<u32>(instr.tlds.GetTextureProcessMode())); 2907 static_cast<u32>(instr.tlds.GetTextureProcessMode()));
2839 } 2908 }
2840 } 2909 }
2841 WriteTexsInstruction(instr, texture); 2910 WriteTexsInstruction(instr, coords, texture);
2842 2911
2843 --shader.scope; 2912 --shader.scope;
2844 shader.AddLine('}'); 2913 shader.AddLine('}');
@@ -2897,14 +2966,17 @@ private:
2897 2966
2898 const std::string texture = "textureGather(" + sampler + ", coords, " + 2967 const std::string texture = "textureGather(" + sampler + ", coords, " +
2899 std::to_string(instr.tld4.component) + ')'; 2968 std::to_string(instr.tld4.component) + ')';
2969
2900 if (!depth_compare) { 2970 if (!depth_compare) {
2971 shader.AddLine("vec4 texture_tmp = " + texture + ';');
2901 std::size_t dest_elem{}; 2972 std::size_t dest_elem{};
2902 for (std::size_t elem = 0; elem < 4; ++elem) { 2973 for (std::size_t elem = 0; elem < 4; ++elem) {
2903 if (!instr.tex.IsComponentEnabled(elem)) { 2974 if (!instr.tex.IsComponentEnabled(elem)) {
2904 // Skip disabled components 2975 // Skip disabled components
2905 continue; 2976 continue;
2906 } 2977 }
2907 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); 2978 regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false,
2979 dest_elem);
2908 ++dest_elem; 2980 ++dest_elem;
2909 } 2981 }
2910 } else { 2982 } else {
@@ -2925,6 +2997,7 @@ private:
2925 // Scope to avoid variable name overlaps. 2997 // Scope to avoid variable name overlaps.
2926 shader.AddLine('{'); 2998 shader.AddLine('{');
2927 ++shader.scope; 2999 ++shader.scope;
3000 std::string coords;
2928 3001
2929 const bool depth_compare = 3002 const bool depth_compare =
2930 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); 3003 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
@@ -2934,20 +3007,19 @@ private:
2934 const std::string sampler = GetSampler( 3007 const std::string sampler = GetSampler(
2935 instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare); 3008 instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare);
2936 if (!depth_compare) { 3009 if (!depth_compare) {
2937 shader.AddLine("vec2 coords = vec2(" + op_a + ", " + op_b + ");"); 3010 coords = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
2938 } else { 3011 } else {
2939 // Note: TLD4S coordinate encoding works just like TEXS's 3012 // Note: TLD4S coordinate encoding works just like TEXS's
2940 shader.AddLine( 3013 const std::string op_y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2941 "float op_y = " + regs.GetRegisterAsFloat(instr.gpr8.Value() + 1) + ';'); 3014 coords = "vec3 coords = vec3(" + op_a + ", " + op_y + ", " + op_b + ");";
2942 shader.AddLine("vec3 coords = vec3(" + op_a + ", op_y, " + op_b + ");");
2943 } 3015 }
2944 const std::string texture = "textureGather(" + sampler + ", coords, " + 3016 const std::string texture = "textureGather(" + sampler + ", coords, " +
2945 std::to_string(instr.tld4s.component) + ')'; 3017 std::to_string(instr.tld4s.component) + ')';
2946 3018
2947 if (!depth_compare) { 3019 if (!depth_compare) {
2948 WriteTexsInstruction(instr, texture); 3020 WriteTexsInstruction(instr, coords, texture);
2949 } else { 3021 } else {
2950 WriteTexsInstruction(instr, "vec4(" + texture + ')'); 3022 WriteTexsInstruction(instr, coords, "vec4(" + texture + ')');
2951 } 3023 }
2952 3024
2953 --shader.scope; 3025 --shader.scope;