From ae7062d5225bb486a7325398a639c27ec6098a97 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Sun, 2 Oct 2022 17:32:54 -0400
Subject: [PATCH] shader_recompiler: add extended LDC to GLASM backend

---
 .../glasm/emit_glasm_context_get_set.cpp      | 25 ++++++++++++++++---
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
index b5c08d611..7e8f37563 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
@@ -13,9 +13,6 @@ namespace Shader::Backend::GLASM {
 namespace {
 void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset,
              std::string_view size) {
-    if (!binding.IsImmediate()) {
-        throw NotImplementedException("Indirect constant buffer loading");
-    }
     const Register ret{ctx.reg_alloc.Define(inst)};
     if (offset.type == Type::U32) {
         // Avoid reading arrays out of bounds, matching hardware's behavior
@@ -24,7 +21,27 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU
             return;
         }
     }
-    ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset);
+
+    if (binding.IsImmediate()) {
+        ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset);
+        return;
+    }
+
+    const ScalarU32 idx{ctx.reg_alloc.Consume(binding)};
+    for (u32 i = 0; i < Info::MAX_INDIRECT_CBUFS; i++) {
+        ctx.Add("SEQ.S.CC RC.x,{},{};"
+                "IF NE.x;"
+                "LDC.{} {},c{}[{}];",
+                idx, i, size, ret, i, offset);
+
+        if (i != Info::MAX_INDIRECT_CBUFS - 1) {
+            ctx.Add("ELSE;");
+        }
+    }
+
+    for (u32 i = 0; i < Info::MAX_INDIRECT_CBUFS; i++) {
+        ctx.Add("ENDIF;");
+    }
 }
 
 bool IsInputArray(Stage stage) {