summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp138
1 files changed, 78 insertions, 60 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 90a88b91a..f4fa6c74a 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1243,14 +1243,7 @@ private:
1243 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1); 1243 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1);
1244 } 1244 }
1245 1245
1246 void WriteTexsInstruction(const Instruction& instr, const std::string& coord, 1246 void WriteTexsInstruction(const Instruction& instr, const std::string& texture) {
1247 const std::string& texture) {
1248 // Add an extra scope and declare the texture coords inside to prevent
1249 // overwriting them in case they are used as outputs of the texs instruction.
1250 shader.AddLine('{');
1251 ++shader.scope;
1252 shader.AddLine(coord);
1253
1254 // TEXS has two destination registers and a swizzle. The first two elements in the swizzle 1247 // TEXS has two destination registers and a swizzle. The first two elements in the swizzle
1255 // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1 1248 // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1
1256 1249
@@ -1273,9 +1266,6 @@ private:
1273 1266
1274 ++written_components; 1267 ++written_components;
1275 } 1268 }
1276
1277 --shader.scope;
1278 shader.AddLine('}');
1279 } 1269 }
1280 1270
1281 static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) { 1271 static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) {
@@ -2563,7 +2553,6 @@ private:
2563 } 2553 }
2564 // TODO: make sure coordinates are always indexed to gpr8 and gpr20 is always bias 2554 // TODO: make sure coordinates are always indexed to gpr8 and gpr20 is always bias
2565 // or lod. 2555 // or lod.
2566 std::string op_c;
2567 2556
2568 const std::string sampler = 2557 const std::string sampler =
2569 GetSampler(instr.sampler, texture_type, is_array, depth_compare); 2558 GetSampler(instr.sampler, texture_type, is_array, depth_compare);
@@ -2586,27 +2575,35 @@ private:
2586 } 2575 }
2587 case Tegra::Shader::TextureProcessMode::LB: 2576 case Tegra::Shader::TextureProcessMode::LB:
2588 case Tegra::Shader::TextureProcessMode::LBA: { 2577 case Tegra::Shader::TextureProcessMode::LBA: {
2589 if (depth_compare) { 2578 const std::string bias = [&]() {
2590 if (is_array) 2579 if (depth_compare) {
2591 op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 2); 2580 if (is_array)
2592 else 2581 return regs.GetRegisterAsFloat(instr.gpr20.Value() + 2);
2593 op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); 2582 else
2594 } else { 2583 return regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
2595 op_c = regs.GetRegisterAsFloat(instr.gpr20); 2584 } else {
2596 } 2585 return regs.GetRegisterAsFloat(instr.gpr20);
2586 }
2587 }();
2588 shader.AddLine("float bias = " + bias + ';');
2589
2597 // TODO: Figure if A suffix changes the equation at all. 2590 // TODO: Figure if A suffix changes the equation at all.
2598 texture = "texture(" + sampler + ", coords, " + op_c + ')'; 2591 texture = "texture(" + sampler + ", coords, bias)";
2599 break; 2592 break;
2600 } 2593 }
2601 case Tegra::Shader::TextureProcessMode::LL: 2594 case Tegra::Shader::TextureProcessMode::LL:
2602 case Tegra::Shader::TextureProcessMode::LLA: { 2595 case Tegra::Shader::TextureProcessMode::LLA: {
2603 if (num_coordinates <= 2) { 2596 const std::string lod = [&]() {
2604 op_c = regs.GetRegisterAsFloat(instr.gpr20); 2597 if (num_coordinates <= 2) {
2605 } else { 2598 return regs.GetRegisterAsFloat(instr.gpr20);
2606 op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); 2599 } else {
2607 } 2600 return regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
2601 }
2602 }();
2603 shader.AddLine("float lod = " + lod + ';');
2604
2608 // TODO: Figure if A suffix changes the equation at all. 2605 // TODO: Figure if A suffix changes the equation at all.
2609 texture = "textureLod(" + sampler + ", coords, " + op_c + ')'; 2606 texture = "textureLod(" + sampler + ", coords, lod)";
2610 break; 2607 break;
2611 } 2608 }
2612 default: { 2609 default: {
@@ -2633,7 +2630,6 @@ private:
2633 break; 2630 break;
2634 } 2631 }
2635 case OpCode::Id::TEXS: { 2632 case OpCode::Id::TEXS: {
2636 std::string coord;
2637 Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()}; 2633 Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
2638 bool is_array{instr.texs.IsArrayTexture()}; 2634 bool is_array{instr.texs.IsArrayTexture()};
2639 2635
@@ -2646,17 +2642,21 @@ private:
2646 if (depth_compare) 2642 if (depth_compare)
2647 num_coordinates += 1; 2643 num_coordinates += 1;
2648 2644
2645 // Scope to avoid variable name overlaps.
2646 shader.AddLine('{');
2647 ++shader.scope;
2648
2649 switch (num_coordinates) { 2649 switch (num_coordinates) {
2650 case 2: { 2650 case 2: {
2651 if (is_array) { 2651 if (is_array) {
2652 const std::string index = regs.GetRegisterAsInteger(instr.gpr8); 2652 const std::string index = regs.GetRegisterAsInteger(instr.gpr8);
2653 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2653 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2654 const std::string y = regs.GetRegisterAsFloat(instr.gpr20); 2654 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
2655 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; 2655 shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + index + ");");
2656 } else { 2656 } else {
2657 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2657 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2658 const std::string y = regs.GetRegisterAsFloat(instr.gpr20); 2658 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
2659 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 2659 shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
2660 } 2660 }
2661 break; 2661 break;
2662 } 2662 }
@@ -2666,13 +2666,13 @@ private:
2666 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2666 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2667 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2); 2667 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2);
2668 const std::string z = regs.GetRegisterAsFloat(instr.gpr20); 2668 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
2669 coord = 2669 shader.AddLine("vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " +
2670 "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " + index + ");"; 2670 index + ");");
2671 } else { 2671 } else {
2672 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2672 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2673 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2673 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2674 const std::string z = regs.GetRegisterAsFloat(instr.gpr20); 2674 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
2675 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; 2675 shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + z + ");");
2676 } 2676 }
2677 break; 2677 break;
2678 } 2678 }
@@ -2683,7 +2683,7 @@ private:
2683 // Fallback to interpreting as a 2D texture for now 2683 // Fallback to interpreting as a 2D texture for now
2684 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2684 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2685 const std::string y = regs.GetRegisterAsFloat(instr.gpr20); 2685 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
2686 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 2686 shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
2687 texture_type = Tegra::Shader::TextureType::Texture2D; 2687 texture_type = Tegra::Shader::TextureType::Texture2D;
2688 is_array = false; 2688 is_array = false;
2689 } 2689 }
@@ -2715,14 +2715,16 @@ private:
2715 } 2715 }
2716 } 2716 }
2717 if (!depth_compare) { 2717 if (!depth_compare) {
2718 WriteTexsInstruction(instr, coord, texture); 2718 WriteTexsInstruction(instr, texture);
2719 } else { 2719 } else {
2720 WriteTexsInstruction(instr, coord, "vec4(" + texture + ')'); 2720 WriteTexsInstruction(instr, "vec4(" + texture + ')');
2721 } 2721 }
2722
2723 shader.AddLine('}');
2724 --shader.scope;
2722 break; 2725 break;
2723 } 2726 }
2724 case OpCode::Id::TLDS: { 2727 case OpCode::Id::TLDS: {
2725 std::string coord;
2726 const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()}; 2728 const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()};
2727 const bool is_array{instr.tlds.IsArrayTexture()}; 2729 const bool is_array{instr.tlds.IsArrayTexture()};
2728 2730
@@ -2736,12 +2738,16 @@ private:
2736 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ), 2738 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ),
2737 "MZ is not implemented"); 2739 "MZ is not implemented");
2738 2740
2739 u32 op_c_offset = 0; 2741 u32 extra_op_offset = 0;
2742
2743 // Scope to avoid variable name overlaps.
2744 shader.AddLine('{');
2745 ++shader.scope;
2740 2746
2741 switch (texture_type) { 2747 switch (texture_type) {
2742 case Tegra::Shader::TextureType::Texture1D: { 2748 case Tegra::Shader::TextureType::Texture1D: {
2743 const std::string x = regs.GetRegisterAsInteger(instr.gpr8); 2749 const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
2744 coord = "int coords = " + x + ';'; 2750 shader.AddLine("int coords = " + x + ';');
2745 break; 2751 break;
2746 } 2752 }
2747 case Tegra::Shader::TextureType::Texture2D: { 2753 case Tegra::Shader::TextureType::Texture2D: {
@@ -2749,8 +2755,8 @@ private:
2749 2755
2750 const std::string x = regs.GetRegisterAsInteger(instr.gpr8); 2756 const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
2751 const std::string y = regs.GetRegisterAsInteger(instr.gpr20); 2757 const std::string y = regs.GetRegisterAsInteger(instr.gpr20);
2752 coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; 2758 shader.AddLine("ivec2 coords = ivec2(" + x + ", " + y + ");");
2753 op_c_offset = 1; 2759 extra_op_offset = 1;
2754 break; 2760 break;
2755 } 2761 }
2756 default: 2762 default:
@@ -2765,9 +2771,10 @@ private:
2765 break; 2771 break;
2766 } 2772 }
2767 case Tegra::Shader::TextureProcessMode::LL: { 2773 case Tegra::Shader::TextureProcessMode::LL: {
2768 const std::string op_c = 2774 shader.AddLine(
2769 regs.GetRegisterAsInteger(instr.gpr20.Value() + op_c_offset); 2775 "float lod = " +
2770 texture = "texelFetch(" + sampler + ", coords, " + op_c + ')'; 2776 regs.GetRegisterAsInteger(instr.gpr20.Value() + extra_op_offset) + ';');
2777 texture = "texelFetch(" + sampler + ", coords, lod)";
2771 break; 2778 break;
2772 } 2779 }
2773 default: { 2780 default: {
@@ -2776,7 +2783,10 @@ private:
2776 static_cast<u32>(instr.tlds.GetTextureProcessMode())); 2783 static_cast<u32>(instr.tlds.GetTextureProcessMode()));
2777 } 2784 }
2778 } 2785 }
2779 WriteTexsInstruction(instr, coord, texture); 2786 WriteTexsInstruction(instr, texture);
2787
2788 --shader.scope;
2789 shader.AddLine('}');
2780 break; 2790 break;
2781 } 2791 }
2782 case OpCode::Id::TLD4: { 2792 case OpCode::Id::TLD4: {
@@ -2799,18 +2809,23 @@ private:
2799 if (depth_compare) 2809 if (depth_compare)
2800 num_coordinates += 1; 2810 num_coordinates += 1;
2801 2811
2812 // Add an extra scope and declare the texture coords inside to prevent
2813 // overwriting them in case they are used as outputs of the texs instruction.
2814 shader.AddLine('{');
2815 ++shader.scope;
2816
2802 switch (num_coordinates) { 2817 switch (num_coordinates) {
2803 case 2: { 2818 case 2: {
2804 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2819 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2805 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2820 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2806 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 2821 shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
2807 break; 2822 break;
2808 } 2823 }
2809 case 3: { 2824 case 3: {
2810 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2825 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2811 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2826 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2812 const std::string z = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2); 2827 const std::string z = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2);
2813 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; 2828 shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + z + ");");
2814 break; 2829 break;
2815 } 2830 }
2816 default: 2831 default:
@@ -2818,17 +2833,13 @@ private:
2818 static_cast<u32>(num_coordinates)); 2833 static_cast<u32>(num_coordinates));
2819 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2834 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2820 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2835 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2821 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 2836 shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
2822 texture_type = Tegra::Shader::TextureType::Texture2D; 2837 texture_type = Tegra::Shader::TextureType::Texture2D;
2823 } 2838 }
2824 2839
2825 const std::string sampler = 2840 const std::string sampler =
2826 GetSampler(instr.sampler, texture_type, false, depth_compare); 2841 GetSampler(instr.sampler, texture_type, false, depth_compare);
2827 // Add an extra scope and declare the texture coords inside to prevent 2842
2828 // overwriting them in case they are used as outputs of the texs instruction.
2829 shader.AddLine("{");
2830 ++shader.scope;
2831 shader.AddLine(coord);
2832 const std::string texture = "textureGather(" + sampler + ", coords, " + 2843 const std::string texture = "textureGather(" + sampler + ", coords, " +
2833 std::to_string(instr.tld4.component) + ')'; 2844 std::to_string(instr.tld4.component) + ')';
2834 if (!depth_compare) { 2845 if (!depth_compare) {
@@ -2845,7 +2856,7 @@ private:
2845 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); 2856 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false);
2846 } 2857 }
2847 --shader.scope; 2858 --shader.scope;
2848 shader.AddLine("}"); 2859 shader.AddLine('}');
2849 break; 2860 break;
2850 } 2861 }
2851 case OpCode::Id::TLD4S: { 2862 case OpCode::Id::TLD4S: {
@@ -2856,6 +2867,10 @@ private:
2856 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), 2867 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
2857 "AOFFI is not implemented"); 2868 "AOFFI is not implemented");
2858 2869
2870 // Scope to avoid variable name overlaps.
2871 shader.AddLine('{');
2872 ++shader.scope;
2873
2859 const bool depth_compare = 2874 const bool depth_compare =
2860 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); 2875 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
2861 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 2876 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
@@ -2863,22 +2878,25 @@ private:
2863 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. 2878 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
2864 const std::string sampler = GetSampler( 2879 const std::string sampler = GetSampler(
2865 instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare); 2880 instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare);
2866 std::string coord;
2867 if (!depth_compare) { 2881 if (!depth_compare) {
2868 coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 2882 shader.AddLine("vec2 coords = vec2(" + op_a + ", " + op_b + ");");
2869 } else { 2883 } else {
2870 // Note: TLD4S coordinate encoding works just like TEXS's 2884 // Note: TLD4S coordinate encoding works just like TEXS's
2871 const std::string op_c = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2885 shader.AddLine(
2872 coord = "vec3 coords = vec3(" + op_a + ", " + op_c + ", " + op_b + ");"; 2886 "float op_y = " + regs.GetRegisterAsFloat(instr.gpr8.Value() + 1) + ';');
2887 shader.AddLine("vec3 coords = vec3(" + op_a + ", op_y, " + op_b + ");");
2873 } 2888 }
2874 const std::string texture = "textureGather(" + sampler + ", coords, " + 2889 const std::string texture = "textureGather(" + sampler + ", coords, " +
2875 std::to_string(instr.tld4s.component) + ')'; 2890 std::to_string(instr.tld4s.component) + ')';
2876 2891
2877 if (!depth_compare) { 2892 if (!depth_compare) {
2878 WriteTexsInstruction(instr, coord, texture); 2893 WriteTexsInstruction(instr, texture);
2879 } else { 2894 } else {
2880 WriteTexsInstruction(instr, coord, "vec4(" + texture + ')'); 2895 WriteTexsInstruction(instr, "vec4(" + texture + ')');
2881 } 2896 }
2897
2898 --shader.scope;
2899 shader.AddLine('}');
2882 break; 2900 break;
2883 } 2901 }
2884 case OpCode::Id::TXQ: { 2902 case OpCode::Id::TXQ: {