From 2a713337165df4d5c4228458999a680e9ab65369 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Thu, 27 May 2021 22:28:33 -0400
Subject: [PATCH] glsl: Fix bindings, add some CC ops

---
 .../backend/glsl/emit_context.cpp             | 57 +++++++++++--------
 .../backend/glsl/emit_context.h               |  5 +-
 .../glsl/emit_glsl_context_get_set.cpp        | 33 ++++++-----
 .../backend/glsl/emit_glsl_image.cpp          | 13 ++---
 .../backend/glsl/emit_glsl_instructions.h     |  4 +-
 .../backend/glsl/emit_glsl_integer.cpp        | 29 +++++++++-
 .../glsl/emit_glsl_not_implemented.cpp        |  2 +-
 .../backend/glsl/emit_glsl_select.cpp         |  7 +--
 8 files changed, 92 insertions(+), 58 deletions(-)

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index 0ddc0443b..7bd6b3605 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -20,6 +20,20 @@ std::string_view InterpDecorator(Interpolation interp) {
     }
     throw InvalidArgument("Invalid interpolation {}", interp);
 }
+
+std::string_view SamplerType(TextureType type) {
+    switch (type) {
+    case TextureType::Color2D:
+        return "sampler2D";
+    case TextureType::ColorArray2D:
+        return "sampler2DArray";
+    case TextureType::Color3D:
+        return "sampler3D";
+    default:
+        throw NotImplementedException("Texture type: {}", type);
+    }
+}
+
 } // namespace
 
 EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
@@ -31,27 +45,23 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
     switch (program.stage) {
     case Stage::VertexA:
     case Stage::VertexB:
-        stage_name = "vertex";
-        attrib_name = "vertex";
+        stage_name = "vs";
         // TODO: add only what's used by the shader
         header +=
             "out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];};";
         break;
     case Stage::TessellationControl:
     case Stage::TessellationEval:
-        stage_name = "primitive";
-        attrib_name = "primitive";
+        stage_name = "ts";
         break;
     case Stage::Geometry:
-        stage_name = "primitive";
-        attrib_name = "vertex";
+        stage_name = "gs";
         break;
     case Stage::Fragment:
-        stage_name = "fragment";
-        attrib_name = "fragment";
+        stage_name = "fs";
         break;
     case Stage::Compute:
-        stage_name = "invocation";
+        stage_name = "cs";
         header += fmt::format("layout(local_size_x={},local_size_y={},local_size_z={}) in;\n",
                               program.workgroup_size[0], program.workgroup_size[1],
                               program.workgroup_size[2]);
@@ -77,12 +87,12 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
             Add("layout(location={}) out vec4 out_attr{};", index, index);
         }
     }
-    DefineConstantBuffers();
-    DefineStorageBuffers();
-    DefineHelperFunctions();
+    DefineConstantBuffers(bindings);
+    DefineStorageBuffers(bindings);
     SetupImages(bindings);
-    Add("void main(){{");
+    DefineHelperFunctions();
 
+    Add("void main(){{");
     if (stage == Stage::VertexA || stage == Stage::VertexB) {
         Add("gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);");
     }
@@ -112,27 +122,25 @@ void EmitContext::SetupExtensions(std::string& header) {
     }
 }
 
