From 0a0b0a73d82057a309b6b0427c29c7e15e2b356f Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Thu, 3 Jun 2021 22:25:06 -0400
Subject: glsl: Fix <32-bit SSBO writes

and more cleanup
---
 .../backend/glsl/emit_context.cpp                  | 52 +++++++++-------------
 .../backend/glsl/emit_glsl_atomic.cpp              |  7 +--
 .../backend/glsl/emit_glsl_context_get_set.cpp     |  2 +-
 .../backend/glsl/emit_glsl_memory.cpp              | 32 ++++++++-----
 4 files changed, 43 insertions(+), 50 deletions(-)

(limited to 'src/shader_recompiler/backend')

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index ae5ac752de..ecc7335baa 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -433,8 +433,7 @@ void EmitContext::DefineHelperFunctions() {
 }
 
 std::string EmitContext::DefineGlobalMemoryFunctions() {
-    const auto define_body{[&](std::string& func, size_t index, u32 num_components,
-                               std::string_view return_statement) {
+    const auto define_body{[&](std::string& func, size_t index, std::string_view return_statement) {
         const auto& ssbo{info.storage_buffers_descriptors[index]};
         const u32 size_cbuf_offset{ssbo.cbuf_offset + 8};
         const auto ssbo_addr{fmt::format("ssbo_addr{}", index)};
@@ -458,42 +457,31 @@ std::string EmitContext::DefineGlobalMemoryFunctions() {
         func += comparison;
 
         const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)};
-        switch (num_components) {
-        case 1:
-            func += fmt::format(return_statement, ssbo_name, ssbo_addr);
-            break;
-        case 2:
-            func += fmt::format(return_statement, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr);
-            break;
-        case 4:
-            func += fmt::format(return_statement, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr,
-                                ssbo_name, ssbo_addr, ssbo_name, ssbo_addr);
-            break;
-        }
+        func += fmt::format(return_statement, ssbo_name, ssbo_addr);
     }};
-    std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){\n"};
-    std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){\n"};
-    std::string write_func_128{"void WriteGlobal128(uint64_t addr,uvec4 data){\n"};
-    std::string load_func{"uint LoadGlobal32(uint64_t addr){\n"};
-    std::string load_func_64{"uvec2 LoadGlobal64(uint64_t addr){\n"};
-    std::string load_func_128{"uvec4 LoadGlobal128(uint64_t addr){\n"};
+    std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){"};
+    std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){"};
+    std::string write_func_128{"void WriteGlobal128(uint64_t addr,uvec4 data){"};
+    std::string load_func{"uint LoadGlobal32(uint64_t addr){"};
+    std::string load_func_64{"uvec2 LoadGlobal64(uint64_t addr){"};
+    std::string load_func_128{"uvec4 LoadGlobal128(uint64_t addr){"};
     const size_t num_buffers{info.storage_buffers_descriptors.size()};
     for (size_t index = 0; index < num_buffers; ++index) {
         if (!info.nvn_buffer_used[index]) {
             continue;
         }
-        define_body(write_func, index, 1, "{}[uint(addr-{})>>2]=data;return;}}");
-        define_body(write_func_64, index, 2,
-                    "{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;return;}}");
-        define_body(write_func_128, index, 4,
-                    "{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;{}[uint("
-                    "addr-{}+8)>>2]=data.z;{}[uint(addr-{}+12)>>2]=data.w;return;}}");
-        define_body(load_func, index, 1, "return {}[uint(addr-{})>>2];}}");
-        define_body(load_func_64, index, 2,
-                    "return uvec2({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2]);}}");
-        define_body(load_func_128, index, 4,
-                    "return uvec4({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2],{}["
-                    "uint(addr-{}+8)>>2],{}[uint(addr-{}+12)>>2]);}}");
+        define_body(write_func, index, "{0}[uint(addr-{1})>>2]=data;return;}}");
+        define_body(write_func_64, index,
+                    "{0}[uint(addr-{1})>>2]=data.x;{0}[uint(addr-{1}+4)>>2]=data.y;return;}}");
+        define_body(write_func_128, index,
+                    "{0}[uint(addr-{1})>>2]=data.x;{0}[uint(addr-{1}+4)>>2]=data.y;{0}[uint("
+                    "addr-{1}+8)>>2]=data.z;{0}[uint(addr-{1}+12)>>2]=data.w;return;}}");
+        define_body(load_func, index, "return {0}[uint(addr-{1})>>2];}}");
+        define_body(load_func_64, index,
+                    "return uvec2({0}[uint(addr-{1})>>2],{0}[uint(addr-{1}+4)>>2]);}}");
+        define_body(load_func_128, index,
+                    "return uvec4({0}[uint(addr-{1})>>2],{0}[uint(addr-{1}+4)>>2],{0}["
+                    "uint(addr-{1}+8)>>2],{0}[uint(addr-{1}+12)>>2]);}}");
     }
     write_func += "}";
     write_func_64 += "}";
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
index 5ba39261b0..1568bb7cfd 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
@@ -11,11 +11,8 @@
 
 namespace Shader::Backend::GLSL {
 namespace {
-constexpr const char cas_loop[]{R"(for (;;){{
-    uint old_value={};
-    {}=atomicCompSwap({},old_value,{}({},{}));
-    if ({}==old_value){{break;}}
-}})"};
+constexpr char cas_loop[]{
+    "for (;;){{uint old={};{}=atomicCompSwap({},old,{}({},{}));if({}==old){{break;}}}}"};
 
 void SharedCasFunction(EmitContext& ctx, IR::Inst& inst, std::string_view offset,
                        std::string_view value, std::string_view function) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
index d986e1b1aa..b2caa222ab 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
@@ -11,7 +11,7 @@
 
 namespace Shader::Backend::GLSL {
 namespace {
-static constexpr std::string_view SWIZZLE{"xyzw"};
+constexpr char SWIZZLE[]{"xyzw"};
 
 u32 CbufIndex(u32 offset) {
     return (offset / 4) % 4;
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
index bc43638241..500e5c2905 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
@@ -9,6 +9,18 @@
 #include "shader_recompiler/frontend/ir/value.h"
 
 namespace Shader::Backend::GLSL {
+namespace {
+constexpr char cas_loop[]{"for(;;){{uint old_value={};uint "
+                          "cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
+                          "if(cas_result==old_value){{break;}}}}"};
+
+void SsboWriteCas(EmitContext& ctx, const IR::Value& binding, std::string_view offset_var,
+                  std::string_view value, std::string_view bit_offset, u32 num_bits) {
+    const auto ssbo{fmt::format("{}_ssbo{}[{}>>2]", ctx.stage_name, binding.U32(), offset_var)};
+    ctx.Add(cas_loop, ssbo, ssbo, ssbo, value, bit_offset, num_bits);
+}
+} // Anonymous namespace
+
 void EmitLoadGlobalU8([[maybe_unused]] EmitContext& ctx) {
     NotImplemented();
 }
@@ -125,9 +137,8 @@ void EmitWriteStorageU8([[maybe_unused]] EmitContext& ctx,
                         [[maybe_unused]] const IR::Value& offset,
                         [[maybe_unused]] std::string_view value) {
     const auto offset_var{ctx.var_alloc.Consume(offset)};
-    ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int({}%4)*8,8);", ctx.stage_name,
-            binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, value,
-            offset_var);
+    const auto bit_offset{fmt::format("int({}%4)*8", offset_var)};
+    SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 8);
 }
 
 void EmitWriteStorageS8([[maybe_unused]] EmitContext& ctx,
@@ -135,9 +146,8 @@ void EmitWriteStorageS8([[maybe_unused]] EmitContext& ctx,
                         [[maybe_unused]] const IR::Value& offset,
                         [[maybe_unused]] std::string_view value) {
     const auto offset_var{ctx.var_alloc.Consume(offset)};
-    ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int({}%4)*8,8);", ctx.stage_name,
-            binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, value,
-            offset_var);
+    const auto bit_offset{fmt::format("int({}%4)*8", offset_var)};
+    SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 8);
 }
 
 void EmitWriteStorageU16([[maybe_unused]] EmitContext& ctx,
@@ -145,9 +155,8 @@ void EmitWriteStorageU16([[maybe_unused]] EmitContext& ctx,
                          [[maybe_unused]] const IR::Value& offset,
                          [[maybe_unused]] std::string_view value) {
     const auto offset_var{ctx.var_alloc.Consume(offset)};
-    ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int(({}>>1)%2)*16,16);",
-            ctx.stage_name, binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var,
-            value, offset_var);
+    const auto bit_offset{fmt::format("int(({}>>1)%2)*16", offset_var)};
+    SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 16);
 }
 
 void EmitWriteStorageS16([[maybe_unused]] EmitContext& ctx,
@@ -155,9 +164,8 @@ void EmitWriteStorageS16([[maybe_unused]] EmitContext& ctx,
                          [[maybe_unused]] const IR::Value& offset,
                          [[maybe_unused]] std::string_view value) {
     const auto offset_var{ctx.var_alloc.Consume(offset)};
-    ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int(({}>>1)%2)*16,16);",
-            ctx.stage_name, binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var,
-            value, offset_var);
+    const auto bit_offset{fmt::format("int(({}>>1)%2)*16", offset_var)};
+    SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 16);
 }
 
 void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
-- 
cgit v1.2.3-70-g09d2