diff --git a/Ryujinx.Graphics.Gpu/Engine/Compute.cs b/Ryujinx.Graphics.Gpu/Engine/Compute.cs
index 108cc197c8..ba7daf67a3 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Compute.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Compute.cs
@@ -10,13 +10,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
 {
     partial class Methods
     {
-        public void Dispatch(int argument)
+        public void Dispatch(GpuState state, int argument)
         {
-            uint dispatchParamsAddress = (uint)_context.State.Get<int>(MethodOffset.DispatchParamsAddress);
+            uint dispatchParamsAddress = (uint)state.Get<int>(MethodOffset.DispatchParamsAddress);
 
             var dispatchParams = _context.MemoryAccessor.Read<ComputeParams>((ulong)dispatchParamsAddress << 8);
 
-            GpuVa shaderBaseAddress = _context.State.Get<GpuVa>(MethodOffset.ShaderBaseAddress);
+            GpuVa shaderBaseAddress = state.Get<GpuVa>(MethodOffset.ShaderBaseAddress);
 
             ulong shaderGpuVa = shaderBaseAddress.Pack() + (uint)dispatchParams.ShaderOffset;
 
@@ -28,15 +28,15 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             _context.Renderer.Pipeline.BindProgram(cs.HostProgram);
 
-            var samplerPool = _context.State.Get<PoolState>(MethodOffset.SamplerPoolState);
+            var samplerPool = state.Get<PoolState>(MethodOffset.SamplerPoolState);
 
             _textureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId);
 
-            var texturePool = _context.State.Get<PoolState>(MethodOffset.TexturePoolState);
+            var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
 
             _textureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
 
-            _textureManager.SetComputeTextureBufferIndex(_context.State.Get<int>(MethodOffset.TextureBufferIndex));
+            _textureManager.SetComputeTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
 
             ShaderProgramInfo info = cs.Shader.Program.Info;
 
@@ -119,7 +119,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 dispatchParams.UnpackGridSizeY(),
                 dispatchParams.UnpackGridSizeZ());
 
-            UpdateShaderState();
+            UpdateShaderState(state);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs b/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs
index 355b7394dc..09de992f88 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Inline2Memory.cs
@@ -12,9 +12,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
         private int _offset;
         private int _size;
 
-        public void LaunchDma(int argument)
+        public void LaunchDma(GpuState state, int argument)
         {
-            _params = _context.State.Get<Inline2MemoryParams>(MethodOffset.I2mParams);
+            _params = state.Get<Inline2MemoryParams>(MethodOffset.I2mParams);
 
             _isLinear = (argument & 1) != 0;
 
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
             _size   = _params.LineLengthIn * _params.LineCount;
         }
 
-        public void LoadInlineData(int argument)
+        public void LoadInlineData(GpuState state, int argument)
         {
             if (_isLinear)
             {
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs b/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs
index b50a176602..da6c94e57d 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodClear.cs
@@ -5,9 +5,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
 {
     partial class Methods
     {
-        private void Clear(int argument)
+        private void Clear(GpuState state, int argument)
         {
-            UpdateRenderTargetStateIfNeeded();
+            UpdateRenderTargetStateIfNeeded(state);
 
             _textureManager.CommitGraphicsBindings();
 
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             if (componentMask != 0)
             {
-                var clearColor = _context.State.Get<ClearColors>(MethodOffset.ClearColors);
+                var clearColor = state.Get<ClearColors>(MethodOffset.ClearColors);
 
                 ColorF color = new ColorF(
                     clearColor.Red,
@@ -33,14 +33,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             if (clearDepth || clearStencil)
             {
-                float depthValue   = _context.State.Get<float>(MethodOffset.ClearDepthValue);
-                int   stencilValue = _context.State.Get<int>  (MethodOffset.ClearStencilValue);
+                float depthValue   = state.Get<float>(MethodOffset.ClearDepthValue);
+                int   stencilValue = state.Get<int>  (MethodOffset.ClearStencilValue);
 
                 int stencilMask = 0;
 
                 if (clearStencil)
                 {
-                    stencilMask = _context.State.Get<StencilTestState>(MethodOffset.StencilTestState).FrontMask;
+                    stencilMask = state.Get<StencilTestState>(MethodOffset.StencilTestState).FrontMask;
                 }
 
                 _context.Renderer.Pipeline.ClearRenderTargetDepthStencil(
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs
index 40560ab13d..0bf836e1a6 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs
@@ -6,11 +6,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
 {
     partial class Methods
     {
-        private void CopyBuffer(int argument)
+        private void CopyBuffer(GpuState state, int argument)
         {
-            var cbp = _context.State.Get<CopyBufferParams>(MethodOffset.CopyBufferParams);
+            var cbp = state.Get<CopyBufferParams>(MethodOffset.CopyBufferParams);
 
-            var swizzle = _context.State.Get<CopyBufferSwizzle>(MethodOffset.CopyBufferSwizzle);
+            var swizzle = state.Get<CopyBufferSwizzle>(MethodOffset.CopyBufferSwizzle);
 
             bool srcLinear = (argument & (1 << 7)) != 0;
             bool dstLinear = (argument & (1 << 8)) != 0;
@@ -29,8 +29,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 int srcBpp = swizzle.UnpackSrcComponentsCount() * swizzle.UnpackComponentSize();
                 int dstBpp = swizzle.UnpackDstComponentsCount() * swizzle.UnpackComponentSize();
 
-                var dst = _context.State.Get<CopyBufferTexture>(MethodOffset.CopyBufferDstTexture);
-                var src = _context.State.Get<CopyBufferTexture>(MethodOffset.CopyBufferSrcTexture);
+                var dst = state.Get<CopyBufferTexture>(MethodOffset.CopyBufferDstTexture);
+                var src = state.Get<CopyBufferTexture>(MethodOffset.CopyBufferSrcTexture);
 
                 var srcCalculator = new OffsetCalculator(
                     src.Width,
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
index 887f520d2c..c482451a33 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
@@ -5,10 +5,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
 {
     partial class Methods
     {
-        private void CopyTexture(int argument)
+        private void CopyTexture(GpuState state, int argument)
         {
-            var dstCopyTexture = _context.State.Get<CopyTexture>(MethodOffset.CopyDstTexture);
-            var srcCopyTexture = _context.State.Get<CopyTexture>(MethodOffset.CopySrcTexture);
+            var dstCopyTexture = state.Get<CopyTexture>(MethodOffset.CopyDstTexture);
+            var srcCopyTexture = state.Get<CopyTexture>(MethodOffset.CopySrcTexture);
 
             Image.Texture srcTexture = _textureManager.FindOrCreateTexture(srcCopyTexture);
 
@@ -32,9 +32,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 return;
             }
 
-            var control = _context.State.Get<CopyTextureControl>(MethodOffset.CopyTextureControl);
+            var control = state.Get<CopyTextureControl>(MethodOffset.CopyTextureControl);
 
-            var region = _context.State.Get<CopyRegion>(MethodOffset.CopyRegion);
+            var region = state.Get<CopyRegion>(MethodOffset.CopyRegion);
 
             int srcX1 = (int)(region.SrcXF >> 32);
             int srcY1 = (int)(region.SrcYF >> 32);
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs b/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs
index ee07ca7694..d69b9ea03e 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodDraw.cs
@@ -24,9 +24,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
         public PrimitiveType PrimitiveType { get; private set; }
 
-        private void DrawEnd(int argument)
+        private void DrawEnd(GpuState state, int argument)
         {
-            UpdateState();
+            UpdateState(state);
 
             bool instanced = _vsUsesInstanceId || _isAnyVbInstanced;
 
@@ -39,12 +39,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
                     _instancedIndexed = _drawIndexed;
 
                     _instancedFirstIndex    = _firstIndex;
-                    _instancedFirstVertex   = _context.State.Get<int>(MethodOffset.FirstVertex);
-                    _instancedFirstInstance = _context.State.Get<int>(MethodOffset.FirstInstance);
+                    _instancedFirstVertex   = state.Get<int>(MethodOffset.FirstVertex);
+                    _instancedFirstInstance = state.Get<int>(MethodOffset.FirstInstance);
 
                     _instancedIndexCount = _indexCount;
 
-                    var drawState = _context.State.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
+                    var drawState = state.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
 
                     _instancedDrawStateFirst = drawState.First;
                     _instancedDrawStateCount = drawState.Count;
@@ -53,13 +53,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 return;
             }
 
-            int firstInstance = _context.State.Get<int>(MethodOffset.FirstInstance);
+            int firstInstance = state.Get<int>(MethodOffset.FirstInstance);
 
             if (_drawIndexed)
             {
                 _drawIndexed = false;
 
-                int firstVertex = _context.State.Get<int>(MethodOffset.FirstVertex);
+                int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
 
                 _context.Renderer.Pipeline.DrawIndexed(
                     _indexCount,
@@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
             }
             else
             {
-                var drawState = _context.State.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
+                var drawState = state.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
 
                 _context.Renderer.Pipeline.Draw(
                     drawState.Count,
@@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
             }
         }
 
-        private void DrawBegin(int argument)
+        private void DrawBegin(GpuState state, int argument)
         {
             PrimitiveType type = (PrimitiveType)(argument & 0xffff);
 
@@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
             }
         }
 
-        private void SetIndexBufferCount(int argument)
+        private void SetIndexBufferCount(GpuState state, int argument)
         {
             _drawIndexed = true;
         }
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
index dd022eb2cd..f73c03cb97 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs
@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
     {
         private ulong _runningCounter;
 
-        private void Report(int argument)
+        private void Report(GpuState state, int argument)
         {
             ReportMode mode = (ReportMode)(argument & 3);
 
@@ -18,16 +18,16 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             switch (mode)
             {
-                case ReportMode.Semaphore: ReportSemaphore();   break;
-                case ReportMode.Counter:   ReportCounter(type); break;
+                case ReportMode.Semaphore: ReportSemaphore(state);     break;
+                case ReportMode.Counter:   ReportCounter(state, type); break;
             }
         }
 
-        private void ReportSemaphore()
+        private void ReportSemaphore(GpuState state)
         {
-            var state = _context.State.Get<ReportState>(MethodOffset.ReportState);
+            var rs = state.Get<ReportState>(MethodOffset.ReportState);
 
-            _context.MemoryAccessor.Write(state.Address.Pack(), state.Payload);
+            _context.MemoryAccessor.Write(rs.Address.Pack(), rs.Payload);
 
             _context.AdvanceSequence();
         }
@@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
             public ulong Timestamp;
         }
 
-        private void ReportCounter(ReportCounterType type)
+        private void ReportCounter(GpuState state, ReportCounterType type)
         {
             CounterData counterData = new CounterData();
 
@@ -78,9 +78,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             Span<byte> data = MemoryMarshal.Cast<CounterData, byte>(counterDataSpan);
 
-            var state = _context.State.Get<ReportState>(MethodOffset.ReportState);
+            var rs = state.Get<ReportState>(MethodOffset.ReportState);
 
-            _context.MemoryAccessor.Write(state.Address.Pack(), data);
+            _context.MemoryAccessor.Write(rs.Address.Pack(), data);
         }
 
         private static ulong ConvertNanosecondsToTicks(ulong nanoseconds)
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodResetCounter.cs b/Ryujinx.Graphics.Gpu/Engine/MethodResetCounter.cs
index 12a878459b..574eb5c8f0 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodResetCounter.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodResetCounter.cs
@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
 {
     partial class Methods
     {
-        private void ResetCounter(int argument)
+        private void ResetCounter(GpuState state, int argument)
         {
             ResetCounterType type = (ResetCounterType)argument;
 
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs
index 823d156e26..87d9612b25 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferBind.cs
@@ -4,32 +4,32 @@ namespace Ryujinx.Graphics.Gpu.Engine
 {
     partial class Methods
     {
-        private void UniformBufferBindVertex(int argument)
+        private void UniformBufferBindVertex(GpuState state, int argument)
         {
-            UniformBufferBind(argument, ShaderType.Vertex);
+            UniformBufferBind(state, argument, ShaderType.Vertex);
         }
 
-        private void UniformBufferBindTessControl(int argument)
+        private void UniformBufferBindTessControl(GpuState state, int argument)
         {
-            UniformBufferBind(argument, ShaderType.TessellationControl);
+            UniformBufferBind(state, argument, ShaderType.TessellationControl);
         }
 
-        private void UniformBufferBindTessEvaluation(int argument)
+        private void UniformBufferBindTessEvaluation(GpuState state, int argument)
         {
-            UniformBufferBind(argument, ShaderType.TessellationEvaluation);
+            UniformBufferBind(state, argument, ShaderType.TessellationEvaluation);
         }
 
-        private void UniformBufferBindGeometry(int argument)
+        private void UniformBufferBindGeometry(GpuState state, int argument)
         {
-            UniformBufferBind(argument, ShaderType.Geometry);
+            UniformBufferBind(state, argument, ShaderType.Geometry);
         }
 
-        private void UniformBufferBindFragment(int argument)
+        private void UniformBufferBindFragment(GpuState state, int argument)
         {
-            UniformBufferBind(argument, ShaderType.Fragment);
+            UniformBufferBind(state, argument, ShaderType.Fragment);
         }
 
-        private void UniformBufferBind(int argument, ShaderType type)
+        private void UniformBufferBind(GpuState state, int argument, ShaderType type)
         {
             bool enable = (argument & 1) != 0;
 
@@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             if (enable)
             {
-                var uniformBuffer = _context.State.Get<UniformBufferState>(MethodOffset.UniformBufferState);
+                var uniformBuffer = state.Get<UniformBufferState>(MethodOffset.UniformBufferState);
 
                 ulong address = uniformBuffer.Address.Pack();
 
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs
index 229e79a84e..43bab2433b 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs
@@ -4,13 +4,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
 {
     partial class Methods
     {
-        private void UniformBufferUpdate(int argument)
+        private void UniformBufferUpdate(GpuState state, int argument)
         {
-            var uniformBuffer = _context.State.Get<UniformBufferState>(MethodOffset.UniformBufferState);
+            var uniformBuffer = state.Get<UniformBufferState>(MethodOffset.UniformBufferState);
 
             _context.MemoryAccessor.Write(uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset, argument);
 
-            _context.State.SetUniformBufferOffset(uniformBuffer.Offset + 4);
+            state.SetUniformBufferOffset(uniformBuffer.Offset + 4);
 
             _context.AdvanceSequence();
         }
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index f48d0a7f82..1832a5e353 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -40,133 +40,131 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             _bufferManager  = new BufferManager(context);
             _textureManager = new TextureManager(context);
-
-            RegisterCallbacks();
         }
 
-        private void RegisterCallbacks()
+        public void RegisterCallbacks(GpuState state)
         {
-            _context.State.RegisterCallback(MethodOffset.LaunchDma,      LaunchDma);
-            _context.State.RegisterCallback(MethodOffset.LoadInlineData, LoadInlineData);
+            state.RegisterCallback(MethodOffset.LaunchDma,      LaunchDma);
+            state.RegisterCallback(MethodOffset.LoadInlineData, LoadInlineData);
 
-            _context.State.RegisterCallback(MethodOffset.Dispatch, Dispatch);
+            state.RegisterCallback(MethodOffset.Dispatch, Dispatch);
 
-            _context.State.RegisterCallback(MethodOffset.CopyBuffer,  CopyBuffer);
-            _context.State.RegisterCallback(MethodOffset.CopyTexture, CopyTexture);
+            state.RegisterCallback(MethodOffset.CopyBuffer,  CopyBuffer);
+            state.RegisterCallback(MethodOffset.CopyTexture, CopyTexture);
 
-            _context.State.RegisterCallback(MethodOffset.TextureBarrier,      TextureBarrier);
-            _context.State.RegisterCallback(MethodOffset.InvalidateTextures,  InvalidateTextures);
-            _context.State.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled);
+            state.RegisterCallback(MethodOffset.TextureBarrier,      TextureBarrier);
+            state.RegisterCallback(MethodOffset.InvalidateTextures,  InvalidateTextures);
+            state.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled);
 
-            _context.State.RegisterCallback(MethodOffset.ResetCounter, ResetCounter);
+            state.RegisterCallback(MethodOffset.ResetCounter, ResetCounter);
 
-            _context.State.RegisterCallback(MethodOffset.DrawEnd,   DrawEnd);
-            _context.State.RegisterCallback(MethodOffset.DrawBegin, DrawBegin);
+            state.RegisterCallback(MethodOffset.DrawEnd,   DrawEnd);
+            state.RegisterCallback(MethodOffset.DrawBegin, DrawBegin);
 
-            _context.State.RegisterCallback(MethodOffset.IndexBufferCount, SetIndexBufferCount);
+            state.RegisterCallback(MethodOffset.IndexBufferCount, SetIndexBufferCount);
 
-            _context.State.RegisterCallback(MethodOffset.Clear, Clear);
+            state.RegisterCallback(MethodOffset.Clear, Clear);
 
-            _context.State.RegisterCallback(MethodOffset.Report, Report);
+            state.RegisterCallback(MethodOffset.Report, Report);
 
-            _context.State.RegisterCallback(MethodOffset.UniformBufferUpdateData, 16, UniformBufferUpdate);
+            state.RegisterCallback(MethodOffset.UniformBufferUpdateData, 16, UniformBufferUpdate);
 
-            _context.State.RegisterCallback(MethodOffset.UniformBufferBindVertex,         UniformBufferBindVertex);
-            _context.State.RegisterCallback(MethodOffset.UniformBufferBindTessControl,    UniformBufferBindTessControl);
-            _context.State.RegisterCallback(MethodOffset.UniformBufferBindTessEvaluation, UniformBufferBindTessEvaluation);
-            _context.State.RegisterCallback(MethodOffset.UniformBufferBindGeometry,       UniformBufferBindGeometry);
-            _context.State.RegisterCallback(MethodOffset.UniformBufferBindFragment,       UniformBufferBindFragment);
+            state.RegisterCallback(MethodOffset.UniformBufferBindVertex,         UniformBufferBindVertex);
+            state.RegisterCallback(MethodOffset.UniformBufferBindTessControl,    UniformBufferBindTessControl);
+            state.RegisterCallback(MethodOffset.UniformBufferBindTessEvaluation, UniformBufferBindTessEvaluation);
+            state.RegisterCallback(MethodOffset.UniformBufferBindGeometry,       UniformBufferBindGeometry);
+            state.RegisterCallback(MethodOffset.UniformBufferBindFragment,       UniformBufferBindFragment);
         }
 
         public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address);
 
-        private void UpdateState()
+        private void UpdateState(GpuState state)
         {
             // Shaders must be the first one to be updated if modified, because
             // some of the other state depends on information from the currently
             // bound shaders.
-            if (_context.State.QueryModified(MethodOffset.ShaderBaseAddress, MethodOffset.ShaderState))
+            if (state.QueryModified(MethodOffset.ShaderBaseAddress, MethodOffset.ShaderState))
             {
-                UpdateShaderState();
+                UpdateShaderState(state);
             }
 
-            UpdateRenderTargetStateIfNeeded();
+            UpdateRenderTargetStateIfNeeded(state);
 
-            if (_context.State.QueryModified(MethodOffset.DepthTestEnable,
+            if (state.QueryModified(MethodOffset.DepthTestEnable,
                                              MethodOffset.DepthWriteEnable,
                                              MethodOffset.DepthTestFunc))
             {
-                UpdateDepthTestState();
+                UpdateDepthTestState(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.ViewportTransform, MethodOffset.ViewportExtents))
+            if (state.QueryModified(MethodOffset.ViewportTransform, MethodOffset.ViewportExtents))
             {
-                UpdateViewportTransform();
+                UpdateViewportTransform(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.DepthBiasState,
+            if (state.QueryModified(MethodOffset.DepthBiasState,
                                              MethodOffset.DepthBiasFactor,
                                              MethodOffset.DepthBiasUnits,
                                              MethodOffset.DepthBiasClamp))
             {
-                UpdateDepthBiasState();
+                UpdateDepthBiasState(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.StencilBackMasks,
+            if (state.QueryModified(MethodOffset.StencilBackMasks,
                                              MethodOffset.StencilTestState,
                                              MethodOffset.StencilBackTestState))
             {
-                UpdateStencilTestState();
+                UpdateStencilTestState(state);
             }
 
             // Pools.
-            if (_context.State.QueryModified(MethodOffset.SamplerPoolState))
+            if (state.QueryModified(MethodOffset.SamplerPoolState))
             {
-                UpdateSamplerPoolState();
+                UpdateSamplerPoolState(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.TexturePoolState))
+            if (state.QueryModified(MethodOffset.TexturePoolState))
             {
-                UpdateTexturePoolState();
+                UpdateTexturePoolState(state);
             }
 
             // Input assembler state.
-            if (_context.State.QueryModified(MethodOffset.VertexAttribState))
+            if (state.QueryModified(MethodOffset.VertexAttribState))
             {
-                UpdateVertexAttribState();
+                UpdateVertexAttribState(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.PrimitiveRestartState))
+            if (state.QueryModified(MethodOffset.PrimitiveRestartState))
             {
-                UpdatePrimitiveRestartState();
+                UpdatePrimitiveRestartState(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.IndexBufferState))
+            if (state.QueryModified(MethodOffset.IndexBufferState))
             {
-                UpdateIndexBufferState();
+                UpdateIndexBufferState(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.VertexBufferDrawState,
+            if (state.QueryModified(MethodOffset.VertexBufferDrawState,
                                              MethodOffset.VertexBufferInstanced,
                                              MethodOffset.VertexBufferState,
                                              MethodOffset.VertexBufferEndAddress))
             {
-                UpdateVertexBufferState();
+                UpdateVertexBufferState(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.FaceState))
+            if (state.QueryModified(MethodOffset.FaceState))
             {
-                UpdateFaceState();
+                UpdateFaceState(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.RtColorMask))
+            if (state.QueryModified(MethodOffset.RtColorMask))
             {
-                UpdateRtColorMask();
+                UpdateRtColorMask(state);
             }
 
-            if (_context.State.QueryModified(MethodOffset.BlendEnable, MethodOffset.BlendState))
+            if (state.QueryModified(MethodOffset.BlendEnable, MethodOffset.BlendState))
             {
-                UpdateBlendState();
+                UpdateBlendState(state);
             }
 
             CommitBindings();
@@ -210,27 +208,27 @@ namespace Ryujinx.Graphics.Gpu.Engine
             }
         }
 
-        private void UpdateRenderTargetStateIfNeeded()
+        private void UpdateRenderTargetStateIfNeeded(GpuState state)
         {
-            if (_context.State.QueryModified(MethodOffset.RtColorState,
+            if (state.QueryModified(MethodOffset.RtColorState,
                                              MethodOffset.RtDepthStencilState,
                                              MethodOffset.RtDepthStencilSize,
                                              MethodOffset.RtDepthStencilEnable))
             {
-                UpdateRenderTargetState();
+                UpdateRenderTargetState(state);
             }
         }
 
-        private void UpdateRenderTargetState()
+        private void UpdateRenderTargetState(GpuState state)
         {
-            var msaaMode = _context.State.Get<TextureMsaaMode>(MethodOffset.RtMsaaMode);
+            var msaaMode = state.Get<TextureMsaaMode>(MethodOffset.RtMsaaMode);
 
             int samplesInX = msaaMode.SamplesInX();
             int samplesInY = msaaMode.SamplesInY();
 
             for (int index = 0; index < Constants.TotalRenderTargets; index++)
             {
-                var colorState = _context.State.Get<RtColorState>(MethodOffset.RtColorState, index);
+                var colorState = state.Get<RtColorState>(MethodOffset.RtColorState, index);
 
                 if (!IsRtEnabled(colorState))
                 {
@@ -252,14 +250,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 }
             }
 
-            bool dsEnable = _context.State.Get<Boolean32>(MethodOffset.RtDepthStencilEnable);
+            bool dsEnable = state.Get<Boolean32>(MethodOffset.RtDepthStencilEnable);
 
             Image.Texture depthStencil = null;
 
             if (dsEnable)
             {
-                var dsState = _context.State.Get<RtDepthStencilState>(MethodOffset.RtDepthStencilState);
-                var dsSize  = _context.State.Get<Size3D>             (MethodOffset.RtDepthStencilSize);
+                var dsState = state.Get<RtDepthStencilState>(MethodOffset.RtDepthStencilState);
+                var dsSize  = state.Get<Size3D>             (MethodOffset.RtDepthStencilSize);
 
                 depthStencil = _textureManager.FindOrCreateTexture(
                     dsState,
@@ -282,22 +280,22 @@ namespace Ryujinx.Graphics.Gpu.Engine
             return colorState.Format != 0 && colorState.WidthOrStride != 0;
         }
 
-        private void UpdateDepthTestState()
+        private void UpdateDepthTestState(GpuState state)
         {
             _context.Renderer.Pipeline.SetDepthTest(new DepthTestDescriptor(
-                _context.State.Get<Boolean32>(MethodOffset.DepthTestEnable),
-                _context.State.Get<Boolean32>(MethodOffset.DepthWriteEnable),
-                _context.State.Get<CompareOp>(MethodOffset.DepthTestFunc)));
+                state.Get<Boolean32>(MethodOffset.DepthTestEnable),
+                state.Get<Boolean32>(MethodOffset.DepthWriteEnable),
+                state.Get<CompareOp>(MethodOffset.DepthTestFunc)));
         }
 
-        private void UpdateViewportTransform()
+        private void UpdateViewportTransform(GpuState state)
         {
             Viewport[] viewports = new Viewport[Constants.TotalViewports];
 
             for (int index = 0; index < Constants.TotalViewports; index++)
             {
-                var transform = _context.State.Get<ViewportTransform>(MethodOffset.ViewportTransform, index);
-                var extents   = _context.State.Get<ViewportExtents>  (MethodOffset.ViewportExtents,   index);
+                var transform = state.Get<ViewportTransform>(MethodOffset.ViewportTransform, index);
+                var extents   = state.Get<ViewportExtents>  (MethodOffset.ViewportExtents,   index);
 
                 float x = transform.TranslateX - MathF.Abs(transform.ScaleX);
                 float y = transform.TranslateY - MathF.Abs(transform.ScaleY);
@@ -320,13 +318,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
             _context.Renderer.Pipeline.SetViewports(0, viewports);
         }
 
-        private void UpdateDepthBiasState()
+        private void UpdateDepthBiasState(GpuState state)
         {
-            var depthBias = _context.State.Get<DepthBiasState>(MethodOffset.DepthBiasState);
+            var depthBias = state.Get<DepthBiasState>(MethodOffset.DepthBiasState);
 
-            float factor = _context.State.Get<float>(MethodOffset.DepthBiasFactor);
-            float units  = _context.State.Get<float>(MethodOffset.DepthBiasUnits);
-            float clamp  = _context.State.Get<float>(MethodOffset.DepthBiasClamp);
+            float factor = state.Get<float>(MethodOffset.DepthBiasFactor);
+            float units  = state.Get<float>(MethodOffset.DepthBiasUnits);
+            float clamp  = state.Get<float>(MethodOffset.DepthBiasClamp);
 
             PolygonModeMask enables = 0;
 
@@ -337,11 +335,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
             _context.Renderer.Pipeline.SetDepthBias(enables, factor, units, clamp);
         }
 
-        private void UpdateStencilTestState()
+        private void UpdateStencilTestState(GpuState state)
         {
-            var backMasks = _context.State.Get<StencilBackMasks>    (MethodOffset.StencilBackMasks);
-            var test      = _context.State.Get<StencilTestState>    (MethodOffset.StencilTestState);
-            var backTest  = _context.State.Get<StencilBackTestState>(MethodOffset.StencilBackTestState);
+            var backMasks = state.Get<StencilBackMasks>    (MethodOffset.StencilBackMasks);
+            var test      = state.Get<StencilTestState>    (MethodOffset.StencilTestState);
+            var backTest  = state.Get<StencilBackTestState>(MethodOffset.StencilBackTestState);
 
             CompareOp backFunc;
             StencilOp backSFail;
@@ -390,29 +388,29 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 backMask));
         }
 
-        private void UpdateSamplerPoolState()
+        private void UpdateSamplerPoolState(GpuState state)
         {
-            var samplerPool = _context.State.Get<PoolState>(MethodOffset.SamplerPoolState);
+            var samplerPool = state.Get<PoolState>(MethodOffset.SamplerPoolState);
 
             _textureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId);
         }
 
-        private void UpdateTexturePoolState()
+        private void UpdateTexturePoolState(GpuState state)
         {
-            var texturePool = _context.State.Get<PoolState>(MethodOffset.TexturePoolState);
+            var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
 
             _textureManager.SetGraphicsTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
 
-            _textureManager.SetGraphicsTextureBufferIndex(_context.State.Get<int>(MethodOffset.TextureBufferIndex));
+            _textureManager.SetGraphicsTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
         }
 
-        private void UpdateVertexAttribState()
+        private void UpdateVertexAttribState(GpuState state)
         {
             VertexAttribDescriptor[] vertexAttribs = new VertexAttribDescriptor[16];
 
             for (int index = 0; index < 16; index++)
             {
-                var vertexAttrib = _context.State.Get<VertexAttribState>(MethodOffset.VertexAttribState, index);
+                var vertexAttrib = state.Get<VertexAttribState>(MethodOffset.VertexAttribState, index);
 
                 if (!FormatTable.TryGetAttribFormat(vertexAttrib.UnpackFormat(), out Format format))
                 {
@@ -430,18 +428,18 @@ namespace Ryujinx.Graphics.Gpu.Engine
             _context.Renderer.Pipeline.BindVertexAttribs(vertexAttribs);
         }
 
-        private void UpdatePrimitiveRestartState()
+        private void UpdatePrimitiveRestartState(GpuState state)
         {
-            PrimitiveRestartState primitiveRestart = _context.State.Get<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState);
+            PrimitiveRestartState primitiveRestart = state.Get<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState);
 
             _context.Renderer.Pipeline.SetPrimitiveRestart(
                 primitiveRestart.Enable,
                 primitiveRestart.Index);
         }
 
-        private void UpdateIndexBufferState()
+        private void UpdateIndexBufferState(GpuState state)
         {
-            var indexBuffer = _context.State.Get<IndexBufferState>(MethodOffset.IndexBufferState);
+            var indexBuffer = state.Get<IndexBufferState>(MethodOffset.IndexBufferState);
 
             _firstIndex = indexBuffer.First;
             _indexCount = indexBuffer.Count;
@@ -467,16 +465,16 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             // The index buffer affects the vertex buffer size calculation, we
             // need to ensure that they are updated.
-            UpdateVertexBufferState();
+            UpdateVertexBufferState(state);
         }
 
-        private void UpdateVertexBufferState()
+        private void UpdateVertexBufferState(GpuState state)
         {
             _isAnyVbInstanced = false;
 
             for (int index = 0; index < 16; index++)
             {
-                var vertexBuffer = _context.State.Get<VertexBufferState>(MethodOffset.VertexBufferState, index);
+                var vertexBuffer = state.Get<VertexBufferState>(MethodOffset.VertexBufferState, index);
 
                 if (!vertexBuffer.UnpackEnable())
                 {
@@ -485,13 +483,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
                     continue;
                 }
 
-                GpuVa endAddress = _context.State.Get<GpuVa>(MethodOffset.VertexBufferEndAddress, index);
+                GpuVa endAddress = state.Get<GpuVa>(MethodOffset.VertexBufferEndAddress, index);
 
                 ulong address = vertexBuffer.Address.Pack();
 
                 int stride = vertexBuffer.UnpackStride();
 
-                bool instanced = _context.State.Get<Boolean32>(MethodOffset.VertexBufferInstanced + index);
+                bool instanced = state.Get<Boolean32>(MethodOffset.VertexBufferInstanced + index);
 
                 int divisor = instanced ? vertexBuffer.Divisor : 0;
 
@@ -509,9 +507,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 {
                     // For non-indexed draws, we can guess the size from the vertex count
                     // and stride.
-                    int firstInstance = _context.State.Get<int>(MethodOffset.FirstInstance);
+                    int firstInstance = state.Get<int>(MethodOffset.FirstInstance);
 
-                    var drawState = _context.State.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
+                    var drawState = state.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
 
                     size = (ulong)((firstInstance + drawState.First + drawState.Count) * stride);
                 }
@@ -520,22 +518,22 @@ namespace Ryujinx.Graphics.Gpu.Engine
             }
         }
 
-        private void UpdateFaceState()
+        private void UpdateFaceState(GpuState state)
         {
-            var face = _context.State.Get<FaceState>(MethodOffset.FaceState);
+            var face = state.Get<FaceState>(MethodOffset.FaceState);
 
             _context.Renderer.Pipeline.SetFaceCulling(face.CullEnable, face.CullFace);
 
             _context.Renderer.Pipeline.SetFrontFace(face.FrontFace);
         }
 
-        private void UpdateRtColorMask()
+        private void UpdateRtColorMask(GpuState state)
         {
             uint[] componentMasks = new uint[Constants.TotalRenderTargets];
 
             for (int index = 0; index < Constants.TotalRenderTargets; index++)
             {
-                var colorMask = _context.State.Get<RtColorMask>(MethodOffset.RtColorMask, index);
+                var colorMask = state.Get<RtColorMask>(MethodOffset.RtColorMask, index);
 
                 uint componentMask = 0;
 
@@ -550,15 +548,15 @@ namespace Ryujinx.Graphics.Gpu.Engine
             _context.Renderer.Pipeline.SetRenderTargetColorMasks(componentMasks);
         }
 
-        private void UpdateBlendState()
+        private void UpdateBlendState(GpuState state)
         {
             BlendState[] blends = new BlendState[8];
 
             for (int index = 0; index < 8; index++)
             {
-                bool enable = _context.State.Get<Boolean32>(MethodOffset.BlendEnable, index);
+                bool enable = state.Get<Boolean32>(MethodOffset.BlendEnable, index);
 
-                var blend = _context.State.Get<BlendState>(MethodOffset.BlendState, index);
+                var blend = state.Get<BlendState>(MethodOffset.BlendState, index);
 
                 BlendDescriptor descriptor = new BlendDescriptor(
                     enable,
@@ -586,7 +584,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
             }
         }
 
-        private void UpdateShaderState()
+        private void UpdateShaderState(GpuState state)
         {
             ShaderAddresses addresses = new ShaderAddresses();
 
@@ -594,11 +592,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             Span<ulong> addressesArray = MemoryMarshal.Cast<ShaderAddresses, ulong>(addressesSpan);
 
-            ulong baseAddress = _context.State.Get<GpuVa>(MethodOffset.ShaderBaseAddress).Pack();
+            ulong baseAddress = state.Get<GpuVa>(MethodOffset.ShaderBaseAddress).Pack();
 
             for (int index = 0; index < 6; index++)
             {
-                var shader = _context.State.Get<ShaderState>(MethodOffset.ShaderState, index);
+                var shader = state.Get<ShaderState>(MethodOffset.ShaderState, index);
 
                 if (!shader.UnpackEnable() && index != 1)
                 {
@@ -711,17 +709,17 @@ namespace Ryujinx.Graphics.Gpu.Engine
             return Target.Texture2D;
         }
 
-        private void TextureBarrier(int argument)
+        private void TextureBarrier(GpuState state, int argument)
         {
             _context.Renderer.Pipeline.TextureBarrier();
         }
 
-        private void InvalidateTextures(int argument)
+        private void InvalidateTextures(GpuState state, int argument)
         {
             _textureManager.Flush();
         }
 
-        private void TextureBarrierTiled(int argument)
+        private void TextureBarrierTiled(GpuState state, int argument)
         {
             _context.Renderer.Pipeline.TextureBarrierTiled();
         }
diff --git a/Ryujinx.Graphics.Gpu/GpuContext.cs b/Ryujinx.Graphics.Gpu/GpuContext.cs
index 1e865e6a72..b52e4e497a 100644
--- a/Ryujinx.Graphics.Gpu/GpuContext.cs
+++ b/Ryujinx.Graphics.Gpu/GpuContext.cs
@@ -12,8 +12,6 @@ namespace Ryujinx.Graphics.Gpu
     {
         public IRenderer Renderer { get; }
 
-        internal GpuState State { get; }
-
         internal IPhysicalMemory PhysicalMemory { get; private set; }
 
         public MemoryManager MemoryManager { get; }
@@ -36,8 +34,6 @@ namespace Ryujinx.Graphics.Gpu
         {
             Renderer = renderer;
 
-            State = new GpuState();
-
             MemoryManager = new MemoryManager();
 
             MemoryAccessor = new MemoryAccessor(this);
diff --git a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs
index 93d5c2ca2e..e424b8ffa9 100644
--- a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs
+++ b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs
@@ -1,4 +1,5 @@
 using Ryujinx.Common.Logging;
+using Ryujinx.Graphics.Gpu.State;
 using System;
 using System.Collections.Generic;
 
@@ -70,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu
             _gprs = new int[8];
         }
 
-        public void Execute(int[] mme, int position, int param)
+        public void Execute(int[] mme, int position, int param, GpuState state)
         {
             Reset();
 
@@ -80,11 +81,11 @@ namespace Ryujinx.Graphics.Gpu
 
             FetchOpCode(mme);
 
-            while (Step(mme));
+            while (Step(mme, state));
 
             // Due to the delay slot, we still need to execute
             // one more instruction before we actually exit.
-            Step(mme);
+            Step(mme, state);
         }
 
         private void Reset()
@@ -100,7 +101,7 @@ namespace Ryujinx.Graphics.Gpu
             _carry = false;
         }
 
-        private bool Step(int[] mme)
+        private bool Step(int[] mme, GpuState state)
         {
             int baseAddr = _pc - 1;
 
@@ -111,7 +112,7 @@ namespace Ryujinx.Graphics.Gpu
                 // Operation produces a value.
                 AssignmentOperation asgOp = (AssignmentOperation)((_opCode >> 4) & 7);
 
-                int result = GetAluResult();
+                int result = GetAluResult(state);
 
                 switch (asgOp)
                 {
@@ -146,7 +147,7 @@ namespace Ryujinx.Graphics.Gpu
                     {
                         SetDstGpr(FetchParam());
 
-                        Send(result);
+                        Send(state, result);
 
                         break;
                     }
@@ -156,7 +157,7 @@ namespace Ryujinx.Graphics.Gpu
                     {
                         SetDstGpr(result);
 
-                        Send(result);
+                        Send(state, result);
 
                         break;
                     }
@@ -178,7 +179,7 @@ namespace Ryujinx.Graphics.Gpu
 
                         SetMethAddr(result);
 
-                        Send(FetchParam());
+                        Send(state, FetchParam());
 
                         break;
                     }
@@ -190,7 +191,7 @@ namespace Ryujinx.Graphics.Gpu
 
                         SetMethAddr(result);
 
-                        Send((result >> 12) & 0x3f);
+                        Send(state, (result >> 12) & 0x3f);
 
                         break;
                     }
@@ -231,7 +232,7 @@ namespace Ryujinx.Graphics.Gpu
             _pipeOp = mme[_pc++];
         }
 
-        private int GetAluResult()
+        private int GetAluResult(GpuState state)
         {
             AluOperation op = (AluOperation)(_opCode & 7);
 
@@ -295,7 +296,7 @@ namespace Ryujinx.Graphics.Gpu
 
                 case AluOperation.ReadImmediate:
                 {
-                    return Read(GetGprA() + GetImm());
+                    return Read(state, GetGprA() + GetImm());
                 }
             }
 
@@ -398,16 +399,16 @@ namespace Ryujinx.Graphics.Gpu
             return value;
         }
 
-        private int Read(int reg)
+        private int Read(GpuState state, int reg)
         {
-            return _context.State.Read(reg);
+            return state.Read(reg);
         }
 
-        private void Send(int value)
+        private void Send(GpuState state, int value)
         {
             MethodParams meth = new MethodParams(_methAddr, value);
 
-            _context.State.CallMethod(meth);
+            state.CallMethod(meth);
 
             _methAddr += _methIncr;
         }
diff --git a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
index f4deea54dc..64947bf63f 100644
--- a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
+++ b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
@@ -1,3 +1,5 @@
+using Ryujinx.Graphics.Gpu.State;
+
 namespace Ryujinx.Graphics.Gpu
 {
     class NvGpuFifo
@@ -37,13 +39,13 @@ namespace Ryujinx.Graphics.Gpu
                 _executionPending = true;
             }
 
-            public void Execute(int[] mme)
+            public void Execute(int[] mme, GpuState state)
             {
                 if (_executionPending)
                 {
                     _executionPending = false;
 
-                    _interpreter?.Execute(mme, Position, _argument);
+                    _interpreter?.Execute(mme, Position, _argument, state);
                 }
             }
 
@@ -60,7 +62,18 @@ namespace Ryujinx.Graphics.Gpu
 
         private int[] _mme;
 
-        private ClassId[] _subChannels;
+        private class SubChannel
+        {
+            public GpuState State { get; }
+            public ClassId  Class { get; set; }
+
+            public SubChannel()
+            {
+                State = new GpuState();
+            }
+        }
+
+        private SubChannel[] _subChannels;
 
         public NvGpuFifo(GpuContext context)
         {
@@ -70,14 +83,21 @@ namespace Ryujinx.Graphics.Gpu
 
             _mme = new int[MmeWords];
 
-            _subChannels = new ClassId[8];
+            _subChannels = new SubChannel[8];
+
+            for (int index = 0; index < _subChannels.Length; index++)
+            {
+                _subChannels[index] = new SubChannel();
+
+                context.Methods.RegisterCallbacks(_subChannels[index].State);
+            }
         }
 
         public void CallMethod(MethodParams meth)
         {
             if ((NvGpuFifoMeth)meth.Method == NvGpuFifoMeth.BindChannel)
             {
-                _subChannels[meth.SubChannel] = (ClassId)meth.Argument;
+                _subChannels[meth.SubChannel].Class = (ClassId)meth.Argument;
             }
             else if (meth.Method < 0x60)
             {
@@ -123,7 +143,7 @@ namespace Ryujinx.Graphics.Gpu
             }
             else if (meth.Method < 0xe00)
             {
-                _context.State.CallMethod(meth);
+                _subChannels[meth.SubChannel].State.CallMethod(meth);
             }
             else
             {
@@ -140,7 +160,7 @@ namespace Ryujinx.Graphics.Gpu
 
                 if (meth.IsLastCall)
                 {
-                    _macros[macroIndex].Execute(_mme);
+                    _macros[macroIndex].Execute(_mme, _subChannels[meth.SubChannel].State);
 
                     _context.Methods.PerformDeferredDraws();
                 }
diff --git a/Ryujinx.Graphics.Gpu/State/GpuState.cs b/Ryujinx.Graphics.Gpu/State/GpuState.cs
index 6c603f306d..ecbaa00459 100644
--- a/Ryujinx.Graphics.Gpu/State/GpuState.cs
+++ b/Ryujinx.Graphics.Gpu/State/GpuState.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.Gpu.State
     {
         private const int RegistersCount = 0xe00;
 
-        public delegate void MethodCallback(int argument);
+        public delegate void MethodCallback(GpuState state, int argument);
 
         private int[] _backingMemory;
 
@@ -71,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu.State
 
             if (callback != null)
             {
-                callback(meth.Argument);
+                callback(this, meth.Argument);
             }
         }