From 1269a0cf8b3844c1a9bb06c843a7698b0a9643d5 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Sun, 30 May 2021 17:27:00 -0400
Subject: glsl: Rework variable allocator to allow for variable reuse

---
 src/shader_recompiler/backend/glsl/var_alloc.cpp | 290 +++++++++++++++++++++++
 1 file changed, 290 insertions(+)
 create mode 100644 src/shader_recompiler/backend/glsl/var_alloc.cpp

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
new file mode 100644
index 0000000000..8c6944f07d
--- /dev/null
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -0,0 +1,290 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <string>
+#include <string_view>
+
+#include <fmt/format.h>
+
+#include "shader_recompiler/backend/glsl/var_alloc.h"
+#include "shader_recompiler/exception.h"
+#include "shader_recompiler/frontend/ir/value.h"
+
+namespace Shader::Backend::GLSL {
+namespace {
+std::string TypePrefix(GlslVarType type) {
+    switch (type) {
+    case GlslVarType::U1:
+        return "b_";
+    case GlslVarType::F16x2:
+        return "f16x2_";
+    case GlslVarType::U32:
+        return "u_";
+    case GlslVarType::S32:
+        return "s_";
+    case GlslVarType::F32:
+        return "f_";
+    case GlslVarType::S64:
+        return "s64_";
+    case GlslVarType::U64:
+        return "u64_";
+    case GlslVarType::F64:
+        return "d_";
+    case GlslVarType::U32x2:
+        return "u2_";
+    case GlslVarType::F32x2:
+        return "f2_";
+    case GlslVarType::U32x3:
+        return "u3_";
+    case GlslVarType::F32x3:
+        return "f3_";
+    case GlslVarType::U32x4:
+        return "u4_";
+    case GlslVarType::F32x4:
+        return "f4_";
+    case GlslVarType::Void:
+        return "";
+    default:
+        throw NotImplementedException("Type {}", type);
+    }
+}
+
+std::string FormatFloat(std::string_view value, IR::Type type) {
+    // TODO: Confirm FP64 nan/inf
+    if (type == IR::Type::F32) {
+        if (value == "nan") {
+            return "uintBitsToFloat(0x7fc00000)";
+        }
+        if (value == "inf") {
+            return "uintBitsToFloat(0x7f800000)";
+        }
+        if (value == "-inf") {
+            return "uintBitsToFloat(0xff800000)";
+        }
+    }
+    if (value.find_first_of('e') != std::string_view::npos) {
+        // scientific notation
+        const auto cast{type == IR::Type::F32 ? "float" : "double"};
+        return fmt::format("{}({})", cast, value);
+    }
+    const bool needs_dot{value.find_first_of('.') == std::string_view::npos};
+    const bool needs_suffix{!value.ends_with('f')};
+    const auto suffix{type == IR::Type::F32 ? "f" : "lf"};
+    return fmt::format("{}{}{}", value, needs_dot ? "." : "", needs_suffix ? suffix : "");
+}
+
+std::string MakeImm(const IR::Value& value) {
+    switch (value.Type()) {
+    case IR::Type::U1:
+        return fmt::format("{}", value.U1() ? "true" : "false");
+    case IR::Type::U32:
+        return fmt::format("{}u", value.U32());
+    case IR::Type::F32:
+        return FormatFloat(fmt::format("{}", value.F32()), IR::Type::F32);
+    case IR::Type::U64:
+        return fmt::format("{}ul", value.U64());
+    case IR::Type::F64:
+        return FormatFloat(fmt::format("{}", value.F64()), IR::Type::F64);
+    case IR::Type::Void:
+        return "";
+    default:
+        throw NotImplementedException("Immediate type {}", value.Type());
+    }
+}
+} // Anonymous namespace
+
+std::string VarAlloc::Representation(u32 index, GlslVarType type) const {
+    const auto prefix{TypePrefix(type)};
+    return fmt::format("{}{}", prefix, index);
+}
+
+std::string VarAlloc::Representation(Id id) const {
+    return Representation(id.index, id.type);
+}
+
+std::string VarAlloc::Define(IR::Inst& inst, GlslVarType type) {
+    if (inst.HasUses()) {
+        inst.SetDefinition<Id>(Alloc(type));
+        return Representation(inst.Definition<Id>());
+    } else {
+        Id id{};
+        id.type.Assign(type);
+        // id.is_null.Assign(1);
+        GetUseTracker(type).uses_temp = true;
+        inst.SetDefinition<Id>(id);
+    }
+    return Representation(inst.Definition<Id>());
+}
+
+std::string VarAlloc::Define(IR::Inst& inst, IR::Type type) {
+    return Define(inst, RegType(type));
+}
+
+std::string VarAlloc::Consume(const IR::Value& value) {
+    return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive());
+}
+
+std::string VarAlloc::ConsumeInst(IR::Inst& inst) {
+    inst.DestructiveRemoveUsage();
+    if (!inst.HasUses()) {
+        Free(inst.Definition<Id>());
+    }
+    return Representation(inst.Definition<Id>());
+}
+
+std::string VarAlloc::GetGlslType(IR::Type type) const {
+    return GetGlslType(RegType(type));
+}
+
+Id VarAlloc::Alloc(GlslVarType type) {
+    auto& use_tracker{GetUseTracker(type)};
+    if (use_tracker.num_used < NUM_VARS) {
+        for (size_t var = 1; var < NUM_VARS; ++var) {
+            if (use_tracker.var_use[var]) {
+                continue;
+            }
+            use_tracker.num_used = std::max(use_tracker.num_used, var + 1);
+            use_tracker.var_use[var] = true;
+            Id ret{};
+            ret.is_valid.Assign(1);
+            ret.type.Assign(type);
+            ret.index.Assign(static_cast<u32>(var));
+            return ret;
+        }
+    }
+    throw NotImplementedException("Variable spilling");
+}
+
+void VarAlloc::Free(Id id) {
+    if (id.is_valid == 0) {
+        // throw LogicError("Freeing invalid variable");
+        return;
+    }
+    auto& use_tracker{GetUseTracker(id.type)};
+    use_tracker.var_use[id.index] = false;
+}
+
+GlslVarType VarAlloc::RegType(IR::Type type) const {
+    switch (type) {
+    case IR::Type::U1:
+        return GlslVarType::U1;
+    case IR::Type::U32:
+        return GlslVarType::U32;
+    case IR::Type::F32:
+        return GlslVarType::F32;
+    case IR::Type::U64:
+        return GlslVarType::U64;
+    case IR::Type::F64:
+        return GlslVarType::F64;
+    default:
+        throw NotImplementedException("IR type {}", type);
+    }
+}
+
+std::string VarAlloc::GetGlslType(GlslVarType type) const {
+    switch (type) {
+    case GlslVarType::U1:
+        return "bool ";
+    case GlslVarType::F16x2:
+        return "f16vec2 ";
+    case GlslVarType::U32:
+        return "uint ";
+    case GlslVarType::S32:
+        return "int ";
+    case GlslVarType::F32:
+        return "float ";
+    case GlslVarType::S64:
+        return "int64_t ";
+    case GlslVarType::U64:
+        return "uint64_t ";
+    case GlslVarType::F64:
+        return "double ";
+    case GlslVarType::U32x2:
+        return "uvec2 ";
+    case GlslVarType::F32x2:
+        return "vec2 ";
+    case GlslVarType::U32x3:
+        return "uvec3 ";
+    case GlslVarType::F32x3:
+        return "vec3 ";
+    case GlslVarType::U32x4:
+        return "uvec4 ";
+    case GlslVarType::F32x4:
+        return "vec4 ";
+    case GlslVarType::Void:
+        return "";
+    default:
+        throw NotImplementedException("Type {}", type);
+    }
+}
+
+VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
+    switch (type) {
+    case GlslVarType::U1:
+        return var_bool;
+    case GlslVarType::U32:
+        return var_u32;
+    case GlslVarType::S32:
+        return var_s32;
+    case GlslVarType::F32:
+        return var_f32;
+    case GlslVarType::S64:
+        return var_s64;
+    case GlslVarType::U64:
+        return var_u64;
+    case GlslVarType::F64:
+        return var_f64;
+    case GlslVarType::U32x2:
+        return var_u32x2;
+    case GlslVarType::F32x2:
+        return var_f32x2;
+    case GlslVarType::U32x3:
+        return var_u32x3;
+    case GlslVarType::F32x3:
+        return var_f32x3;
+    case GlslVarType::U32x4:
+        return var_u32x4;
+    case GlslVarType::F32x4:
+        return var_f32x4;
+    default:
+        throw NotImplementedException("Type {}", type);
+    }
+}
+
+const VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) const {
+    switch (type) {
+    case GlslVarType::U1:
+        return var_bool;
+    case GlslVarType::F16x2:
+        return var_f16x2;
+    case GlslVarType::U32:
+        return var_u32;
+    case GlslVarType::S32:
+        return var_s32;
+    case GlslVarType::F32:
+        return var_f32;
+    case GlslVarType::S64:
+        return var_s64;
+    case GlslVarType::U64:
+        return var_u64;
+    case GlslVarType::F64:
+        return var_f64;
+    case GlslVarType::U32x2:
+        return var_u32x2;
+    case GlslVarType::F32x2:
+        return var_f32x2;
+    case GlslVarType::U32x3:
+        return var_u32x3;
+    case GlslVarType::F32x3:
+        return var_f32x3;
+    case GlslVarType::U32x4:
+        return var_u32x4;
+    case GlslVarType::F32x4:
+        return var_f32x4;
+    default:
+        throw NotImplementedException("Type {}", type);
+    }
+}
+
+} // namespace Shader::Backend::GLSL
-- 
cgit v1.2.3-70-g09d2


From 9f3ffb996b0d02ca64b492d22ff158e8f3659257 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Sun, 30 May 2021 19:13:22 -0400
Subject: glsl: Rework var alloc to not assign unused results

---
 .../backend/glsl/emit_context.cpp                  |  8 ++--
 src/shader_recompiler/backend/glsl/emit_context.h  |  8 +++-
 .../backend/glsl/emit_glsl_atomic.cpp              |  9 ++--
 .../backend/glsl/emit_glsl_bitwise_conversion.cpp  |  8 +++-
 .../backend/glsl/emit_glsl_composite.cpp           | 50 ++++++++++++++--------
 .../backend/glsl/emit_glsl_instructions.h          | 26 +++++------
 .../backend/glsl/emit_glsl_not_implemented.cpp     |  8 ++--
 src/shader_recompiler/backend/glsl/var_alloc.cpp   | 17 +++++++-
 src/shader_recompiler/backend/glsl/var_alloc.h     |  6 +++
 9 files changed, 91 insertions(+), 49 deletions(-)

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index b9594de402..da29290a2c 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -122,11 +122,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
 
 void EmitContext::SetupExtensions(std::string&) {
     header += "#extension GL_ARB_separate_shader_objects : enable\n";
-    if (stage != Stage::Compute) {
-        // TODO: track this usage
-        header += "#extension GL_ARB_sparse_texture2 : enable\n";
-        header += "#extension GL_EXT_texture_shadow_lod : enable\n";
-    }
+    // TODO: track this usage
+    header += "#extension GL_ARB_sparse_texture2 : enable\n";
+    header += "#extension GL_EXT_texture_shadow_lod : enable\n";
     if (info.uses_int64) {
         header += "#extension GL_ARB_gpu_shader_int64 : enable\n";
     }
diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 2f1062954e..423fc61046 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -37,7 +37,13 @@ public:
 
     template <GlslVarType type, typename... Args>
     void Add(const char* format_str, IR::Inst& inst, Args&&... args) {
-        code += fmt::format(format_str, var_alloc.Define(inst, type), std::forward<Args>(args)...);
+        const auto var_def{var_alloc.AddDefine(inst, type)};
+        if (var_def.empty()) {
+            // skip assigment.
+            code += fmt::format(&format_str[3], std::forward<Args>(args)...);
+        } else {
+            code += fmt::format(format_str, var_def, std::forward<Args>(args)...);
+        }
         // TODO: Remove this
         code += '\n';
     }
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
index 918f900589..db4c60002f 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
@@ -11,8 +11,7 @@
 
 namespace Shader::Backend::GLSL {
 namespace {
-static constexpr std::string_view cas_loop{R"({};
-for (;;){{
+static constexpr std::string_view cas_loop{R"(for (;;){{
     uint old_value={};
     {}=atomicCompSwap({},old_value,{}({},{}));
     if ({}==old_value){{break;}}
@@ -22,14 +21,14 @@ void SharedCasFunction(EmitContext& ctx, IR::Inst& inst, std::string_view offset
                        std::string_view value, std::string_view function) {
     const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
     const std::string smem{fmt::format("smem[{}/4]", offset)};
-    ctx.Add(cas_loop.data(), ret, smem, ret, smem, function, smem, value, ret);
+    ctx.Add(cas_loop.data(), smem, ret, smem, function, smem, value, ret);
 }
 
 void SsboCasFunction(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                      const IR::Value& offset, std::string_view value, std::string_view function) {
     const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
     const std::string ssbo{fmt::format("ssbo{}[{}]", binding.U32(), offset.U32())};
-    ctx.Add(cas_loop.data(), ret, ssbo, ret, ssbo, function, ssbo, value, ret);
+    ctx.Add(cas_loop.data(), ssbo, ret, ssbo, function, ssbo, value, ret);
 }
 
 void SsboCasFunctionF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
@@ -37,7 +36,7 @@ void SsboCasFunctionF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& bindi
                         std::string_view function) {
     const std::string ssbo{fmt::format("ssbo{}[{}]", binding.U32(), offset.U32())};
     const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
-    ctx.Add(cas_loop.data(), ret, ssbo, ret, ssbo, function, ssbo, value, ret);
+    ctx.Add(cas_loop.data(), ssbo, ret, ssbo, function, ssbo, value, ret);
     ctx.AddF32("{}=uintBitsToFloat({});", inst, ret);
 }
 } // namespace
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
index 2b08aa593e..9d844b831b 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
@@ -26,7 +26,13 @@ void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) {
 }
 
 void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) {
-    ctx.AddU1("{}={};", inst, ctx.var_alloc.Consume(value));
+    // Fake one usage to get a real variable out of the condition
+    inst.DestructiveAddUsage(1);
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U1)};
+    const auto input{ctx.var_alloc.Consume(value)};
+    if (ret != input) {
+        ctx.Add("{}={};", ret, input);
+    }
 }
 
 void EmitBitCastU16F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
index 0fd667c8f7..44a719fc3c 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
@@ -9,8 +9,14 @@
 #include "shader_recompiler/frontend/ir/value.h"
 
 namespace Shader::Backend::GLSL {
+namespace {
 static constexpr std::string_view SWIZZLE{"xyzw"};
-
+void CompositeInsert(EmitContext& ctx, std::string_view result, std::string_view composite,
+                     std::string_view object, u32 index) {
+    ctx.Add("{}={};", result, composite);
+    ctx.Add("{}.{}={};", result, SWIZZLE[index], object);
+}
+} // namespace
 void EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view e1,
                                  std::string_view e2) {
     ctx.AddU32x2("{}=uvec2({},{});", inst, e1, e2);
@@ -41,19 +47,22 @@ void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, std::string_vie
     ctx.AddU32("{}={}.{};", inst, composite, SWIZZLE[index]);
 }
 
-void EmitCompositeInsertU32x2(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x2)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
-void EmitCompositeInsertU32x3(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertU32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x3)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
-void EmitCompositeInsertU32x4(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x4)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
 void EmitCompositeConstructF16x2([[maybe_unused]] EmitContext& ctx,
@@ -146,19 +155,22 @@ void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, std::string_vie
     ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
 }
 
-void EmitCompositeInsertF32x2(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32x2)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
-void EmitCompositeInsertF32x3(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32x3)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
-void EmitCompositeInsertF32x4(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index) {
-    ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+void EmitCompositeInsertF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index) {
+    const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
+    CompositeInsert(ctx, ret, composite, object, index);
 }
 
 void EmitCompositeConstructF64x2([[maybe_unused]] EmitContext& ctx) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index 703db80ee6..c2e5aff16b 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -26,7 +26,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& inst);
 void EmitVoid(EmitContext& ctx);
 void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
 void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
