diff options
| author | bunnei <bunneidev@gmail.com> | 2018-09-06 18:45:49 -0400 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2018-09-08 02:53:38 -0400 | 
| commit | 07313831240243396c212ece04d25c976eaa5381 (patch) | |
| tree | ccac785093a9587dcdfe9ca6bbfa977eff97efc8 | |
| parent | 05f6f59ffba2253e7c47263c919ef374e53571e5 (diff) | |
gl_shader_decompiler: Partially implement several non-2D texture types (Subv).
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 125 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.h | 50 | 
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:          }          declarations.AddNewLine(); -        // Append the sampler2D array for the used textures. -        const size_t num_samplers = used_samplers.size(); -        if (num_samplers > 0) { -            declarations.AddLine("uniform sampler2D " + SamplerEntry::GetArrayName(stage) + '[' + -                                 std::to_string(num_samplers) + "];"); -            declarations.AddNewLine(); +        const auto& samplers = GetSamplers(); +        for (const auto& sampler : samplers) { +            declarations.AddLine("uniform " + sampler.GetTypeString() + ' ' + sampler.GetName() + +                                 ';');          } +        declarations.AddNewLine();      }      /// Returns a list of constant buffer declarations @@ -461,13 +460,14 @@ public:      }      /// Returns a list of samplers used in the shader -    std::vector<SamplerEntry> GetSamplers() const { +    const std::vector<SamplerEntry>& GetSamplers() const {          return used_samplers;      }      /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if      /// necessary. -    std::string AccessSampler(const Sampler& sampler) { +    std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, +                              bool is_array) {          size_t offset = static_cast<size_t>(sampler.index.Value());          // If this sampler has already been used, return the existing mapping. @@ -476,12 +476,13 @@ public:                           [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; });          if (itr != used_samplers.end()) { +            ASSERT(itr->GetType() == type && itr->IsArray() == is_array);              return itr->GetName();          }          // Otherwise create a new mapping for this sampler          size_t next_index = used_samplers.size(); -        SamplerEntry entry{stage, offset, next_index}; +        SamplerEntry entry{stage, offset, next_index, type, is_array};          used_samplers.emplace_back(entry);          return entry.GetName();      } @@ -722,8 +723,8 @@ private:      }      /// Generates code representing a texture sampler. -    std::string GetSampler(const Sampler& sampler) { -        return regs.AccessSampler(sampler); +    std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array) { +        return regs.AccessSampler(sampler, type, is_array);      }      /** @@ -1753,10 +1754,35 @@ private:                  break;              }              case OpCode::Id::TEX: { -                const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); -                const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); -                const std::string sampler = GetSampler(instr.sampler); -                const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; +                ASSERT_MSG(instr.tex.array == 0, "TEX arrays unimplemented"); +                Tegra::Shader::TextureType texture_type{instr.tex.texture_type}; +                std::string coord; + +                switch (texture_type) { +                case Tegra::Shader::TextureType::Texture1D: { +                    std::string x = regs.GetRegisterAsFloat(instr.gpr8); +                    coord = "float coords = " + x + ';'; +                    break; +                } +                case Tegra::Shader::TextureType::Texture2D: { +                    std::string x = regs.GetRegisterAsFloat(instr.gpr8); +                    std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); +                    coord = "vec2 coords = vec2(" + x + ", " + y + ");"; +                    break; +                } +                default: +                    LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", +                                 static_cast<u32>(texture_type)); +                    UNREACHABLE(); + +                    // Fallback to interpreting as a 2D texture for now +                    std::string x = regs.GetRegisterAsFloat(instr.gpr8); +                    std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); +                    coord = "vec2 coords = vec2(" + x + ", " + y + ");"; +                    texture_type = Tegra::Shader::TextureType::Texture2D; +                } + +                const std::string sampler = GetSampler(instr.sampler, texture_type, false);                  // Add an extra scope and declare the texture coords inside to prevent                  // overwriting them in case they are used as outputs of the texs instruction.                  shader.AddLine("{"); @@ -1778,20 +1804,65 @@ private:                  break;              }              case OpCode::Id::TEXS: { -                const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); -                const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); -                const std::string sampler = GetSampler(instr.sampler); -                const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; +                std::string coord; +                Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()}; +                bool is_array{instr.texs.IsArrayTexture()}; + +                switch (texture_type) { +                case Tegra::Shader::TextureType::Texture2D: { +                    if (is_array) { +                        std::string index = regs.GetRegisterAsInteger(instr.gpr8); +                        std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); +                        std::string y = regs.GetRegisterAsFloat(instr.gpr20); +                        coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; +                    } else { +                        std::string x = regs.GetRegisterAsFloat(instr.gpr8); +                        std::string y = regs.GetRegisterAsFloat(instr.gpr20); +                        coord = "vec2 coords = vec2(" + x + ", " + y + ");"; +                    } +                    break; +                } +                default: +                    LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", +                                 static_cast<u32>(texture_type)); +                    UNREACHABLE(); +                    // Fallback to interpreting as a 2D texture for now +                    std::string x = regs.GetRegisterAsFloat(instr.gpr8); +                    std::string y = regs.GetRegisterAsFloat(instr.gpr20); +                    coord = "vec2 coords = vec2(" + x + ", " + y + ");"; +                    texture_type = Tegra::Shader::TextureType::Texture2D; +                    is_array = false; +                } +                const std::string sampler = GetSampler(instr.sampler, texture_type, is_array);                  const std::string texture = "texture(" + sampler + ", coords)";                  WriteTexsInstruction(instr, coord, texture);                  break;              }              case OpCode::Id::TLDS: { -                const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); -                const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20); -                const std::string sampler = GetSampler(instr.sampler); -                const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");"; +                ASSERT(instr.tlds.GetTextureType() == Tegra::Shader::TextureType::Texture2D); +                ASSERT(instr.tlds.IsArrayTexture() == false); +                std::string coord; + +                switch (instr.tlds.GetTextureType()) { +                case Tegra::Shader::TextureType::Texture2D: { +                    if (instr.tlds.IsArrayTexture()) { +                        LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture"); +                        UNREACHABLE(); +                    } else { +                        std::string x = regs.GetRegisterAsInteger(instr.gpr8); +                        std::string y = regs.GetRegisterAsInteger(instr.gpr20); +                        coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; +                    } +                    break; +                } +                default: +                    LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", +                                 static_cast<u32>(instr.tlds.GetTextureType())); +                    UNREACHABLE(); +                } +                const std::string sampler = GetSampler(instr.sampler, instr.tlds.GetTextureType(), +                                                       instr.tlds.IsArrayTexture());                  const std::string texture = "texelFetch(" + sampler + ", coords, 0)";                  WriteTexsInstruction(instr, coord, texture);                  break; @@ -1799,7 +1870,7 @@ private:              case OpCode::Id::TLD4: {                  ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D);                  ASSERT(instr.tld4.array == 0); -                std::string coord{}; +                std::string coord;                  switch (instr.tld4.texture_type) {                  case Tegra::Shader::TextureType::Texture2D: { @@ -1814,7 +1885,8 @@ private:                      UNREACHABLE();                  } -                const std::string sampler = GetSampler(instr.sampler); +                const std::string sampler = +                    GetSampler(instr.sampler, instr.tld4.texture_type, false);                  // Add an extra scope and declare the texture coords inside to prevent                  // overwriting them in case they are used as outputs of the texs instruction.                  shader.AddLine("{"); @@ -1840,7 +1912,8 @@ private:                  const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);                  const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);                  // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. -                const std::string sampler = GetSampler(instr.sampler); +                const std::string sampler = +                    GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false);                  const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";                  const std::string texture = "textureGather(" + sampler + ", coords, " +                                              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 @@  #include <vector>  #include "common/common_types.h" +#include "video_core/engines/shader_bytecode.h"  namespace OpenGL::GLShader { @@ -73,8 +74,9 @@ class SamplerEntry {      using Maxwell = Tegra::Engines::Maxwell3D::Regs;  public: -    SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index) -        : offset(offset), stage(stage), sampler_index(index) {} +    SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index, +                 Tegra::Shader::TextureType type, bool is_array) +        : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array) {}      size_t GetOffset() const {          return offset; @@ -89,8 +91,41 @@ public:      }      std::string GetName() const { -        return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '[' + -               std::to_string(sampler_index) + ']'; +        return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '_' + +               std::to_string(sampler_index); +    } + +    std::string GetTypeString() const { +        using Tegra::Shader::TextureType; +        std::string glsl_type; + +        switch (type) { +        case TextureType::Texture1D: +            glsl_type = "sampler1D"; +            break; +        case TextureType::Texture2D: +            glsl_type = "sampler2D"; +            break; +        case TextureType::Texture3D: +            glsl_type = "sampler3D"; +            break; +        case TextureType::TextureCube: +            glsl_type = "samplerCube"; +            break; +        default: +            UNIMPLEMENTED(); +        } +        if (is_array) +            glsl_type += "Array"; +        return glsl_type; +    } + +    Tegra::Shader::TextureType GetType() const { +        return type; +    } + +    bool IsArray() const { +        return is_array;      }      u32 GetHash() const { @@ -105,11 +140,14 @@ private:      static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = {          "tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs",      }; +      /// Offset in TSC memory from which to read the sampler object, as specified by the sampling      /// instruction.      size_t offset; -    Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used. -    size_t sampler_index;       ///< Value used to index into the generated GLSL sampler array. +    Maxwell::ShaderStage stage;      ///< Shader stage where this sampler was used. +    size_t sampler_index;            ///< Value used to index into the generated GLSL sampler array. +    Tegra::Shader::TextureType type; ///< The type used to sample this texture (Texture2D, etc) +    bool is_array; ///< Whether the texture is being sampled as an array texture or not.  };  struct ShaderEntries {  | 
