summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Marcos Vitali2018-12-07 19:09:36 -0300
committerGravatar Marcos Vitali2018-12-07 19:09:36 -0300
commitf4fa7ecb0e88b83e630063925e34e406f137ae2a (patch)
treeeb0e893820d0ce12bd2a5d7e5e7c27817fcc7bcb /src
parentMerge pull request #1868 from lioncash/config (diff)
downloadyuzu-f4fa7ecb0e88b83e630063925e34e406f137ae2a.tar.gz
yuzu-f4fa7ecb0e88b83e630063925e34e406f137ae2a.tar.xz
yuzu-f4fa7ecb0e88b83e630063925e34e406f137ae2a.zip
gl_shader_decompiler: TLDS/TLD4/TLD4S Reworked reflecting the source registers, bugs fixed and modularize.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp240
1 files changed, 134 insertions, 106 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 4fc09cac6..e7057a9cb 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1681,7 +1681,7 @@ private:
1681 for (size_t i = 0; i < coord_count; ++i) { 1681 for (size_t i = 0; i < coord_count; ++i) {
1682 const bool last = (i == (coord_count - 1)) && (coord_count > 1); 1682 const bool last = (i == (coord_count - 1)) && (coord_count > 1);
1683 coord += regs.GetRegisterAsFloat(last ? last_coord_register : coord_register + i); 1683 coord += regs.GetRegisterAsFloat(last ? last_coord_register : coord_register + i);
1684 if (!last) { 1684 if (i < coord_count - 1) {
1685 coord += ','; 1685 coord += ',';
1686 } 1686 }
1687 } 1687 }
@@ -1702,6 +1702,99 @@ private:
1702 is_array, (coord_count > 2 ? 1 : 0))); 1702 is_array, (coord_count > 2 ? 1 : 0)));
1703 } 1703 }
1704 1704
1705 std::pair<std::string, std::string> GetTLD4Code(const Instruction& instr,
1706 const Tegra::Shader::TextureType texture_type,
1707 const bool depth_compare, const bool is_array) {
1708
1709 const size_t coord_count = TextureCoordinates(texture_type);
1710 const size_t total_coord_count = coord_count + (is_array ? 1 : 0);
1711 const size_t total_reg_count = total_coord_count + (depth_compare ? 1 : 0);
1712
1713 constexpr std::array<const char*, 5> coord_container{
1714 {"", "", "vec2 coord = vec2(", "vec3 coord = vec3(", "vec4 coord = vec4("}};
1715
1716 // If enabled arrays index is always stored in the gpr8 field
1717 const u64 array_register = instr.gpr8.Value();
1718 // First coordinate index is the gpr8 or gpr8 + 1 when arrays are used
1719 const u64 coord_register = array_register + (is_array ? 1 : 0);
1720
1721 std::string coord = coord_container[total_coord_count];
1722 for (size_t i = 0; i < coord_count;) {
1723 coord += regs.GetRegisterAsFloat(coord_register + i);
1724 ++i;
1725 if (i != coord_count) {
1726 coord += ',';
1727 }
1728 }
1729
1730 if (is_array) {
1731 coord += ',' + regs.GetRegisterAsInteger(array_register);
1732 }
1733 coord += ");";
1734
1735 const std::string sampler =
1736 GetSampler(instr.sampler, texture_type, is_array, depth_compare);
1737
1738 std::string texture = "textureGather(" + sampler + ", coord, ";
1739 if (depth_compare) {
1740 // Depth is always stored in the register signaled by gpr20
1741 texture += regs.GetRegisterAsFloat(instr.gpr20.Value()) + ')';
1742 } else {
1743 texture += std::to_string(instr.tld4.component) + ')';
1744 }
1745 return std::make_pair(coord, texture);
1746 }
1747
1748 std::pair<std::string, std::string> GetTLDSCode(const Instruction& instr,
1749 const Tegra::Shader::TextureType texture_type,
1750 const bool is_array) {
1751
1752 const size_t coord_count = TextureCoordinates(texture_type);
1753 const size_t total_coord_count = coord_count + (is_array ? 1 : 0);
1754 const bool lod_enabled =
1755 instr.tlds.GetTextureProcessMode() == Tegra::Shader::TextureProcessMode::LL;
1756
1757 constexpr std::array<const char*, 4> coord_container{
1758 {"", "int coord = (", "ivec2 coord = ivec2(", "ivec3 coord = ivec3("}};
1759
1760 std::string coord = coord_container[total_coord_count];
1761
1762 // If enabled arrays index is always stored in the gpr8 field
1763 const u64 array_register = instr.gpr8.Value();
1764
1765 // if is array gpr20 is used
1766 const u64 coord_register = is_array ? instr.gpr20.Value() : instr.gpr8.Value();
1767
1768 const u64 last_coord_register =
1769 ((coord_count > 2) || (coord_count == 2 && !lod_enabled)) && !is_array
1770 ? static_cast<u64>(instr.gpr20.Value())
1771 : coord_register + 1;
1772
1773 for (size_t i = 0; i < coord_count; ++i) {
1774 const bool last = (i == (coord_count - 1)) && (coord_count > 1);
1775 coord += regs.GetRegisterAsInteger(last ? last_coord_register : coord_register + i);
1776 if (i < coord_count - 1) {
1777 coord += ',';
1778 }
1779 }
1780 if (is_array) {
1781 coord += ',' + regs.GetRegisterAsInteger(array_register);
1782 }
1783 coord += ");";
1784
1785 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array, false);
1786
1787 std::string texture = "texelFetch(" + sampler + ", coords";
1788
1789 if (lod_enabled) {
1790 // When lod is used always is in grp20
1791 texture += ", " + regs.GetRegisterAsInteger(instr.gpr20) + ')';
1792 } else {
1793 texture += ", 0)";
1794 }
1795 return std::make_pair(coord, texture);
1796 }
1797
1705 /** 1798 /**
1706 * Compiles a single instruction from Tegra to GLSL. 1799 * Compiles a single instruction from Tegra to GLSL.
1707 * @param offset the offset of the Tegra shader instruction. 1800 * @param offset the offset of the Tegra shader instruction.
@@ -2825,9 +2918,6 @@ private:
2825 const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()}; 2918 const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()};
2826 const bool is_array{instr.tlds.IsArrayTexture()}; 2919 const bool is_array{instr.tlds.IsArrayTexture()};
2827 2920
2828 ASSERT(texture_type == Tegra::Shader::TextureType::Texture2D);
2829 ASSERT(is_array == false);
2830
2831 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), 2921 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
2832 "NODEP is not implemented"); 2922 "NODEP is not implemented");
2833 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), 2923 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
@@ -2835,54 +2925,16 @@ private:
2835 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ), 2925 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ),
2836 "MZ is not implemented"); 2926 "MZ is not implemented");
2837 2927
2838 u32 extra_op_offset = 0; 2928 const auto [coord, texture] = GetTLDSCode(instr, texture_type, is_array);
2839
2840 ShaderScopedScope scope = shader.Scope();
2841
2842 switch (texture_type) {
2843 case Tegra::Shader::TextureType::Texture1D: {
2844 const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
2845 shader.AddLine("float coords = " + x + ';');
2846 break;
2847 }
2848 case Tegra::Shader::TextureType::Texture2D: {
2849 UNIMPLEMENTED_IF_MSG(is_array, "Unhandled 2d array texture");
2850
2851 const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
2852 const std::string y = regs.GetRegisterAsInteger(instr.gpr20);
2853 // shader.AddLine("ivec2 coords = ivec2(" + x + ", " + y + ");");
2854 shader.AddLine("ivec2 coords = ivec2(" + x + ", " + y + ");");
2855 extra_op_offset = 1;
2856 break;
2857 }
2858 default:
2859 UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<u32>(texture_type));
2860 }
2861 const std::string sampler =
2862 GetSampler(instr.sampler, texture_type, is_array, false);
2863 2929
2864 const std::string texture = [&]() { 2930 const auto scope = shader.Scope();
2865 switch (instr.tlds.GetTextureProcessMode()) {
2866 case Tegra::Shader::TextureProcessMode::LZ:
2867 return "texelFetch(" + sampler + ", coords, 0)";
2868 case Tegra::Shader::TextureProcessMode::LL:
2869 shader.AddLine(
2870 "float lod = " +
2871 regs.GetRegisterAsInteger(instr.gpr20.Value() + extra_op_offset) + ';');
2872 return "texelFetch(" + sampler + ", coords, lod)";
2873 default:
2874 UNIMPLEMENTED_MSG("Unhandled texture process mode {}",
2875 static_cast<u32>(instr.tlds.GetTextureProcessMode()));
2876 return "texelFetch(" + sampler + ", coords, 0)";
2877 }
2878 }();
2879 2931
2880 WriteTexsInstructionFloat(instr, texture); 2932 shader.AddLine(coord);
2933 shader.AddLine("vec4 texture_tmp = " + texture + ';');
2934 WriteTexsInstructionFloat(instr, "texture_tmp");
2881 break; 2935 break;
2882 } 2936 }
2883 case OpCode::Id::TLD4: { 2937 case OpCode::Id::TLD4: {
2884 ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D);
2885 ASSERT(instr.tld4.array == 0);
2886 2938
2887 UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), 2939 UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
2888 "NODEP is not implemented"); 2940 "NODEP is not implemented");
@@ -2892,56 +2944,29 @@ private:
2892 "NDV is not implemented"); 2944 "NDV is not implemented");
2893 UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP), 2945 UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP),
2894 "PTP is not implemented"); 2946 "PTP is not implemented");
2947
2948 auto texture_type = instr.tld4.texture_type.Value();
2895 const bool depth_compare = 2949 const bool depth_compare =
2896 instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); 2950 instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
2897 auto texture_type = instr.tld4.texture_type.Value(); 2951 const bool is_array = instr.tld4.array != 0;
2898 u32 num_coordinates = TextureCoordinates(texture_type);
2899 if (depth_compare)
2900 num_coordinates += 1;
2901
2902 const auto scope = shader.Scope();
2903 2952
2904 switch (num_coordinates) { 2953 const auto [coord, texture] =
2905 case 2: { 2954 GetTLD4Code(instr, texture_type, depth_compare, is_array);
2906 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2907 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2908 shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
2909 break;
2910 }
2911 case 3: {
2912 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2913 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2914 const std::string z = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2);
2915 shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + z + ");");
2916 break;
2917 }
2918 default:
2919 UNIMPLEMENTED_MSG("Unhandled coordinates number {}",
2920 static_cast<u32>(num_coordinates));
2921 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2922 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2923 shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
2924 texture_type = Tegra::Shader::TextureType::Texture2D;
2925 }
2926 2955
2927 const std::string sampler = 2956 const auto scope = shader.Scope();
2928 GetSampler(instr.sampler, texture_type, false, depth_compare);
2929 2957
2930 const std::string texture = "textureGather(" + sampler + ", coords, " + 2958 shader.AddLine(coord);
2931 std::to_string(instr.tld4.component) + ')'; 2959 std::size_t dest_elem{};
2932 2960
2933 if (depth_compare) { 2961 shader.AddLine("vec4 texture_tmp = " + texture + ';');
2934 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); 2962 for (std::size_t elem = 0; elem < 4; ++elem) {
2935 } else { 2963 if (!instr.tex.IsComponentEnabled(elem)) {
2936 std::size_t dest_elem{}; 2964 // Skip disabled components
2937 for (std::size_t elem = 0; elem < 4; ++elem) { 2965 continue;
2938 if (!instr.tex.IsComponentEnabled(elem)) {
2939 // Skip disabled components
2940 continue;
2941 }
2942 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem);
2943 ++dest_elem;
2944 } 2966 }
2967 regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false,
2968 dest_elem);
2969 ++dest_elem;
2945 } 2970 }
2946 break; 2971 break;
2947 } 2972 }
@@ -2955,28 +2980,31 @@ private:
2955 2980
2956 const auto scope = shader.Scope(); 2981 const auto scope = shader.Scope();
2957 2982
2983 std::string coords;
2984
2958 const bool depth_compare = 2985 const bool depth_compare =
2959 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); 2986 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
2960 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 2987
2961 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
2962 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
2963 const std::string sampler = GetSampler( 2988 const std::string sampler = GetSampler(
2964 instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare); 2989 instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare);
2965 if (depth_compare) {
2966 // Note: TLD4S coordinate encoding works just like TEXS's
2967 const std::string op_y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2968 shader.AddLine("vec3 coords = vec3(" + op_a + ", " + op_y + ", " + op_b + ");");
2969 } else {
2970 shader.AddLine("vec2 coords = vec2(" + op_a + ", " + op_b + ");");
2971 }
2972 2990
2973 std::string texture = "textureGather(" + sampler + ", coords, " + 2991 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
2974 std::to_string(instr.tld4s.component) + ')'; 2992 coords = "vec2 coords = vec2(" + op_a + ", ";
2975 if (depth_compare) { 2993 std::string texture = "textureGather(" + sampler + ", coords, ";
2976 texture = "vec4(" + texture + ')';
2977 }
2978 2994
2979 WriteTexsInstructionFloat(instr, texture); 2995 if (!depth_compare) {
2996 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
2997 coords += op_b + ");";
2998 texture += std::to_string(instr.tld4s.component) + ')';
2999 } else {
3000 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
3001 const std::string op_c = regs.GetRegisterAsFloat(instr.gpr20);
3002 coords += op_b + ");";
3003 texture += op_c + ')';
3004 }
3005 shader.AddLine(coords);
3006 shader.AddLine("vec4 texture_tmp = " + texture + ';');
3007 WriteTexsInstructionFloat(instr, "texture_tmp");
2980 break; 3008 break;
2981 } 3009 }
2982 case OpCode::Id::TXQ: { 3010 case OpCode::Id::TXQ: {