Просмотр исходного кода

gl_shader_decompiler: Add AOFFI backing implementation

ReinUsesLisp 7 лет назад
Родитель
Сommit
e8abe4b77c
1 измененных файлов с 85 добавлено и 38 удалено
  1. 85 38
      src/video_core/renderer_opengl/gl_shader_decompiler.cpp

+ 85 - 38
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -34,14 +34,20 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs;
 using ShaderStage = Tegra::Engines::Maxwell3D::Regs::ShaderStage;
 using ShaderStage = Tegra::Engines::Maxwell3D::Regs::ShaderStage;
 using Operation = const OperationNode&;
 using Operation = const OperationNode&;
 
 
+enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat };
+
+namespace {
+struct TextureAoffi {};
+using TextureArgument = std::pair<Type, Node>;
+using TextureIR = std::variant<TextureAoffi, TextureArgument>;
+} // namespace
+
 enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 };
 enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 };
 constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
 constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
     static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float));
     static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float));
 constexpr u32 MAX_GLOBALMEMORY_ELEMENTS =
 constexpr u32 MAX_GLOBALMEMORY_ELEMENTS =
     static_cast<u32>(RasterizerOpenGL::MaxGlobalMemorySize) / sizeof(float);
     static_cast<u32>(RasterizerOpenGL::MaxGlobalMemorySize) / sizeof(float);
 
 
-enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat };
-
 class ShaderWriter {
 class ShaderWriter {
 public:
 public:
     void AddExpression(std::string_view text) {
     void AddExpression(std::string_view text) {
@@ -718,8 +724,8 @@ private:
                                                          result_type));
                                                          result_type));
     }
     }
 
 
-    std::string GenerateTexture(Operation operation, const std::string& func,
-                                const std::vector<std::pair<Type, Node>>& extras) {
+    std::string GenerateTexture(Operation operation, const std::string& function_suffix,
+                                const std::vector<TextureIR>& extras) {
         constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"};
         constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"};
 
 
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
@@ -729,11 +735,11 @@ private:
         const bool has_array = meta->sampler.IsArray();
         const bool has_array = meta->sampler.IsArray();
         const bool has_shadow = meta->sampler.IsShadow();
         const bool has_shadow = meta->sampler.IsShadow();
 
 
-        std::string expr = func;
-        expr += '(';
-        expr += GetSampler(meta->sampler);
-        expr += ", ";
-
+        std::string expr = "texture" + function_suffix;
+        if (!meta->aoffi.empty()) {
+            expr += "Offset";
+        }
+        expr += '(' + GetSampler(meta->sampler) + ", ";
         expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow ? 1 : 0) - 1);
         expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow ? 1 : 0) - 1);
         expr += '(';
         expr += '(';
         for (std::size_t i = 0; i < count; ++i) {
         for (std::size_t i = 0; i < count; ++i) {
@@ -751,36 +757,74 @@ private:
         }
         }
         expr += ')';
         expr += ')';
 
 
