From 92bebecf4632fb5435d74a77d45bf56535eb85e4 Mon Sep 17 00:00:00 2001
From: vonchenplus <vonchenplus@gmail.com>
Date: Tue, 26 Oct 2021 23:09:44 +0800
Subject: [PATCH] Support gl_FrontSecondaryColor attribute

---
 .../backend/spirv/emit_context.cpp               | 16 ++++++++++++++++
 .../backend/spirv/emit_context.h                 |  2 ++
 .../backend/spirv/emit_spirv_context_get_set.cpp | 15 +++++++++++++++
 3 files changed, 33 insertions(+)

diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 9d84c4fc62..7726bc9c6d 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -1286,6 +1286,14 @@ void EmitContext::DefineInputs(const IR::Program& program) {
         Decorate(id, spv::Decoration::Location, location);
         input_front_color = id;
     }
+    if (loads.AnyComponent(IR::Attribute::ColorFrontSpecularR)) {
+        const size_t location = FindNextUnusedLocation(used_locations, previous_unused_location);
+        previous_unused_location = location;
+        used_locations.set(location);
+        const Id id{DefineInput(*this, F32[4], true)};
+        Decorate(id, spv::Decoration::Location, location);
+        input_front_secondary_color = id;
+    }
     if (loads.AnyComponent(IR::Attribute::ColorBackDiffuseR)) {
         const size_t location = FindNextUnusedLocation(used_locations, previous_unused_location);
         previous_unused_location = location;
@@ -1371,6 +1379,14 @@ void EmitContext::DefineOutputs(const IR::Program& program) {
         Decorate(id, spv::Decoration::Location, static_cast<u32>(location));
         output_front_color = id;
     }
+    if (info.stores.AnyComponent(IR::Attribute::ColorFrontSpecularR)) {
+        const size_t location = FindNextUnusedLocation(used_locations, previous_unused_location);
+        previous_unused_location = location;
+        used_locations.set(location);
+        const Id id{DefineOutput(*this, F32[4], invocations)};
+        Decorate(id, spv::Decoration::Location, static_cast<u32>(location));
+        output_front_secondary_color = id;
+    }
     if (info.stores.AnyComponent(IR::Attribute::ColorBackDiffuseR)) {
         const size_t location = FindNextUnusedLocation(used_locations, previous_unused_location);
         previous_unused_location = location;
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index d2bc0a952f..8818269a55 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -269,6 +269,7 @@ public:
 
     Id input_position{};
     Id input_front_color{};
+    Id input_front_secondary_color{};
     Id input_back_color{};
     std::array<Id, 10> input_fixed_fnc_textures{};
     std::array<Id, 32> input_generics{};
@@ -276,6 +277,7 @@ public:
     Id output_point_size{};
     Id output_position{};
     Id output_front_color{};
+    Id output_front_secondary_color{};
     Id output_back_color{};
     std::array<Id, 10> output_fixed_fnc_textures{};
     std::array<std::array<GenericElementInfo, 4>, 32> output_generics{};
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 899df62941..2da76493a7 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -119,6 +119,14 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
         const Id element_id{ctx.Const(element)};
         return OutputAccessChain(ctx, ctx.output_f32, ctx.output_front_color, element_id);
     }
+    case IR::Attribute::ColorFrontSpecularR:
+    case IR::Attribute::ColorFrontSpecularG:
+    case IR::Attribute::ColorFrontSpecularB:
+    case IR::Attribute::ColorFrontSpecularA: {
+        const u32 element{static_cast<u32>(attr) % 4};
+        const Id element_id{ctx.Const(element)};
+        return OutputAccessChain(ctx, ctx.output_f32, ctx.output_front_secondary_color, element_id);
+    }
     case IR::Attribute::ColorBackDiffuseR:
     case IR::Attribute::ColorBackDiffuseG:
     case IR::Attribute::ColorBackDiffuseB:
@@ -371,6 +379,13 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
         return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_front_color,
                                                   ctx.Const(element)));
     }
+    case IR::Attribute::ColorFrontSpecularR:
+    case IR::Attribute::ColorFrontSpecularG:
+    case IR::Attribute::ColorFrontSpecularB:
+    case IR::Attribute::ColorFrontSpecularA: {
+        return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_front_secondary_color,
+                                                  ctx.Const(element)));
+    }
     case IR::Attribute::ColorBackDiffuseR:
     case IR::Attribute::ColorBackDiffuseG:
     case IR::Attribute::ColorBackDiffuseB: