Răsfoiți Sursa

glasm: Implement indirect attribute loads

ReinUsesLisp 5 ani în urmă
părinte
comite
e30d4fa976

+ 1 - 2
src/shader_recompiler/backend/glasm/emit_context.cpp

@@ -30,9 +30,8 @@ bool IsInputArray(Stage stage) {
 
 EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
                          const RuntimeInfo& runtime_info_)
-    : profile{profile_}, runtime_info{runtime_info_} {
+    : info{program.info}, profile{profile_}, runtime_info{runtime_info_} {
     // FIXME: Temporary partial implementation
-    const auto& info{program.info};
     u32 cbuf_index{};
     for (const auto& desc : info.constant_buffer_descriptors) {
         if (desc.count != 1) {

+ 1 - 0
src/shader_recompiler/backend/glasm/emit_context.h

@@ -58,6 +58,7 @@ public:
 
     std::string code;
     RegAlloc reg_alloc{*this};
+    const Info& info;
     const Profile& profile;
     const RuntimeInfo& runtime_info;
 

+ 62 - 3
src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp

@@ -8,6 +8,7 @@
 #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
 #include "shader_recompiler/frontend/ir/value.h"
 #include "shader_recompiler/profile.h"
+#include "shader_recompiler/shader_info.h"
 
 namespace Shader::Backend::GLASM {
 namespace {
@@ -153,9 +154,67 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value,
     }
 }
 
-void EmitGetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset,
-                             [[maybe_unused]] ScalarU32 vertex) {
-    throw NotImplementedException("GLASM instruction");
+void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex) {
+    // RC.x = base_index
+    // RC.y = masked_index
+    // RC.z = compare_index
+    ctx.Add("SHR.S RC.x,{},2;"
+            "AND.S RC.y,RC.x,3;"
+            "SHR.S RC.z,{},4;",
+            offset, offset);
+
+    const Register ret{ctx.reg_alloc.Define(inst)};
+    u32 num_endifs{};
+    const auto read{[&](u32 compare_index, const std::array<std::string, 4>& values) {
+        ++num_endifs;
+        ctx.Add("SEQ.S.CC RC.w,RC.z,{};" // compare_index
+                "IF NE.w;"
+                // X
+                "SEQ.S.CC RC.w,RC.y,0;"
+                "IF NE.w;"
+                "MOV {}.x,{};"
+                "ELSE;"
+                // Y
+                "SEQ.S.CC RC.w,RC.y,1;"
+                "IF NE.w;"
+                "MOV {}.x,{};"
+                "ELSE;"
+                // Z
+                "SEQ.S.CC RC.w,RC.y,2;"
+                "IF NE.w;"
+                "MOV {}.x,{};"
+                "ELSE;"
+                // W
+                "MOV {}.x,{};"
+                "ENDIF;"
+                "ENDIF;"
+                "ENDIF;"
+                "ELSE;",
+                compare_index, ret, values[0], ret, values[1], ret, values[2], ret, values[3]);
+    }};
+    const auto read_swizzled{[&](u32 compare_index, std::string_view value) {
+        const std::array values{fmt::format("{}.x", value), fmt::format("{}.y", value),
+                                fmt::format("{}.z", value), fmt::format("{}.w", value)};
+        read(compare_index, values);
+    }};
+    if (ctx.info.loads_position) {
+        const u32 index{static_cast<u32>(IR::Attribute::PositionX)};
+        if (IsInputArray(ctx.stage)) {
+            read_swizzled(index, fmt::format("vertex_position{}", VertexIndex(ctx, vertex)));
+        } else {
+            read_swizzled(index, fmt::format("{}.position", ctx.attrib_name));
+        }
+    }
+    const u32 base_attribute_value{static_cast<u32>(IR::Attribute::Generic0X) >> 2};
+    for (u32 index = 0; index < ctx.info.input_generics.size(); ++index) {
+        if (!ctx.info.input_generics[index].used) {
+            continue;
+        }
+        read_swizzled(index, fmt::format("in_attr{}{}[0]", index, VertexIndex(ctx, vertex)));
+    }
+    for (u32 i = 0; i < num_endifs; ++i) {
+        ctx.Add("ENDIF;");
+    }
 }
 
 void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset,

+ 1 - 1
src/shader_recompiler/backend/glasm/emit_glasm_instructions.h

@@ -51,7 +51,7 @@ void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
 void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
 void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex);
 void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex);
-void EmitGetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarU32 vertex);
+void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex);
 void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex);
 void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch);
 void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value);