Explorar el Código

Merge pull request #3520 from ReinUsesLisp/legacy-varyings

gl_shader_decompiler: Implement legacy varyings
bunnei hace 6 años
padre
commit
e6aff11057

+ 6 - 0
src/video_core/engines/shader_bytecode.h

@@ -82,6 +82,10 @@ union Attribute {
         Position = 7,
         Attribute_0 = 8,
         Attribute_31 = 39,
+        FrontColor = 40,
+        FrontSecondaryColor = 41,
+        BackColor = 42,
+        BackSecondaryColor = 43,
         ClipDistances0123 = 44,
         ClipDistances4567 = 45,
         PointCoord = 46,
@@ -89,6 +93,8 @@ union Attribute {
         // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
         // shader.
         TessCoordInstanceIDVertexID = 47,
+        TexCoord_0 = 48,
+        TexCoord_7 = 55,
         // This attribute contains a tuple of (Unk, Unk, Unk, gl_FrontFacing) when inside a fragment
         // shader. It is unknown what the other values contain.
         FrontFacing = 63,

+ 55 - 12
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -366,10 +366,19 @@ constexpr bool IsGenericAttribute(Attribute::Index index) {
     return index >= Attribute::Index::Attribute_0 && index <= Attribute::Index::Attribute_31;
 }
 
+constexpr bool IsLegacyTexCoord(Attribute::Index index) {
+    return static_cast<int>(index) >= static_cast<int>(Attribute::Index::TexCoord_0) &&
+           static_cast<int>(index) <= static_cast<int>(Attribute::Index::TexCoord_7);
+}
+
 constexpr Attribute::Index ToGenericAttribute(u64 value) {
     return static_cast<Attribute::Index>(value + static_cast<u64>(Attribute::Index::Attribute_0));
 }
 
+constexpr int GetLegacyTexCoordIndex(Attribute::Index index) {
+    return static_cast<int>(index) - static_cast<int>(Attribute::Index::TexCoord_0);
+}
+
 u32 GetGenericAttributeIndex(Attribute::Index index) {
     ASSERT(IsGenericAttribute(index));
     return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
@@ -498,7 +507,7 @@ private:
         if (!identifier.empty()) {
             code.AddLine("// {}", identifier);
         }
-        code.AddLine("#version 440 core");
+        code.AddLine("#version 440 {}", ir.UsesLegacyVaryings() ? "compatibility" : "core");
         code.AddLine("#extension GL_ARB_separate_shader_objects : enable");
         if (device.HasShaderBallot()) {
             code.AddLine("#extension GL_ARB_shader_ballot : require");
@@ -561,6 +570,16 @@ private:
         if (stage != ShaderType::Fragment) {
             return;
         }
+        if (ir.UsesLegacyVaryings()) {
+            code.AddLine("in gl_PerFragment {{");
+            ++code.scope;
+            code.AddLine("vec4 gl_TexCoord[8];");
+            code.AddLine("vec4 gl_Color;");
+            code.AddLine("vec4 gl_SecondaryColor;");
+            --code.scope;
+            code.AddLine("}};");
+        }
+
         for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) {
             code.AddLine("layout (location = {}) out vec4 frag_color{};", rt, rt);
         }
@@ -617,12 +636,12 @@ private:
             code.AddLine("float gl_PointSize;");
         }
 
-        if (ir.UsesInstanceId()) {
-            code.AddLine("int gl_InstanceID;");
-        }
-
-        if (ir.UsesVertexId()) {
-            code.AddLine("int gl_VertexID;");
+        if (ir.UsesLegacyVaryings()) {
+            code.AddLine("vec4 gl_TexCoord[8];");
+            code.AddLine("vec4 gl_FrontColor;");
+            code.AddLine("vec4 gl_FrontSecondaryColor;");
+            code.AddLine("vec4 gl_BackColor;");
+            code.AddLine("vec4 gl_BackSecondaryColor;");
         }
 
         --code.scope;
@@ -1128,6 +1147,10 @@ private:
             default:
                 UNREACHABLE();
             }
+        case Attribute::Index::FrontColor:
+            return {"gl_Color"s + GetSwizzle(element), Type::Float};
+        case Attribute::Index::FrontSecondaryColor:
+            return {"gl_SecondaryColor"s + GetSwizzle(element), Type::Float};
         case Attribute::Index::PointCoord:
             switch (element) {
             case 0:
@@ -1168,6 +1191,12 @@ private:
                 return {GeometryPass(GetGenericInputAttribute(attribute)) + GetSwizzle(element),
                         Type::Float};
             }
+            if (IsLegacyTexCoord(attribute)) {
+                UNIMPLEMENTED_IF(stage == ShaderType::Geometry);
+                return {fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute),
+                                    GetSwizzle(element)),
+                        Type::Float};
+            }
             break;
         }
         UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
@@ -1206,11 +1235,12 @@ private:
     }
 
     std::optional<Expression> GetOutputAttribute(const AbufNode* abuf) {
+        const u32 element = abuf->GetElement();
         switch (const auto attribute = abuf->GetIndex()) {
         case Attribute::Index::Position:
-            return {{"gl_Position"s + GetSwizzle(abuf->GetElement()), Type::Float}};
+            return {{"gl_Position"s + GetSwizzle(element), Type::Float}};
         case Attribute::Index::LayerViewportPointSize:
-            switch (abuf->GetElement()) {
+            switch (element) {
             case 0:
                 UNIMPLEMENTED();
                 return {};
@@ -1228,13 +1258,26 @@ private:
                 return {{"gl_PointSize", Type::Float}};
             }
             return {};
+        case Attribute::Index::FrontColor:
+            return {{"gl_FrontColor"s + GetSwizzle(element), Type::Float}};
+        case Attribute::Index::FrontSecondaryColor:
+            return {{"gl_FrontSecondaryColor"s + GetSwizzle(element), Type::Float}};
+        case Attribute::Index::BackColor:
+            return {{"gl_BackColor"s + GetSwizzle(element), Type::Float}};
+        case Attribute::Index::BackSecondaryColor:
+            return {{"gl_BackSecondaryColor"s + GetSwizzle(element), Type::Float}};
         case Attribute::Index::ClipDistances0123:
-            return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement()), Type::Float}};
+            return {{fmt::format("gl_ClipDistance[{}]", element), Type::Float}};
         case Attribute::Index::ClipDistances4567:
-            return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), Type::Float}};
+            return {{fmt::format("gl_ClipDistance[{}]", element + 4), Type::Float}};
         default:
             if (IsGenericAttribute(attribute)) {
-                return {{GetGenericOutputAttribute(attribute, abuf->GetElement()), Type::Float}};
+                return {{GetGenericOutputAttribute(attribute, element), Type::Float}};
+            }
+            if (IsLegacyTexCoord(attribute)) {
+                return {{fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute),
+                                     GetSwizzle(element)),
+                         Type::Float}};
             }
             UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute));
             return {};

+ 50 - 35
src/video_core/shader/shader_ir.cpp

@@ -96,6 +96,7 @@ Node ShaderIR::GetPredicate(bool immediate) {
 }
 
 Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) {
+    MarkAttributeUsage(index, element);
     used_input_attributes.emplace(index);
     return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer));
 }
@@ -106,42 +107,8 @@ Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_addres
 }
 
 Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) {
-    if (index == Attribute::Index::LayerViewportPointSize) {
-        switch (element) {
-        case 0:
-            UNIMPLEMENTED();
-            break;
-        case 1:
-            uses_layer = true;
-            break;
-        case 2:
-            uses_viewport_index = true;
-            break;
-        case 3:
-            uses_point_size = true;
-            break;
-        }
-    }
-    if (index == Attribute::Index::TessCoordInstanceIDVertexID) {
-        switch (element) {
-        case 2:
-            uses_instance_id = true;
-            break;
-        case 3:
-            uses_vertex_id = true;
-            break;
-        default:
-            break;
-        }
-    }
-    if (index == Attribute::Index::ClipDistances0123 ||
-        index == Attribute::Index::ClipDistances4567) {
-        const auto clip_index =
-            static_cast<u32>((index == Attribute::Index::ClipDistances4567 ? 1 : 0) + element);
-        used_clip_distances.at(clip_index) = true;
-    }
+    MarkAttributeUsage(index, element);
     used_output_attributes.insert(index);
-
     return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer));
 }
 
@@ -452,6 +419,54 @@ Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 bits) {
                      Immediate(bits));
 }
 
+void ShaderIR::MarkAttributeUsage(Attribute::Index index, u64 element) {
+    switch (index) {
+    case Attribute::Index::LayerViewportPointSize:
+        switch (element) {
+        case 0:
+            UNIMPLEMENTED();
+            break;
+        case 1:
+            uses_layer = true;
+            break;
+        case 2:
+            uses_viewport_index = true;
+            break;
+        case 3:
+            uses_point_size = true;
+            break;
+        }
+        break;
+    case Attribute::Index::TessCoordInstanceIDVertexID:
+        switch (element) {
+        case 2:
+            uses_instance_id = true;
+            break;
+        case 3:
+            uses_vertex_id = true;
+            break;
+        }
+        break;
+    case Attribute::Index::ClipDistances0123:
+    case Attribute::Index::ClipDistances4567: {
+        const u64 clip_index = (index == Attribute::Index::ClipDistances4567 ? 4 : 0) + element;
+        used_clip_distances.at(clip_index) = true;
+        break;
+    }
+    case Attribute::Index::FrontColor:
+    case Attribute::Index::FrontSecondaryColor:
+    case Attribute::Index::BackColor:
+    case Attribute::Index::BackSecondaryColor:
+        uses_legacy_varyings = true;
+        break;
+    default:
+        if (index >= Attribute::Index::TexCoord_0 && index <= Attribute::Index::TexCoord_7) {
+            uses_legacy_varyings = true;
+        }
+        break;
+    }
+}
+
 std::size_t ShaderIR::DeclareAmend(Node new_amend) {
     const std::size_t id = amend_code.size();
     amend_code.push_back(new_amend);

+ 8 - 0
src/video_core/shader/shader_ir.h

@@ -137,6 +137,10 @@ public:
         return uses_vertex_id;
     }
 
+    bool UsesLegacyVaryings() const {
+        return uses_legacy_varyings;
+    }
+
     bool UsesWarps() const {
         return uses_warps;
     }
@@ -343,6 +347,9 @@ private:
     /// Inserts a sequence of bits from a node
     Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits);
 
+    /// Marks the usage of a input or output attribute.
+    void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element);
+
     void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
                                   const Node4& components);
 
@@ -443,6 +450,7 @@ private:
     bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes
     bool uses_instance_id{};
     bool uses_vertex_id{};
+    bool uses_legacy_varyings{};
     bool uses_warps{};
     bool uses_indexed_samplers{};