-        for (const auto& extra_pair : extras) {
-            const auto [type, operand] = extra_pair;
-            if (operand == nullptr) {
-                continue;
+        for (const auto& variant : extras) {
+            if (const auto argument = std::get_if<TextureArgument>(&variant)) {
+                expr += GenerateTextureArgument(*argument);
+            } else if (std::get_if<TextureAoffi>(&variant)) {
+                expr += GenerateTextureAoffi(meta->aoffi);
+            } else {
+                UNREACHABLE();
             }
             }
-            expr += ", ";
+        }
 
 
-            switch (type) {
-            case Type::Int:
-                if (const auto immediate = std::get_if<ImmediateNode>(operand)) {
-                    // Inline the string as an immediate integer in GLSL (some extra arguments are
-                    // required to be constant)
-                    expr += std::to_string(static_cast<s32>(immediate->GetValue()));
-                } else {
-                    expr += "ftoi(" + Visit(operand) + ')';
-                }
-                break;
-            case Type::Float:
-                expr += Visit(operand);
-                break;
-            default: {
-                const auto type_int = static_cast<u32>(type);
-                UNIMPLEMENTED_MSG("Unimplemented extra type={}", type_int);
-                expr += '0';
-                break;
+        return expr + ')';
+    }
+
+    std::string GenerateTextureArgument(TextureArgument argument) {
+        const auto [type, operand] = argument;
+        if (operand == nullptr) {
+            return {};
+        }
+
+        std::string expr = ", ";
+        switch (type) {
+        case Type::Int:
+            if (const auto immediate = std::get_if<ImmediateNode>(operand)) {
+                // Inline the string as an immediate integer in GLSL (some extra arguments are
+                // required to be constant)
+                expr += std::to_string(static_cast<s32>(immediate->GetValue()));
+            } else {
+                expr += "ftoi(" + Visit(operand) + ')';
             }
             }
+            break;
+        case Type::Float:
+            expr += Visit(operand);
+            break;
+        default: {
+            const auto type_int = static_cast<u32>(type);
+            UNIMPLEMENTED_MSG("Unimplemented extra type={}", type_int);
+            expr += '0';
+            break;
+        }
+        }
+        return expr;
+    }
+
+    std::string GenerateTextureAoffi(const std::vector<Node>& aoffi) {
+        if (aoffi.empty()) {
+            return {};
+        }
+        constexpr std::array<const char*, 3> coord_constructors = {"int", "ivec2", "ivec3"};
+        std::string expr = ", ";
+        expr += coord_constructors.at(aoffi.size() - 1);
+        expr += '(';
+
+        for (std::size_t index = 0; index < aoffi.size(); ++index) {
+            const auto operand{aoffi.at(index)};
+            if (const auto immediate = std::get_if<ImmediateNode>(operand)) {
+                // Inline the string as an immediate integer in GLSL (AOFFI arguments are required
+                // to be constant by the standard).
+                expr += std::to_string(static_cast<s32>(immediate->GetValue()));
+            } else {
+                expr += "ftoi(" + Visit(operand) + ')';
+            }
+            if (index + 1 < aoffi.size()) {
+                expr += ", ";
             }
             }
         }
         }
+        expr += ')';
 
 
-        return expr + ')';
+        return expr;
     }
     }
 
 
     std::string Assign(Operation operation) {
     std::string Assign(Operation operation) {
@@ -1159,7 +1203,8 @@ private:
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
         ASSERT(meta);
         ASSERT(meta);
 
 
-        std::string expr = GenerateTexture(operation, "texture", {{Type::Float, meta->bias}});
+        std::string expr = GenerateTexture(
+            operation, "", {TextureAoffi{}, TextureArgument{Type::Float, meta->bias}});
         if (meta->sampler.IsShadow()) {
         if (meta->sampler.IsShadow()) {
             expr = "vec4(" + expr + ')';
             expr = "vec4(" + expr + ')';
         }
         }
@@ -1170,7 +1215,8 @@ private:
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
         ASSERT(meta);
         ASSERT(meta);
 
 
-        std::string expr = GenerateTexture(operation, "textureLod", {{Type::Float, meta->lod}});
+        std::string expr = GenerateTexture(
+            operation, "Lod", {TextureArgument{Type::Float, meta->lod}, TextureAoffi{}});
         if (meta->sampler.IsShadow()) {
         if (meta->sampler.IsShadow()) {
             expr = "vec4(" + expr + ')';
             expr = "vec4(" + expr + ')';
         }
         }
@@ -1182,7 +1228,8 @@ private:
         ASSERT(meta);
         ASSERT(meta);
 
 
         const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int;
         const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int;
-        return GenerateTexture(operation, "textureGather", {{type, meta->component}}) +
+        return GenerateTexture(operation, "Gather",
+                               {TextureArgument{type, meta->component}, TextureAoffi{}}) +
                GetSwizzle(meta->element);
                GetSwizzle(meta->element);
     }
     }
 
 
@@ -1211,8 +1258,8 @@ private:
         ASSERT(meta);
         ASSERT(meta);
 
 
         if (meta->element < 2) {
         if (meta->element < 2) {
-            return "itof(int((" + GenerateTexture(operation, "textureQueryLod", {}) +
-                   " * vec2(256))" + GetSwizzle(meta->element) + "))";
+            return "itof(int((" + GenerateTexture(operation, "QueryLod", {}) + " * vec2(256))" +
+                   GetSwizzle(meta->element) + "))";
         }
         }
         return "0";
         return "0";
     }
     }