aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.GAL/Multithreading/Commands
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.GAL/Multithreading/Commands')
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/BarrierCommand.cs12
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/BeginTransformFeedbackCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferDisposeCommand.cs19
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs29
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferSetDataCommand.cs27
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/ClearBufferCommand.cs24
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetColorCommand.cs22
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetDepthStencilCommand.cs24
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/CommandBufferBarrierCommand.cs12
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/CopyBufferCommand.cs26
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventDisposeCommand.cs21
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventFlushCommand.cs21
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/DispatchComputeCommand.cs22
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/DrawCommand.cs26
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedCommand.cs24
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/EndHostConditionalRenderingCommand.cs12
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/EndTransformFeedbackCommand.cs12
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/IGALCommand.cs7
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/MultiDrawIndexedIndirectCountCommand.cs29
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/MultiDrawIndirectCountCommand.cs29
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramCheckLinkCommand.cs27
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramDisposeCommand.cs21
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramGetBinaryCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ActionCommand.cs21
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CompileShaderCommand.cs22
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateProgramCommand.cs28
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSamplerCommand.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSyncCommand.cs20
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateTextureCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/GetCapabilitiesCommand.cs20
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/PreFrameCommand.cs14
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ReportCounterCommand.cs30
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ResetCounterCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/UpdateCountersCommand.cs12
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Sampler/SamplerDisposeCommand.cs21
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetAlphaTestCommand.cs22
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateCommand.cs20
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthBiasCommand.cs24
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthClampCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthModeCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthTestCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs20
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetFrontFaceCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetIndexBufferCommand.cs21
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetLineParametersCommand.cs20
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetLogicOpStateCommand.cs20
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetPointParametersCommand.cs24
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveRestartCommand.cs20
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveTopologyCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetProgramCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetRasterizerDiscardCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetColorMasksCommand.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetScaleCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetsCommand.cs24
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetSamplerCommand.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetScissorCommand.cs28
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetStencilTestCommand.cs18
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetTextureCommand.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetTransformFeedbackBuffersCommand.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetUserClipDistanceCommand.cs20
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexAttribsCommand.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexBuffersCommand.cs24
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/SetViewportsCommand.cs26
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Shader/ShaderDisposeCommand.cs21
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToCommand.cs28
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToScaledCommand.cs30
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToSliceCommand.cs32
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCreateViewCommand.cs30
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs26
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureReleaseCommand.cs21
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs29
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetStorageCommand.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierCommand.cs12
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierTiledCommand.cs12
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingFlushCommand.cs25
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs28
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Window/WindowPresentCommand.cs27
83 files changed, 1832 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/BarrierCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/BarrierCommand.cs
new file mode 100644
index 00000000..f187c3c2
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/BarrierCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct BarrierCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.Barrier;
+
+ public static void Run(ref BarrierCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.Barrier();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/BeginTransformFeedbackCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/BeginTransformFeedbackCommand.cs
new file mode 100644
index 00000000..ea547d8b
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/BeginTransformFeedbackCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct BeginTransformFeedbackCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.BeginTransformFeedback;
+ private PrimitiveTopology _topology;
+
+ public void Set(PrimitiveTopology topology)
+ {
+ _topology = topology;
+ }
+
+ public static void Run(ref BeginTransformFeedbackCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.BeginTransformFeedback(command._topology);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferDisposeCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferDisposeCommand.cs
new file mode 100644
index 00000000..68167be0
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferDisposeCommand.cs
@@ -0,0 +1,19 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer
+{
+ struct BufferDisposeCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.BufferDispose;
+ private BufferHandle _buffer;
+
+ public void Set(BufferHandle buffer)
+ {
+ _buffer = buffer;
+ }
+
+ public static void Run(ref BufferDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.DeleteBuffer(threaded.Buffers.MapBuffer(command._buffer));
+ threaded.Buffers.UnassignBuffer(command._buffer);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs
new file mode 100644
index 00000000..786ed87c
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs
@@ -0,0 +1,29 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer
+{
+ struct BufferGetDataCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.BufferGetData;
+ private BufferHandle _buffer;
+ private int _offset;
+ private int _size;
+ private TableRef<ResultBox<PinnedSpan<byte>>> _result;
+
+ public void Set(BufferHandle buffer, int offset, int size, TableRef<ResultBox<PinnedSpan<byte>>> result)
+ {
+ _buffer = buffer;
+ _offset = offset;
+ _size = size;
+ _result = result;
+ }
+
+ public static void Run(ref BufferGetDataCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ReadOnlySpan<byte> result = renderer.GetBufferData(threaded.Buffers.MapBuffer(command._buffer), command._offset, command._size);
+
+ command._result.Get(threaded).Result = new PinnedSpan<byte>(result);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferSetDataCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferSetDataCommand.cs
new file mode 100644
index 00000000..6f39898e
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferSetDataCommand.cs
@@ -0,0 +1,27 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer
+{
+ struct BufferSetDataCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.BufferSetData;
+ private BufferHandle _buffer;
+ private int _offset;
+ private SpanRef<byte> _data;
+
+ public void Set(BufferHandle buffer, int offset, SpanRef<byte> data)
+ {
+ _buffer = buffer;
+ _offset = offset;
+ _data = data;
+ }
+
+ public static void Run(ref BufferSetDataCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ReadOnlySpan<byte> data = command._data.Get(threaded);
+ renderer.SetBufferData(threaded.Buffers.MapBuffer(command._buffer), command._offset, data);
+ command._data.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearBufferCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearBufferCommand.cs
new file mode 100644
index 00000000..2b194b46
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearBufferCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct ClearBufferCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ClearBuffer;
+ private BufferHandle _destination;
+ private int _offset;
+ private int _size;
+ private uint _value;
+
+ public void Set(BufferHandle destination, int offset, int size, uint value)
+ {
+ _destination = destination;
+ _offset = offset;
+ _size = size;
+ _value = value;
+ }
+
+ public static void Run(ref ClearBufferCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.ClearBuffer(threaded.Buffers.MapBuffer(command._destination), command._offset, command._size, command._value);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetColorCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetColorCommand.cs
new file mode 100644
index 00000000..57509f1c
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetColorCommand.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct ClearRenderTargetColorCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ClearRenderTargetColor;
+ private int _index;
+ private uint _componentMask;
+ private ColorF _color;
+
+ public void Set(int index, uint componentMask, ColorF color)
+ {
+ _index = index;
+ _componentMask = componentMask;
+ _color = color;
+ }
+
+ public static void Run(ref ClearRenderTargetColorCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.ClearRenderTargetColor(command._index, command._componentMask, command._color);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetDepthStencilCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetDepthStencilCommand.cs
new file mode 100644
index 00000000..3692cd37
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetDepthStencilCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct ClearRenderTargetDepthStencilCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ClearRenderTargetDepthStencil;
+ private float _depthValue;
+ private bool _depthMask;
+ private int _stencilValue;
+ private int _stencilMask;
+
+ public void Set(float depthValue, bool depthMask, int stencilValue, int stencilMask)
+ {
+ _depthValue = depthValue;
+ _depthMask = depthMask;
+ _stencilValue = stencilValue;
+ _stencilMask = stencilMask;
+ }
+
+ public static void Run(ref ClearRenderTargetDepthStencilCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.ClearRenderTargetDepthStencil(command._depthValue, command._depthMask, command._stencilValue, command._stencilMask);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/CommandBufferBarrierCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/CommandBufferBarrierCommand.cs
new file mode 100644
index 00000000..8c828648
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/CommandBufferBarrierCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct CommandBufferBarrierCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CommandBufferBarrier;
+
+ public static void Run(ref CommandBufferBarrierCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.CommandBufferBarrier();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/CopyBufferCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/CopyBufferCommand.cs
new file mode 100644
index 00000000..e8f80d98
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/CopyBufferCommand.cs
@@ -0,0 +1,26 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct CopyBufferCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CopyBuffer;
+ private BufferHandle _source;
+ private BufferHandle _destination;
+ private int _srcOffset;
+ private int _dstOffset;
+ private int _size;
+
+ public void Set(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
+ {
+ _source = source;
+ _destination = destination;
+ _srcOffset = srcOffset;
+ _dstOffset = dstOffset;
+ _size = size;
+ }
+
+ public static void Run(ref CopyBufferCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.CopyBuffer(threaded.Buffers.MapBuffer(command._source), threaded.Buffers.MapBuffer(command._destination), command._srcOffset, command._dstOffset, command._size);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventDisposeCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventDisposeCommand.cs
new file mode 100644
index 00000000..ae634e6a
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventDisposeCommand.cs
@@ -0,0 +1,21 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.CounterEvent
+{
+ struct CounterEventDisposeCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CounterEventDispose;
+ private TableRef<ThreadedCounterEvent> _event;
+
+ public void Set(TableRef<ThreadedCounterEvent> evt)
+ {
+ _event = evt;
+ }
+
+ public static void Run(ref CounterEventDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._event.Get(threaded).Base.Dispose();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventFlushCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventFlushCommand.cs
new file mode 100644
index 00000000..e4ff4c18
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventFlushCommand.cs
@@ -0,0 +1,21 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.CounterEvent
+{
+ struct CounterEventFlushCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CounterEventFlush;
+ private TableRef<ThreadedCounterEvent> _event;
+
+ public void Set(TableRef<ThreadedCounterEvent> evt)
+ {
+ _event = evt;
+ }
+
+ public static void Run(ref CounterEventFlushCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._event.Get(threaded).Base.Flush();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/DispatchComputeCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/DispatchComputeCommand.cs
new file mode 100644
index 00000000..26c88062
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/DispatchComputeCommand.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DispatchComputeCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.DispatchCompute;
+ private int _groupsX;
+ private int _groupsY;
+ private int _groupsZ;
+
+ public void Set(int groupsX, int groupsY, int groupsZ)
+ {
+ _groupsX = groupsX;
+ _groupsY = groupsY;
+ _groupsZ = groupsZ;
+ }
+
+ public static void Run(ref DispatchComputeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.DispatchCompute(command._groupsX, command._groupsY, command._groupsZ);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawCommand.cs
new file mode 100644
index 00000000..ff27303a
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawCommand.cs
@@ -0,0 +1,26 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawIndexedCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.DrawIndexed;
+ private int _indexCount;
+ private int _instanceCount;
+ private int _firstIndex;
+ private int _firstVertex;
+ private int _firstInstance;
+
+ public void Set(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance)
+ {
+ _indexCount = indexCount;
+ _instanceCount = instanceCount;
+ _firstIndex = firstIndex;
+ _firstVertex = firstVertex;
+ _firstInstance = firstInstance;
+ }
+
+ public static void Run(ref DrawIndexedCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.DrawIndexed(command._indexCount, command._instanceCount, command._firstIndex, command._firstVertex, command._firstInstance);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedCommand.cs
new file mode 100644
index 00000000..fc84819a
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.Draw;
+ private int _vertexCount;
+ private int _instanceCount;
+ private int _firstVertex;
+ private int _firstInstance;
+
+ public void Set(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
+ {
+ _vertexCount = vertexCount;
+ _instanceCount = instanceCount;
+ _firstVertex = firstVertex;
+ _firstInstance = firstInstance;
+ }
+
+ public static void Run(ref DrawCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.Draw(command._vertexCount, command._instanceCount, command._firstVertex, command._firstInstance);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/EndHostConditionalRenderingCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/EndHostConditionalRenderingCommand.cs
new file mode 100644
index 00000000..e0edd9ab
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/EndHostConditionalRenderingCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct EndHostConditionalRenderingCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.EndHostConditionalRendering;
+
+ public static void Run(IRenderer renderer)
+ {
+ renderer.Pipeline.EndHostConditionalRendering();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/EndTransformFeedbackCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/EndTransformFeedbackCommand.cs
new file mode 100644
index 00000000..561996e3
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/EndTransformFeedbackCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct EndTransformFeedbackCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.EndTransformFeedback;
+
+ public static void Run(ref EndTransformFeedbackCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.EndTransformFeedback();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/IGALCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/IGALCommand.cs
new file mode 100644
index 00000000..5fb04c80
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/IGALCommand.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ interface IGALCommand
+ {
+ CommandType CommandType { get; }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/MultiDrawIndexedIndirectCountCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/MultiDrawIndexedIndirectCountCommand.cs
new file mode 100644
index 00000000..6798f8cc
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/MultiDrawIndexedIndirectCountCommand.cs
@@ -0,0 +1,29 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct MultiDrawIndexedIndirectCountCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.MultiDrawIndexedIndirectCount;
+ private BufferRange _indirectBuffer;
+ private BufferRange _parameterBuffer;
+ private int _maxDrawCount;
+ private int _stride;
+
+ public void Set(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
+ {
+ _indirectBuffer = indirectBuffer;
+ _parameterBuffer = parameterBuffer;
+ _maxDrawCount = maxDrawCount;
+ _stride = stride;
+ }
+
+ public static void Run(ref MultiDrawIndexedIndirectCountCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.MultiDrawIndexedIndirectCount(
+ threaded.Buffers.MapBufferRange(command._indirectBuffer),
+ threaded.Buffers.MapBufferRange(command._parameterBuffer),
+ command._maxDrawCount,
+ command._stride
+ );
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/MultiDrawIndirectCountCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/MultiDrawIndirectCountCommand.cs
new file mode 100644
index 00000000..7a9d07f3
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/MultiDrawIndirectCountCommand.cs
@@ -0,0 +1,29 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct MultiDrawIndirectCountCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.MultiDrawIndirectCount;
+ private BufferRange _indirectBuffer;
+ private BufferRange _parameterBuffer;
+ private int _maxDrawCount;
+ private int _stride;
+
+ public void Set(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
+ {
+ _indirectBuffer = indirectBuffer;
+ _parameterBuffer = parameterBuffer;
+ _maxDrawCount = maxDrawCount;
+ _stride = stride;
+ }
+
+ public static void Run(ref MultiDrawIndirectCountCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.MultiDrawIndirectCount(
+ threaded.Buffers.MapBufferRange(command._indirectBuffer),
+ threaded.Buffers.MapBufferRange(command._parameterBuffer),
+ command._maxDrawCount,
+ command._stride
+ );
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramCheckLinkCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramCheckLinkCommand.cs
new file mode 100644
index 00000000..7ae887f4
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramCheckLinkCommand.cs
@@ -0,0 +1,27 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Program
+{
+ struct ProgramCheckLinkCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ProgramCheckLink;
+ private TableRef<ThreadedProgram> _program;
+ private bool _blocking;
+ private TableRef<ResultBox<ProgramLinkStatus>> _result;
+
+ public void Set(TableRef<ThreadedProgram> program, bool blocking, TableRef<ResultBox<ProgramLinkStatus>> result)
+ {
+ _program = program;
+ _blocking = blocking;
+ _result = result;
+ }
+
+ public static void Run(ref ProgramCheckLinkCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ProgramLinkStatus result = command._program.Get(threaded).Base.CheckProgramLink(command._blocking);
+
+ command._result.Get(threaded).Result = result;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramDisposeCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramDisposeCommand.cs
new file mode 100644
index 00000000..e614c392
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramDisposeCommand.cs
@@ -0,0 +1,21 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Program
+{
+ struct ProgramDisposeCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ProgramDispose;
+ private TableRef<ThreadedProgram> _program;
+
+ public void Set(TableRef<ThreadedProgram> program)
+ {
+ _program = program;
+ }
+
+ public static void Run(ref ProgramDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._program.Get(threaded).Base.Dispose();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramGetBinaryCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramGetBinaryCommand.cs
new file mode 100644
index 00000000..92c0a6d6
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramGetBinaryCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Program
+{
+ struct ProgramGetBinaryCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ProgramGetBinary;
+ private TableRef<ThreadedProgram> _program;
+ private TableRef<ResultBox<byte[]>> _result;
+
+ public void Set(TableRef<ThreadedProgram> program, TableRef<ResultBox<byte[]>> result)
+ {
+ _program = program;
+ _result = result;
+ }
+
+ public static void Run(ref ProgramGetBinaryCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ byte[] result = command._program.Get(threaded).Base.GetBinary();
+
+ command._result.Get(threaded).Result = result;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ActionCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ActionCommand.cs
new file mode 100644
index 00000000..07e55c96
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ActionCommand.cs
@@ -0,0 +1,21 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct ActionCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.Action;
+ private TableRef<Action> _action;
+
+ public void Set(TableRef<Action> action)
+ {
+ _action = action;
+ }
+
+ public static void Run(ref ActionCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._action.Get(threaded)();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CompileShaderCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CompileShaderCommand.cs
new file mode 100644
index 00000000..2bd9725d
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CompileShaderCommand.cs
@@ -0,0 +1,22 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct CompileShaderCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CompileShader;
+ private TableRef<ThreadedShader> _shader;
+
+ public void Set(TableRef<ThreadedShader> shader)
+ {
+ _shader = shader;
+ }
+
+ public static void Run(ref CompileShaderCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedShader shader = command._shader.Get(threaded);
+ shader.EnsureCreated();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs
new file mode 100644
index 00000000..4d1cbb28
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+using Ryujinx.Graphics.Shader;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct CreateBufferCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateBuffer;
+ private BufferHandle _threadedHandle;
+ private int _size;
+
+ public void Set(BufferHandle threadedHandle, int size)
+ {
+ _threadedHandle = threadedHandle;
+ _size = size;
+ }
+
+ public static void Run(ref CreateBufferCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ threaded.Buffers.AssignBuffer(command._threadedHandle, renderer.CreateBuffer(command._size));
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateProgramCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateProgramCommand.cs
new file mode 100644
index 00000000..e24505e5
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateProgramCommand.cs
@@ -0,0 +1,28 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources.Programs;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct CreateProgramCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateProgram;
+ private TableRef<IProgramRequest> _request;
+
+ public void Set(TableRef<IProgramRequest> request)
+ {
+ _request = request;
+ }
+
+ public static void Run(ref CreateProgramCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ IProgramRequest request = command._request.Get(threaded);
+
+ if (request.Threaded.Base == null)
+ {
+ request.Threaded.Base = request.Create(renderer);
+ }
+
+ threaded.Programs.ProcessQueue();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSamplerCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSamplerCommand.cs
new file mode 100644
index 00000000..bca98cfb
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSamplerCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct CreateSamplerCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateSampler;
+ private TableRef<ThreadedSampler> _sampler;
+ private SamplerCreateInfo _info;
+
+ public void Set(TableRef<ThreadedSampler> sampler, SamplerCreateInfo info)
+ {
+ _sampler = sampler;
+ _info = info;
+ }
+
+ public static void Run(ref CreateSamplerCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._sampler.Get(threaded).Base = renderer.CreateSampler(command._info);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSyncCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSyncCommand.cs
new file mode 100644
index 00000000..2e23760e
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSyncCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct CreateSyncCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateSync;
+ private ulong _id;
+
+ public void Set(ulong id)
+ {
+ _id = id;
+ }
+
+ public static void Run(ref CreateSyncCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.CreateSync(command._id);
+
+ threaded.Sync.AssignSync(command._id);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateTextureCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateTextureCommand.cs
new file mode 100644
index 00000000..f9240125
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateTextureCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct CreateTextureCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateTexture;
+ private TableRef<ThreadedTexture> _texture;
+ private TextureCreateInfo _info;
+ private float _scale;
+
+ public void Set(TableRef<ThreadedTexture> texture, TextureCreateInfo info, float scale)
+ {
+ _texture = texture;
+ _info = info;
+ _scale = scale;
+ }
+
+ public static void Run(ref CreateTextureCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._texture.Get(threaded).Base = renderer.CreateTexture(command._info, command._scale);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/GetCapabilitiesCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/GetCapabilitiesCommand.cs
new file mode 100644
index 00000000..102ed9da
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/GetCapabilitiesCommand.cs
@@ -0,0 +1,20 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct GetCapabilitiesCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.GetCapabilities;
+ private TableRef<ResultBox<Capabilities>> _result;
+
+ public void Set(TableRef<ResultBox<Capabilities>> result)
+ {
+ _result = result;
+ }
+
+ public static void Run(ref GetCapabilitiesCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._result.Get(threaded).Result = renderer.GetCapabilities();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/PreFrameCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/PreFrameCommand.cs
new file mode 100644
index 00000000..67cafd18
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/PreFrameCommand.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct PreFrameCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.PreFrame;
+
+ public static void Run(ref PreFrameCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.PreFrame();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ReportCounterCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ReportCounterCommand.cs
new file mode 100644
index 00000000..d477f235
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ReportCounterCommand.cs
@@ -0,0 +1,30 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct ReportCounterCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ReportCounter;
+ private TableRef<ThreadedCounterEvent> _event;
+ private CounterType _type;
+ private TableRef<EventHandler<ulong>> _resultHandler;
+ private bool _hostReserved;
+
+ public void Set(TableRef<ThreadedCounterEvent> evt, CounterType type, TableRef<EventHandler<ulong>> resultHandler, bool hostReserved)
+ {
+ _event = evt;
+ _type = type;
+ _resultHandler = resultHandler;
+ _hostReserved = hostReserved;
+ }
+
+ public static void Run(ref ReportCounterCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedCounterEvent evt = command._event.Get(threaded);
+
+ evt.Create(renderer, command._type, command._resultHandler.Get(threaded), command._hostReserved);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ResetCounterCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ResetCounterCommand.cs
new file mode 100644
index 00000000..2835bf31
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ResetCounterCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct ResetCounterCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ResetCounter;
+ private CounterType _type;
+
+ public void Set(CounterType type)
+ {
+ _type = type;
+ }
+
+ public static void Run(ref ResetCounterCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.ResetCounter(command._type);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/UpdateCountersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/UpdateCountersCommand.cs
new file mode 100644
index 00000000..f28bf080
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/UpdateCountersCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct UpdateCountersCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.UpdateCounters;
+
+ public static void Run(ref UpdateCountersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.UpdateCounters();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Sampler/SamplerDisposeCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Sampler/SamplerDisposeCommand.cs
new file mode 100644
index 00000000..8f4dfb7e
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Sampler/SamplerDisposeCommand.cs
@@ -0,0 +1,21 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Sampler
+{
+ struct SamplerDisposeCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SamplerDispose;
+ private TableRef<ThreadedSampler> _sampler;
+
+ public void Set(TableRef<ThreadedSampler> sampler)
+ {
+ _sampler = sampler;
+ }
+
+ public static void Run(ref SamplerDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._sampler.Get(threaded).Base.Dispose();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetAlphaTestCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetAlphaTestCommand.cs
new file mode 100644
index 00000000..89379387
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetAlphaTestCommand.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetAlphaTestCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetAlphaTest;
+ private bool _enable;
+ private float _reference;
+ private CompareOp _op;
+
+ public void Set(bool enable, float reference, CompareOp op)
+ {
+ _enable = enable;
+ _reference = reference;
+ _op = op;
+ }
+
+ public static void Run(ref SetAlphaTestCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetAlphaTest(command._enable, command._reference, command._op);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateCommand.cs
new file mode 100644
index 00000000..6cc4894e
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetBlendStateCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetBlendState;
+ private int _index;
+ private BlendDescriptor _blend;
+
+ public void Set(int index, BlendDescriptor blend)
+ {
+ _index = index;
+ _blend = blend;
+ }
+
+ public static void Run(ref SetBlendStateCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetBlendState(command._index, command._blend);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthBiasCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthBiasCommand.cs
new file mode 100644
index 00000000..352242a3
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthBiasCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetDepthBiasCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetDepthBias;
+ private PolygonModeMask _enables;
+ private float _factor;
+ private float _units;
+ private float _clamp;
+
+ public void Set(PolygonModeMask enables, float factor, float units, float clamp)
+ {
+ _enables = enables;
+ _factor = factor;
+ _units = units;
+ _clamp = clamp;
+ }
+
+ public static void Run(ref SetDepthBiasCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetDepthBias(command._enables, command._factor, command._units, command._clamp);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthClampCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthClampCommand.cs
new file mode 100644
index 00000000..21c8f3e6
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthClampCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetDepthClampCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetDepthClamp;
+ private bool _clamp;
+
+ public void Set(bool clamp)
+ {
+ _clamp = clamp;
+ }
+
+ public static void Run(ref SetDepthClampCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetDepthClamp(command._clamp);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthModeCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthModeCommand.cs
new file mode 100644
index 00000000..28c36be8
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthModeCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetDepthModeCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetDepthMode;
+ private DepthMode _mode;
+
+ public void Set(DepthMode mode)
+ {
+ _mode = mode;
+ }
+
+ public static void Run(ref SetDepthModeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetDepthMode(command._mode);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthTestCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthTestCommand.cs
new file mode 100644
index 00000000..585d3e8b
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthTestCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetDepthTestCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetDepthTest;
+ private DepthTestDescriptor _depthTest;
+
+ public void Set(DepthTestDescriptor depthTest)
+ {
+ _depthTest = depthTest;
+ }
+
+ public static void Run(ref SetDepthTestCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetDepthTest(command._depthTest);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs
new file mode 100644
index 00000000..2a2b41ca
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetFaceCullingCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetFaceCulling;
+ private bool _enable;
+ private Face _face;
+
+ public void Set(bool enable, Face face)
+ {
+ _enable = enable;
+ _face = face;
+ }
+
+ public static void Run(ref SetFaceCullingCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetFaceCulling(command._enable, command._face);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFrontFaceCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFrontFaceCommand.cs
new file mode 100644
index 00000000..a415237f
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFrontFaceCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetFrontFaceCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetFrontFace;
+ private FrontFace _frontFace;
+
+ public void Set(FrontFace frontFace)
+ {
+ _frontFace = frontFace;
+ }
+
+ public static void Run(ref SetFrontFaceCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetFrontFace(command._frontFace);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs
new file mode 100644
index 00000000..4223a621
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetImageCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetImage;
+ private int _binding;
+ private TableRef<ITexture> _texture;
+ private Format _imageFormat;
+
+ public void Set(int binding, TableRef<ITexture> texture, Format imageFormat)
+ {
+ _binding = binding;
+ _texture = texture;
+ _imageFormat = imageFormat;
+ }
+
+ public static void Run(ref SetImageCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetImage(command._binding, command._texture.GetAs<ThreadedTexture>(threaded)?.Base, command._imageFormat);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetIndexBufferCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetIndexBufferCommand.cs
new file mode 100644
index 00000000..753e21f9
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetIndexBufferCommand.cs
@@ -0,0 +1,21 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetIndexBufferCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetIndexBuffer;
+ private BufferRange _buffer;
+ private IndexType _type;
+
+ public void Set(BufferRange buffer, IndexType type)
+ {
+ _buffer = buffer;
+ _type = type;
+ }
+
+ public static void Run(ref SetIndexBufferCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ BufferRange range = threaded.Buffers.MapBufferRange(command._buffer);
+ renderer.Pipeline.SetIndexBuffer(range, command._type);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLineParametersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLineParametersCommand.cs
new file mode 100644
index 00000000..7fd2e5b1
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLineParametersCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetLineParametersCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetLineParameters;
+ private float _width;
+ private bool _smooth;
+
+ public void Set(float width, bool smooth)
+ {
+ _width = width;
+ _smooth = smooth;
+ }
+
+ public static void Run(ref SetLineParametersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetLineParameters(command._width, command._smooth);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLogicOpStateCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLogicOpStateCommand.cs
new file mode 100644
index 00000000..253ef138
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLogicOpStateCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetLogicOpStateCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetLogicOpState;
+ private bool _enable;
+ private LogicalOp _op;
+
+ public void Set(bool enable, LogicalOp op)
+ {
+ _enable = enable;
+ _op = op;
+ }
+
+ public static void Run(ref SetLogicOpStateCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetLogicOpState(command._enable, command._op);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPointParametersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPointParametersCommand.cs
new file mode 100644
index 00000000..37833a0e
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPointParametersCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetPointParametersCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetPointParameters;
+ private float _size;
+ private bool _isProgramPointSize;
+ private bool _enablePointSprite;
+ private Origin _origin;
+
+ public void Set(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin)
+ {
+ _size = size;
+ _isProgramPointSize = isProgramPointSize;
+ _enablePointSprite = enablePointSprite;
+ _origin = origin;
+ }
+
+ public static void Run(ref SetPointParametersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetPointParameters(command._size, command._isProgramPointSize, command._enablePointSprite, command._origin);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveRestartCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveRestartCommand.cs
new file mode 100644
index 00000000..e5f6ecf3
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveRestartCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetPrimitiveRestartCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetPrimitiveRestart;
+ private bool _enable;
+ private int _index;
+
+ public void Set(bool enable, int index)
+ {
+ _enable = enable;
+ _index = index;
+ }
+
+ public static void Run(ref SetPrimitiveRestartCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetPrimitiveRestart(command._enable, command._index);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveTopologyCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveTopologyCommand.cs
new file mode 100644
index 00000000..0bf29260
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveTopologyCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetPrimitiveTopologyCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetPrimitiveTopology;
+ private PrimitiveTopology _topology;
+
+ public void Set(PrimitiveTopology topology)
+ {
+ _topology = topology;
+ }
+
+ public static void Run(ref SetPrimitiveTopologyCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetPrimitiveTopology(command._topology);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetProgramCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetProgramCommand.cs
new file mode 100644
index 00000000..c35d9c1f
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetProgramCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetProgramCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetProgram;
+ private TableRef<IProgram> _program;
+
+ public void Set(TableRef<IProgram> program)
+ {
+ _program = program;
+ }
+
+ public static void Run(ref SetProgramCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedProgram program = command._program.GetAs<ThreadedProgram>(threaded);
+
+ threaded.Programs.WaitForProgram(program);
+
+ renderer.Pipeline.SetProgram(program.Base);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRasterizerDiscardCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRasterizerDiscardCommand.cs
new file mode 100644
index 00000000..4f92ce99
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRasterizerDiscardCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetRasterizerDiscardCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetRasterizerDiscard;
+ private bool _discard;
+
+ public void Set(bool discard)
+ {
+ _discard = discard;
+ }
+
+ public static void Run(ref SetRasterizerDiscardCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetRasterizerDiscard(command._discard);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetColorMasksCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetColorMasksCommand.cs
new file mode 100644
index 00000000..1e75ddb8
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetColorMasksCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetRenderTargetColorMasksCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetRenderTargetColorMasks;
+ private SpanRef<uint> _componentMask;
+
+ public void Set(SpanRef<uint> componentMask)
+ {
+ _componentMask = componentMask;
+ }
+
+ public static void Run(ref SetRenderTargetColorMasksCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ReadOnlySpan<uint> componentMask = command._componentMask.Get(threaded);
+ renderer.Pipeline.SetRenderTargetColorMasks(componentMask);
+ command._componentMask.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetScaleCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetScaleCommand.cs
new file mode 100644
index 00000000..a97a63db
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetScaleCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetRenderTargetScaleCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetRenderTargetScale;
+ private float _scale;
+
+ public void Set(float scale)
+ {
+ _scale = scale;
+ }
+
+ public static void Run(ref SetRenderTargetScaleCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetRenderTargetScale(command._scale);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetsCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetsCommand.cs
new file mode 100644
index 00000000..30f798dd
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetsCommand.cs
@@ -0,0 +1,24 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+using System.Linq;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetRenderTargetsCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetRenderTargets;
+ private TableRef<ITexture[]> _colors;
+ private TableRef<ITexture> _depthStencil;
+
+ public void Set(TableRef<ITexture[]> colors, TableRef<ITexture> depthStencil)
+ {
+ _colors = colors;
+ _depthStencil = depthStencil;
+ }
+
+ public static void Run(ref SetRenderTargetsCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetRenderTargets(command._colors.Get(threaded).Select(color => ((ThreadedTexture)color)?.Base).ToArray(), command._depthStencil.GetAs<ThreadedTexture>(threaded)?.Base);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetSamplerCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetSamplerCommand.cs
new file mode 100644
index 00000000..f3be24db
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetSamplerCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetSamplerCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetSampler;
+ private int _index;
+ private TableRef<ISampler> _sampler;
+
+ public void Set(int index, TableRef<ISampler> sampler)
+ {
+ _index = index;
+ _sampler = sampler;
+ }
+
+ public static void Run(ref SetSamplerCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetSampler(command._index, command._sampler.GetAs<ThreadedSampler>(threaded)?.Base);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetScissorCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetScissorCommand.cs
new file mode 100644
index 00000000..6c95d096
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetScissorCommand.cs
@@ -0,0 +1,28 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetScissorCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetScissor;
+ private int _index;
+ private bool _enable;
+ private int _x;
+ private int _y;
+ private int _width;
+ private int _height;
+
+ public void Set(int index, bool enable, int x, int y, int width, int height)
+ {
+ _index = index;
+ _enable = enable;
+ _x = x;
+ _y = y;
+ _width = width;
+ _height = height;
+ }
+
+ public static void Run(ref SetScissorCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetScissor(command._index, command._enable, command._x, command._y, command._width, command._height);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStencilTestCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStencilTestCommand.cs
new file mode 100644
index 00000000..cc5db4df
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStencilTestCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetStencilTestCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetStencilTest;
+ private StencilTestDescriptor _stencilTest;
+
+ public void Set(StencilTestDescriptor stencilTest)
+ {
+ _stencilTest = stencilTest;
+ }
+
+ public static void Run(ref SetStencilTestCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetStencilTest(command._stencilTest);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs
new file mode 100644
index 00000000..c2963373
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetStorageBuffersCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetStorageBuffers;
+ private int _first;
+ private SpanRef<BufferRange> _buffers;
+
+ public void Set(int first, SpanRef<BufferRange> buffers)
+ {
+ _first = first;
+ _buffers = buffers;
+ }
+
+ public static void Run(ref SetStorageBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ Span<BufferRange> buffers = command._buffers.Get(threaded);
+ renderer.Pipeline.SetStorageBuffers(command._first, threaded.Buffers.MapBufferRanges(buffers));
+ command._buffers.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTextureCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTextureCommand.cs
new file mode 100644
index 00000000..e86f512b
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTextureCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetTextureCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetTexture;
+ private int _binding;
+ private TableRef<ITexture> _texture;
+
+ public void Set(int binding, TableRef<ITexture> texture)
+ {
+ _binding = binding;
+ _texture = texture;
+ }
+
+ public static void Run(ref SetTextureCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetTexture(command._binding, command._texture.GetAs<ThreadedTexture>(threaded)?.Base);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTransformFeedbackBuffersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTransformFeedbackBuffersCommand.cs
new file mode 100644
index 00000000..5125447c
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTransformFeedbackBuffersCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetTransformFeedbackBuffersCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetTransformFeedbackBuffers;
+ private SpanRef<BufferRange> _buffers;
+
+ public void Set(SpanRef<BufferRange> buffers)
+ {
+ _buffers = buffers;
+ }
+
+ public static void Run(ref SetTransformFeedbackBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ Span<BufferRange> buffers = command._buffers.Get(threaded);
+ renderer.Pipeline.SetTransformFeedbackBuffers(threaded.Buffers.MapBufferRanges(buffers));
+ command._buffers.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs
new file mode 100644
index 00000000..750d8dac
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetUniformBuffersCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetUniformBuffers;
+ private int _first;
+ private SpanRef<BufferRange> _buffers;
+
+ public void Set(int first, SpanRef<BufferRange> buffers)
+ {
+ _first = first;
+ _buffers = buffers;
+ }
+
+ public static void Run(ref SetUniformBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ Span<BufferRange> buffers = command._buffers.Get(threaded);
+ renderer.Pipeline.SetUniformBuffers(command._first, threaded.Buffers.MapBufferRanges(buffers));
+ command._buffers.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUserClipDistanceCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUserClipDistanceCommand.cs
new file mode 100644
index 00000000..f0f05779
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUserClipDistanceCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetUserClipDistanceCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetUserClipDistance;
+ private int _index;
+ private bool _enableClip;
+
+ public void Set(int index, bool enableClip)
+ {
+ _index = index;
+ _enableClip = enableClip;
+ }
+
+ public static void Run(ref SetUserClipDistanceCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetUserClipDistance(command._index, command._enableClip);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexAttribsCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexAttribsCommand.cs
new file mode 100644
index 00000000..cbc313e9
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexAttribsCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetVertexAttribsCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetVertexAttribs;
+ private SpanRef<VertexAttribDescriptor> _vertexAttribs;
+
+ public void Set(SpanRef<VertexAttribDescriptor> vertexAttribs)
+ {
+ _vertexAttribs = vertexAttribs;
+ }
+
+ public static void Run(ref SetVertexAttribsCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ReadOnlySpan<VertexAttribDescriptor> vertexAttribs = command._vertexAttribs.Get(threaded);
+ renderer.Pipeline.SetVertexAttribs(vertexAttribs);
+ command._vertexAttribs.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexBuffersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexBuffersCommand.cs
new file mode 100644
index 00000000..bdaba2c9
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexBuffersCommand.cs
@@ -0,0 +1,24 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+using System.Buffers;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetVertexBuffersCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetVertexBuffers;
+ private SpanRef<VertexBufferDescriptor> _vertexBuffers;
+
+ public void Set(SpanRef<VertexBufferDescriptor> vertexBuffers)
+ {
+ _vertexBuffers = vertexBuffers;
+ }
+
+ public static void Run(ref SetVertexBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ Span<VertexBufferDescriptor> vertexBuffers = command._vertexBuffers.Get(threaded);
+ renderer.Pipeline.SetVertexBuffers(threaded.Buffers.MapBufferRanges(vertexBuffers));
+ command._vertexBuffers.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetViewportsCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetViewportsCommand.cs
new file mode 100644
index 00000000..e11b00e8
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetViewportsCommand.cs
@@ -0,0 +1,26 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+using System.Buffers;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetViewportsCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetViewports;
+ private int _first;
+ private SpanRef<Viewport> _viewports;
+
+ public void Set(int first, SpanRef<Viewport> viewports)
+ {
+ _first = first;
+ _viewports = viewports;
+ }
+
+ public static void Run(ref SetViewportsCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ReadOnlySpan<Viewport> viewports = command._viewports.Get(threaded);
+ renderer.Pipeline.SetViewports(command._first, viewports);
+ command._viewports.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Shader/ShaderDisposeCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Shader/ShaderDisposeCommand.cs
new file mode 100644
index 00000000..ebb2c927
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Shader/ShaderDisposeCommand.cs
@@ -0,0 +1,21 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Shader
+{
+ struct ShaderDisposeCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.ShaderDispose;
+ private TableRef<ThreadedShader> _shader;
+
+ public void Set(TableRef<ThreadedShader> shader)
+ {
+ _shader = shader;
+ }
+
+ public static void Run(ref ShaderDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._shader.Get(threaded).Base.Dispose();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToCommand.cs
new file mode 100644
index 00000000..112c1fd1
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToCommand.cs
@@ -0,0 +1,28 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureCopyToCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureCopyTo;
+ private TableRef<ThreadedTexture> _texture;
+ private TableRef<ThreadedTexture> _destination;
+ private int _firstLayer;
+ private int _firstLevel;
+
+ public void Set(TableRef<ThreadedTexture> texture, TableRef<ThreadedTexture> destination, int firstLayer, int firstLevel)
+ {
+ _texture = texture;
+ _destination = destination;
+ _firstLayer = firstLayer;
+ _firstLevel = firstLevel;
+ }
+
+ public static void Run(ref TextureCopyToCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedTexture source = command._texture.Get(threaded);
+ source.Base.CopyTo(command._destination.Get(threaded).Base, command._firstLayer, command._firstLevel);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToScaledCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToScaledCommand.cs
new file mode 100644
index 00000000..11843361
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToScaledCommand.cs
@@ -0,0 +1,30 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureCopyToScaledCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureCopyToScaled;
+ private TableRef<ThreadedTexture> _texture;
+ private TableRef<ThreadedTexture> _destination;
+ private Extents2D _srcRegion;
+ private Extents2D _dstRegion;
+ private bool _linearFilter;
+
+ public void Set(TableRef<ThreadedTexture> texture, TableRef<ThreadedTexture> destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
+ {
+ _texture = texture;
+ _destination = destination;
+ _srcRegion = srcRegion;
+ _dstRegion = dstRegion;
+ _linearFilter = linearFilter;
+ }
+
+ public static void Run(ref TextureCopyToScaledCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedTexture source = command._texture.Get(threaded);
+ source.Base.CopyTo(command._destination.Get(threaded).Base, command._srcRegion, command._dstRegion, command._linearFilter);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToSliceCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToSliceCommand.cs
new file mode 100644
index 00000000..363edb00
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToSliceCommand.cs
@@ -0,0 +1,32 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureCopyToSliceCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureCopyToSlice;
+ private TableRef<ThreadedTexture> _texture;
+ private TableRef<ThreadedTexture> _destination;
+ private int _srcLayer;
+ private int _dstLayer;
+ private int _srcLevel;
+ private int _dstLevel;
+
+ public void Set(TableRef<ThreadedTexture> texture, TableRef<ThreadedTexture> destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel)
+ {
+ _texture = texture;
+ _destination = destination;
+ _srcLayer = srcLayer;
+ _dstLayer = dstLayer;
+ _srcLevel = srcLevel;
+ _dstLevel = dstLevel;
+ }
+
+ public static void Run(ref TextureCopyToSliceCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedTexture source = command._texture.Get(threaded);
+ source.Base.CopyTo(command._destination.Get(threaded).Base, command._srcLayer, command._dstLayer, command._srcLevel, command._dstLevel);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCreateViewCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCreateViewCommand.cs
new file mode 100644
index 00000000..7c385407
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCreateViewCommand.cs
@@ -0,0 +1,30 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureCreateViewCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureCreateView;
+ private TableRef<ThreadedTexture> _texture;
+ private TableRef<ThreadedTexture> _destination;
+ private TextureCreateInfo _info;
+ private int _firstLayer;
+ private int _firstLevel;
+
+ public void Set(TableRef<ThreadedTexture> texture, TableRef<ThreadedTexture> destination, TextureCreateInfo info, int firstLayer, int firstLevel)
+ {
+ _texture = texture;
+ _destination = destination;
+ _info = info;
+ _firstLayer = firstLayer;
+ _firstLevel = firstLevel;
+ }
+
+ public static void Run(ref TextureCreateViewCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedTexture source = command._texture.Get(threaded);
+ command._destination.Get(threaded).Base = source.Base.CreateView(command._info, command._firstLayer, command._firstLevel);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs
new file mode 100644
index 00000000..9e7d0c64
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs
@@ -0,0 +1,26 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureGetDataCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureGetData;
+ private TableRef<ThreadedTexture> _texture;
+ private TableRef<ResultBox<PinnedSpan<byte>>> _result;
+
+ public void Set(TableRef<ThreadedTexture> texture, TableRef<ResultBox<PinnedSpan<byte>>> result)
+ {
+ _texture = texture;
+ _result = result;
+ }
+
+ public static void Run(ref TextureGetDataCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ReadOnlySpan<byte> result = command._texture.Get(threaded).Base.GetData();
+
+ command._result.Get(threaded).Result = new PinnedSpan<byte>(result);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureReleaseCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureReleaseCommand.cs
new file mode 100644
index 00000000..591b2214
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureReleaseCommand.cs
@@ -0,0 +1,21 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureReleaseCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureRelease;
+ private TableRef<ThreadedTexture> _texture;
+
+ public void Set(TableRef<ThreadedTexture> texture)
+ {
+ _texture = texture;
+ }
+
+ public static void Run(ref TextureReleaseCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._texture.Get(threaded).Base.Release();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs
new file mode 100644
index 00000000..a8a6d274
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureSetDataCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureSetData;
+ private TableRef<ThreadedTexture> _texture;
+ private TableRef<byte[]> _data;
+
+ public void Set(TableRef<ThreadedTexture> texture, TableRef<byte[]> data)
+ {
+ _texture = texture;
+ _data = data;
+ }
+
+ public static void Run(ref TextureSetDataCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedTexture texture = command._texture.Get(threaded);
+ texture.Base.SetData(new ReadOnlySpan<byte>(command._data.Get(threaded)));
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs
new file mode 100644
index 00000000..0179ff11
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs
@@ -0,0 +1,29 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureSetDataSliceCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureSetDataSlice;
+ private TableRef<ThreadedTexture> _texture;
+ private TableRef<byte[]> _data;
+ private int _layer;
+ private int _level;
+
+ public void Set(TableRef<ThreadedTexture> texture, TableRef<byte[]> data, int layer, int level)
+ {
+ _texture = texture;
+ _data = data;
+ _layer = layer;
+ _level = level;
+ }
+
+ public static void Run(ref TextureSetDataSliceCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedTexture texture = command._texture.Get(threaded);
+ texture.Base.SetData(new ReadOnlySpan<byte>(command._data.Get(threaded)), command._layer, command._level);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetStorageCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetStorageCommand.cs
new file mode 100644
index 00000000..f86a9c44
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetStorageCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
+{
+ struct TextureSetStorageCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureSetStorage;
+ private TableRef<ThreadedTexture> _texture;
+ private BufferRange _storage;
+
+ public void Set(TableRef<ThreadedTexture> texture, BufferRange storage)
+ {
+ _texture = texture;
+ _storage = storage;
+ }
+
+ public static void Run(ref TextureSetStorageCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._texture.Get(threaded).Base.SetStorage(threaded.Buffers.MapBufferRange(command._storage));
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierCommand.cs
new file mode 100644
index 00000000..b0b46021
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct TextureBarrierCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureBarrier;
+
+ public static void Run(ref TextureBarrierCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.TextureBarrier();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierTiledCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierTiledCommand.cs
new file mode 100644
index 00000000..f92abe5b
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierTiledCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct TextureBarrierTiledCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TextureBarrierTiled;
+
+ public static void Run(ref TextureBarrierTiledCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.TextureBarrierTiled();
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs
new file mode 100644
index 00000000..65e1748d
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct TryHostConditionalRenderingCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TryHostConditionalRendering;
+ private TableRef<ThreadedCounterEvent> _value;
+ private ulong _compare;
+ private bool _isEqual;
+
+ public void Set(TableRef<ThreadedCounterEvent> value, ulong compare, bool isEqual)
+ {
+ _value = value;
+ _compare = compare;
+ _isEqual = isEqual;
+ }
+
+ public static void Run(ref TryHostConditionalRenderingCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.TryHostConditionalRendering(command._value.Get(threaded)?.Base, command._compare, command._isEqual);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingFlushCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingFlushCommand.cs
new file mode 100644
index 00000000..29eb8dd4
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingFlushCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct TryHostConditionalRenderingFlushCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.TryHostConditionalRenderingFlush;
+ private TableRef<ThreadedCounterEvent> _value;
+ private TableRef<ThreadedCounterEvent> _compare;
+ private bool _isEqual;
+
+ public void Set(TableRef<ThreadedCounterEvent> value, TableRef<ThreadedCounterEvent> compare, bool isEqual)
+ {
+ _value = value;
+ _compare = compare;
+ _isEqual = isEqual;
+ }
+
+ public static void Run(ref TryHostConditionalRenderingFlushCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.TryHostConditionalRendering(command._value.Get(threaded)?.Base, command._compare.Get(threaded)?.Base, command._isEqual);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs
new file mode 100644
index 00000000..fafb52a8
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs
@@ -0,0 +1,28 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.Shader;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct UpdateRenderScaleCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.UpdateRenderScale;
+ private ShaderStage _stage;
+ private SpanRef<float> _scales;
+ private int _textureCount;
+ private int _imageCount;
+
+ public void Set(ShaderStage stage, SpanRef<float> scales, int textureCount, int imageCount)
+ {
+ _stage = stage;
+ _scales = scales;
+ _textureCount = textureCount;
+ _imageCount = imageCount;
+ }
+
+ public static void Run(ref UpdateRenderScaleCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.UpdateRenderScale(command._stage, command._scales.Get(threaded), command._textureCount, command._imageCount);
+ command._scales.Dispose(threaded);
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Window/WindowPresentCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Window/WindowPresentCommand.cs
new file mode 100644
index 00000000..c4f3b553
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Window/WindowPresentCommand.cs
@@ -0,0 +1,27 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Window
+{
+ struct WindowPresentCommand : IGALCommand
+ {
+ public CommandType CommandType => CommandType.WindowPresent;
+ private TableRef<ThreadedTexture> _texture;
+ private ImageCrop _crop;
+ private TableRef<Action> _swapBuffersCallback;
+
+ public void Set(TableRef<ThreadedTexture> texture, ImageCrop crop, TableRef<Action> swapBuffersCallback)
+ {
+ _texture = texture;
+ _crop = crop;
+ _swapBuffersCallback = swapBuffersCallback;
+ }
+
+ public static void Run(ref WindowPresentCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ threaded.SignalFrame();
+ renderer.Window.Present(command._texture.Get(threaded)?.Base, command._crop, command._swapBuffersCallback.Get(threaded));
+ }
+ }
+}