-void EmitContext::DefineConstantBuffers() {
+void EmitContext::DefineConstantBuffers(Bindings& bindings) {
     if (info.constant_buffer_descriptors.empty()) {
         return;
     }
-    u32 binding{};
     for (const auto& desc : info.constant_buffer_descriptors) {
-        Add("layout(std140,binding={}) uniform cbuf_{}{{vec4 cbuf{}[{}];}};", binding, desc.index,
-            desc.index, 4 * 1024);
-        ++binding;
+        Add("layout(std140,binding={}) uniform {}_cbuf_{}{{vec4 {}_cbuf{}[{}];}};",
+            bindings.uniform_buffer, stage_name, desc.index, stage_name, desc.index, 4 * 1024);
+        bindings.uniform_buffer += desc.count;
     }
 }
 
-void EmitContext::DefineStorageBuffers() {
+void EmitContext::DefineStorageBuffers(Bindings& bindings) {
     if (info.storage_buffers_descriptors.empty()) {
         return;
     }
-    u32 binding{};
     for (const auto& desc : info.storage_buffers_descriptors) {
-        Add("layout(std430,binding={}) buffer ssbo_{}{{uint ssbo{}[];}};", binding, binding,
-            desc.cbuf_index, desc.count);
-        ++binding;
+        Add("layout(std430,binding={}) buffer ssbo_{}{{uint ssbo{}[];}};", bindings.storage_buffer,
+            bindings.storage_buffer, desc.cbuf_index);
+        bindings.storage_buffer += desc.count;
     }
 }
 
@@ -203,10 +211,11 @@ void EmitContext::SetupImages(Bindings& bindings) {
     }
     texture_bindings.reserve(info.texture_descriptors.size());
     for (const auto& desc : info.texture_descriptors) {
+        const auto sampler_type{SamplerType(desc.type)};
         texture_bindings.push_back(bindings.texture);
         const auto indices{bindings.texture + desc.count};
         for (u32 index = bindings.texture; index < indices; ++index) {
-            Add("layout(binding={}) uniform sampler2D tex{};", bindings.texture, index);
+            Add("layout(binding={}) uniform {} tex{};", bindings.texture, sampler_type, index);
         }
         bindings.texture += desc.count;
     }
diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 07dad6e57..9dff921db 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -127,7 +127,6 @@ public:
 
     Stage stage{};
     std::string_view stage_name = "invalid";
-    std::string_view attrib_name = "invalid";
 
     std::vector<u32> texture_buffer_bindings;
     std::vector<u32> image_buffer_bindings;
@@ -138,8 +137,8 @@ public:
 
 private:
     void SetupExtensions(std::string& header);
-    void DefineConstantBuffers();
-    void DefineStorageBuffers();
+    void DefineConstantBuffers(Bindings& bindings);
+    void DefineStorageBuffers(Bindings& bindings);
     void DefineHelperFunctions();
     void SetupImages(Bindings& bindings);
 };
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 38ad9de35..67d308c49 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
@@ -43,23 +43,24 @@ void EmitGetCbufS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const IR
 void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                     const IR::Value& offset) {
     if (offset.IsImmediate()) {
-        ctx.AddU32("{}=floatBitsToUint(cbuf{}[{}].{});", inst, binding.U32(), offset.U32() / 16,
-                   OffsetSwizzle(offset.U32()));
+        ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}].{});", inst, ctx.stage_name, binding.U32(),
+                   offset.U32() / 16, OffsetSwizzle(offset.U32()));
     } else {
         const auto offset_var{ctx.reg_alloc.Consume(offset)};
-        ctx.AddU32("{}=floatBitsToUint(cbuf{}[{}/16][({}/4)%4]);", inst, binding.U32(), offset_var,
-                   offset_var);
+        ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}/16][({}/4)%4]);", inst, ctx.stage_name,
+                   binding.U32(), offset_var, offset_var);
     }
 }
 
 void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                     const IR::Value& offset) {
     if (offset.IsImmediate()) {
-        ctx.AddF32("{}=cbuf{}[{}].{};", inst, binding.U32(), offset.U32() / 16,
+        ctx.AddF32("{}={}_cbuf{}[{}].{};", inst, ctx.stage_name, binding.U32(), offset.U32() / 16,
                    OffsetSwizzle(offset.U32()));
     } else {
         const auto offset_var{ctx.reg_alloc.Consume(offset)};
-        ctx.AddF32("{}=cbuf{}[{}/16][({}/4)%4];", inst, binding.U32(), offset_var, offset_var);
+        ctx.AddF32("{}={}_cbuf{}[{}/16][({}/4)%4];", inst, ctx.stage_name, binding.U32(),
+                   offset_var, offset_var);
     }
 }
 
@@ -68,15 +69,17 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding
     if (offset.IsImmediate()) {
         const auto u32_offset{offset.U32()};
         const auto index{(u32_offset / 4) % 4};
-        ctx.AddU32x2("{}=uvec2(floatBitsToUint(cbuf{}[{}].{}),floatBitsToUint(cbuf{}[{}].{}));",
-                     inst, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
-                     binding.U32(), (offset.U32() + 1) / 16, OffsetSwizzle(offset.U32() + 1));
+        ctx.AddU32x2(
+            "{}=uvec2(floatBitsToUint({}_cbuf{}[{}].{}),floatBitsToUint({}_cbuf{}[{}].{}));", inst,
+            ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
+            ctx.stage_name, binding.U32(), (offset.U32() + 1) / 16,
+            OffsetSwizzle(offset.U32() + 1));
     } else {
         const auto offset_var{ctx.reg_alloc.Consume(offset)};
-        ctx.AddU32x2("{}=uvec2(floatBitsToUint(cbuf{}[{}/16][({}/"
-                     "4)%4]),floatBitsToUint(cbuf{}[({}+1)/16][(({}+1/4))%4]));",
-                     inst, binding.U32(), offset_var, offset_var, binding.U32(), offset_var,
-                     offset_var);
+        ctx.AddU32x2("{}=uvec2(floatBitsToUint({}_cbuf{}[{}/16][({}/"
+                     "4)%4]),floatBitsToUint({}_cbuf{}[({}+1)/16][(({}+1/4))%4]));",
+                     inst, ctx.stage_name, binding.U32(), offset_var, offset_var, ctx.stage_name,
+                     binding.U32(), offset_var, offset_var);
     }
 }
 
