diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 44281e407..945cdb42b 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -60,11 +60,10 @@ public:
         Add(spv::ImageOperandsMask::ConstOffsets, offsets);
     }
 
-    explicit ImageOperands(EmitContext& ctx, const IR::Value& offset, Id lod, Id ms) {
+    explicit ImageOperands(Id lod, Id ms) {
         if (Sirit::ValidId(lod)) {
             Add(spv::ImageOperandsMask::Lod, lod);
         }
-        AddOffset(ctx, offset, ImageFetchOffsetAllowed);
         if (Sirit::ValidId(ms)) {
             Add(spv::ImageOperandsMask::Sample, ms);
         }
@@ -312,6 +311,43 @@ Id ImageGatherSubpixelOffset(EmitContext& ctx, const IR::TextureInstInfo& info,
         return coords;
     }
 }
+
+void AddOffsetToCoordinates(EmitContext& ctx, const IR::TextureInstInfo& info, Id& coords,
+                            Id offset) {
+    if (!Sirit::ValidId(offset)) {
+        return;
+    }
+
+    Id result_type{};
+    switch (info.type) {
+    case TextureType::Buffer:
+    case TextureType::Color1D: {
+        result_type = ctx.U32[1];
+        break;
+    }
+    case TextureType::ColorArray1D:
+        offset = ctx.OpCompositeConstruct(ctx.U32[2], offset, ctx.u32_zero_value);
+        [[fallthrough]];
+    case TextureType::Color2D:
+    case TextureType::Color2DRect: {
+        result_type = ctx.U32[2];
+        break;
+    }
+    case TextureType::ColorArray2D:
+        offset = ctx.OpCompositeConstruct(ctx.U32[3], ctx.OpCompositeExtract(ctx.U32[1], coords, 0),
+                                          ctx.OpCompositeExtract(ctx.U32[1], coords, 1),
+                                          ctx.u32_zero_value);
+        [[fallthrough]];
+    case TextureType::Color3D: {
+        result_type = ctx.U32[3];
+        break;
+    }
+    case TextureType::ColorCube:
+    case TextureType::ColorArrayCube:
+        return;
+    }
+    coords = ctx.OpIAdd(result_type, coords, offset);
+}
 } // Anonymous namespace
 
 Id EmitBindlessImageSampleImplicitLod(EmitContext&) {
@@ -494,9 +530,10 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
                 operands.Span());
 }
 
-Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
-                  const IR::Value& offset, Id lod, Id ms) {
+Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
+                  Id lod, Id ms) {
     const auto info{inst->Flags<IR::TextureInstInfo>()};
+    AddOffsetToCoordinates(ctx, info, coords, offset);
     if (info.type == TextureType::Buffer) {
         lod = Id{};
     }
@@ -504,7 +541,7 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
         // This image is multisampled, lod must be implicit
         lod = Id{};
     }
-    const ImageOperands operands(ctx, offset, lod, ms);
+    const ImageOperands operands(lod, ms);
     return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
                 TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
 }
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
index 08fcabd58..5c01b1012 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
@@ -537,8 +537,8 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id
                    const IR::Value& offset, const IR::Value& offset2);
 Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
                        const IR::Value& offset, const IR::Value& offset2, Id dref);
-Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
-                  const IR::Value& offset, Id lod, Id ms);
+Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
+                  Id lod, Id ms);
 Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod,
                             const IR::Value& skip_mips);
 Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);