-void EmitReference(EmitContext&);
+void EmitReference(EmitContext& ctx, const IR::Value& value);
 void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value);
 void EmitBranch(EmitContext& ctx, std::string_view label);
 void EmitBranchConditional(EmitContext& ctx, std::string_view condition,
@@ -165,12 +165,12 @@ void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, std::string_vie
                                u32 index);
 void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
                                u32 index);
-void EmitCompositeInsertU32x2(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
-void EmitCompositeInsertU32x3(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
-void EmitCompositeInsertU32x4(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
+void EmitCompositeInsertU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
+void EmitCompositeInsertU32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
+void EmitCompositeInsertU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
 void EmitCompositeConstructF16x2(EmitContext& ctx, std::string_view e1, std::string_view e2);
 void EmitCompositeConstructF16x3(EmitContext& ctx, std::string_view e1, std::string_view e2,
                                  std::string_view e3);
@@ -197,12 +197,12 @@ void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, std::string_vie
                                u32 index);
 void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
                                u32 index);
-void EmitCompositeInsertF32x2(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
-void EmitCompositeInsertF32x3(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
-void EmitCompositeInsertF32x4(EmitContext& ctx, std::string_view composite, std::string_view object,
-                              u32 index);
+void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
+void EmitCompositeInsertF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
+void EmitCompositeInsertF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                              std::string_view object, u32 index);
 void EmitCompositeConstructF64x2(EmitContext& ctx);
 void EmitCompositeConstructF64x3(EmitContext& ctx);
 void EmitCompositeConstructF64x4(EmitContext& ctx);
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 806c4777b3..599ff90e0e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -25,7 +25,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& phi) {
     }
     if (!phi.Definition<Id>().is_valid) {
         // The phi node wasn't forward defined
-        ctx.Add("{};", ctx.var_alloc.Define(phi, phi.Arg(0).Type()));
+        ctx.var_alloc.PhiDefine(phi, phi.Arg(0).Type());
     }
 }
 
@@ -33,8 +33,8 @@ void EmitVoid(EmitContext& ctx) {
     // NotImplemented();
 }
 
-void EmitReference(EmitContext&) {
-    // NotImplemented();
+void EmitReference(EmitContext& ctx, const IR::Value& value) {
+    ctx.var_alloc.Consume(value);
 }
 
 void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) {
@@ -42,7 +42,7 @@ void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value&
     const auto phi_type{phi.Arg(0).Type()};
     if (!phi.Definition<Id>().is_valid) {
         // The phi node wasn't forward defined
-        ctx.Add("{};", ctx.var_alloc.Define(phi, phi_type));
+        ctx.var_alloc.PhiDefine(phi, phi_type);
     }
     const auto phi_reg{ctx.var_alloc.Consume(IR::Value{&phi})};
     const auto val_reg{ctx.var_alloc.Consume(value)};
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 8c6944f07d..896457248b 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -110,7 +110,6 @@ std::string VarAlloc::Define(IR::Inst& inst, GlslVarType type) {
     } else {
         Id id{};
         id.type.Assign(type);
-        // id.is_null.Assign(1);
         GetUseTracker(type).uses_temp = true;
         inst.SetDefinition<Id>(id);
     }
@@ -121,6 +120,20 @@ std::string VarAlloc::Define(IR::Inst& inst, IR::Type type) {
     return Define(inst, RegType(type));
 }
 
+std::string VarAlloc::PhiDefine(IR::Inst& inst, IR::Type type) {
+    return AddDefine(inst, RegType(type));
+}
+
+std::string VarAlloc::AddDefine(IR::Inst& inst, GlslVarType type) {
+    if (inst.HasUses()) {
+        inst.SetDefinition<Id>(Alloc(type));
+        return Representation(inst.Definition<Id>());
+    } else {
+        return "";
+    }
+    return Representation(inst.Definition<Id>());
+}
+
 std::string VarAlloc::Consume(const IR::Value& value) {
     return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive());
 }
@@ -223,6 +236,8 @@ VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
     switch (type) {
     case GlslVarType::U1:
         return var_bool;
+    case GlslVarType::F16x2:
+        return var_f16x2;
     case GlslVarType::U32:
         return var_u32;
     case GlslVarType::S32:
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.h b/src/shader_recompiler/backend/glsl/var_alloc.h
index 29d78a571d..574960b1a8 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.h
+++ b/src/shader_recompiler/backend/glsl/var_alloc.h
@@ -62,9 +62,15 @@ public:
         bool uses_temp{};
     };
 
+    /// Used for explicit usages of variables, may revert to temporaries
     std::string Define(IR::Inst& inst, GlslVarType type);
     std::string Define(IR::Inst& inst, IR::Type type);
 
+    /// Used to assign variables used by the IR. May return a blank string if
+    /// the instruction's result is unused in the IR.
+    std::string AddDefine(IR::Inst& inst, GlslVarType type);
+    std::string PhiDefine(IR::Inst& inst, IR::Type type);
+
     std::string Consume(const IR::Value& value);
     std::string ConsumeInst(IR::Inst& inst);
 
-- 
cgit v1.2.3-70-g09d2


From e10366974edd7c75111d0bef16daf941db9e9a30 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Sun, 30 May 2021 22:44:28 -0400
Subject: glsl: Implement precise fp variable allocation

---
 src/shader_recompiler/backend/glsl/emit_context.h  | 10 ++++++
 .../backend/glsl/emit_glsl_floating_point.cpp      | 41 ++++++++++++++++++----
 src/shader_recompiler/backend/glsl/var_alloc.cpp   | 16 +++++++++
 src/shader_recompiler/backend/glsl/var_alloc.h     |  8 +++--
 4 files changed, 67 insertions(+), 8 deletions(-)

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 423fc61046..48786a2c76 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -118,6 +118,16 @@ public:
         Add<GlslVarType::F32x4>(format_str, inst, args...);
     }
 
+    template <typename... Args>
+    void AddPrecF32(const char* format_str, IR::Inst& inst, Args&&... args) {
+        Add<GlslVarType::PrecF32>(format_str, inst, args...);
+    }
+
+    template <typename... Args>
+    void AddPrecF64(const char* format_str, IR::Inst& inst, Args&&... args) {
+        Add<GlslVarType::PrecF64>(format_str, inst, args...);
+    }
+
     template <typename... Args>
     void Add(const char* format_str, Args&&... args) {
         code += fmt::format(format_str, std::forward<Args>(args)...);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
index 5f9603602d..342d4efb2e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
@@ -6,6 +6,7 @@
 
 #include "shader_recompiler/backend/glsl/emit_context.h"
 #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
+#include "shader_recompiler/frontend/ir/modifiers.h"
 #include "shader_recompiler/frontend/ir/value.h"
 
 namespace Shader::Backend::GLSL {
@@ -20,6 +21,10 @@ void Compare(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string
     }
     ctx.code += ";";
 }
+
+bool Precise(IR::Inst& inst) {
+    return {inst.Flags<IR::FpControl>().no_contraction};
+}
 } // namespace
 
 void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -41,11 +46,19 @@ void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 }
 
 void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddF32("{}=float({})+float({});", inst, a, b);
+    if (Precise(inst)) {
+        ctx.AddPrecF32("{}=float({})+float({});", inst, a, b);
+    } else {
+        ctx.AddF32("{}=float({})+float({});", inst, a, b);
+    }
 }
 
 void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddF64("{}=double({})+double({});", inst, a, b);
+    if (Precise(inst)) {
+        ctx.AddPrecF64("{}=double({})+double({});", inst, a, b);
+    } else {
+        ctx.AddF64("{}=double({})+double({});", inst, a, b);
+    }
 }
 
 void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -56,12 +69,20 @@ void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 
 void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
                  std::string_view c) {
-    ctx.AddF32("{}=fma({},{},{});", inst, a, b, c);
+    if (Precise(inst)) {
+        ctx.AddPrecF32("{}=fma({},{},{});", inst, a, b, c);
+    } else {
+        ctx.AddF32("{}=fma({},{},{});", inst, a, b, c);
+    }
 }
 
 void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
                  std::string_view c) {
-    ctx.AddF64("{}=fma({},{},{});", inst, a, b, c);
+    if (Precise(inst)) {
+        ctx.AddPrecF64("{}=fma({},{},{});", inst, a, b, c);
+    } else {
+        ctx.AddF64("{}=fma({},{},{});", inst, a, b, c);
+    }
 }
 
 void EmitFPMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
@@ -86,11 +107,19 @@ void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 }
 
 void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddF32("{}={}*{};", inst, a, b);
+    if (Precise(inst)) {
+        ctx.AddPrecF32("{}={}*{};", inst, a, b);
+    } else {
+        ctx.AddF32("{}={}*{};", inst, a, b);
+    }
 }
 
 void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddF64("{}={}*{};", inst, a, b);
+    if (Precise(inst)) {
+        ctx.AddPrecF64("{}={}*{};", inst, a, b);
+    } else {
+        ctx.AddF64("{}={}*{};", inst, a, b);
+    }
 }
 
 void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 896457248b..2ecdec7f21 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -43,6 +43,10 @@ std::string TypePrefix(GlslVarType type) {
         return "u4_";
     case GlslVarType::F32x4:
         return "f4_";
+    case GlslVarType::PrecF32:
+        return "pf_";
+    case GlslVarType::PrecF64:
+        return "pd_";
     case GlslVarType::Void:
         return "";
     default:
@@ -225,6 +229,10 @@ std::string VarAlloc::GetGlslType(GlslVarType type) const {
         return "uvec4 ";
     case GlslVarType::F32x4:
         return "vec4 ";
+    case GlslVarType::PrecF32:
+        return "precise float ";
+    case GlslVarType::PrecF64:
+        return "precise double ";
     case GlslVarType::Void:
         return "";
     default:
@@ -262,6 +270,10 @@ VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
         return var_u32x4;
     case GlslVarType::F32x4:
         return var_f32x4;
+    case GlslVarType::PrecF32:
+        return var_precf32;
+    case GlslVarType::PrecF64:
+        return var_precf64;
     default:
         throw NotImplementedException("Type {}", type);
     }
@@ -297,6 +309,10 @@ const VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) const {
         return var_u32x4;
     case GlslVarType::F32x4:
         return var_f32x4;
+    case GlslVarType::PrecF32:
+        return var_precf32;
+    case GlslVarType::PrecF64:
+        return var_precf64;
     default:
         throw NotImplementedException("Type {}", type);
     }
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.h b/src/shader_recompiler/backend/glsl/var_alloc.h
index 574960b1a8..be21a87ea3 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.h
+++ b/src/shader_recompiler/backend/glsl/var_alloc.h
@@ -33,6 +33,8 @@ enum class GlslVarType : u32 {
     F32x3,
     U32x4,
     F32x4,
+    PrecF32,
+    PrecF64,
     Void,
 };
 