@@ -107,10 +110,10 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
         }
         break;
     case IR::Attribute::InstanceId:
-        ctx.AddS32("{}=gl_InstanceID;", inst, ctx.attrib_name);
+        ctx.AddS32("{}=gl_InstanceID;", inst);
         break;
     case IR::Attribute::VertexId:
-        ctx.AddS32("{}=gl_VertexID;", inst, ctx.attrib_name);
+        ctx.AddS32("{}=gl_VertexID;", inst);
         break;
     default:
         fmt::print("Get attribute {}", attr);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
index 6b7f1eaad..c070fba0e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
@@ -32,14 +32,13 @@ void EmitImageSampleImplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unuse
     if (info.has_lod_clamp) {
         throw NotImplementedException("Lod clamp samples");
     }
-    if (!offset.IsEmpty()) {
-        throw NotImplementedException("Offset");
-    }
-    if (info.type != TextureType::Color2D) {
-        throw NotImplementedException("Texture type: {}", info.type.Value());
-    }
     const auto texture{Texture(ctx, info, index)};
-    ctx.AddF32x4("{}=texture({},{});", inst, texture, coords);
+    if (!offset.IsEmpty()) {
+        ctx.AddF32x4("{}=textureOffset({},{},ivec2({}));", inst, texture, coords,
+                     ctx.reg_alloc.Consume(offset));
+    } else {
+        ctx.AddF32x4("{}=texture({},{});", inst, texture, coords);
+    }
 }
 
 void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index f08ed0ece..b54fe684e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -207,8 +207,8 @@ void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std:
                               u32 index);
 void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object,
                               u32 index);
-void EmitSelectU1(EmitContext& ctx, std::string_view cond, std::string_view true_value,
-                  std::string_view false_value);
+void EmitSelectU1(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
+                  std::string_view true_value, std::string_view false_value);
 void EmitSelectU8(EmitContext& ctx, std::string_view cond, std::string_view true_value,
                   std::string_view false_value);
 void EmitSelectU16(EmitContext& ctx, std::string_view cond, std::string_view true_value,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
index ce6e12623..84e01b151 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
@@ -8,8 +8,30 @@
 #include "shader_recompiler/frontend/ir/value.h"
 
 namespace Shader::Backend::GLSL {
+namespace {
+void SetZeroFlag(EmitContext& ctx, IR::Inst& inst, std::string_view result) {
+    IR::Inst* const zero{inst.GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)};
+    if (!zero) {
+        return;
+    }
+    ctx.AddU1("{}={}==0;", *zero, result);
+    zero->Invalidate();
+}
+
+void SetSignFlag(EmitContext& ctx, IR::Inst& inst, std::string_view result) {
+    IR::Inst* const sign{inst.GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)};
+    if (!sign) {
+        return;
+    }
+    ctx.AddU1("{}=int({})<0;", *sign, result);
+    sign->Invalidate();
+}
+} // Anonymous namespace
 void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddU32("{}={}+{};", inst, a, b);
+    const auto result{ctx.reg_alloc.Define(inst)};
+    ctx.Add("uint {}={}+{};", result, a, b);
+    SetZeroFlag(ctx, inst, result);
+    SetSignFlag(ctx, inst, result);
 }
 
 void EmitIAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
@@ -98,7 +120,10 @@ void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, std::string_view bas
 
 void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, std::string_view base,
                           std::string_view offset, std::string_view count) {
-    ctx.AddU32("{}=bitfieldExtract({}, int({}), int({}));", inst, base, offset, count);
+    const auto result{ctx.reg_alloc.Define(inst)};
+    ctx.Add("uint {}=bitfieldExtract({},int({}),int({}));", result, base, offset, count);
+    SetZeroFlag(ctx, inst, result);
+    SetSignFlag(ctx, inst, result);
 }
 
 void EmitBitReverse32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
index 110d3322e..3bac8899b 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -29,7 +29,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& phi) {
 }
 
 void EmitVoid(EmitContext& ctx) {
-    NotImplemented();
+    // NotImplemented();
 }
 
 void EmitReference(EmitContext&) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
index 1f2790b7d..ad3713f2d 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
@@ -8,10 +8,9 @@
 #include "shader_recompiler/frontend/ir/value.h"
 
 namespace Shader::Backend::GLSL {
-void EmitSelectU1([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond,
-                  [[maybe_unused]] std::string_view true_value,
-                  [[maybe_unused]] std::string_view false_value) {
-    throw NotImplementedException("GLSL Instruction");
+void EmitSelectU1(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
+                  std::string_view true_value, std::string_view false_value) {
+    ctx.AddU1("{}={}?{}:{};", inst, cond, true_value, false_value);
 }
 
 void EmitSelectU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond,