diff --git a/Ryujinx.Graphics.Shader/Decoders/BitfieldExtensions.cs b/Ryujinx.Graphics.Shader/Decoders/BitfieldExtensions.cs
index 3bb9bc1f4c..d902fc863e 100644
--- a/Ryujinx.Graphics.Shader/Decoders/BitfieldExtensions.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/BitfieldExtensions.cs
@@ -4,12 +4,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
     {
         public static bool Extract(this int value, int lsb)
         {
-            return ((int)(value >> lsb) & 1) != 0;
+            return ((value >> lsb) & 1) != 0;
         }
 
         public static int Extract(this int value, int lsb, int length)
         {
-            return (int)(value >> lsb) & (int)(uint.MaxValue >> (32 - length));
+            return (value >> lsb) & (int)(uint.MaxValue >> (32 - length));
         }
 
         public static bool Extract(this long value, int lsb)
diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
index be93f1375a..eef36a9544 100644
--- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
@@ -176,6 +176,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
             Set("1110111110010x", InstEmit.Ldc,     typeof(OpCodeLdc));
             Set("1110111011010x", InstEmit.Ldg,     typeof(OpCodeMemory));
             Set("1110111101001x", InstEmit.Lds,     typeof(OpCodeMemory));
+            Set("010010111101xx", InstEmit.Lea,     typeof(OpCodeAluCbuf));
+            Set("0011011x11010x", InstEmit.Lea,     typeof(OpCodeAluImm));
+            Set("0101101111010x", InstEmit.Lea,     typeof(OpCodeAluReg));
             Set("0100110001000x", InstEmit.Lop,     typeof(OpCodeLopCbuf));
             Set("0011100001000x", InstEmit.Lop,     typeof(OpCodeLopImm));
             Set("000001xxxxxxxx", InstEmit.Lop,     typeof(OpCodeLopImm32));
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
index 7c3d55c417..e55f1f322d 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
@@ -384,6 +384,27 @@ namespace Ryujinx.Graphics.Shader.Instructions
             context.Copy(Register(op.Predicate0), p1Res);
         }
 
+        public static void Lea(EmitterContext context)
+        {
+            OpCodeAlu op = (OpCodeAlu)context.CurrOp;
+
+            bool negateA = op.RawOpCode.Extract(45);
+
+            int shift = op.RawOpCode.Extract(39, 5);
+
+            Operand srcA = GetSrcA(context);
+            Operand srcB = GetSrcB(context);
+
+            srcA = context.ShiftLeft(srcA, Const(shift));
+            srcA = context.INegate(srcA, negateA);
+
+            Operand res = context.IAdd(srcA, srcB);
+
+            context.Copy(GetDest(context), res);
+
+            // TODO: CC, X
+        }
+
         public static void Lop(EmitterContext context)
         {
             IOpCodeLop op = (IOpCodeLop)context.CurrOp;
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
index 43e5822e74..304906d0ea 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
@@ -99,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
 
                     if (!op.IsBindless)
                     {
-                        operation.Format = GetTextureFormat(context, handle);
+                        operation.Format = context.Config.GetTextureFormat(handle);
                     }
 
                     context.Add(operation);
@@ -228,7 +228,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
 
                 if (!op.IsBindless)
                 {
-                    format = GetTextureFormat(context, op.Immediate);
+                    format = context.Config.GetTextureFormat(op.Immediate);
                 }
             }
             else
@@ -1223,27 +1223,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
             };
         }
 
