summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp125
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.h50
2 files changed, 143 insertions, 32 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 841647ebe..172ba8335 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -443,13 +443,12 @@ public:
443 } 443 }
444 declarations.AddNewLine(); 444 declarations.AddNewLine();
445 445
446 // Append the sampler2D array for the used textures. 446 const auto& samplers = GetSamplers();
447 const size_t num_samplers = used_samplers.size(); 447 for (const auto& sampler : samplers) {
448 if (num_samplers > 0) { 448 declarations.AddLine("uniform " + sampler.GetTypeString() + ' ' + sampler.GetName() +
449 declarations.AddLine("uniform sampler2D " + SamplerEntry::GetArrayName(stage) + '[' + 449 ';');
450 std::to_string(num_samplers) + "];");
451 declarations.AddNewLine();
452 } 450 }
451 declarations.AddNewLine();
453 } 452 }
454 453
455 /// Returns a list of constant buffer declarations 454 /// Returns a list of constant buffer declarations
@@ -461,13 +460,14 @@ public:
461 } 460 }
462 461
463 /// Returns a list of samplers used in the shader 462 /// Returns a list of samplers used in the shader
464 std::vector<SamplerEntry> GetSamplers() const { 463 const std::vector<SamplerEntry>& GetSamplers() const {
465 return used_samplers; 464 return used_samplers;
466 } 465 }
467 466
468 /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if 467 /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if
469 /// necessary. 468 /// necessary.
470 std::string AccessSampler(const Sampler& sampler) { 469 std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type,
470 bool is_array) {
471 size_t offset = static_cast<size_t>(sampler.index.Value()); 471 size_t offset = static_cast<size_t>(sampler.index.Value());
472 472
473 // If this sampler has already been used, return the existing mapping. 473 // If this sampler has already been used, return the existing mapping.
@@ -476,12 +476,13 @@ public:
476 [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); 476 [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; });
477 477
478 if (itr != used_samplers.end()) { 478 if (itr != used_samplers.end()) {
479 ASSERT(itr->GetType() == type && itr->IsArray() == is_array);
479 return itr->GetName(); 480 return itr->GetName();
480 } 481 }
481 482
482 // Otherwise create a new mapping for this sampler 483 // Otherwise create a new mapping for this sampler
483 size_t next_index = used_samplers.size(); 484 size_t next_index = used_samplers.size();
484 SamplerEntry entry{stage, offset, next_index}; 485 SamplerEntry entry{stage, offset, next_index, type, is_array};
485 used_samplers.emplace_back(entry); 486 used_samplers.emplace_back(entry);
486 return entry.GetName(); 487 return entry.GetName();
487 } 488 }
@@ -722,8 +723,8 @@ private:
722 } 723 }
723 724
724 /// Generates code representing a texture sampler. 725 /// Generates code representing a texture sampler.
725 std::string GetSampler(const Sampler& sampler) { 726 std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array) {
726 return regs.AccessSampler(sampler); 727 return regs.AccessSampler(sampler, type, is_array);
727 } 728 }
728 729
729 /** 730 /**
@@ -1753,10 +1754,35 @@ private:
1753 break; 1754 break;
1754 } 1755 }
1755 case OpCode::Id::TEX: { 1756 case OpCode::Id::TEX: {
1756 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 1757 ASSERT_MSG(instr.tex.array == 0, "TEX arrays unimplemented");
1757 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 1758 Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
1758 const std::string sampler = GetSampler(instr.sampler); 1759 std::string coord;
1759 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 1760
1761 switch (texture_type) {
1762 case Tegra::Shader::TextureType::Texture1D: {
1763 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1764 coord = "float coords = " + x + ';';
1765 break;
1766 }
1767 case Tegra::Shader::TextureType::Texture2D: {
1768 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1769 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1770 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1771 break;
1772 }
1773 default:
1774 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
1775 static_cast<u32>(texture_type));
1776 UNREACHABLE();
1777
1778 // Fallback to interpreting as a 2D texture for now
1779 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1780 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1781 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1782 texture_type = Tegra::Shader::TextureType::Texture2D;
1783 }
1784
1785 const std::string sampler = GetSampler(instr.sampler, texture_type, false);
1760 // Add an extra scope and declare the texture coords inside to prevent 1786 // Add an extra scope and declare the texture coords inside to prevent
1761 // overwriting them in case they are used as outputs of the texs instruction. 1787 // overwriting them in case they are used as outputs of the texs instruction.
1762 shader.AddLine("{"); 1788 shader.AddLine("{");
@@ -1778,20 +1804,65 @@ private:
1778 break; 1804 break;
1779 } 1805 }
1780 case OpCode::Id::TEXS: { 1806 case OpCode::Id::TEXS: {
1781 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 1807 std::string coord;
1782 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); 1808 Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
1783 const std::string sampler = GetSampler(instr.sampler); 1809 bool is_array{instr.texs.IsArrayTexture()};
1784 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 1810
1811 switch (texture_type) {
1812 case Tegra::Shader::TextureType::Texture2D: {
1813 if (is_array) {
1814 std::string index = regs.GetRegisterAsInteger(instr.gpr8);
1815 std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1816 std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1817 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");";
1818 } else {
1819 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1820 std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1821 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1822 }
1823 break;
1824 }
1825 default:
1826 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
1827 static_cast<u32>(texture_type));
1828 UNREACHABLE();
1785 1829
1830 // Fallback to interpreting as a 2D texture for now
1831 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1832 std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1833 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1834 texture_type = Tegra::Shader::TextureType::Texture2D;
1835 is_array = false;
1836 }
1837 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array);
1786 const std::string texture = "texture(" + sampler + ", coords)"; 1838 const std::string texture = "texture(" + sampler + ", coords)";
1787 WriteTexsInstruction(instr, coord, texture); 1839 WriteTexsInstruction(instr, coord, texture);
1788 break; 1840 break;
1789 } 1841 }
1790 case OpCode::Id::TLDS: { 1842 case OpCode::Id::TLDS: {
1791 const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); 1843 ASSERT(instr.tlds.GetTextureType() == Tegra::Shader::TextureType::Texture2D);
1792 const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20); 1844 ASSERT(instr.tlds.IsArrayTexture() == false);
1793 const std::string sampler = GetSampler(instr.sampler); 1845 std::string coord;
1794 const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");"; 1846
1847 switch (instr.tlds.GetTextureType()) {
1848 case Tegra::Shader::TextureType::Texture2D: {
1849 if (instr.tlds.IsArrayTexture()) {
1850 LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture");
1851 UNREACHABLE();
1852 } else {
1853 std::string x = regs.GetRegisterAsInteger(instr.gpr8);
1854 std::string y = regs.GetRegisterAsInteger(instr.gpr20);
1855 coord = "ivec2 coords = ivec2(" + x + ", " + y + ");";
1856 }
1857 break;
1858 }
1859 default:
1860 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
1861 static_cast<u32>(instr.tlds.GetTextureType()));
1862 UNREACHABLE();
1863 }
1864 const std::string sampler = GetSampler(instr.sampler, instr.tlds.GetTextureType(),
1865 instr.tlds.IsArrayTexture());
1795 const std::string texture = "texelFetch(" + sampler + ", coords, 0)"; 1866 const std::string texture = "texelFetch(" + sampler + ", coords, 0)";
1796 WriteTexsInstruction(instr, coord, texture); 1867 WriteTexsInstruction(instr, coord, texture);
1797 break; 1868 break;
@@ -1799,7 +1870,7 @@ private:
1799 case OpCode::Id::TLD4: { 1870 case OpCode::Id::TLD4: {
1800 ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D); 1871 ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D);
1801 ASSERT(instr.tld4.array == 0); 1872 ASSERT(instr.tld4.array == 0);
1802 std::string coord{}; 1873 std::string coord;
1803 1874
1804 switch (instr.tld4.texture_type) { 1875 switch (instr.tld4.texture_type) {
1805 case Tegra::Shader::TextureType::Texture2D: { 1876 case Tegra::Shader::TextureType::Texture2D: {
@@ -1814,7 +1885,8 @@ private:
1814 UNREACHABLE(); 1885 UNREACHABLE();
1815 } 1886 }
1816 1887
1817 const std::string sampler = GetSampler(instr.sampler); 1888 const std::string sampler =
1889 GetSampler(instr.sampler, instr.tld4.texture_type, false);
1818 // Add an extra scope and declare the texture coords inside to prevent 1890 // Add an extra scope and declare the texture coords inside to prevent
1819 // overwriting them in case they are used as outputs of the texs instruction. 1891 // overwriting them in case they are used as outputs of the texs instruction.
1820 shader.AddLine("{"); 1892 shader.AddLine("{");
@@ -1840,7 +1912,8 @@ private:
1840 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 1912 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
1841 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); 1913 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
1842 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. 1914 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
1843 const std::string sampler = GetSampler(instr.sampler); 1915 const std::string sampler =
1916 GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false);
1844 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 1917 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
1845 const std::string texture = "textureGather(" + sampler + ", coords, " + 1918 const std::string texture = "textureGather(" + sampler + ", coords, " +
1846 std::to_string(instr.tld4s.component) + ')'; 1919 std::to_string(instr.tld4s.component) + ')';
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h
index cbb2090ea..a43e2997b 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.h
+++ b/src/video_core/renderer_opengl/gl_shader_gen.h
@@ -9,6 +9,7 @@
9#include <vector> 9#include <vector>
10 10
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/engines/shader_bytecode.h"
12 13
13namespace OpenGL::GLShader { 14namespace OpenGL::GLShader {
14 15
@@ -73,8 +74,9 @@ class SamplerEntry {
73 using Maxwell = Tegra::Engines::Maxwell3D::Regs; 74 using Maxwell = Tegra::Engines::Maxwell3D::Regs;
74 75
75public: 76public:
76 SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index) 77 SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index,
77 : offset(offset), stage(stage), sampler_index(index) {} 78 Tegra::Shader::TextureType type, bool is_array)
79 : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array) {}
78 80
79 size_t GetOffset() const { 81 size_t GetOffset() const {
80 return offset; 82 return offset;
@@ -89,8 +91,41 @@ public:
89 } 91 }
90 92
91 std::string GetName() const { 93 std::string GetName() const {
92 return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '[' + 94 return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '_' +
93 std::to_string(sampler_index) + ']'; 95 std::to_string(sampler_index);
96 }
97
98 std::string GetTypeString() const {
99 using Tegra::Shader::TextureType;
100 std::string glsl_type;
101
102 switch (type) {
103 case TextureType::Texture1D:
104 glsl_type = "sampler1D";
105 break;
106 case TextureType::Texture2D:
107 glsl_type = "sampler2D";
108 break;
109 case TextureType::Texture3D:
110 glsl_type = "sampler3D";
111 break;
112 case TextureType::TextureCube:
113 glsl_type = "samplerCube";
114 break;
115 default:
116 UNIMPLEMENTED();
117 }
118 if (is_array)
119 glsl_type += "Array";
120 return glsl_type;
121 }
122
123 Tegra::Shader::TextureType GetType() const {
124 return type;
125 }
126
127 bool IsArray() const {
128 return is_array;
94 } 129 }
95 130
96 u32 GetHash() const { 131 u32 GetHash() const {
@@ -105,11 +140,14 @@ private:
105 static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = { 140 static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = {
106 "tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs", 141 "tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs",
107 }; 142 };
143
108 /// Offset in TSC memory from which to read the sampler object, as specified by the sampling 144 /// Offset in TSC memory from which to read the sampler object, as specified by the sampling
109 /// instruction. 145 /// instruction.
110 size_t offset; 146 size_t offset;
111 Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used. 147 Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used.
112 size_t sampler_index; ///< Value used to index into the generated GLSL sampler array. 148 size_t sampler_index; ///< Value used to index into the generated GLSL sampler array.
149 Tegra::Shader::TextureType type; ///< The type used to sample this texture (Texture2D, etc)
150 bool is_array; ///< Whether the texture is being sampled as an array texture or not.
113}; 151};
114 152
115struct ShaderEntries { 153struct ShaderEntries {