@@ -40,8 +42,8 @@ struct Id {
     union {
         u32 raw;
         BitField<0, 1, u32> is_valid;
-        BitField<1, 4, GlslVarType> type;
-        BitField<5, 27, u32> index;
+        BitField<1, 5, GlslVarType> type;
+        BitField<6, 26, u32> index;
     };
 
     bool operator==(Id rhs) const noexcept {
@@ -101,6 +103,8 @@ private:
     UseTracker var_u64{};
     UseTracker var_s64{};
     UseTracker var_f64{};
+    UseTracker var_precf32{};
+    UseTracker var_precf64{};
 };
 
 } // namespace Shader::Backend::GLSL
-- 
cgit v1.2.3-70-g09d2


From 59576b82a8c06943e6b9fafbff6ed1884a4132a7 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Tue, 1 Jun 2021 00:07:14 -0400
Subject: glsl: Fix precise variable declaration

and add some more separation in the shader for better debugability when dumped
---
 .../backend/glsl/emit_context.cpp                  |  3 +-
 src/shader_recompiler/backend/glsl/emit_glsl.cpp   | 12 ++++----
 src/shader_recompiler/backend/glsl/var_alloc.cpp   | 34 ++++++++++------------
 3 files changed, 25 insertions(+), 24 deletions(-)

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index 01403ca17e..2375b7a068 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -150,7 +150,7 @@ void SetupOutPerVertex(Stage stage, const Info& info, std::string& header) {
     if (info.stores_clip_distance) {
         header += "float gl_ClipDistance[];";
     }
-    header += "};";
+    header += "};\n";
 }
 } // namespace
 
@@ -223,6 +223,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
             header += declaration;
         }
     }
+    header += "\n";
     DefineConstantBuffers(bindings);
     DefineStorageBuffers(bindings);
     SetupImages(bindings);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
index f467d978c7..bfc42e1b47 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
@@ -180,13 +180,15 @@ void DefineVariables(const EmitContext& ctx, std::string& header) {
         const auto type{static_cast<GlslVarType>(i)};
         const auto& tracker{ctx.var_alloc.GetUseTracker(type)};
         const auto type_name{ctx.var_alloc.GetGlslType(type)};
+        const auto precise{
+            (type == GlslVarType::PrecF32 || type == GlslVarType::PrecF64) ? "precise " : ""};
         // Temps/return types that are never used are stored at index 0
         if (tracker.uses_temp) {
-            header += fmt::format("{}{}={}(0);", type_name, ctx.var_alloc.Representation(0, type),
-                                  type_name);
+            header += fmt::format("{}{} {}={}(0);", precise, type_name,
+                                  ctx.var_alloc.Representation(0, type), type_name);
         }
         for (u32 index = 1; index <= tracker.num_used; ++index) {
-            header += fmt::format("{}{}={}(0);", type_name,
+            header += fmt::format("{}{} {}={}(0);", precise, type_name,
                                   ctx.var_alloc.Representation(index, type), type_name);
         }
     }
@@ -198,7 +200,7 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo& runtime_info, IR
     EmitContext ctx{program, bindings, profile, runtime_info};
     Precolor(program);
     EmitCode(ctx, program);
-    const std::string version{fmt::format("#version 450{}\n", GlslVersionSpecifier(ctx))};
+    const std::string version{fmt::format("#version 460{}\n", GlslVersionSpecifier(ctx))};
     ctx.header.insert(0, version);
     if (program.local_memory_size > 0) {
         ctx.header += fmt::format("uint lmem[{}];", program.local_memory_size / 4);
@@ -206,7 +208,7 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo& runtime_info, IR
     if (program.shared_memory_size > 0) {
         ctx.header += fmt::format("shared uint smem[{}];", program.shared_memory_size / 4);
     }
-    ctx.header += "void main(){\n";
+    ctx.header += "\nvoid main(){\n";
     if (program.stage == Stage::VertexA || program.stage == Stage::VertexB) {
         ctx.header += "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);";
         // TODO: Properly resolve attribute issues
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 2ecdec7f21..1ab64add4b 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -202,37 +202,35 @@ GlslVarType VarAlloc::RegType(IR::Type type) const {
 std::string VarAlloc::GetGlslType(GlslVarType type) const {
     switch (type) {
     case GlslVarType::U1:
-        return "bool ";
+        return "bool";
     case GlslVarType::F16x2:
-        return "f16vec2 ";
+        return "f16vec2";
     case GlslVarType::U32:
-        return "uint ";
+        return "uint";
     case GlslVarType::S32:
-        return "int ";
+        return "int";
     case GlslVarType::F32:
-        return "float ";
+    case GlslVarType::PrecF32:
+        return "float";
     case GlslVarType::S64:
-        return "int64_t ";
+        return "int64_t";
     case GlslVarType::U64:
-        return "uint64_t ";
+        return "uint64_t";
     case GlslVarType::F64:
-        return "double ";
+    case GlslVarType::PrecF64:
+        return "double";
     case GlslVarType::U32x2:
-        return "uvec2 ";
+        return "uvec2";
     case GlslVarType::F32x2:
-        return "vec2 ";
+        return "vec2";
     case GlslVarType::U32x3:
-        return "uvec3 ";
+        return "uvec3";
     case GlslVarType::F32x3:
-        return "vec3 ";
+        return "vec3";
     case GlslVarType::U32x4:
-        return "uvec4 ";
+        return "uvec4";
     case GlslVarType::F32x4:
-        return "vec4 ";
-    case GlslVarType::PrecF32:
-        return "precise float ";
-    case GlslVarType::PrecF64:
-        return "precise double ";
+        return "vec4";
     case GlslVarType::Void:
         return "";
     default:
-- 
cgit v1.2.3-70-g09d2


From 8d8ce24f20649be639dbb3cc0f3edc90c6a6481e Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Thu, 3 Jun 2021 19:15:36 -0400
Subject: glsl: Implement Load/WriteGlobal

along with some other misc changes and fixes
---
 .../backend/glsl/emit_context.cpp                  | 86 +++++++++++++++++++++-
 .../backend/glsl/emit_glsl_atomic.cpp              |  2 +-
 .../backend/glsl/emit_glsl_bitwise_conversion.cpp  |  4 +-
 .../backend/glsl/emit_glsl_context_get_set.cpp     | 57 +++++++-------
 .../backend/glsl/emit_glsl_image.cpp               | 10 ++-
 .../backend/glsl/emit_glsl_instructions.h          |  6 +-
 .../backend/glsl/emit_glsl_memory.cpp              | 56 ++++++++++++++
 .../backend/glsl/emit_glsl_not_implemented.cpp     | 56 --------------
 src/shader_recompiler/backend/glsl/var_alloc.cpp   |  6 +-
 9 files changed, 185 insertions(+), 98 deletions(-)

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index 5048c8b689..f68f332129 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -9,6 +9,14 @@
 
 namespace Shader::Backend::GLSL {
 namespace {
+u32 CbufIndex(u32 offset) {
+    return (offset / 4) % 4;
+}
+
+char OffsetSwizzle(u32 offset) {
+    return "xyzw"[CbufIndex(offset)];
+}
+
 std::string_view InterpDecorator(Interpolation interp) {
     switch (interp) {
     case Interpolation::Smooth:
@@ -382,6 +390,8 @@ void EmitContext::DefineGenericOutput(size_t index, u32 invocations) {
 }
 
 void EmitContext::DefineHelperFunctions() {
+    header += "\n#define ftoi floatBitsToInt\n#define ftou floatBitsToUint\n"
+              "#define itof intBitsToFloat\n#define utof uintBitsToFloat\n";
     if (info.uses_global_increment || info.uses_shared_increment) {
         header += "uint CasIncrement(uint op_a,uint op_b){return(op_a>=op_b)?0u:(op_a+1u);}\n";
     }
@@ -391,7 +401,7 @@ void EmitContext::DefineHelperFunctions() {
     }
     if (info.uses_atomic_f32_add) {
         header += "uint CasFloatAdd(uint op_a,float op_b){return "
-                  "floatBitsToUint(uintBitsToFloat(op_a)+op_b);}\n";
+                  "ftou(utof(op_a)+op_b);}\n";
     }
     if (info.uses_atomic_f32x2_add) {
         header += "uint CasFloatAdd32x2(uint op_a,vec2 op_b){return "
@@ -423,6 +433,80 @@ void EmitContext::DefineHelperFunctions() {
     if (info.uses_atomic_s32_max) {
         header += "uint CasMaxS32(uint op_a,uint op_b){return uint(max(int(op_a),int(op_b)));}";
     }
+    if (info.uses_global_memory) {
+        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"};
+        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;
+            }
+            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)};
+            const auto cbuf{fmt::format("{}_cbuf{}", stage_name, ssbo.cbuf_index)};
+            const auto cbuf_value{fmt::format(
+                "uint64_t {}=packUint2x32(uvec2(ftou({}[{}].{}),ftou({}[{}].{})));", ssbo_addr,
+                cbuf, ssbo.cbuf_offset / 16, OffsetSwizzle(ssbo.cbuf_offset), cbuf,
+                (ssbo.cbuf_offset + 4) / 16, OffsetSwizzle(ssbo.cbuf_offset + 4))};
+
+            write_func += cbuf_value;
+            write_func_64 += cbuf_value;
+            write_func_128 += cbuf_value;
+            load_func += cbuf_value;
+            load_func_64 += cbuf_value;
+            load_func_128 += cbuf_value;
+            const auto ssbo_size{fmt::format("ftou({}[{}].{}),ftou({}[{}].{})", cbuf,
+                                             size_cbuf_offset / 16, OffsetSwizzle(size_cbuf_offset),
+                                             cbuf, (size_cbuf_offset + 4) / 16,
+                                             OffsetSwizzle(size_cbuf_offset + 4))};
+            const auto comparison{fmt::format("if((addr>={})&&(addr<({}+\nuint64_t(uvec2({}))))){{",
+                                              ssbo_addr, ssbo_addr, ssbo_size)};
+            write_func += comparison;
+            write_func_64 += comparison;
+            write_func_128 += comparison;
+            load_func += comparison;
+            load_func_64 += comparison;
+            load_func_128 += comparison;
+
+            const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)};
+            write_func += fmt::format("{}[uint(addr-{})>>2]=data;return;}}", ssbo_name, ssbo_addr);
+            write_func_64 +=
+                fmt::format("{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;return;}}",
+                            ssbo_name, ssbo_addr, ssbo_name, ssbo_addr);
+            write_func_128 +=
+                fmt::format("{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;{}[uint("
+                            "addr-{}+8)>>2]=data.z;{}[uint(addr-{}+12)>>2]=data.w;return;}}",
+                            ssbo_name, ssbo_addr, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr,
+                            ssbo_name, ssbo_addr);
+            load_func += fmt::format("return {}[uint(addr-{})>>2];}}", ssbo_name, ssbo_addr);
+            load_func_64 +=
+                fmt::format("return uvec2({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2]);}}",
+                            ssbo_name, ssbo_addr, ssbo_name, ssbo_addr);
+            load_func_128 += fmt::format("return "
+                                         "uvec4({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2],{}["
+                                         "uint(addr-{}+8)>>2],{}[uint(addr-{}+12)>>2]);}}",
+                                         ssbo_name, ssbo_addr, ssbo_name, ssbo_addr, ssbo_name,
+                                         ssbo_addr, ssbo_name, ssbo_addr);
+        }
+        write_func += "}\n";
+        write_func_64 += "}\n";
+        write_func_128 += "}\n";
+        load_func += "return 0u;}\n";
+        load_func_64 += "return uvec2(0);}\n";
+        load_func_128 += "return uvec4(0);}\n";
+        header += write_func;
+        header += write_func_64;
+        header += write_func_128;
+        header += load_func;
+        header += load_func_64;
+        header += load_func_128;
+    }
 }
 
 void EmitContext::SetupImages(Bindings& bindings) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
index 5394f4a8c8..f8d2c12dbb 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
@@ -39,7 +39,7 @@ void SsboCasFunctionF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& bindi
                                        ctx.var_alloc.Consume(offset))};
     const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
     ctx.Add(cas_loop.data(), ssbo, ret, ssbo, function, ssbo, value, ret);
-    ctx.AddF32("{}=uintBitsToFloat({});", inst, ret);
+    ctx.AddF32("{}=utof({});", inst, ret);
 }
 } // namespace
 
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
index 1e860f11aa..0e617c8d8f 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
@@ -40,7 +40,7 @@ void EmitBitCastU16F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddU32("{}=floatBitsToUint({});", inst, value);
+    ctx.AddU32("{}=ftou({});", inst, value);
 }
 
 void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
@@ -52,7 +52,7 @@ void EmitBitCastF16U16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF32("{}=uintBitsToFloat({});", inst, value);
+    ctx.AddF32("{}=utof({});", inst, value);
 }
 
 void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
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 ebaf50abde..19b51a8133 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
@@ -45,14 +45,13 @@ void EmitGetCbufU8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst&
                    [[maybe_unused]] const IR::Value& binding,
                    [[maybe_unused]] const IR::Value& offset) {
     if (offset.IsImmediate()) {
-        ctx.AddU32("{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}].{}),int({}),8);", inst,
-                   ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
+        ctx.AddU32("{}=bitfieldExtract(ftou({}_cbuf{}[{}].{}),int({}),8);", inst, ctx.stage_name,
+                   binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
                    (offset.U32() % 4) * 8);
     } else {
         const auto offset_var{ctx.var_alloc.Consume(offset)};
-        ctx.AddU32(
-            "{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}/16][({}>>2)%4]),int(({}%4)*8),8);",
-            inst, ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
+        ctx.AddU32("{}=bitfieldExtract(ftou({}_cbuf{}[{}/16][({}>>2)%4]),int(({}%4)*8),8);", inst,
+                   ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
     }
 }
 
@@ -60,14 +59,13 @@ void EmitGetCbufS8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst&
                    [[maybe_unused]] const IR::Value& binding,
                    [[maybe_unused]] const IR::Value& offset) {
     if (offset.IsImmediate()) {
-        ctx.AddU32("{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}].{}),int({}),8);", inst,
-                   ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
+        ctx.AddU32("{}=bitfieldExtract(ftoi({}_cbuf{}[{}].{}),int({}),8);", inst, ctx.stage_name,
+                   binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
                    (offset.U32() % 4) * 8);
     } else {
         const auto offset_var{ctx.var_alloc.Consume(offset)};
-        ctx.AddU32(
-            "{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}/16][({}>>2)%4]),int(({}%4)*8),8);",
-            inst, ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
+        ctx.AddU32("{}=bitfieldExtract(ftoi({}_cbuf{}[{}/16][({}>>2)%4]),int(({}%4)*8),8);", inst,
+                   ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
     }
 }
 
@@ -75,12 +73,12 @@ void EmitGetCbufU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst
                     [[maybe_unused]] const IR::Value& binding,
                     [[maybe_unused]] const IR::Value& offset) {
     if (offset.IsImmediate()) {
-        ctx.AddU32("{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}].{}),int({}),16);", inst,
-                   ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
+        ctx.AddU32("{}=bitfieldExtract(ftou({}_cbuf{}[{}].{}),int({}),16);", inst, ctx.stage_name,
+                   binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
                    ((offset.U32() / 2) % 2) * 16);
     } else {
         const auto offset_var{ctx.var_alloc.Consume(offset)};
-        ctx.AddU32("{}=bitfieldExtract(floatBitsToUint({}_cbuf{}[{}/16][({}>>2)%4]),int((({}/"
+        ctx.AddU32("{}=bitfieldExtract(ftou({}_cbuf{}[{}/16][({}>>2)%4]),int((({}/"
                    "2)%2)*16),16);",
                    inst, ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
     }
@@ -90,12 +88,12 @@ void EmitGetCbufS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst
                     [[maybe_unused]] const IR::Value& binding,
                     [[maybe_unused]] const IR::Value& offset) {
     if (offset.IsImmediate()) {
-        ctx.AddU32("{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}].{}),int({}),16);", inst,
-                   ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
+        ctx.AddU32("{}=bitfieldExtract(ftoi({}_cbuf{}[{}].{}),int({}),16);", inst, ctx.stage_name,
+                   binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
                    ((offset.U32() / 2) % 2) * 16);
     } else {
         const auto offset_var{ctx.var_alloc.Consume(offset)};
-        ctx.AddU32("{}=bitfieldExtract(floatBitsToInt({}_cbuf{}[{}/16][({}>>2)%4]),int((({}/"
+        ctx.AddU32("{}=bitfieldExtract(ftoi({}_cbuf{}[{}/16][({}>>2)%4]),int((({}/"
                    "2)%2)*16),16);",
                    inst, ctx.stage_name, binding.U32(), offset_var, offset_var, offset_var);
     }
@@ -104,12 +102,12 @@ void EmitGetCbufS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst
 void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                     const IR::Value& offset) {
     if (offset.IsImmediate()) {
-        ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}].{});", inst, ctx.stage_name, binding.U32(),
+        ctx.AddU32("{}=ftou({}_cbuf{}[{}].{});", inst, ctx.stage_name, binding.U32(),
                    offset.U32() / 16, OffsetSwizzle(offset.U32()));
     } else {
         const auto offset_var{ctx.var_alloc.Consume(offset)};
-        ctx.AddU32("{}=floatBitsToUint({}_cbuf{}[{}/16][({}>>2)%4]);", inst, ctx.stage_name,
-                   binding.U32(), offset_var, offset_var);
+        ctx.AddU32("{}=ftou({}_cbuf{}[{}/16][({}>>2)%4]);", inst, ctx.stage_name, binding.U32(),
+                   offset_var, offset_var);
     }
 }
 
@@ -128,15 +126,14 @@ void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
 void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                       const IR::Value& offset) {
     if (offset.IsImmediate()) {
-        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() + 4) / 16,
-            OffsetSwizzle(offset.U32() + 4));
+        ctx.AddU32x2("{}=uvec2(ftou({}_cbuf{}[{}].{}),ftou({}_cbuf{}[{}].{}));", inst,
+                     ctx.stage_name, binding.U32(), offset.U32() / 16, OffsetSwizzle(offset.U32()),
+                     ctx.stage_name, binding.U32(), (offset.U32() + 4) / 16,
+                     OffsetSwizzle(offset.U32() + 4));
     } else {
         const auto offset_var{ctx.var_alloc.Consume(offset)};
-        ctx.AddU32x2("{}=uvec2(floatBitsToUint({}_cbuf{}[{}/16][({}/"
-                     "4)%4]),floatBitsToUint({}_cbuf{}[({}+4)/16][(({}+4)>>2)%4]));",
+        ctx.AddU32x2("{}=uvec2(ftou({}_cbuf{}[{}/16][({}/"
+                     "4)%4]),ftou({}_cbuf{}[({}+4)/16][(({}+4)>>2)%4]));",
                      inst, ctx.stage_name, binding.U32(), offset_var, offset_var, ctx.stage_name,
                      binding.U32(), offset_var, offset_var);
     }
@@ -180,13 +177,13 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
         ctx.AddF32("{}=gl_PointCoord.{};", inst, swizzle);
         break;
     case IR::Attribute::InstanceId:
-        ctx.AddF32("{}=intBitsToFloat(gl_InstanceID);", inst);
+        ctx.AddF32("{}=itof(gl_InstanceID);", inst);
         break;
     case IR::Attribute::VertexId:
-        ctx.AddF32("{}=intBitsToFloat(gl_VertexID);", inst);
+        ctx.AddF32("{}=itof(gl_VertexID);", inst);
         break;
     case IR::Attribute::FrontFace:
-        ctx.AddF32("{}=intBitsToFloat(gl_FrontFacing?-1:0);", inst);
+        ctx.AddF32("{}=itof(gl_FrontFacing?-1:0);", inst);
         break;
     case IR::Attribute::TessellationEvaluationPointU:
     case IR::Attribute::TessellationEvaluationPointV:
@@ -231,7 +228,7 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
             // layer extension");
             break;
         }
-        ctx.Add("gl_ViewportIndex=floatBitsToInt({});", value);
+        ctx.Add("gl_ViewportIndex=ftoi({});", value);
         break;
     case IR::Attribute::ClipDistance0:
     case IR::Attribute::ClipDistance1:
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
index 8c54f0fb34..37ddd57d31 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
@@ -212,7 +212,11 @@ void EmitImageSampleDrefImplicitLod([[maybe_unused]] EmitContext& ctx,
         }
     } else {
         if (ctx.stage == Stage::Fragment) {
-            ctx.AddF32("{}=texture({},{}({},{}){});", inst, texture, cast, coords, dref, bias);
+            if (info.type == TextureType::ColorArrayCube) {
+                ctx.AddF32("{}=texture({},vec4({}),{});", inst, texture, coords, dref);
+            } else {
+                ctx.AddF32("{}=texture({},{}({},{}){});", inst, texture, cast, coords, dref, bias);
+            }
         } else {
             ctx.AddF32("{}=textureLod({},{}({},{}),0.0);", inst, texture, cast, coords, dref);
         }
@@ -238,6 +242,7 @@ void EmitImageSampleDrefExplicitLod([[maybe_unused]] EmitContext& ctx,
         throw NotImplementedException("EmitImageSampleDrefExplicitLod Lod clamp samples");
     }
     const auto texture{Texture(ctx, info, index)};
+    const auto cast{ShadowSamplerVecCast(info.type)};
     if (!offset.IsEmpty()) {
         const auto offset_str{CastToIntVec(ctx.var_alloc.Consume(offset), info)};
         if (info.type == TextureType::ColorArrayCube) {
@@ -251,7 +256,8 @@ void EmitImageSampleDrefExplicitLod([[maybe_unused]] EmitContext& ctx,
         if (info.type == TextureType::ColorArrayCube) {
             ctx.AddF32("{}=textureLod({},{},{},{});", inst, texture, coords, dref, lod_lc);
         } else {
-            ctx.AddF32("{}=textureLod({},vec3({},{}),{});", inst, texture, coords, dref, lod_lc);
+            ctx.AddF32("{}=textureLod({},{}({},{}),{});", inst, texture, cast, coords, dref,
+                       lod_lc);
         }
     }
 }
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index 89ded3614e..90dcfcef72 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -105,9 +105,9 @@ void EmitLoadGlobalU8(EmitContext& ctx);
 void EmitLoadGlobalS8(EmitContext& ctx);
 void EmitLoadGlobalU16(EmitContext& ctx);
 void EmitLoadGlobalS16(EmitContext& ctx);
-void EmitLoadGlobal32(EmitContext& ctx, std::string_view address);
-void EmitLoadGlobal64(EmitContext& ctx, std::string_view address);
-void EmitLoadGlobal128(EmitContext& ctx, std::string_view address);
+void EmitLoadGlobal32(EmitContext& ctx, IR::Inst& inst, std::string_view address);
+void EmitLoadGlobal64(EmitContext& ctx, IR::Inst& inst, std::string_view address);
+void EmitLoadGlobal128(EmitContext& ctx, IR::Inst& inst, std::string_view address);
 void EmitWriteGlobalU8(EmitContext& ctx);
 void EmitWriteGlobalS8(EmitContext& ctx);
 void EmitWriteGlobalU16(EmitContext& ctx);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
index a4411b68bf..bc43638241 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
@@ -9,6 +9,62 @@
 #include "shader_recompiler/frontend/ir/value.h"
 
 namespace Shader::Backend::GLSL {
+void EmitLoadGlobalU8([[maybe_unused]] EmitContext& ctx) {
+    NotImplemented();
+}
+
+void EmitLoadGlobalS8([[maybe_unused]] EmitContext& ctx) {
+    NotImplemented();
+}
+
+void EmitLoadGlobalU16([[maybe_unused]] EmitContext& ctx) {
+    NotImplemented();
+}
+
+void EmitLoadGlobalS16([[maybe_unused]] EmitContext& ctx) {
+    NotImplemented();
+}
+
+void EmitLoadGlobal32(EmitContext& ctx, IR::Inst& inst, std::string_view address) {
+    ctx.AddU32("{}=LoadGlobal32({});", inst, address);
+}
+
+void EmitLoadGlobal64(EmitContext& ctx, IR::Inst& inst, std::string_view address) {
+    ctx.AddU32x2("{}=LoadGlobal64({});", inst, address);
+}
+
+void EmitLoadGlobal128(EmitContext& ctx, IR::Inst& inst, std::string_view address) {
+    ctx.AddU32x4("{}=LoadGlobal128({});", inst, address);
+}
+
+void EmitWriteGlobalU8([[maybe_unused]] EmitContext& ctx) {
+    NotImplemented();
+}
+
+void EmitWriteGlobalS8([[maybe_unused]] EmitContext& ctx) {
+    NotImplemented();
+}
+
+void EmitWriteGlobalU16([[maybe_unused]] EmitContext& ctx) {
+    NotImplemented();
+}
+
+void EmitWriteGlobalS16([[maybe_unused]] EmitContext& ctx) {
+    NotImplemented();
+}
+
+void EmitWriteGlobal32(EmitContext& ctx, std::string_view address, std::string_view value) {
+    ctx.Add("WriteGlobal32({},{});", address, value);
+}
+
+void EmitWriteGlobal64(EmitContext& ctx, std::string_view address, std::string_view value) {
+    ctx.Add("WriteGlobal64({},{});", address, value);
+}
+
+void EmitWriteGlobal128(EmitContext& ctx, std::string_view address, std::string_view value) {
+    ctx.Add("WriteGlobal128({},{});", address, value);
+}
+
 void EmitLoadStorageU8([[maybe_unused]] EmitContext& ctx, IR::Inst& inst,
                        [[maybe_unused]] const IR::Value& binding,
                        [[maybe_unused]] const IR::Value& offset) {
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 cf7b2a51e5..cac803146b 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -232,62 +232,6 @@ void EmitUndefU64(EmitContext& ctx, IR::Inst& inst) {
     NotImplemented();
 }
 
-void EmitLoadGlobalU8(EmitContext& ctx) {
-    NotImplemented();
-}
-
-void EmitLoadGlobalS8(EmitContext& ctx) {
-    NotImplemented();
-}
-
-void EmitLoadGlobalU16(EmitContext& ctx) {
-    NotImplemented();
-}
-
-void EmitLoadGlobalS16(EmitContext& ctx) {
-    NotImplemented();
-}
-
-void EmitLoadGlobal32(EmitContext& ctx, std::string_view address) {
-    NotImplemented();
-}
-
-void EmitLoadGlobal64(EmitContext& ctx, std::string_view address) {
-    NotImplemented();
-}
-
-void EmitLoadGlobal128(EmitContext& ctx, std::string_view address) {
-    NotImplemented();
-}
-
-void EmitWriteGlobalU8(EmitContext& ctx) {
-    NotImplemented();
-}
-
-void EmitWriteGlobalS8(EmitContext& ctx) {
-    NotImplemented();
-}
-
-void EmitWriteGlobalU16(EmitContext& ctx) {
-    NotImplemented();
-}
-
-void EmitWriteGlobalS16(EmitContext& ctx) {
-    NotImplemented();
-}
-
-void EmitWriteGlobal32(EmitContext& ctx, std::string_view address, std::string_view value) {
-    NotImplemented();
-}
-
-void EmitWriteGlobal64(EmitContext& ctx, std::string_view address, std::string_view value) {
-    NotImplemented();
-}
-
-void EmitWriteGlobal128(EmitContext& ctx, std::string_view address, std::string_view value) {
-    NotImplemented();
-}
-
 void EmitGetZeroFromOp(EmitContext& ctx) {
     NotImplemented();
 }
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 1ab64add4b..0ae56651e7 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -58,13 +58,13 @@ std::string FormatFloat(std::string_view value, IR::Type type) {
     // TODO: Confirm FP64 nan/inf
     if (type == IR::Type::F32) {
         if (value == "nan") {
-            return "uintBitsToFloat(0x7fc00000)";
+            return "utof(0x7fc00000)";
         }
         if (value == "inf") {
-            return "uintBitsToFloat(0x7f800000)";
+            return "utof(0x7f800000)";
         }
         if (value == "-inf") {
-            return "uintBitsToFloat(0xff800000)";
+            return "utof(0xff800000)";
         }
     }
     if (value.find_first_of('e') != std::string_view::npos) {
-- 
cgit v1.2.3-70-g09d2


From 258106038e921de6863d3e871a82fb7a0c77f10d Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Mon, 7 Jun 2021 18:04:01 -0400
Subject: glsl: Allow dynamic tracking of variable allocation

---
 src/shader_recompiler/backend/glsl/emit_glsl.cpp | 17 +++++++++---
 src/shader_recompiler/backend/glsl/var_alloc.cpp | 34 ++++++++++++++----------
 src/shader_recompiler/backend/glsl/var_alloc.h   |  5 ++--
 3 files changed, 35 insertions(+), 21 deletions(-)

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
index 7b57c1e912..b189f6c116 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
@@ -172,19 +172,28 @@ std::string GlslVersionSpecifier(const EmitContext& ctx) {
     return "";
 }
 
+bool IsPreciseType(GlslVarType type) {
+    switch (type) {
+    case GlslVarType::PrecF32:
+    case GlslVarType::PrecF64:
+        return true;
+    default:
+        return false;
+    }
+}
+
 void DefineVariables(const EmitContext& ctx, std::string& header) {
     for (u32 i = 0; i < static_cast<u32>(GlslVarType::Void); ++i) {
         const auto type{static_cast<GlslVarType>(i)};
         const auto& tracker{ctx.var_alloc.GetUseTracker(type)};
         const auto type_name{ctx.var_alloc.GetGlslType(type)};
-        const auto precise{
-            (type == GlslVarType::PrecF32 || type == GlslVarType::PrecF64) ? "precise " : ""};
+        const auto precise{IsPreciseType(type) ? "precise " : ""};
         // Temps/return types that are never used are stored at index 0
         if (tracker.uses_temp) {
-            header += fmt::format("{}{} {}={}(0);", precise, type_name,
+            header += fmt::format("{}{} t{}={}(0);", precise, type_name,
                                   ctx.var_alloc.Representation(0, type), type_name);
         }
-        for (u32 index = 1; index <= tracker.num_used; ++index) {
+        for (u32 index = 0; index < tracker.num_used; ++index) {
             header += fmt::format("{}{} {}={}(0);", precise, type_name,
                                   ctx.var_alloc.Representation(index, type), type_name);
         }
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 0ae56651e7..95e8233e21 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -116,8 +116,8 @@ std::string VarAlloc::Define(IR::Inst& inst, GlslVarType type) {
         id.type.Assign(type);
         GetUseTracker(type).uses_temp = true;
         inst.SetDefinition<Id>(id);
+        return "t" + Representation(inst.Definition<Id>());
     }
-    return Representation(inst.Definition<Id>());
 }
 
 std::string VarAlloc::Define(IR::Inst& inst, IR::Type type) {
@@ -156,21 +156,27 @@ std::string VarAlloc::GetGlslType(IR::Type type) const {
 
 Id VarAlloc::Alloc(GlslVarType type) {
     auto& use_tracker{GetUseTracker(type)};
-    if (use_tracker.num_used < NUM_VARS) {
-        for (size_t var = 1; var < NUM_VARS; ++var) {
-            if (use_tracker.var_use[var]) {
-                continue;
-            }
-            use_tracker.num_used = std::max(use_tracker.num_used, var + 1);
-            use_tracker.var_use[var] = true;
-            Id ret{};
-            ret.is_valid.Assign(1);
-            ret.type.Assign(type);
-            ret.index.Assign(static_cast<u32>(var));
-            return ret;
+    const auto num_vars{use_tracker.var_use.size()};
+    for (size_t var = 0; var < num_vars; ++var) {
+        if (use_tracker.var_use[var]) {
+            continue;
         }
+        use_tracker.num_used = std::max(use_tracker.num_used, var + 1);
+        use_tracker.var_use[var] = true;
+        Id ret{};
+        ret.is_valid.Assign(1);
+        ret.type.Assign(type);
+        ret.index.Assign(static_cast<u32>(var));
+        return ret;
     }
-    throw NotImplementedException("Variable spilling");
+    // Allocate a new variable
+    use_tracker.var_use.push_back(true);
+    Id ret{};
+    ret.is_valid.Assign(1);
+    ret.type.Assign(type);
+    ret.index.Assign(static_cast<u32>(use_tracker.num_used));
+    ++use_tracker.num_used;
+    return ret;
 }
 
 void VarAlloc::Free(Id id) {
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.h b/src/shader_recompiler/backend/glsl/var_alloc.h
index ed936f8dc2..ab1d1acbde 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.h
+++ b/src/shader_recompiler/backend/glsl/var_alloc.h
@@ -57,11 +57,10 @@ static_assert(sizeof(Id) == sizeof(u32));
 
 class VarAlloc {
 public:
-    static constexpr size_t NUM_VARS = 1023;
     struct UseTracker {
-        size_t num_used{};
-        std::bitset<NUM_VARS> var_use{};
         bool uses_temp{};
+        size_t num_used{};
+        std::vector<bool> var_use;
     };
 
     /// Used for explicit usages of variables, may revert to temporaries
-- 
cgit v1.2.3-70-g09d2


From 4759db28d0b98c79f9a630b63ba13c4cd0df9109 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Fri, 11 Jun 2021 00:33:33 -0400
Subject: glsl: Address Rodrigo's feedback

---
 .../backend/glsl/emit_context.cpp                  | 31 +++++++++---------
 src/shader_recompiler/backend/glsl/emit_context.h  |  2 +-
 src/shader_recompiler/backend/glsl/emit_glsl.cpp   |  9 ++---
 .../backend/glsl/emit_glsl_bitwise_conversion.cpp  |  2 +-
 .../backend/glsl/emit_glsl_composite.cpp           |  9 +++--
 .../backend/glsl/emit_glsl_context_get_set.cpp     | 31 +++++++++++-------
 .../backend/glsl/emit_glsl_control_flow.cpp        |  3 +-
 .../backend/glsl/emit_glsl_convert.cpp             | 38 +++++++++++-----------
 .../backend/glsl/emit_glsl_floating_point.cpp      | 19 +++++------
 .../backend/glsl/emit_glsl_instructions.h          |  2 +-
 .../backend/glsl/emit_glsl_select.cpp              |  4 +--
 .../backend/glsl/emit_glsl_warp.cpp                | 10 +++---
 src/shader_recompiler/backend/glsl/var_alloc.cpp   |  2 +-
 13 files changed, 87 insertions(+), 75 deletions(-)

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index 4845484677..cbcf0a1eb9 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -13,7 +13,7 @@ u32 CbufIndex(size_t offset) {
     return (offset / 4) % 4;
 }
 
-char CbufSwizzle(size_t offset) {
+char Swizzle(size_t offset) {
     return "xyzw"[CbufIndex(offset)];
 }
 
@@ -341,8 +341,8 @@ void EmitContext::SetupExtensions(std::string&) {
             header += "#extension GL_NV_shader_thread_shuffle : enable\n";
         }
     }
-    if (info.stores_viewport_index && profile.support_viewport_index_layer_non_geometry &&
-        stage != Stage::Geometry) {
+    if ((info.stores_viewport_index || info.stores_layer) &&
+        profile.support_viewport_index_layer_non_geometry && stage != Stage::Geometry) {
         header += "#extension GL_ARB_shader_viewport_layer_array : enable\n";
     }
     if (info.uses_sparse_residency) {
@@ -428,16 +428,16 @@ void EmitContext::DefineHelperFunctions() {
         header += "uint CasIncrement(uint op_a,uint op_b){return op_a>=op_b?0u:(op_a+1u);}";
     }
     if (info.uses_global_decrement || info.uses_shared_decrement) {
-        header += "uint CasDecrement(uint op_a,uint "
-                  "op_b){return op_a==0||op_a>op_b?op_b:(op_a-1u);}";
+        header += "uint CasDecrement(uint op_a,uint op_b){"
+                  "return op_a==0||op_a>op_b?op_b:(op_a-1u);}";
     }
     if (info.uses_atomic_f32_add) {
-        header += "uint CasFloatAdd(uint op_a,float op_b){return "
-                  "ftou(utof(op_a)+op_b);}";
+        header += "uint CasFloatAdd(uint op_a,float op_b){"
+                  "return ftou(utof(op_a)+op_b);}";
     }
     if (info.uses_atomic_f32x2_add) {
-        header += "uint CasFloatAdd32x2(uint op_a,vec2 op_b){return "
-                  "packHalf2x16(unpackHalf2x16(op_a)+op_b);}";
+        header += "uint CasFloatAdd32x2(uint op_a,vec2 op_b){"
+                  "return packHalf2x16(unpackHalf2x16(op_a)+op_b);}";
     }
     if (info.uses_atomic_f32x2_min) {
         header += "uint CasFloatMin32x2(uint op_a,vec2 op_b){return "
@@ -476,9 +476,10 @@ void EmitContext::DefineHelperFunctions() {
                         "masked_index=uint(base_index)&3u;switch(base_index>>2){{",
                         vertex_arg)};
         if (info.loads_position) {
-            func += fmt::format("case {}:", static_cast<u32>(IR::Attribute::PositionX) >> 2);
             const auto position_idx{is_array ? "gl_in[vertex]." : ""};
-            func += fmt::format("return {}{}[masked_index];", position_idx, position_name);
+            func += fmt::format("case {}:return {}{}[masked_index];",
+                                static_cast<u32>(IR::Attribute::PositionX) >> 2, position_idx,
+                                position_name);
         }
         const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2;
         for (u32 i = 0; i < info.input_generics.size(); ++i) {
@@ -486,8 +487,8 @@ void EmitContext::DefineHelperFunctions() {
                 continue;
             }
             const auto vertex_idx{is_array ? "[vertex]" : ""};
-            func += fmt::format("case {}:", base_attribute_value + i);
-            func += fmt::format("return in_attr{}{}[masked_index];", i, vertex_idx);
+            func += fmt::format("case {}:return in_attr{}{}[masked_index];",
+                                base_attribute_value + i, i, vertex_idx);
         }
         func += "default: return 0.0;}}";
         header += func;
@@ -508,8 +509,8 @@ std::string EmitContext::DefineGlobalMemoryFunctions() {
         for (size_t i = 0; i < addr_xy.size(); ++i) {
             const auto addr_loc{ssbo.cbuf_offset + 4 * i};
             const auto size_loc{size_cbuf_offset + 4 * i};
-            addr_xy[i] = fmt::format("ftou({}[{}].{})", cbuf, addr_loc / 16, CbufSwizzle(addr_loc));
-            size_xy[i] = fmt::format("ftou({}[{}].{})", cbuf, size_loc / 16, CbufSwizzle(size_loc));
+            addr_xy[i] = fmt::format("ftou({}[{}].{})", cbuf, addr_loc / 16, Swizzle(addr_loc));
+            size_xy[i] = fmt::format("ftou({}[{}].{})", cbuf, size_loc / 16, Swizzle(size_loc));
         }
         const auto addr_pack{fmt::format("packUint2x32(uvec2({},{}))", addr_xy[0], addr_xy[1])};
         const auto addr_statment{fmt::format("uint64_t {}={};", ssbo_addr, addr_pack)};
diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 2b0d22ce54..0d18abe90d 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -46,7 +46,7 @@ public:
         const auto var_def{var_alloc.AddDefine(inst, type)};
         if (var_def.empty()) {
             // skip assigment.
-            code += fmt::format(&format_str[3], std::forward<Args>(args)...);
+            code += fmt::format(format_str + 3, std::forward<Args>(args)...);
         } else {
             code += fmt::format(format_str, var_def, std::forward<Args>(args)...);
         }
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
index b189f6c116..3e6add7cda 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
@@ -5,6 +5,7 @@
 #include <ranges>
 #include <string>
 
+#include "common/alignment.h"
 #include "shader_recompiler/backend/glsl/emit_context.h"
 #include "shader_recompiler/backend/glsl/emit_glsl.h"
 #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
@@ -159,8 +160,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) {
                     ctx.var_alloc.Consume(node.data.repeat.cond));
             break;
         default:
-            throw NotImplementedException("AbstractSyntaxNode::Type {}", node.type);
-            break;
+            throw NotImplementedException("AbstractSyntaxNode Type {}", node.type);
         }
     }
 }
@@ -209,10 +209,11 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo& runtime_info, IR
     const std::string version{fmt::format("#version 450{}\n", GlslVersionSpecifier(ctx))};
     ctx.header.insert(0, version);
     if (program.local_memory_size > 0) {
-        ctx.header += fmt::format("uint lmem[{}];", program.local_memory_size / 4);
+        ctx.header += fmt::format("uint lmem[{}];", Common::AlignUp(program.local_memory_size, 4));
     }
     if (program.shared_memory_size > 0) {
-        ctx.header += fmt::format("shared uint smem[{}];", program.shared_memory_size / 4);
+        ctx.header +=
+            fmt::format("shared uint smem[{}];", Common::AlignUp(program.shared_memory_size, 4));
     }
     ctx.header += "\nvoid main(){\n";
     if (program.stage == Stage::VertexA || program.stage == Stage::VertexB) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
index eff672cc46..3c1714e89f 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
@@ -19,7 +19,7 @@ void Alias(IR::Inst& inst, const IR::Value& value) {
     value_inst.DestructiveRemoveUsage();
     inst.SetDefinition(value_inst.Definition<Id>());
 }
-} // namespace
+} // Anonymous namespace
 
 void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) {
     Alias(inst, value);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
index 954fc67b1b..7421ce97d0 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
@@ -13,8 +13,13 @@ namespace {
 constexpr std::string_view SWIZZLE{"xyzw"};
 void CompositeInsert(EmitContext& ctx, std::string_view result, std::string_view composite,
                      std::string_view object, u32 index) {
-    ctx.Add("{}={};", result, composite);
-    ctx.Add("{}.{}={};", result, SWIZZLE[index], object);
+    if (result == composite) {
+        // The result is aliased with the composite
+        ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
+    } else {
+        ctx.Add("{}={};", result, composite);
+        ctx.Add("{}.{}={};", result, SWIZZLE[index], object);
+    }
 }
 } // Anonymous namespace
 
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 0546c1c816..711b568b1c 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
@@ -31,12 +31,7 @@ std::string InputVertexIndex(EmitContext& ctx, std::string_view vertex) {
 }
 
 std::string OutputVertexIndex(EmitContext& ctx) {
-    switch (ctx.stage) {
-    case Stage::TessellationControl:
-        return "[gl_InvocationID]";
-    default:
-        return "";
-    }
+    return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
 }
 } // Anonymous namespace
 
@@ -219,7 +214,11 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
     case IR::Attribute::ColorFrontDiffuseG:
     case IR::Attribute::ColorFrontDiffuseB:
     case IR::Attribute::ColorFrontDiffuseA:
-        ctx.AddF32("{}=gl_FrontMaterial.diffuse.{};", inst, swizzle);
+        if (ctx.stage == Stage::Fragment) {
+            ctx.AddF32("{}=gl_Color.{};", inst, swizzle);
+        } else {
+            ctx.AddF32("{}=gl_FrontColor.{};", inst, swizzle);
+        }
         break;
     case IR::Attribute::PointSpriteS:
     case IR::Attribute::PointSpriteT:
@@ -300,28 +299,36 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
     case IR::Attribute::ColorFrontDiffuseG:
     case IR::Attribute::ColorFrontDiffuseB:
     case IR::Attribute::ColorFrontDiffuseA:
-        ctx.Add("gl_FrontMaterial.diffuse.{}={};", swizzle, value);
+        if (ctx.stage == Stage::Fragment) {
+            ctx.Add("gl_Color.{}={};", swizzle, value);
+        } else {
+            ctx.Add("gl_FrontColor.{}={};", swizzle, value);
+        }
         break;
     case IR::Attribute::ColorFrontSpecularR:
     case IR::Attribute::ColorFrontSpecularG:
     case IR::Attribute::ColorFrontSpecularB:
     case IR::Attribute::ColorFrontSpecularA:
-        ctx.Add("gl_FrontMaterial.specular.{}={};", swizzle, value);
+        if (ctx.stage == Stage::Fragment) {
+            ctx.Add("gl_SecondaryColor.{}={};", swizzle, value);
+        } else {
+            ctx.Add("gl_FrontSecondaryColor.{}={};", swizzle, value);
+        }
         break;
     case IR::Attribute::ColorBackDiffuseR:
     case IR::Attribute::ColorBackDiffuseG:
     case IR::Attribute::ColorBackDiffuseB:
     case IR::Attribute::ColorBackDiffuseA:
-        ctx.Add("gl_BackMaterial.diffuse.{}={};", swizzle, value);
+        ctx.Add("gl_BackColor.{}={};", swizzle, value);
         break;
     case IR::Attribute::ColorBackSpecularR:
     case IR::Attribute::ColorBackSpecularG:
     case IR::Attribute::ColorBackSpecularB:
     case IR::Attribute::ColorBackSpecularA:
-        ctx.Add("gl_BackMaterial.specular.{}={};", swizzle, value);
+        ctx.Add("gl_BackSecondaryColor.{}={};", swizzle, value);
         break;
     case IR::Attribute::FogCoordinate:
-        ctx.Add("gl_FragCoord.x={};", value);
+        ctx.Add("gl_FogFragCoord.x={};", value);
         break;
     case IR::Attribute::ClipDistance0:
     case IR::Attribute::ClipDistance1:
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
index 59522fdbd1..53f8896be7 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
@@ -14,8 +14,7 @@ void EmitJoin(EmitContext&) {
     throw NotImplementedException("Join shouldn't be emitted");
 }
 
-void EmitDemoteToHelperInvocation(EmitContext& ctx,
-                                  [[maybe_unused]] std::string_view continue_label) {
+void EmitDemoteToHelperInvocation(EmitContext& ctx) {
     ctx.Add("discard;");
 }
 
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
index 8d823e4667..777e290b44 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
@@ -15,7 +15,7 @@ void EmitConvertS16F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertS16F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS32("{}=int(float({}))&0xffff;", inst, value);
+    ctx.AddS32("{}=(int({})&0xffff)|(bitfieldExtract(int({}),31,1)<<15);", inst, value, value);
 }
 
 void EmitConvertS16F64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -29,11 +29,11 @@ void EmitConvertS32F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertS32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS32("{}=int(float({}));", inst, value);
+    ctx.AddS32("{}=int({});", inst, value);
 }
 
 void EmitConvertS32F64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS32("{}=int(double({}));", inst, value);
+    ctx.AddS32("{}=int({});", inst, value);
 }
 
 void EmitConvertS64F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -42,11 +42,11 @@ void EmitConvertS64F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertS64F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS64("{}=int64_t(double(float({})));", inst, value);
+    ctx.AddS64("{}=int64_t(double({}));", inst, value);
 }
 
 void EmitConvertS64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS64("{}=int64_t(double({}));", inst, value);
+    ctx.AddS64("{}=int64_t({});", inst, value);
 }
 
 void EmitConvertU16F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -70,11 +70,11 @@ void EmitConvertU32F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertU32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddU32("{}=uint(float({}));", inst, value);
+    ctx.AddU32("{}=uint({});", inst, value);
 }
 
 void EmitConvertU32F64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddU32("{}=uint(double({}));", inst, value);
+    ctx.AddU32("{}=uint({});", inst, value);
 }
 
 void EmitConvertU64F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -83,19 +83,19 @@ void EmitConvertU64F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertU64F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddU64("{}=uint64_t(float({}));", inst, value);
+    ctx.AddU64("{}=uint64_t({});", inst, value);
 }
 
 void EmitConvertU64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddU64("{}=uint64_t(double({}));", inst, value);
+    ctx.AddU64("{}=uint64_t({});", inst, value);
 }
 
 void EmitConvertU64U32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddU64("{}=uint64_t(uint({}));", inst, value);
+    ctx.AddU64("{}=uint64_t({});", inst, value);
 }
 
 void EmitConvertU32U64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddU32("{}=uint(uint64_t({}));", inst, value);
+    ctx.AddU32("{}=uint({});", inst, value);
 }
 
 void EmitConvertF16F32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -109,11 +109,11 @@ void EmitConvertF32F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertF32F64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF32("{}=float(double({}));", inst, value);
+    ctx.AddF32("{}=float({});", inst, value);
 }
 
 void EmitConvertF64F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF64("{}=double(float({}));", inst, value);
+    ctx.AddF64("{}=double({});", inst, value);
 }
 
 void EmitConvertF16S8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -171,7 +171,7 @@ void EmitConvertF32S32(EmitContext& ctx, IR::Inst& inst, std::string_view value)
 }
 
 void EmitConvertF32S64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF32("{}=float(double(int64_t({})));", inst, value);
+    ctx.AddF32("{}=float(int64_t({}));", inst, value);
 }
 
 void EmitConvertF32U8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -180,15 +180,15 @@ void EmitConvertF32U8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::In
 }
 
 void EmitConvertF32U16(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF32("{}=float(uint({}&0xffff));", inst, value);
+    ctx.AddF32("{}=float({}&0xffff);", inst, value);
 }
 
 void EmitConvertF32U32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF32("{}=float(uint({}));", inst, value);
+    ctx.AddF32("{}=float({});", inst, value);
 }
 
 void EmitConvertF32U64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF32("{}=float(double(uint64_t({})));", inst, value);
+    ctx.AddF32("{}=float({});", inst, value);
 }
 
 void EmitConvertF64S8([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -220,11 +220,11 @@ void EmitConvertF64U16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertF64U32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF64("{}=double(uint({}));", inst, value);
+    ctx.AddF64("{}=double({});", inst, value);
 }
 
 void EmitConvertF64U64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddF64("{}=double(uint64_t({}));", inst, value);
+    ctx.AddF64("{}=double({});", inst, value);
 }
 
 } // namespace Shader::Backend::GLSL
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
index fbf66015f9..b11be5bd7a 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
@@ -15,14 +15,13 @@ void Compare(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string
              std::string_view op, bool ordered) {
     ctx.AddU1("{}={}{}{}", inst, lhs, op, rhs, lhs, rhs);
     if (ordered) {
-        ctx.code += fmt::format("&&!isnan({})&&!isnan({})", lhs, rhs);
+        ctx.Add("&&!isnan({})&&!isnan({});", lhs, rhs);
     } else {
-        ctx.code += fmt::format("||isnan({})||isnan({})", lhs, rhs);
+        ctx.Add("||isnan({})||isnan({});", lhs, rhs);
     }
-    ctx.code += ";";
 }
 
-bool Precise(IR::Inst& inst) {
+bool IsPrecise(const IR::Inst& inst) {
     return {inst.Flags<IR::FpControl>().no_contraction};
 }
 } // Anonymous namespace
@@ -46,7 +45,7 @@ void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 }
 
 void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    if (Precise(inst)) {
+    if (IsPrecise(inst)) {
         ctx.AddPrecF32("{}={}+{};", inst, a, b);
     } else {
         ctx.AddF32("{}={}+{};", inst, a, b);
@@ -54,7 +53,7 @@ void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::stri
 }
 
 void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    if (Precise(inst)) {
+    if (IsPrecise(inst)) {
         ctx.AddPrecF64("{}={}+{};", inst, a, b);
     } else {
         ctx.AddF64("{}={}+{};", inst, a, b);
@@ -69,7 +68,7 @@ void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 
 void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
                  std::string_view c) {
-    if (Precise(inst)) {
+    if (IsPrecise(inst)) {
         ctx.AddPrecF32("{}=fma({},{},{});", inst, a, b, c);
     } else {
         ctx.AddF32("{}=fma({},{},{});", inst, a, b, c);
@@ -78,7 +77,7 @@ void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::stri
 
 void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
                  std::string_view c) {
-    if (Precise(inst)) {
+    if (IsPrecise(inst)) {
         ctx.AddPrecF64("{}=fma({},{},{});", inst, a, b, c);
     } else {
         ctx.AddF64("{}=fma({},{},{});", inst, a, b, c);
@@ -107,7 +106,7 @@ void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 }
 
 void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    if (Precise(inst)) {
+    if (IsPrecise(inst)) {
         ctx.AddPrecF32("{}={}*{};", inst, a, b);
     } else {
         ctx.AddF32("{}={}*{};", inst, a, b);
@@ -115,7 +114,7 @@ void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::stri
 }
 
 void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    if (Precise(inst)) {
+    if (IsPrecise(inst)) {
         ctx.AddPrecF64("{}={}*{};", inst, a, b);
     } else {
         ctx.AddF64("{}={}*{};", inst, a, b);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index 1257575c08..0c717664f4 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -31,7 +31,7 @@ void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
 void EmitReference(EmitContext& ctx, const IR::Value& value);
 void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value);
 void EmitJoin(EmitContext& ctx);
-void EmitDemoteToHelperInvocation(EmitContext& ctx, std::string_view continue_label);
+void EmitDemoteToHelperInvocation(EmitContext& ctx);
 void EmitBarrier(EmitContext& ctx);
 void EmitWorkgroupMemoryBarrier(EmitContext& ctx);
 void EmitDeviceMemoryBarrier(EmitContext& ctx);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
index 49fba9073a..7aa6096e68 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
@@ -28,12 +28,12 @@ void EmitSelectU16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::stri
 
 void EmitSelectU32(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
                    std::string_view true_value, std::string_view false_value) {
-    ctx.AddU32("{}={}?{}:{};", inst, cond, true_value, false_value);
+    ctx.AddU32("{}={}?uint({}):uint({});", inst, cond, true_value, false_value);
 }
 
 void EmitSelectU64(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
                    std::string_view true_value, std::string_view false_value) {
-    ctx.AddU64("{}={}?{}:{};", inst, cond, true_value, false_value);
+    ctx.AddU64("{}={}?uint64_t({}):uint64_t({});", inst, cond, true_value, false_value);
 }
 
 void EmitSelectF16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view cond,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
index 6ced0776cc..7047928fdf 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
@@ -89,23 +89,23 @@ void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, std::string_view pred)
 }
 
 void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst) {
-    ctx.AddU32("{}=uvec2(gl_SubGroupEqMaskARB).x;", inst);
+    ctx.AddU32("{}=uint(gl_SubGroupEqMaskARB.x);", inst);
 }
 
 void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst) {
-    ctx.AddU32("{}=uvec2(gl_SubGroupLtMaskARB).x;", inst);
+    ctx.AddU32("{}=uint(gl_SubGroupLtMaskARB.x);", inst);
 }
 
 void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst) {
-    ctx.AddU32("{}=uvec2(gl_SubGroupLeMaskARB).x;", inst);
+    ctx.AddU32("{}=uint(gl_SubGroupLeMaskARB.x);", inst);
 }
 
 void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst) {
-    ctx.AddU32("{}=uvec2(gl_SubGroupGtMaskARB).x;", inst);
+    ctx.AddU32("{}=uint(gl_SubGroupGtMaskARB.x);", inst);
 }
 
 void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) {
-    ctx.AddU32("{}=uvec2(gl_SubGroupGeMaskARB).x;", inst);
+    ctx.AddU32("{}=uint(gl_SubGroupGeMaskARB.x);", inst);
 }
 
 void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value,
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 95e8233e21..6a19aa549b 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -116,7 +116,7 @@ std::string VarAlloc::Define(IR::Inst& inst, GlslVarType type) {
         id.type.Assign(type);
         GetUseTracker(type).uses_temp = true;
         inst.SetDefinition<Id>(id);
-        return "t" + Representation(inst.Definition<Id>());
+        return 't' + Representation(inst.Definition<Id>());
     }
 }
 
