From 3d086e6130a2c5f0546ccef3b234c65ef2f0c99b Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Wed, 26 May 2021 00:16:20 -0400
Subject: [PATCH] glsl: Implement some attribute getters and setters

---
 .../backend/glsl/emit_context.cpp             |  52 ++++-
 .../backend/glsl/emit_context.h               |   9 +
 .../backend/glsl/emit_glsl_composite.cpp      |  14 +-
 .../glsl/emit_glsl_context_get_set.cpp        |  53 +++++
 .../backend/glsl/emit_glsl_image.cpp          | 205 ++++++++++++++++++
 .../backend/glsl/emit_glsl_instructions.h     |   9 +-
 .../glsl/emit_glsl_not_implemented.cpp        | 178 +--------------
 .../backend/glsl/reg_alloc.cpp                |   6 +
 .../backend/glsl/reg_alloc.h                  |   2 +
 .../renderer_opengl/gl_shader_cache.cpp       |   1 -
 10 files changed, 337 insertions(+), 192 deletions(-)

diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp
index 7b6c6d22b..8e5983909 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_context.cpp
@@ -14,17 +14,63 @@ EmitContext::EmitContext(IR::Program& program, [[maybe_unused]] Bindings& bindin
     : info{program.info}, profile{profile_} {
     std::string header = "#version 450\n";
     SetupExtensions(header);
-    if (program.stage == Stage::Compute) {
+    stage = program.stage;
+    switch (program.stage) {
+    case Stage::VertexA:
+    case Stage::VertexB:
+        stage_name = "vertex";
+        attrib_name = "vertex";
+        // TODO: add only what's used by the shader
+        header +=
+            "out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];};";
+        break;
+    case Stage::TessellationControl:
+    case Stage::TessellationEval:
+        stage_name = "primitive";
+        attrib_name = "primitive";
+        break;
+    case Stage::Geometry:
+        stage_name = "primitive";
+        attrib_name = "vertex";
+        break;
+    case Stage::Fragment:
+        stage_name = "fragment";
+        attrib_name = "fragment";
+        break;
+    case Stage::Compute:
+        stage_name = "invocation";
         header += fmt::format("layout(local_size_x={},local_size_y={},local_size_z={}) in;\n",
                               program.workgroup_size[0], program.workgroup_size[1],
                               program.workgroup_size[2]);
+        break;
     }
     code += header;
-
+    const std::string_view attr_stage{stage == Stage::Fragment ? "fragment" : "vertex"};
+    for (size_t index = 0; index < info.input_generics.size(); ++index) {
+        const auto& generic{info.input_generics[index]};
+        if (generic.used) {
+            Add("layout(location={})in vec4 in_attr{};", index, index);
+        }
+    }
+    for (size_t index = 0; index < info.stores_frag_color.size(); ++index) {
+        if (!info.stores_frag_color[index]) {
+            continue;
+        }
+        Add("layout(location={})out vec4 frag_color{};", index, index);
+    }
+    for (size_t index = 0; index < info.stores_generics.size(); ++index) {
+        if (info.stores_generics[index]) {
+            Add("layout(location={}) out vec4 out_attr{};", index, index);
+        }
+    }
     DefineConstantBuffers();
     DefineStorageBuffers();
     DefineHelperFunctions();
-    code += "void main(){\n";
+    Add("void main(){{");
+
+    if (stage == Stage::VertexA || stage == Stage::VertexB) {
+        Add("gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);");
+    }
 }
 
 void EmitContext::SetupExtensions(std::string& header) {
diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 7f8857fa7..087eaff6a 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -88,6 +88,11 @@ public:
         Add<Type::F32x2>(format_str, inst, args...);
     }
 
+    template <typename... Args>
+    void AddF32x4(const char* format_str, IR::Inst& inst, Args&&... args) {
+        Add<Type::F32x4>(format_str, inst, args...);
+    }
+
     template <typename... Args>
     void Add(const char* format_str, Args&&... args) {
         code += fmt::format(format_str, std::forward<Args>(args)...);
@@ -100,6 +105,10 @@ public:
     const Info& info;
     const Profile& profile;
 
+    Stage stage{};
+    std::string_view stage_name = "invalid";
+    std::string_view attrib_name = "invalid";
+
 private:
     void SetupExtensions(std::string& header);
     void DefineConstantBuffers();
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
index 8e7ad68bd..048b12f38 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
@@ -155,16 +155,14 @@ void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, std::string_vie
     ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
 }
 
-void EmitCompositeExtractF32x3([[maybe_unused]] EmitContext& ctx,
-                               [[maybe_unused]] std::string_view composite,
-                               [[maybe_unused]] u32 index) {
-    throw NotImplementedException("GLSL Instruction");
+void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                               u32 index) {
+    ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
 }
 
-void EmitCompositeExtractF32x4([[maybe_unused]] EmitContext& ctx,
-                               [[maybe_unused]] std::string_view composite,
-                               [[maybe_unused]] u32 index) {
-    throw NotImplementedException("GLSL Instruction");
+void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                               u32 index) {
+    ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
 }
 
 void EmitCompositeInsertF32x2([[maybe_unused]] EmitContext& ctx,
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 7c9cadd7e..441818c0b 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
@@ -51,4 +51,57 @@ void EmitGetCbufU32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const
                       [[maybe_unused]] const IR::Value& offset) {
     throw NotImplementedException("GLSL");
 }
+
+void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
+                      [[maybe_unused]] std::string_view vertex) {
+    const u32 element{static_cast<u32>(attr) % 4};
+    const char swizzle{"xyzw"[element]};
+    if (IR::IsGeneric(attr)) {
+        const u32 index{IR::GenericAttributeIndex(attr)};
+        ctx.AddF32("{}=in_attr{}.{};", inst, index, swizzle);
+        return;
+    }
+    switch (attr) {
+    case IR::Attribute::PositionX:
+    case IR::Attribute::PositionY:
+    case IR::Attribute::PositionZ:
+    case IR::Attribute::PositionW:
+        ctx.AddF32("{}=gl_Position.{};", inst, swizzle);
+        break;
+    default:
+        fmt::print("Get attribute {}", attr);
+        throw NotImplementedException("Get attribute {}", attr);
+    }
+}
+
+void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
+                      [[maybe_unused]] std::string_view vertex) {
+    const u32 element{static_cast<u32>(attr) % 4};
+    const char swizzle{"xyzw"[element]};
+    if (IR::IsGeneric(attr)) {
+        const u32 index{IR::GenericAttributeIndex(attr)};
+        ctx.Add("out_attr{}.{}={};", index, swizzle, value);
+        return;
+    }
+    switch (attr) {
+    case IR::Attribute::PointSize:
+        ctx.Add("gl_Pointsize={};", value);
+        break;
+    case IR::Attribute::PositionX:
+    case IR::Attribute::PositionY:
+    case IR::Attribute::PositionZ:
+    case IR::Attribute::PositionW:
+        ctx.Add("gl_Position.{}={};", swizzle, value);
+        break;
+    default:
+        fmt::print("Set attribute {}", attr);
+        throw NotImplementedException("Set attribute {}", attr);
+    }
+}
+
+void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) {
+    const char swizzle{"xyzw"[component]};
+    ctx.Add("frag_color{}.{}={};", index, swizzle, value);
+}
+
 } // namespace Shader::Backend::GLSL
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
index e69de29bb..109938e0e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
@@ -0,0 +1,205 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <string_view>
+
+#include "shader_recompiler/backend/glsl/emit_context.h"
+#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
+#include "shader_recompiler/frontend/ir/value.h"
+#include "shader_recompiler/profile.h"
+
+namespace Shader::Backend::GLSL {
+
+void EmitImageSampleImplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                                [[maybe_unused]] const IR::Value& index,
+                                [[maybe_unused]] std::string_view coords,
+                                [[maybe_unused]] std::string_view bias_lc,
+                                [[maybe_unused]] const IR::Value& offset) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageSampleExplicitLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                                [[maybe_unused]] const IR::Value& index,
+                                [[maybe_unused]] std::string_view coords,
+                                [[maybe_unused]] std::string_view lod_lc,
+                                [[maybe_unused]] const IR::Value& offset) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageSampleDrefImplicitLod([[maybe_unused]] EmitContext& ctx,
+                                    [[maybe_unused]] IR::Inst& inst,
+                                    [[maybe_unused]] const IR::Value& index,
+                                    [[maybe_unused]] std::string_view coords,
+                                    [[maybe_unused]] std::string_view dref,
+                                    [[maybe_unused]] std::string_view bias_lc,
+                                    [[maybe_unused]] const IR::Value& offset) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageSampleDrefExplicitLod([[maybe_unused]] EmitContext& ctx,
+                                    [[maybe_unused]] IR::Inst& inst,
+                                    [[maybe_unused]] const IR::Value& index,
+                                    [[maybe_unused]] std::string_view coords,
+                                    [[maybe_unused]] std::string_view dref,
+                                    [[maybe_unused]] std::string_view lod_lc,
+                                    [[maybe_unused]] const IR::Value& offset) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageGather([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                     [[maybe_unused]] const IR::Value& index,
+                     [[maybe_unused]] std::string_view coords,
+                     [[maybe_unused]] const IR::Value& offset,
+                     [[maybe_unused]] const IR::Value& offset2) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageGatherDref([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                         [[maybe_unused]] const IR::Value& index,
+                         [[maybe_unused]] std::string_view coords,
+                         [[maybe_unused]] const IR::Value& offset,
+                         [[maybe_unused]] const IR::Value& offset2,
+                         [[maybe_unused]] std::string_view dref) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageFetch([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                    [[maybe_unused]] const IR::Value& index,
+                    [[maybe_unused]] std::string_view coords,
+                    [[maybe_unused]] std::string_view offset, [[maybe_unused]] std::string_view lod,
+                    [[maybe_unused]] std::string_view ms) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageQueryDimensions([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                              [[maybe_unused]] const IR::Value& index,
+                              [[maybe_unused]] std::string_view lod) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageQueryLod([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                       [[maybe_unused]] const IR::Value& index,
+                       [[maybe_unused]] std::string_view coords) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageGradient([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                       [[maybe_unused]] const IR::Value& index,
+                       [[maybe_unused]] std::string_view coords,
+                       [[maybe_unused]] std::string_view derivates,
+                       [[maybe_unused]] std::string_view offset,
+                       [[maybe_unused]] std::string_view lod_clamp) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageRead([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                   [[maybe_unused]] const IR::Value& index,
+                   [[maybe_unused]] std::string_view coords) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitImageWrite([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
+                    [[maybe_unused]] const IR::Value& index,
+                    [[maybe_unused]] std::string_view coords,
+                    [[maybe_unused]] std::string_view color) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageSampleImplicitLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageSampleExplicitLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageSampleDrefImplicitLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageSampleDrefExplicitLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageGather(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageGatherDref(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageFetch(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageQueryDimensions(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageQueryLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageGradient(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageRead(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBindlessImageWrite(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageSampleImplicitLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageSampleExplicitLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageSampleDrefImplicitLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageSampleDrefExplicitLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageGather(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageGatherDref(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageFetch(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageQueryDimensions(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageQueryLod(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageGradient(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageRead(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBoundImageWrite(EmitContext&) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+} // namespace Shader::Backend::GLSL
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index 9f32070b0..49ab108bb 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -61,7 +61,8 @@ void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
 void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
                     const IR::Value& offset);
 void EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
-void EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view vertex);
+void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
+                      std::string_view vertex);
 void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
                       std::string_view vertex);
 void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex);
@@ -180,8 +181,10 @@ void EmitCompositeConstructF32x4(EmitContext& ctx, std::string_view e1, std::str
                                  std::string_view e3, std::string_view e4);
 void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
                                u32 index);
-void EmitCompositeExtractF32x3(EmitContext& ctx, std::string_view composite, u32 index);
-void EmitCompositeExtractF32x4(EmitContext& ctx, std::string_view composite, u32 index);
+void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
+                               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,
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 b37b3c76d..14a2edd74 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -83,7 +83,7 @@ void EmitUnreachable(EmitContext& ctx) {
 }
 
 void EmitDemoteToHelperInvocation(EmitContext& ctx, std::string_view continue_label) {
-    NotImplemented();
+    ctx.Add("discard;");
 }
 
 void EmitBarrier(EmitContext& ctx) {
@@ -146,15 +146,6 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) {
     NotImplemented();
 }
 
-void EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view vertex) {
-    NotImplemented();
-}
-
-void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
-                      std::string_view vertex) {
-    NotImplemented();
-}
-
 void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex) {
     NotImplemented();
 }
@@ -172,10 +163,6 @@ void EmitSetPatch(EmitContext& ctx, IR::Patch patch, std::string_view value) {
     NotImplemented();
 }
 
-void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, std::string_view value) {
-    NotImplemented();
-}
-
 void EmitSetSampleMask(EmitContext& ctx, std::string_view value) {
     NotImplemented();
 }
@@ -456,169 +443,6 @@ void EmitSharedAtomicExchange64(EmitContext& ctx, std::string_view pointer_offse
     NotImplemented();
 }
 
-void EmitBindlessImageSampleImplicitLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageSampleExplicitLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageSampleDrefImplicitLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageSampleDrefExplicitLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageGather(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageGatherDref(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageFetch(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageQueryDimensions(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageQueryLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageGradient(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageRead(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBindlessImageWrite(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageSampleImplicitLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageSampleExplicitLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageSampleDrefImplicitLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageSampleDrefExplicitLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageGather(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageGatherDref(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageFetch(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageQueryDimensions(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageQueryLod(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageGradient(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageRead(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitBoundImageWrite(EmitContext&) {
-    NotImplemented();
-}
-
-void EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                                std::string_view coords, std::string_view bias_lc,
-                                const IR::Value& offset) {
-    NotImplemented();
-}
-
-void EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                                std::string_view coords, std::string_view lod_lc,
-                                const IR::Value& offset) {
-    NotImplemented();
-}
-
-void EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                                    std::string_view coords, std::string_view dref,
-                                    std::string_view bias_lc, const IR::Value& offset) {
-    NotImplemented();
-}
-
-void EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                                    std::string_view coords, std::string_view dref,
-                                    std::string_view lod_lc, const IR::Value& offset) {
-    NotImplemented();
-}
-
-void EmitImageGather(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                     std::string_view coords, const IR::Value& offset, const IR::Value& offset2) {
-    NotImplemented();
-}
-
-void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                         std::string_view coords, const IR::Value& offset, const IR::Value& offset2,
-                         std::string_view dref) {
-    NotImplemented();
-}
-
-void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                    std::string_view coords, std::string_view offset, std::string_view lod,
-                    std::string_view ms) {
-    NotImplemented();
-}
-
-void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                              std::string_view lod) {
-    NotImplemented();
-}
-
-void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                       std::string_view coords) {
-    NotImplemented();
-}
-
-void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                       std::string_view coords, std::string_view derivates, std::string_view offset,
-                       std::string_view lod_clamp) {
-    NotImplemented();
-}
-
-void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                   std::string_view coords) {
-    NotImplemented();
-}
-
-void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
-                    std::string_view coords, std::string_view color) {
-    NotImplemented();
-}
-
 void EmitBindlessImageAtomicIAdd32(EmitContext&) {
     NotImplemented();
 }
diff --git a/src/shader_recompiler/backend/glsl/reg_alloc.cpp b/src/shader_recompiler/backend/glsl/reg_alloc.cpp
index c60a87d91..a080d5341 100644
--- a/src/shader_recompiler/backend/glsl/reg_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/reg_alloc.cpp
@@ -55,6 +55,8 @@ std::string MakeImm(const IR::Value& value) {
         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());
     }
@@ -131,6 +133,10 @@ std::string RegAlloc::GetType(Type type, u32 index) {
         return "uvec2 ";
     case Type::F32x2:
         return "vec2 ";
+    case Type::U32x4:
+        return "uvec4 ";
+    case Type::F32x4:
+        return "vec4 ";
     case Type::Void:
         return "";
     default:
diff --git a/src/shader_recompiler/backend/glsl/reg_alloc.h b/src/shader_recompiler/backend/glsl/reg_alloc.h
index 419e1e761..df067d3ad 100644
--- a/src/shader_recompiler/backend/glsl/reg_alloc.h
+++ b/src/shader_recompiler/backend/glsl/reg_alloc.h
@@ -27,6 +27,8 @@ enum class Type : u32 {
     F64,
     U32x2,
     F32x2,
+    U32x4,
+    F32x4,
     Void,
 };
 
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index e00d01e34..8a052851b 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -440,7 +440,6 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
             assembly_programs[stage_index] = CompileProgram(code, AssemblyStage(stage_index));
         } else {
             const auto code{EmitGLSL(profile, runtime_info, program, binding)};
-            OGLShader shader;
             AttachShader(Stage(stage_index), source_program.handle, code);
         }
     }