-        private static TextureFormat GetTextureFormat(EmitterContext context, int handle)
-        {
-            // When the formatted load extension is supported, we don't need to
-            // specify a format, we can just declare it without a format and the GPU will handle it.
-            if (context.Config.GpuAccessor.QuerySupportsImageLoadFormatted())
-            {
-                return TextureFormat.Unknown;
-            }
-
-            var format = context.Config.GpuAccessor.QueryTextureFormat(handle);
-
-            if (format == TextureFormat.Unknown)
-            {
-                context.Config.GpuAccessor.Log($"Unknown format for texture {handle}.");
-
-                format = TextureFormat.R8G8B8A8Unorm;
-            }
-
-            return format;
-        }
-
         private static TextureFormat GetTextureFormat(IntegerSize size)
         {
             return size switch
diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
index 9515c349cd..a26c81c93e 100644
--- a/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
@@ -5,7 +5,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
 {
     class BindlessElimination
     {
-        public static void RunPass(BasicBlock block)
+        private const int NvnTextureBufferSlot = 2;
+
+        public static void RunPass(BasicBlock block, ShaderConfig config)
         {
             // We can turn a bindless into regular access by recognizing the pattern
             // produced by the compiler for separate texture and sampler.
@@ -24,26 +26,39 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
                     continue;
                 }
 
-                if (!(texOp.GetSource(0).AsgOp is Operation handleCombineOp))
+                if (texOp.Inst == Instruction.TextureSample)
                 {
-                    continue;
-                }
+                    if (!(texOp.GetSource(0).AsgOp is Operation handleCombineOp))
+                    {
+                        continue;
+                    }
 
-                if (handleCombineOp.Inst != Instruction.BitwiseOr)
+                    if (handleCombineOp.Inst != Instruction.BitwiseOr)
+                    {
+                        continue;
+                    }
+
+                    Operand src0 = handleCombineOp.GetSource(0);
+                    Operand src1 = handleCombineOp.GetSource(1);
+
+                    if (src0.Type != OperandType.ConstantBuffer || src0.GetCbufSlot() != NvnTextureBufferSlot ||
+                        src1.Type != OperandType.ConstantBuffer || src1.GetCbufSlot() != NvnTextureBufferSlot)
+                    {
+                        continue;
+                    }
+
+                    texOp.SetHandle(src0.GetCbufOffset() | (src1.GetCbufOffset() << 16));
+                }
+                else if (texOp.Inst == Instruction.ImageLoad || texOp.Inst == Instruction.ImageStore)
                 {
-                    continue;
+                    Operand src0 = texOp.GetSource(0);
+
+                    if (src0.Type == OperandType.ConstantBuffer && src0.GetCbufSlot() == NvnTextureBufferSlot)
+                    {
+                        texOp.SetHandle(src0.GetCbufOffset());
+                        texOp.Format = config.GetTextureFormat(texOp.Handle);
+                    }
                 }
-
-                Operand src0 = handleCombineOp.GetSource(0);
-                Operand src1 = handleCombineOp.GetSource(1);
-
-                if (src0.Type != OperandType.ConstantBuffer || src0.GetCbufSlot() != 2 ||
-                    src1.Type != OperandType.ConstantBuffer || src1.GetCbufSlot() != 2)
-                {
-                    continue;
-                }
-
-                texOp.SetHandle(src0.GetCbufOffset() | (src1.GetCbufOffset() << 16));
             }
         }
     }
diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs
index 10a0e7801d..286574cf5b 100644
--- a/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs
@@ -89,7 +89,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
             for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
             {
                 BindlessToIndexed.RunPass(blocks[blkIndex]);
-                BindlessElimination.RunPass(blocks[blkIndex]);
+                BindlessElimination.RunPass(blocks[blkIndex], config);
 
                 // Try to eliminate any operations that are now unused.
                 LinkedListNode<INode> node = blocks[blkIndex].Operations.First;
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index 9e8329de99..8b38afb9a3 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -68,5 +68,26 @@ namespace Ryujinx.Graphics.Shader.Translation
             // The depth register is always two registers after the last color output.
             return count + 1;
         }
+
+        public TextureFormat GetTextureFormat(int handle)
+        {
+            // When the formatted load extension is supported, we don't need to
+            // specify a format, we can just declare it without a format and the GPU will handle it.
+            if (GpuAccessor.QuerySupportsImageLoadFormatted())
+            {
+                return TextureFormat.Unknown;
+            }
+
+            var format = GpuAccessor.QueryTextureFormat(handle);
+
+            if (format == TextureFormat.Unknown)
+            {
+                GpuAccessor.Log($"Unknown format for texture {handle}.");
+
+                format = TextureFormat.R8G8B8A8Unorm;
+            }
+
+            return format;
+        }
     }
 }
\ No newline at end of file