diff options
| author | 2018-12-07 19:09:36 -0300 | |
|---|---|---|
| committer | 2018-12-07 19:09:36 -0300 | |
| commit | f4fa7ecb0e88b83e630063925e34e406f137ae2a (patch) | |
| tree | eb0e893820d0ce12bd2a5d7e5e7c27817fcc7bcb /src | |
| parent | Merge pull request #1868 from lioncash/config (diff) | |
| download | yuzu-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.cpp | 240 |
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: { |