-- 
cgit v1.2.3-70-g09d2


From 7d89a82a4891f78e2c068a24ad3bb56d74c92055 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Fri, 11 Jun 2021 00:41:28 -0400
Subject: glsl: Remove Signed Integer variables

---
 src/shader_recompiler/backend/glsl/emit_context.h        | 10 ----------
 src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp  |  4 ++--
 src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp | 10 +++++-----
 src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp |  2 +-
 src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp  |  4 ++--
 .../backend/glsl/emit_glsl_shared_memory.cpp             |  4 ++--
 src/shader_recompiler/backend/glsl/var_alloc.cpp         | 16 ----------------
 src/shader_recompiler/backend/glsl/var_alloc.h           |  6 +-----
 8 files changed, 13 insertions(+), 43 deletions(-)

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 0d18abe90d..9d8be0c9af 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -69,21 +69,11 @@ public:
         Add<GlslVarType::U32>(format_str, inst, args...);
     }
 
-    template <typename... Args>
-    void AddS32(const char* format_str, IR::Inst& inst, Args&&... args) {
-        Add<GlslVarType::S32>(format_str, inst, args...);
-    }
-
     template <typename... Args>
     void AddF32(const char* format_str, IR::Inst& inst, Args&&... args) {
         Add<GlslVarType::F32>(format_str, inst, args...);
     }
 
-    template <typename... Args>
-    void AddS64(const char* format_str, IR::Inst& inst, Args&&... args) {
-        Add<GlslVarType::S64>(format_str, inst, args...);
-    }
-
     template <typename... Args>
     void AddU64(const char* format_str, IR::Inst& inst, Args&&... args) {
         Add<GlslVarType::U64>(format_str, inst, args...);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
index 7353d5d4e3..850eee1e1e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
@@ -183,7 +183,7 @@ void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value&
 void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                              const IR::Value& offset, std::string_view value) {
     // LOG_WARNING(..., "Op falling to non-atomic");
-    ctx.AddS64("{}=packInt2x32(ivec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
+    ctx.AddU64("{}=packInt2x32(ivec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
                ctx.stage_name, binding.U32(), ctx.var_alloc.Consume(offset), ctx.stage_name,
                binding.U32(), ctx.var_alloc.Consume(offset));
     ctx.Add("for(int i=0;i<2;++i){{ "
@@ -208,7 +208,7 @@ void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value&
 void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                              const IR::Value& offset, std::string_view value) {
     // LOG_WARNING(..., "Op falling to non-atomic");
-    ctx.AddS64("{}=packInt2x32(ivec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
+    ctx.AddU64("{}=packInt2x32(ivec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
                ctx.stage_name, binding.U32(), ctx.var_alloc.Consume(offset), ctx.stage_name,
                binding.U32(), ctx.var_alloc.Consume(offset));
     ctx.Add("for(int i=0;i<2;++i){{ "
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
index 777e290b44..c9f173e2f1 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
@@ -15,7 +15,7 @@ void EmitConvertS16F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertS16F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS32("{}=(int({})&0xffff)|(bitfieldExtract(int({}),31,1)<<15);", inst, value, value);
+    ctx.AddU32("{}=(int({})&0xffff)|(bitfieldExtract(int({}),31,1)<<15);", inst, value, value);
 }
 
 void EmitConvertS16F64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -29,11 +29,11 @@ void EmitConvertS32F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertS32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS32("{}=int({});", inst, value);
+    ctx.AddU32("{}=int({});", inst, value);
 }
 
 void EmitConvertS32F64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS32("{}=int({});", inst, value);
+    ctx.AddU32("{}=int({});", inst, value);
 }
 
 void EmitConvertS64F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -42,11 +42,11 @@ void EmitConvertS64F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::I
 }
 
 void EmitConvertS64F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS64("{}=int64_t(double({}));", inst, value);
+    ctx.AddU64("{}=int64_t(double({}));", inst, value);
 }
 
 void EmitConvertS64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
-    ctx.AddS64("{}=int64_t({});", inst, value);
+    ctx.AddU64("{}=int64_t({});", inst, value);
 }
 
 void EmitConvertU16F16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
