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

gl_shader_decompiler: Declare all possible varyings on physical attribute usage

ReinUsesLisp 7 лет назад
Родитель
Сommit
bd81a03d9d

+ 1 - 0
src/video_core/engines/maxwell_3d.h

@@ -51,6 +51,7 @@ public:
         static constexpr std::size_t NumCBData = 16;
         static constexpr std::size_t NumVertexArrays = 32;
         static constexpr std::size_t NumVertexAttributes = 32;
+        static constexpr std::size_t NumVaryings = 31;
         static constexpr std::size_t NumTextureSamplers = 32;
         static constexpr std::size_t NumClipDistances = 8;
         static constexpr std::size_t MaxShaderProgram = 6;

+ 9 - 0
src/video_core/renderer_opengl/gl_device.cpp

@@ -21,9 +21,18 @@ T GetInteger(GLenum pname) {
 
 Device::Device() {
     uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+    max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
+    max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
     has_variable_aoffi = TestVariableAoffi();
 }
 
+Device::Device(std::nullptr_t) {
+    uniform_buffer_alignment = 0;
+    max_vertex_attributes = 16;
+    max_varyings = 15;
+    has_variable_aoffi = true;
+}
+
 bool Device::TestVariableAoffi() {
     const GLchar* AOFFI_TEST = R"(#version 430 core
 uniform sampler2D tex;

+ 13 - 1
src/video_core/renderer_opengl/gl_device.h

@@ -5,17 +5,27 @@
 #pragma once
 
 #include <cstddef>
+#include "common/common_types.h"
 
 namespace OpenGL {
 
 class Device {
 public:
-    Device();
+    explicit Device();
+    explicit Device(std::nullptr_t);
 
     std::size_t GetUniformBufferAlignment() const {
         return uniform_buffer_alignment;
     }
 
+    u32 GetMaxVertexAttributes() const {
+        return max_vertex_attributes;
+    }
+
+    u32 GetMaxVaryings() const {
+        return max_varyings;
+    }
+
     bool HasVariableAoffi() const {
         return has_variable_aoffi;
     }
@@ -24,6 +34,8 @@ private:
     static bool TestVariableAoffi();
 
     std::size_t uniform_buffer_alignment{};
+    u32 max_vertex_attributes{};
+    u32 max_varyings{};
     bool has_variable_aoffi{};
 };
 

+ 65 - 26
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -316,55 +316,85 @@ private:
     }
 
     void DeclareInputAttributes() {
+        if (ir.HasPhysicalAttributes()) {
+            const u32 num_inputs{stage == ShaderStage::Vertex ? GetNumPhysicalAttributes()
+                                                              : GetNumPhysicalVaryings()};
+            for (u32 i = 0; i < num_inputs; ++i) {
+                constexpr auto generic_base{static_cast<u32>(Attribute::Index::Attribute_0)};
+                const auto index{static_cast<Attribute::Index>(generic_base + i)};
+                DeclareInputAttribute(index);
+            }
+            code.AddNewLine();
+            return;
+        }
+
         const auto& attributes = ir.GetInputAttributes();
         for (const auto index : attributes) {
             if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) {
                 // Skip when it's not a generic attribute
                 continue;
             }
-
-            // TODO(bunnei): Use proper number of elements for these
-            u32 idx = static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
-            if (stage != ShaderStage::Vertex) {
-                // If inputs are varyings, add an offset
-                idx += GENERIC_VARYING_START_LOCATION;
-            }
-
-            std::string attr = GetInputAttribute(index);
-            if (stage == ShaderStage::Geometry) {
-                attr = "gs_" + attr + "[]";
-            }
-            std::string suffix;
-            if (stage == ShaderStage::Fragment) {
-                const auto input_mode =
-                    header.ps.GetAttributeUse(idx - GENERIC_VARYING_START_LOCATION);
-                suffix = GetInputFlags(input_mode);
-            }
-            code.AddLine("layout (location = " + std::to_string(idx) + ") " + suffix + "in vec4 " +
-                         attr + ';');
+            DeclareInputAttribute(index);
         }
         if (!attributes.empty())
             code.AddNewLine();
     }
 
+    void DeclareInputAttribute(Attribute::Index index) {
+        const u32 generic_index{static_cast<u32>(index) -
+                                static_cast<u32>(Attribute::Index::Attribute_0)};
+
+        std::string name{GetInputAttribute(index)};
+        if (stage == ShaderStage::Geometry) {
+            name = "gs_" + name + "[]";
+        }
+        std::string suffix;
+        if (stage == ShaderStage::Fragment) {
+            const auto input_mode{header.ps.GetAttributeUse(generic_index)};
+            suffix = GetInputFlags(input_mode);
+        }
+
+        u32 location = generic_index;
+        if (stage != ShaderStage::Vertex) {
+            // If inputs are varyings, add an offset
+            location += GENERIC_VARYING_START_LOCATION;
+        }
+
+        code.AddLine("layout (location = " + std::to_string(location) + ") " + suffix + "in vec4 " +
+                     name + ';');
+    }
+
     void DeclareOutputAttributes() {
+        if (ir.HasPhysicalAttributes()) {
+            for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) {
+                constexpr auto generic_base{static_cast<u32>(Attribute::Index::Attribute_0)};
+                const auto index{static_cast<Attribute::Index>(generic_base + i)};
+                DeclareOutputAttribute(index);
+            }
+            code.AddNewLine();
+            return;
+        }
+
         const auto& attributes = ir.GetOutputAttributes();
         for (const auto index : attributes) {
             if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) {
                 // Skip when it's not a generic attribute
                 continue;
             }
-            // TODO(bunnei): Use proper number of elements for these
-            const auto idx = static_cast<u32>(index) -
-                             static_cast<u32>(Attribute::Index::Attribute_0) +
-                             GENERIC_VARYING_START_LOCATION;
-            code.AddLine("layout (location = " + std::to_string(idx) + ") out vec4 " +
-                         GetOutputAttribute(index) + ';');
+            DeclareOutputAttribute(index);
         }
         if (!attributes.empty())
             code.AddNewLine();
     }
 
+    void DeclareOutputAttribute(Attribute::Index index) {
+        const auto location{static_cast<u32>(index) -
+                            static_cast<u32>(Attribute::Index::Attribute_0) +
+                            GENERIC_VARYING_START_LOCATION};
+        code.AddLine("layout (location = " + std::to_string(location) + ") out vec4 " +
+                     GetOutputAttribute(index) + ';');
+    }
+
     void DeclareConstantBuffers() {
         for (const auto& entry : ir.GetConstantBuffers()) {
             const auto [index, size] = entry;
@@ -1650,6 +1680,15 @@ private:
         return name + '_' + std::to_string(index) + '_' + suffix;
     }
 
+    u32 GetNumPhysicalAttributes() const {
+        return std::min<u32>(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes);
+    }
+
+    u32 GetNumPhysicalVaryings() const {
+        return std::min<u32>(device.GetMaxVaryings() - GENERIC_VARYING_START_LOCATION,
+                             Maxwell::NumVaryings);
+    }
+
     const Device& device;
     const ShaderIR& ir;
     const ShaderStage stage;