index 6e04c6cb28..7a2f79d106 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
@@ -103,7 +103,7 @@ void EmitShiftRightLogical64(EmitContext& ctx, IR::Inst& inst, std::string_view
 
 void EmitShiftRightArithmetic32(EmitContext& ctx, IR::Inst& inst, std::string_view base,
                                 std::string_view shift) {
-    ctx.AddS32("{}=int({})>>{};", inst, base, shift);
+    ctx.AddU32("{}=int({})>>{};", inst, base, shift);
 }
 
 void EmitShiftRightArithmetic64(EmitContext& ctx, IR::Inst& inst, std::string_view base,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
index af3dadf71d..daef5fb848 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
@@ -87,7 +87,7 @@ void EmitLoadStorageU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& bindin
 void EmitLoadStorageS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                        const IR::Value& offset) {
     const auto offset_var{ctx.var_alloc.Consume(offset)};
-    ctx.AddS32("{}=bitfieldExtract(int({}_ssbo{}[{}>>2]),int({}%4)*8,8);", inst, ctx.stage_name,
+    ctx.AddU32("{}=bitfieldExtract(int({}_ssbo{}[{}>>2]),int({}%4)*8,8);", inst, ctx.stage_name,
                binding.U32(), offset_var, offset_var);
 }
 
@@ -101,7 +101,7 @@ void EmitLoadStorageU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& bindi
 void EmitLoadStorageS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                         const IR::Value& offset) {
     const auto offset_var{ctx.var_alloc.Consume(offset)};
-    ctx.AddS32("{}=bitfieldExtract(int({}_ssbo{}[{}>>2]),int(({}>>1)%2)*16,16);", inst,
+    ctx.AddU32("{}=bitfieldExtract(int({}_ssbo{}[{}>>2]),int(({}>>1)%2)*16,16);", inst,
                ctx.stage_name, binding.U32(), offset_var, offset_var);
 }
 
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
index 5b61759033..7abc6575fc 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
@@ -14,7 +14,7 @@ void EmitLoadSharedU8(EmitContext& ctx, IR::Inst& inst, std::string_view offset)
 }
 
 void EmitLoadSharedS8(EmitContext& ctx, IR::Inst& inst, std::string_view offset) {
-    ctx.AddS32("{}=bitfieldExtract(int(smem[{}>>2]),int({}%4)*8,8);", inst, offset, offset);
+    ctx.AddU32("{}=bitfieldExtract(int(smem[{}>>2]),int({}%4)*8,8);", inst, offset, offset);
 }
 
 void EmitLoadSharedU16(EmitContext& ctx, IR::Inst& inst, std::string_view offset) {
@@ -22,7 +22,7 @@ void EmitLoadSharedU16(EmitContext& ctx, IR::Inst& inst, std::string_view offset
 }
 
 void EmitLoadSharedS16(EmitContext& ctx, IR::Inst& inst, std::string_view offset) {
-    ctx.AddS32("{}=bitfieldExtract(int(smem[{}>>2]),int(({}>>1)%2)*16,16);", inst, offset, offset);
+    ctx.AddU32("{}=bitfieldExtract(int(smem[{}>>2]),int(({}>>1)%2)*16,16);", inst, offset, offset);
 }
 
 void EmitLoadSharedU32(EmitContext& ctx, IR::Inst& inst, std::string_view offset) {
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 6a19aa549b..cbf56491c1 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -21,12 +21,8 @@ std::string TypePrefix(GlslVarType type) {
         return "f16x2_";
     case GlslVarType::U32:
         return "u_";
-    case GlslVarType::S32:
-        return "s_";
     case GlslVarType::F32:
         return "f_";
-    case GlslVarType::S64:
-        return "s64_";
     case GlslVarType::U64:
         return "u64_";
     case GlslVarType::F64:
@@ -213,13 +209,9 @@ std::string VarAlloc::GetGlslType(GlslVarType type) const {
         return "f16vec2";
     case GlslVarType::U32:
         return "uint";
-    case GlslVarType::S32:
-        return "int";
     case GlslVarType::F32:
     case GlslVarType::PrecF32:
         return "float";
-    case GlslVarType::S64:
-        return "int64_t";
     case GlslVarType::U64:
         return "uint64_t";
     case GlslVarType::F64:
@@ -252,12 +244,8 @@ VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
         return var_f16x2;
     case GlslVarType::U32:
         return var_u32;
-    case GlslVarType::S32:
-        return var_s32;
     case GlslVarType::F32:
         return var_f32;
-    case GlslVarType::S64:
-        return var_s64;
     case GlslVarType::U64:
         return var_u64;
     case GlslVarType::F64:
@@ -291,12 +279,8 @@ const VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) const {
         return var_f16x2;
     case GlslVarType::U32:
         return var_u32;
-    case GlslVarType::S32:
-        return var_s32;
     case GlslVarType::F32:
         return var_f32;
-    case GlslVarType::S64:
-        return var_s64;
     case GlslVarType::U64:
         return var_u64;
     case GlslVarType::F64:
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.h b/src/shader_recompiler/backend/glsl/var_alloc.h
index ab1d1acbde..8b49f32a69 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.h
+++ b/src/shader_recompiler/backend/glsl/var_alloc.h
@@ -21,10 +21,8 @@ namespace Shader::Backend::GLSL {
 enum class GlslVarType : u32 {
     U1,
     F16x2,
-    S32,
     U32,
     F32,
-    S64,
     U64,
     F64,
     U32x2,
@@ -42,7 +40,7 @@ struct Id {
     union {
         u32 raw;
         BitField<0, 1, u32> is_valid;
-        BitField<1, 5, GlslVarType> type;
+        BitField<1, 4, GlslVarType> type;
         BitField<6, 26, u32> index;
     };
 
@@ -90,7 +88,6 @@ private:
 
     UseTracker var_bool{};
     UseTracker var_f16x2{};
-    UseTracker var_s32{};
     UseTracker var_u32{};
     UseTracker var_u32x2{};
     UseTracker var_u32x3{};
@@ -100,7 +97,6 @@ private:
     UseTracker var_f32x3{};
     UseTracker var_f32x4{};
     UseTracker var_u64{};
-    UseTracker var_s64{};
     UseTracker var_f64{};
     UseTracker var_precf32{};
     UseTracker var_precf64{};
-- 
cgit v1.2.3-70-g09d2


From 6eea88d6149f7122777b325c7fc8549e2a974e64 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Mon, 14 Jun 2021 23:02:07 -0400
Subject: glsl: Cleanup/Address feedback

---
 src/shader_recompiler/backend/glsl/emit_glsl.cpp       |  8 ++++----
 .../backend/glsl/emit_glsl_atomic.cpp                  | 12 ++++++------
 .../backend/glsl/emit_glsl_composite.cpp               |  3 +--
 .../backend/glsl/emit_glsl_context_get_set.cpp         | 18 +++++-------------
 .../backend/glsl/emit_glsl_integer.cpp                 |  1 +
 .../backend/glsl/emit_glsl_shared_memory.cpp           |  1 +
 src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp  |  2 +-
 src/shader_recompiler/backend/glsl/var_alloc.cpp       |  3 +--
 src/shader_recompiler/profile.h                        |  2 ++
 src/video_core/renderer_opengl/gl_shader_cache.cpp     |  2 ++
 10 files changed, 24 insertions(+), 28 deletions(-)

(limited to 'src/shader_recompiler/backend/glsl/var_alloc.cpp')

diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
index 6d64913bbc..9f8cf659ff 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
@@ -156,8 +156,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) {
             ctx.Add("for(;;){{");
             break;
         case IR::AbstractSyntaxNode::Type::Repeat:
-            ctx.Add("if({}){{continue;}}else{{break;}}}}",
-                    ctx.var_alloc.Consume(node.data.repeat.cond));
+            ctx.Add("if(!{}){{break;}}}}", ctx.var_alloc.Consume(node.data.repeat.cond));
             break;
         default:
             throw NotImplementedException("AbstractSyntaxNode Type {}", node.type);
@@ -166,7 +165,7 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) {
 }
 
 std::string GlslVersionSpecifier(const EmitContext& ctx) {
-    if (ctx.uses_y_direction || ctx.info.stores_legacy_varyings) {
+    if (ctx.uses_y_direction || ctx.info.stores_legacy_varyings || ctx.info.loads_legacy_varyings) {
         return " compatibility";
     }
     return "";
@@ -187,7 +186,8 @@ void DefineVariables(const EmitContext& ctx, std::string& header) {
         const auto type{static_cast<GlslVarType>(i)};
         const auto& tracker{ctx.var_alloc.GetUseTracker(type)};
         const auto type_name{ctx.var_alloc.GetGlslType(type)};
-        const auto precise{IsPreciseType(type) ? "precise " : ""};
+        const bool has_precise_bug{ctx.stage == Stage::Fragment && ctx.profile.has_gl_precise_bug};
+        const auto precise{!has_precise_bug && IsPreciseType(type) ? "precise " : ""};
         // Temps/return types that are never used are stored at index 0
         if (tracker.uses_temp) {
             header += fmt::format("{}{} t{}={}(0);", precise, type_name,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
index 9152ace983..772acc5a4a 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
@@ -98,7 +98,7 @@ void EmitSharedAtomicExchange32(EmitContext& ctx, IR::Inst& inst, std::string_vi
 
 void EmitSharedAtomicExchange64(EmitContext& ctx, IR::Inst& inst, std::string_view pointer_offset,
                                 std::string_view value) {
-    LOG_WARNING(Shader_GLSL, "Int64 Atomics not supported, fallback to non-atomic");
+    LOG_WARNING(Shader_GLSL, "Int64 atomics not supported, fallback to non-atomic");
     ctx.AddU64("{}=packUint2x32(uvec2(smem[{}>>2],smem[({}+4)>>2]));", inst, pointer_offset,
                pointer_offset);
     ctx.Add("smem[{}>>2]=unpackUint2x32({}).x;smem[({}+4)>>2]=unpackUint2x32({}).y;",
@@ -171,7 +171,7 @@ void EmitStorageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Val
 
 void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                              const IR::Value& offset, std::string_view value) {
-    LOG_WARNING(Shader_GLSL, "Int64 Atomics not supported, fallback to non-atomic");
+    LOG_WARNING(Shader_GLSL, "Int64 atomics not supported, fallback to non-atomic");
     ctx.AddU64("{}=packUint2x32(uvec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
                ctx.stage_name, binding.U32(), ctx.var_alloc.Consume(offset), ctx.stage_name,
                binding.U32(), ctx.var_alloc.Consume(offset));
@@ -182,7 +182,7 @@ void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value&
 
 void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                              const IR::Value& offset, std::string_view value) {
-    LOG_WARNING(Shader_GLSL, "Int64 Atomics not supported, fallback to non-atomic");
+    LOG_WARNING(Shader_GLSL, "Int64 atomics not supported, fallback to non-atomic");
     ctx.AddU64("{}=packInt2x32(ivec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
                ctx.stage_name, binding.U32(), ctx.var_alloc.Consume(offset), ctx.stage_name,
                binding.U32(), ctx.var_alloc.Consume(offset));
@@ -195,7 +195,7 @@ void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value&
 
 void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                              const IR::Value& offset, std::string_view value) {
-    LOG_WARNING(Shader_GLSL, "Int64 Atomics not supported, fallback to non-atomic");
+    LOG_WARNING(Shader_GLSL, "Int64 atomics not supported, fallback to non-atomic");
     ctx.AddU64("{}=packUint2x32(uvec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
                ctx.stage_name, binding.U32(), ctx.var_alloc.Consume(offset), ctx.stage_name,
                binding.U32(), ctx.var_alloc.Consume(offset));
@@ -207,7 +207,7 @@ void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value&
 
 void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                              const IR::Value& offset, std::string_view value) {
-    LOG_WARNING(Shader_GLSL, "Int64 Atomics not supported, fallback to non-atomic");
+    LOG_WARNING(Shader_GLSL, "Int64 atomics not supported, fallback to non-atomic");
     ctx.AddU64("{}=packInt2x32(ivec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
                ctx.stage_name, binding.U32(), ctx.var_alloc.Consume(offset), ctx.stage_name,
                binding.U32(), ctx.var_alloc.Consume(offset));
@@ -220,7 +220,7 @@ void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value&
 
 void EmitStorageAtomicUMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                              const IR::Value& offset, std::string_view value) {
-    LOG_WARNING(Shader_GLSL, "Int64 Atomics not supported, fallback to non-atomic");
+    LOG_WARNING(Shader_GLSL, "Int64 atomics not supported, fallback to non-atomic");
     ctx.AddU64("{}=packUint2x32(uvec2({}_ssbo{}[{}>>2],{}_ssbo{}[({}>>2)+1]));", inst,
                ctx.stage_name, binding.U32(), ctx.var_alloc.Consume(offset), ctx.stage_name,
                binding.U32(), ctx.var_alloc.Consume(offset));
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
index 7421ce97d0..49a66e3ec0 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
@@ -17,8 +17,7 @@ void CompositeInsert(EmitContext& ctx, std::string_view result, std::string_view
         // The result is aliased with the composite
         ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
     } else {
-        ctx.Add("{}={};", result, composite);
-        ctx.Add("{}.{}={};", result, SWIZZLE[index], object);
+        ctx.Add("{}={};{}.{}={};", result, composite, result, SWIZZLE[index], object);
     }
 }
 } // Anonymous namespace
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 0d1e5ed7fc..edeecc26e1 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
@@ -30,7 +30,7 @@ std::string InputVertexIndex(EmitContext& ctx, std::string_view vertex) {
     return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : "";
 }
 
-std::string OutputVertexIndex(EmitContext& ctx) {
+std::string_view OutputVertexIndex(EmitContext& ctx) {
     return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
 }
 
@@ -40,7 +40,7 @@ void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding,
     const bool is_immediate{offset.IsImmediate()};
     if (is_immediate) {
         const s32 signed_offset{static_cast<s32>(offset.U32())};
-        static constexpr u32 cbuf_size{4096 * 16};
+        static constexpr u32 cbuf_size{0x10000};
         if (signed_offset < 0 || offset.U32() > cbuf_size) {
             LOG_WARNING(Shader_GLSL, "Immediate constant buffer offset is out of bounds");
             ctx.Add("{}=0u;", ret);
@@ -140,7 +140,7 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding
                       const IR::Value& offset) {
     const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())};
     if (offset.IsImmediate()) {
-        static constexpr u32 cbuf_size{4096 * 16};
+        static constexpr u32 cbuf_size{0x10000};
         const u32 u32_offset{offset.U32()};
         const s32 signed_offset{static_cast<s32>(offset.U32())};
         if (signed_offset < 0 || u32_offset > cbuf_size) {
@@ -308,21 +308,13 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
     case IR::Attribute::ColorFrontDiffuseG:
     case IR::Attribute::ColorFrontDiffuseB:
     case IR::Attribute::ColorFrontDiffuseA:
-        if (ctx.stage == Stage::Fragment) {
-            ctx.Add("gl_Color.{}={};", swizzle, value);
-        } else {
-            ctx.Add("gl_FrontColor.{}={};", swizzle, value);
-        }
+        ctx.Add("gl_FrontColor.{}={};", swizzle, value);
         break;
     case IR::Attribute::ColorFrontSpecularR:
     case IR::Attribute::ColorFrontSpecularG:
     case IR::Attribute::ColorFrontSpecularB:
     case IR::Attribute::ColorFrontSpecularA:
-        if (ctx.stage == Stage::Fragment) {
-            ctx.Add("gl_SecondaryColor.{}={};", swizzle, value);
-        } else {
-            ctx.Add("gl_FrontSecondaryColor.{}={};", swizzle, value);
-        }
+        ctx.Add("gl_FrontSecondaryColor.{}={};", swizzle, value);
         break;
     case IR::Attribute::ColorBackDiffuseR:
     case IR::Attribute::ColorBackDiffuseG:
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
index 7a2f79d106..983e6d95df 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
@@ -28,6 +28,7 @@ void SetSignFlag(EmitContext& ctx, IR::Inst& inst, std::string_view result) {
     sign->Invalidate();
 }
 } // Anonymous namespace
+
 void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
     const auto result{ctx.var_alloc.Define(inst, GlslVarType::U32)};
     if (IR::Inst* const carry{inst.GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp)}) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
index 8a13bf617f..518b78f064 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
@@ -20,6 +20,7 @@ void SharedWriteCas(EmitContext& ctx, std::string_view offset, std::string_view
     ctx.Add(cas_loop, smem, smem, smem, value, bit_offset, num_bits);
 }
 } // Anonymous namespace
+
 void EmitLoadSharedU8(EmitContext& ctx, IR::Inst& inst, std::string_view offset) {
     ctx.AddU32("{}=bitfieldExtract(smem[{}>>2],int({}%4)*8,8);", inst, offset, offset);
 }
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
index 7047928fdf..4d418cbbc7 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
@@ -43,7 +43,7 @@ void UseShuffleNv(EmitContext& ctx, IR::Inst& inst, std::string_view shfl_op,
     ctx.AddU32("{}={}({},{},{},shfl_in_bounds);", inst, shfl_op, value, index, width);
     SetInBoundsFlag(ctx, inst);
 }
-} // namespace
+} // Anonymous namespace
 
 void EmitLaneId(EmitContext& ctx, IR::Inst& inst) {
     ctx.AddU32("{}=gl_SubGroupInvocationARB&31u;", inst);
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index cbf56491c1..194f926cad 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -177,8 +177,7 @@ Id VarAlloc::Alloc(GlslVarType type) {
 
 void VarAlloc::Free(Id id) {
     if (id.is_valid == 0) {
-        // throw LogicError("Freeing invalid variable");
-        return;
+        throw LogicError("Freeing invalid variable");
     }
     auto& use_tracker{GetUseTracker(id.type)};
     use_tracker.var_use[id.index] = false;
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h
index 236c79a0a9..6db794e910 100644
--- a/src/shader_recompiler/profile.h
+++ b/src/shader_recompiler/profile.h
@@ -105,6 +105,8 @@ struct Profile {
     bool has_broken_signed_operations{};
     /// Dynamic vec4 indexing is broken on some OpenGL drivers
     bool has_gl_component_indexing_bug{};
+    /// The precise type qualifier is broken in the fragment stage of some drivers
+    bool has_gl_precise_bug{};
     /// Ignores SPIR-V ordered vs unordered using GLSL semantics
     bool ignore_nan_fp_comparisons{};
 };
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index d082b9f738..5ffe28d45d 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -196,6 +196,8 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
           .has_broken_spirv_clamp = true,
           .has_broken_unsigned_image_offsets = true,
           .has_broken_signed_operations = true,
+          .has_gl_component_indexing_bug = device.HasComponentIndexingBug(),
+          .has_gl_precise_bug = device.HasPreciseBug(),
           .ignore_nan_fp_comparisons = true,
       } {
     if (use_asynchronous_shaders) {
-- 
cgit v1.2.3-70-g09d2