From cee712105850ac3385cd0091a923438167433f9f Mon Sep 17 00:00:00 2001
From: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
Date: Sat, 8 Apr 2023 01:22:00 +0200
Subject: Move solution and projects to src
---
.../Multithreading/BufferMap.cs | 194 ++++++++
.../Multithreading/CommandHelper.cs | 149 +++++++
.../Multithreading/CommandType.cs | 102 +++++
.../Multithreading/Commands/BarrierCommand.cs | 12 +
.../Commands/BeginTransformFeedbackCommand.cs | 18 +
.../Commands/Buffer/BufferDisposeCommand.cs | 19 +
.../Commands/Buffer/BufferGetDataCommand.cs | 29 ++
.../Commands/Buffer/BufferSetDataCommand.cs | 27 ++
.../Multithreading/Commands/ClearBufferCommand.cs | 24 +
.../Commands/ClearRenderTargetColorCommand.cs | 26 ++
.../ClearRenderTargetDepthStencilCommand.cs | 28 ++
.../Commands/CommandBufferBarrierCommand.cs | 12 +
.../Multithreading/Commands/CopyBufferCommand.cs | 26 ++
.../CounterEvent/CounterEventDisposeCommand.cs | 21 +
.../CounterEvent/CounterEventFlushCommand.cs | 21 +
.../Commands/DispatchComputeCommand.cs | 22 +
.../Multithreading/Commands/DrawCommand.cs | 26 ++
.../Multithreading/Commands/DrawIndexedCommand.cs | 24 +
.../Commands/DrawIndexedIndirectCommand.cs | 18 +
.../Commands/DrawIndexedIndirectCountCommand.cs | 29 ++
.../Multithreading/Commands/DrawIndirectCommand.cs | 18 +
.../Commands/DrawIndirectCountCommand.cs | 29 ++
.../Multithreading/Commands/DrawTextureCommand.cs | 31 ++
.../Commands/EndHostConditionalRenderingCommand.cs | 12 +
.../Commands/EndTransformFeedbackCommand.cs | 12 +
.../Multithreading/Commands/IGALCommand.cs | 12 +
.../Commands/Program/ProgramCheckLinkCommand.cs | 27 ++
.../Commands/Program/ProgramDisposeCommand.cs | 21 +
.../Commands/Program/ProgramGetBinaryCommand.cs | 25 ++
.../Commands/Renderer/ActionCommand.cs | 21 +
.../Commands/Renderer/CreateBufferCommand.cs | 29 ++
.../Commands/Renderer/CreateProgramCommand.cs | 28 ++
.../Commands/Renderer/CreateSamplerCommand.cs | 23 +
.../Commands/Renderer/CreateSyncCommand.cs | 22 +
.../Commands/Renderer/CreateTextureCommand.cs | 25 ++
.../Commands/Renderer/GetCapabilitiesCommand.cs | 20 +
.../Commands/Renderer/PreFrameCommand.cs | 12 +
.../Commands/Renderer/ReportCounterCommand.cs | 30 ++
.../Commands/Renderer/ResetCounterCommand.cs | 18 +
.../Commands/Renderer/UpdateCountersCommand.cs | 12 +
.../Commands/Sampler/SamplerDisposeCommand.cs | 21 +
.../Multithreading/Commands/SetAlphaTestCommand.cs | 22 +
.../Commands/SetBlendStateAdvancedCommand.cs | 18 +
.../Commands/SetBlendStateCommand.cs | 20 +
.../Multithreading/Commands/SetDepthBiasCommand.cs | 24 +
.../Commands/SetDepthClampCommand.cs | 18 +
.../Multithreading/Commands/SetDepthModeCommand.cs | 18 +
.../Multithreading/Commands/SetDepthTestCommand.cs | 18 +
.../Commands/SetFaceCullingCommand.cs | 20 +
.../Multithreading/Commands/SetFrontFaceCommand.cs | 18 +
.../Multithreading/Commands/SetImageCommand.cs | 25 ++
.../Commands/SetIndexBufferCommand.cs | 21 +
.../Commands/SetLineParametersCommand.cs | 20 +
.../Commands/SetLogicOpStateCommand.cs | 20 +
.../Commands/SetMultisampleStateCommand.cs | 18 +
.../Commands/SetPatchParametersCommand.cs | 25 ++
.../Commands/SetPointParametersCommand.cs | 24 +
.../Commands/SetPolygonModeCommand.cs | 20 +
.../Commands/SetPrimitiveRestartCommand.cs | 20 +
.../Commands/SetPrimitiveTopologyCommand.cs | 18 +
.../Multithreading/Commands/SetProgramCommand.cs | 25 ++
.../Commands/SetRasterizerDiscardCommand.cs | 18 +
.../Commands/SetRenderTargetColorMasksCommand.cs | 23 +
.../Commands/SetRenderTargetScaleCommand.cs | 18 +
.../Commands/SetRenderTargetsCommand.cs | 24 +
.../Multithreading/Commands/SetScissorsCommand.cs | 22 +
.../Commands/SetStencilTestCommand.cs | 18 +
.../Commands/SetStorageBuffersCommand.cs | 23 +
.../Commands/SetTextureAndSamplerCommand.cs | 28 ++
.../Commands/SetTransformFeedbackBuffersCommand.cs | 23 +
.../Commands/SetUniformBuffersCommand.cs | 23 +
.../Commands/SetUserClipDistanceCommand.cs | 20 +
.../Commands/SetVertexAttribsCommand.cs | 23 +
.../Commands/SetVertexBuffersCommand.cs | 23 +
.../Multithreading/Commands/SetViewportsCommand.cs | 25 ++
.../Commands/Texture/TextureCopyToCommand.cs | 28 ++
.../Commands/Texture/TextureCopyToScaledCommand.cs | 30 ++
.../Commands/Texture/TextureCopyToSliceCommand.cs | 32 ++
.../Commands/Texture/TextureCreateViewCommand.cs | 30 ++
.../Commands/Texture/TextureGetDataCommand.cs | 26 ++
.../Commands/Texture/TextureGetDataSliceCommand.cs | 30 ++
.../Commands/Texture/TextureReleaseCommand.cs | 21 +
.../Commands/Texture/TextureSetDataCommand.cs | 25 ++
.../Commands/Texture/TextureSetDataSliceCommand.cs | 29 ++
.../Texture/TextureSetDataSliceRegionCommand.cs | 31 ++
.../Commands/Texture/TextureSetStorageCommand.cs | 23 +
.../Commands/TextureBarrierCommand.cs | 12 +
.../Commands/TextureBarrierTiledCommand.cs | 12 +
.../Commands/TryHostConditionalRenderingCommand.cs | 25 ++
.../TryHostConditionalRenderingFlushCommand.cs | 25 ++
.../Commands/UpdateRenderScaleCommand.cs | 25 ++
.../Commands/Window/WindowPresentCommand.cs | 27 ++
.../Multithreading/Model/CircularSpanPool.cs | 89 ++++
.../Multithreading/Model/ResultBox.cs | 7 +
.../Multithreading/Model/SpanRef.cs | 39 ++
.../Multithreading/Model/TableRef.cs | 22 +
.../Multithreading/Resources/ProgramQueue.cs | 107 +++++
.../Resources/Programs/BinaryProgramRequest.cs | 25 ++
.../Resources/Programs/IProgramRequest.cs | 8 +
.../Resources/Programs/SourceProgramRequest.cs | 23 +
.../Resources/ThreadedCounterEvent.cs | 80 ++++
.../Multithreading/Resources/ThreadedProgram.cs | 48 ++
.../Multithreading/Resources/ThreadedSampler.cs | 22 +
.../Multithreading/Resources/ThreadedTexture.cs | 141 ++++++
src/Ryujinx.Graphics.GAL/Multithreading/SyncMap.cs | 62 +++
.../Multithreading/ThreadedHelpers.cs | 28 ++
.../Multithreading/ThreadedPipeline.cs | 380 ++++++++++++++++
.../Multithreading/ThreadedRenderer.cs | 488 +++++++++++++++++++++
.../Multithreading/ThreadedWindow.cs | 42 ++
109 files changed, 4040 insertions(+)
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/BarrierCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/BeginTransformFeedbackCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferDisposeCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferSetDataCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearBufferCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetColorCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetDepthStencilCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/CommandBufferBarrierCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/CopyBufferCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventDisposeCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventFlushCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/DispatchComputeCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedIndirectCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedIndirectCountCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndirectCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndirectCountCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawTextureCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/EndHostConditionalRenderingCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/EndTransformFeedbackCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/IGALCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramCheckLinkCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramDisposeCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramGetBinaryCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ActionCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateProgramCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSamplerCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSyncCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateTextureCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/GetCapabilitiesCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/PreFrameCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ReportCounterCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ResetCounterCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/UpdateCountersCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Sampler/SamplerDisposeCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetAlphaTestCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateAdvancedCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthBiasCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthClampCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthModeCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthTestCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFrontFaceCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetIndexBufferCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLineParametersCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLogicOpStateCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetMultisampleStateCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPatchParametersCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPointParametersCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPolygonModeCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveRestartCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveTopologyCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetProgramCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRasterizerDiscardCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetColorMasksCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetScaleCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetsCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetScissorsCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStencilTestCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTextureAndSamplerCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTransformFeedbackBuffersCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUserClipDistanceCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexAttribsCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetVertexBuffersCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetViewportsCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToScaledCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCopyToSliceCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureCreateViewCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataSliceCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureReleaseCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceRegionCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetStorageCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureBarrierTiledCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingFlushCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Commands/Window/WindowPresentCommand.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Model/CircularSpanPool.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Model/ResultBox.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Model/SpanRef.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Model/TableRef.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Resources/ProgramQueue.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Resources/Programs/BinaryProgramRequest.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Resources/Programs/IProgramRequest.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Resources/Programs/SourceProgramRequest.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedCounterEvent.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedProgram.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedSampler.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/SyncMap.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/ThreadedHelpers.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs
create mode 100644 src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs
(limited to 'src/Ryujinx.Graphics.GAL/Multithreading')
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs b/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs
new file mode 100644
index 00000000..24b0af2d
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs
@@ -0,0 +1,194 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace Ryujinx.Graphics.GAL.Multithreading
+{
+ ///
+ /// Buffer handles given to the client are not the same as those provided by the backend,
+ /// as their handle is created at a later point on the queue.
+ /// The handle returned is a unique identifier that will map to the real buffer when it is available.
+ /// Note that any uses within the queue should be safe, but outside you must use MapBufferBlocking.
+ ///
+ class BufferMap
+ {
+ private ulong _bufferHandle = 0;
+
+ private Dictionary _bufferMap = new Dictionary();
+ private HashSet _inFlight = new HashSet();
+ private AutoResetEvent _inFlightChanged = new AutoResetEvent(false);
+
+ internal BufferHandle CreateBufferHandle()
+ {
+ ulong handle64 = Interlocked.Increment(ref _bufferHandle);
+
+ BufferHandle threadedHandle = Unsafe.As(ref handle64);
+
+ lock (_inFlight)
+ {
+ _inFlight.Add(threadedHandle);
+ }
+
+ return threadedHandle;
+ }
+
+ internal void AssignBuffer(BufferHandle threadedHandle, BufferHandle realHandle)
+ {
+ lock (_bufferMap)
+ {
+ _bufferMap[threadedHandle] = realHandle;
+ }
+
+ lock (_inFlight)
+ {
+ _inFlight.Remove(threadedHandle);
+ }
+
+ _inFlightChanged.Set();
+ }
+
+ internal void UnassignBuffer(BufferHandle threadedHandle)
+ {
+ lock (_bufferMap)
+ {
+ _bufferMap.Remove(threadedHandle);
+ }
+ }
+
+ internal BufferHandle MapBuffer(BufferHandle handle)
+ {
+ // Maps a threaded buffer to a backend one.
+ // Threaded buffers are returned on creation as the buffer
+ // isn't actually created until the queue runs the command.
+
+ BufferHandle result;
+
+ lock (_bufferMap)
+ {
+ if (!_bufferMap.TryGetValue(handle, out result))
+ {
+ result = BufferHandle.Null;
+ }
+
+ return result;
+ }
+ }
+
+ internal BufferHandle MapBufferBlocking(BufferHandle handle)
+ {
+ // Blocks until the handle is available.
+
+ BufferHandle result;
+
+ lock (_bufferMap)
+ {
+ if (_bufferMap.TryGetValue(handle, out result))
+ {
+ return result;
+ }
+ }
+
+ bool signal = false;
+
+ while (true)
+ {
+ lock (_inFlight)
+ {
+ if (!_inFlight.Contains(handle))
+ {
+ break;
+ }
+ }
+
+ _inFlightChanged.WaitOne();
+ signal = true;
+ }
+
+ if (signal)
+ {
+ // Signal other threads which might still be waiting.
+ _inFlightChanged.Set();
+ }
+
+ return MapBuffer(handle);
+ }
+
+ internal BufferRange MapBufferRange(BufferRange range)
+ {
+ return new BufferRange(MapBuffer(range.Handle), range.Offset, range.Size);
+ }
+
+ internal Span MapBufferRanges(Span ranges)
+ {
+ // Rewrite the buffer ranges to point to the mapped handles.
+
+ lock (_bufferMap)
+ {
+ for (int i = 0; i < ranges.Length; i++)
+ {
+ ref BufferRange range = ref ranges[i];
+ BufferHandle result;
+
+ if (!_bufferMap.TryGetValue(range.Handle, out result))
+ {
+ result = BufferHandle.Null;
+ }
+
+ range = new BufferRange(result, range.Offset, range.Size);
+ }
+ }
+
+ return ranges;
+ }
+
+ internal Span MapBufferRanges(Span ranges)
+ {
+ // Rewrite the buffer ranges to point to the mapped handles.
+
+ lock (_bufferMap)
+ {
+ for (int i = 0; i < ranges.Length; i++)
+ {
+ ref BufferAssignment assignment = ref ranges[i];
+ BufferRange range = assignment.Range;
+ BufferHandle result;
+
+ if (!_bufferMap.TryGetValue(range.Handle, out result))
+ {
+ result = BufferHandle.Null;
+ }
+
+ assignment = new BufferAssignment(ranges[i].Binding, new BufferRange(result, range.Offset, range.Size));
+ }
+ }
+
+ return ranges;
+ }
+
+ internal Span MapBufferRanges(Span ranges)
+ {
+ // Rewrite the buffer ranges to point to the mapped handles.
+
+ lock (_bufferMap)
+ {
+ for (int i = 0; i < ranges.Length; i++)
+ {
+ BufferRange range = ranges[i].Buffer;
+ BufferHandle result;
+
+ if (!_bufferMap.TryGetValue(range.Handle, out result))
+ {
+ result = BufferHandle.Null;
+ }
+
+ range = new BufferRange(result, range.Offset, range.Size);
+
+ ranges[i] = new VertexBufferDescriptor(range, ranges[i].Stride, ranges[i].Divisor);
+ }
+ }
+
+ return ranges;
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs b/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs
new file mode 100644
index 00000000..063b7edf
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs
@@ -0,0 +1,149 @@
+using Ryujinx.Graphics.GAL.Multithreading.Commands;
+using Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer;
+using Ryujinx.Graphics.GAL.Multithreading.Commands.CounterEvent;
+using Ryujinx.Graphics.GAL.Multithreading.Commands.Program;
+using Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer;
+using Ryujinx.Graphics.GAL.Multithreading.Commands.Sampler;
+using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture;
+using Ryujinx.Graphics.GAL.Multithreading.Commands.Window;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Graphics.GAL.Multithreading
+{
+ static class CommandHelper
+ {
+ private delegate void CommandDelegate(Span memory, ThreadedRenderer threaded, IRenderer renderer);
+
+ private static int _totalCommands = (int)Enum.GetValues().Max() + 1;
+ private static CommandDelegate[] _lookup = new CommandDelegate[_totalCommands];
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static ref T GetCommand(Span memory)
+ {
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(memory));
+ }
+
+ public static int GetMaxCommandSize()
+ {
+ return InitLookup() + 1; // 1 byte reserved for command size.
+ }
+
+ private static int InitLookup()
+ {
+ int maxCommandSize = 0;
+
+ void Register(CommandType commandType) where T : unmanaged, IGALCommand, IGALCommand
+ {
+ maxCommandSize = Math.Max(maxCommandSize, Unsafe.SizeOf());
+ _lookup[(int)commandType] = (memory, threaded, renderer) => T.Run(ref GetCommand(memory), threaded, renderer);
+ }
+
+ Register(CommandType.Action);
+ Register(CommandType.CreateBuffer);
+ Register(CommandType.CreateProgram);
+ Register(CommandType.CreateSampler);
+ Register(CommandType.CreateSync);
+ Register(CommandType.CreateTexture);
+ Register(CommandType.GetCapabilities);
+ Register(CommandType.PreFrame);
+ Register(CommandType.ReportCounter);
+ Register(CommandType.ResetCounter);
+ Register(CommandType.UpdateCounters);
+
+ Register(CommandType.BufferDispose);
+ Register(CommandType.BufferGetData);
+ Register(CommandType.BufferSetData);
+
+ Register(CommandType.CounterEventDispose);
+ Register(CommandType.CounterEventFlush);
+
+ Register(CommandType.ProgramDispose);
+ Register(CommandType.ProgramGetBinary);
+ Register(CommandType.ProgramCheckLink);
+
+ Register(CommandType.SamplerDispose);
+
+ Register(CommandType.TextureCopyTo);
+ Register(CommandType.TextureCopyToScaled);
+ Register(CommandType.TextureCopyToSlice);
+ Register(CommandType.TextureCreateView);
+ Register(CommandType.TextureGetData);
+ Register(CommandType.TextureGetDataSlice);
+ Register(CommandType.TextureRelease);
+ Register(CommandType.TextureSetData);
+ Register(CommandType.TextureSetDataSlice);
+ Register(CommandType.TextureSetDataSliceRegion);
+ Register(CommandType.TextureSetStorage);
+
+ Register(CommandType.WindowPresent);
+
+ Register(CommandType.Barrier);
+ Register(CommandType.BeginTransformFeedback);
+ Register(CommandType.ClearBuffer);
+ Register(CommandType.ClearRenderTargetColor);
+ Register(CommandType.ClearRenderTargetDepthStencil);
+ Register(CommandType.CommandBufferBarrier);
+ Register(CommandType.CopyBuffer);
+ Register(CommandType.DispatchCompute);
+ Register(CommandType.Draw);
+ Register(CommandType.DrawIndexed);
+ Register(CommandType.DrawIndexedIndirect);
+ Register(CommandType.DrawIndexedIndirectCount);
+ Register(CommandType.DrawIndirect);
+ Register(CommandType.DrawIndirectCount);
+ Register(CommandType.DrawTexture);
+ Register(CommandType.EndHostConditionalRendering);
+ Register(CommandType.EndTransformFeedback);
+ Register(CommandType.SetAlphaTest);
+ Register(CommandType.SetBlendStateAdvanced);
+ Register(CommandType.SetBlendState);
+ Register(CommandType.SetDepthBias);
+ Register(CommandType.SetDepthClamp);
+ Register(CommandType.SetDepthMode);
+ Register(CommandType.SetDepthTest);
+ Register(CommandType.SetFaceCulling);
+ Register(CommandType.SetFrontFace);
+ Register(CommandType.SetStorageBuffers);
+ Register(CommandType.SetTransformFeedbackBuffers);
+ Register(CommandType.SetUniformBuffers);
+ Register(CommandType.SetImage);
+ Register(CommandType.SetIndexBuffer);
+ Register(CommandType.SetLineParameters);
+ Register(CommandType.SetLogicOpState);
+ Register(CommandType.SetMultisampleState);
+ Register(CommandType.SetPatchParameters);
+ Register(CommandType.SetPointParameters);
+ Register(CommandType.SetPolygonMode);
+ Register(CommandType.SetPrimitiveRestart);
+ Register(CommandType.SetPrimitiveTopology);
+ Register(CommandType.SetProgram);
+ Register(CommandType.SetRasterizerDiscard);
+ Register(CommandType.SetRenderTargetColorMasks);
+ Register(CommandType.SetRenderTargetScale);
+ Register(CommandType.SetRenderTargets);
+ Register(CommandType.SetScissor);
+ Register(CommandType.SetStencilTest);
+ Register(CommandType.SetTextureAndSampler);
+ Register(CommandType.SetUserClipDistance);
+ Register(CommandType.SetVertexAttribs);
+ Register(CommandType.SetVertexBuffers);
+ Register(CommandType.SetViewports);
+ Register(CommandType.TextureBarrier);
+ Register(CommandType.TextureBarrierTiled);
+ Register(CommandType.TryHostConditionalRendering);
+ Register(CommandType.TryHostConditionalRenderingFlush);
+ Register(CommandType.UpdateRenderScale);
+
+ return maxCommandSize;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void RunCommand(Span memory, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ _lookup[memory[memory.Length - 1]](memory, threaded, renderer);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs b/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs
new file mode 100644
index 00000000..61e729b4
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs
@@ -0,0 +1,102 @@
+namespace Ryujinx.Graphics.GAL.Multithreading
+{
+ enum CommandType : byte
+ {
+ Action,
+ CreateBuffer,
+ CreateProgram,
+ CreateSampler,
+ CreateSync,
+ CreateTexture,
+ GetCapabilities,
+ Unused,
+ PreFrame,
+ ReportCounter,
+ ResetCounter,
+ UpdateCounters,
+
+ BufferDispose,
+ BufferGetData,
+ BufferSetData,
+
+ CounterEventDispose,
+ CounterEventFlush,
+
+ ProgramDispose,
+ ProgramGetBinary,
+ ProgramCheckLink,
+
+ SamplerDispose,
+
+ TextureCopyTo,
+ TextureCopyToScaled,
+ TextureCopyToSlice,
+ TextureCreateView,
+ TextureGetData,
+ TextureGetDataSlice,
+ TextureRelease,
+ TextureSetData,
+ TextureSetDataSlice,
+ TextureSetDataSliceRegion,
+ TextureSetStorage,
+
+ WindowPresent,
+
+ Barrier,
+ BeginTransformFeedback,
+ ClearBuffer,
+ ClearRenderTargetColor,
+ ClearRenderTargetDepthStencil,
+ CommandBufferBarrier,
+ CopyBuffer,
+ DispatchCompute,
+ Draw,
+ DrawIndexed,
+ DrawIndexedIndirect,
+ DrawIndexedIndirectCount,
+ DrawIndirect,
+ DrawIndirectCount,
+ DrawTexture,
+ EndHostConditionalRendering,
+ EndTransformFeedback,
+ SetAlphaTest,
+ SetBlendStateAdvanced,
+ SetBlendState,
+ SetDepthBias,
+ SetDepthClamp,
+ SetDepthMode,
+ SetDepthTest,
+ SetFaceCulling,
+ SetFrontFace,
+ SetStorageBuffers,
+ SetTransformFeedbackBuffers,
+ SetUniformBuffers,
+ SetImage,
+ SetIndexBuffer,
+ SetLineParameters,
+ SetLogicOpState,
+ SetMultisampleState,
+ SetPatchParameters,
+ SetPointParameters,
+ SetPolygonMode,
+ SetPrimitiveRestart,
+ SetPrimitiveTopology,
+ SetProgram,
+ SetRasterizerDiscard,
+ SetRenderTargetColorMasks,
+ SetRenderTargetScale,
+ SetRenderTargets,
+ SetScissor,
+ SetStencilTest,
+ SetTextureAndSampler,
+ SetUserClipDistance,
+ SetVertexAttribs,
+ SetVertexBuffers,
+ SetViewports,
+ TextureBarrier,
+ TextureBarrierTiled,
+ TryHostConditionalRendering,
+ TryHostConditionalRenderingFlush,
+ UpdateRenderScale
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/BarrierCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/BarrierCommand.cs
new file mode 100644
index 00000000..4f8e1b08
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/BarrierCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct BarrierCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.Barrier;
+
+ public static void Run(ref BarrierCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.Barrier();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/BeginTransformFeedbackCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/BeginTransformFeedbackCommand.cs
new file mode 100644
index 00000000..50032635
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/BeginTransformFeedbackCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct BeginTransformFeedbackCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferDisposeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferDisposeCommand.cs
new file mode 100644
index 00000000..5be42fff
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferDisposeCommand.cs
@@ -0,0 +1,19 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer
+{
+ struct BufferDisposeCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs
new file mode 100644
index 00000000..031c6153
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.BufferGetData;
+ private BufferHandle _buffer;
+ private int _offset;
+ private int _size;
+ private TableRef>> _result;
+
+ public void Set(BufferHandle buffer, int offset, int size, TableRef>> result)
+ {
+ _buffer = buffer;
+ _offset = offset;
+ _size = size;
+ _result = result;
+ }
+
+ public static void Run(ref BufferGetDataCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ PinnedSpan result = renderer.GetBufferData(threaded.Buffers.MapBuffer(command._buffer), command._offset, command._size);
+
+ command._result.Get(threaded).Result = result;
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferSetDataCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferSetDataCommand.cs
new file mode 100644
index 00000000..dcb8c2f2
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.BufferSetData;
+ private BufferHandle _buffer;
+ private int _offset;
+ private SpanRef _data;
+
+ public void Set(BufferHandle buffer, int offset, SpanRef data)
+ {
+ _buffer = buffer;
+ _offset = offset;
+ _data = data;
+ }
+
+ public static void Run(ref BufferSetDataCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ReadOnlySpan data = command._data.Get(threaded);
+ renderer.SetBufferData(threaded.Buffers.MapBuffer(command._buffer), command._offset, data);
+ command._data.Dispose(threaded);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearBufferCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearBufferCommand.cs
new file mode 100644
index 00000000..1d70460a
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearBufferCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct ClearBufferCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetColorCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetColorCommand.cs
new file mode 100644
index 00000000..f8c2bdfe
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetColorCommand.cs
@@ -0,0 +1,26 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct ClearRenderTargetColorCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.ClearRenderTargetColor;
+ private int _index;
+ private int _layer;
+ private int _layerCount;
+ private uint _componentMask;
+ private ColorF _color;
+
+ public void Set(int index, int layer, int layerCount, uint componentMask, ColorF color)
+ {
+ _index = index;
+ _layer = layer;
+ _layerCount = layerCount;
+ _componentMask = componentMask;
+ _color = color;
+ }
+
+ public static void Run(ref ClearRenderTargetColorCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.ClearRenderTargetColor(command._index, command._layer, command._layerCount, command._componentMask, command._color);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetDepthStencilCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetDepthStencilCommand.cs
new file mode 100644
index 00000000..ca86673e
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ClearRenderTargetDepthStencilCommand.cs
@@ -0,0 +1,28 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct ClearRenderTargetDepthStencilCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.ClearRenderTargetDepthStencil;
+ private int _layer;
+ private int _layerCount;
+ private float _depthValue;
+ private bool _depthMask;
+ private int _stencilValue;
+ private int _stencilMask;
+
+ public void Set(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
+ {
+ _layer = layer;
+ _layerCount = layerCount;
+ _depthValue = depthValue;
+ _depthMask = depthMask;
+ _stencilValue = stencilValue;
+ _stencilMask = stencilMask;
+ }
+
+ public static void Run(ref ClearRenderTargetDepthStencilCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.ClearRenderTargetDepthStencil(command._layer, command._layerCount, command._depthValue, command._depthMask, command._stencilValue, command._stencilMask);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CommandBufferBarrierCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CommandBufferBarrierCommand.cs
new file mode 100644
index 00000000..ad3ab0f8
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CommandBufferBarrierCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct CommandBufferBarrierCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.CommandBufferBarrier;
+
+ public static void Run(ref CommandBufferBarrierCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.CommandBufferBarrier();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CopyBufferCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CopyBufferCommand.cs
new file mode 100644
index 00000000..43111bce
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CopyBufferCommand.cs
@@ -0,0 +1,26 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct CopyBufferCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventDisposeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventDisposeCommand.cs
new file mode 100644
index 00000000..e5250212
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.CounterEventDispose;
+ private TableRef _event;
+
+ public void Set(TableRef evt)
+ {
+ _event = evt;
+ }
+
+ public static void Run(ref CounterEventDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._event.Get(threaded).Base.Dispose();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventFlushCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/CounterEvent/CounterEventFlushCommand.cs
new file mode 100644
index 00000000..608cf8f9
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.CounterEventFlush;
+ private TableRef _event;
+
+ public void Set(TableRef evt)
+ {
+ _event = evt;
+ }
+
+ public static void Run(ref CounterEventFlushCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._event.Get(threaded).Base.Flush();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DispatchComputeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DispatchComputeCommand.cs
new file mode 100644
index 00000000..29568837
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DispatchComputeCommand.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DispatchComputeCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawCommand.cs
new file mode 100644
index 00000000..804eaa49
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawCommand.cs
@@ -0,0 +1,26 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawIndexedCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedCommand.cs
new file mode 100644
index 00000000..1b28afcd
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedIndirectCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedIndirectCommand.cs
new file mode 100644
index 00000000..521b2f0c
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedIndirectCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawIndexedIndirectCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.DrawIndexedIndirect;
+ private BufferRange _indirectBuffer;
+
+ public void Set(BufferRange indirectBuffer)
+ {
+ _indirectBuffer = indirectBuffer;
+ }
+
+ public static void Run(ref DrawIndexedIndirectCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.DrawIndexedIndirect(threaded.Buffers.MapBufferRange(command._indirectBuffer));
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedIndirectCountCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedIndirectCountCommand.cs
new file mode 100644
index 00000000..6bdf376d
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndexedIndirectCountCommand.cs
@@ -0,0 +1,29 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawIndexedIndirectCountCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.DrawIndexedIndirectCount;
+ 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 DrawIndexedIndirectCountCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.DrawIndexedIndirectCount(
+ threaded.Buffers.MapBufferRange(command._indirectBuffer),
+ threaded.Buffers.MapBufferRange(command._parameterBuffer),
+ command._maxDrawCount,
+ command._stride
+ );
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndirectCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndirectCommand.cs
new file mode 100644
index 00000000..e1947084
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndirectCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawIndirectCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.DrawIndirect;
+ private BufferRange _indirectBuffer;
+
+ public void Set(BufferRange indirectBuffer)
+ {
+ _indirectBuffer = indirectBuffer;
+ }
+
+ public static void Run(ref DrawIndirectCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.DrawIndirect(threaded.Buffers.MapBufferRange(command._indirectBuffer));
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndirectCountCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndirectCountCommand.cs
new file mode 100644
index 00000000..ef56ffb2
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawIndirectCountCommand.cs
@@ -0,0 +1,29 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawIndirectCountCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.DrawIndirectCount;
+ 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 DrawIndirectCountCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.DrawIndirectCount(
+ threaded.Buffers.MapBufferRange(command._indirectBuffer),
+ threaded.Buffers.MapBufferRange(command._parameterBuffer),
+ command._maxDrawCount,
+ command._stride
+ );
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawTextureCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawTextureCommand.cs
new file mode 100644
index 00000000..b3e9c4b5
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/DrawTextureCommand.cs
@@ -0,0 +1,31 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct DrawTextureCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.DrawTexture;
+ private TableRef _texture;
+ private TableRef _sampler;
+ private Extents2DF _srcRegion;
+ private Extents2DF _dstRegion;
+
+ public void Set(TableRef texture, TableRef sampler, Extents2DF srcRegion, Extents2DF dstRegion)
+ {
+ _texture = texture;
+ _sampler = sampler;
+ _srcRegion = srcRegion;
+ _dstRegion = dstRegion;
+ }
+
+ public static void Run(ref DrawTextureCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.DrawTexture(
+ command._texture.GetAs(threaded)?.Base,
+ command._sampler.GetAs(threaded)?.Base,
+ command._srcRegion,
+ command._dstRegion);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/EndHostConditionalRenderingCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/EndHostConditionalRenderingCommand.cs
new file mode 100644
index 00000000..877af23b
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/EndHostConditionalRenderingCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct EndHostConditionalRenderingCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.EndHostConditionalRendering;
+
+ public static void Run(ref EndHostConditionalRenderingCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.EndHostConditionalRendering();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/EndTransformFeedbackCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/EndTransformFeedbackCommand.cs
new file mode 100644
index 00000000..33df325f
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/EndTransformFeedbackCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct EndTransformFeedbackCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.EndTransformFeedback;
+
+ public static void Run(ref EndTransformFeedbackCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.EndTransformFeedback();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/IGALCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/IGALCommand.cs
new file mode 100644
index 00000000..ea831c8d
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/IGALCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ interface IGALCommand
+ {
+ CommandType CommandType { get; }
+ }
+
+ interface IGALCommand where T : IGALCommand
+ {
+ abstract static void Run(ref T command, ThreadedRenderer threaded, IRenderer renderer);
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramCheckLinkCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramCheckLinkCommand.cs
new file mode 100644
index 00000000..f3662424
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.ProgramCheckLink;
+ private TableRef _program;
+ private bool _blocking;
+ private TableRef> _result;
+
+ public void Set(TableRef program, bool blocking, TableRef> 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramDisposeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramDisposeCommand.cs
new file mode 100644
index 00000000..d1ec4298
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.ProgramDispose;
+ private TableRef _program;
+
+ public void Set(TableRef program)
+ {
+ _program = program;
+ }
+
+ public static void Run(ref ProgramDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._program.Get(threaded).Base.Dispose();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramGetBinaryCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Program/ProgramGetBinaryCommand.cs
new file mode 100644
index 00000000..16963245
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.ProgramGetBinary;
+ private TableRef _program;
+ private TableRef> _result;
+
+ public void Set(TableRef program, TableRef> 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ActionCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ActionCommand.cs
new file mode 100644
index 00000000..41987da1
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.Action;
+ private TableRef _action;
+
+ public void Set(TableRef action)
+ {
+ _action = action;
+ }
+
+ public static void Run(ref ActionCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._action.Get(threaded)();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs
new file mode 100644
index 00000000..b36d8bbe
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs
@@ -0,0 +1,29 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct CreateBufferCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateBuffer;
+ private BufferHandle _threadedHandle;
+ private int _size;
+ private BufferHandle _storageHint;
+
+ public void Set(BufferHandle threadedHandle, int size, BufferHandle storageHint)
+ {
+ _threadedHandle = threadedHandle;
+ _size = size;
+ _storageHint = storageHint;
+ }
+
+ public static void Run(ref CreateBufferCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ BufferHandle hint = BufferHandle.Null;
+
+ if (command._storageHint != BufferHandle.Null)
+ {
+ hint = threaded.Buffers.MapBuffer(command._storageHint);
+ }
+
+ threaded.Buffers.AssignBuffer(command._threadedHandle, renderer.CreateBuffer(command._size, hint));
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateProgramCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateProgramCommand.cs
new file mode 100644
index 00000000..19563e12
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateProgram;
+ private TableRef _request;
+
+ public void Set(TableRef 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSamplerCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSamplerCommand.cs
new file mode 100644
index 00000000..6ab862d4
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateSampler;
+ private TableRef _sampler;
+ private SamplerCreateInfo _info;
+
+ public void Set(TableRef 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSyncCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSyncCommand.cs
new file mode 100644
index 00000000..32afb051
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateSyncCommand.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct CreateSyncCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateSync;
+ private ulong _id;
+ private bool _strict;
+
+ public void Set(ulong id, bool strict)
+ {
+ _id = id;
+ _strict = strict;
+ }
+
+ public static void Run(ref CreateSyncCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.CreateSync(command._id, command._strict);
+
+ threaded.Sync.AssignSync(command._id);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateTextureCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateTextureCommand.cs
new file mode 100644
index 00000000..0347ded4
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.CreateTexture;
+ private TableRef _texture;
+ private TextureCreateInfo _info;
+ private float _scale;
+
+ public void Set(TableRef 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/GetCapabilitiesCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/GetCapabilitiesCommand.cs
new file mode 100644
index 00000000..4111dcfd
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.GetCapabilities;
+ private TableRef> _result;
+
+ public void Set(TableRef> result)
+ {
+ _result = result;
+ }
+
+ public static void Run(ref GetCapabilitiesCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._result.Get(threaded).Result = renderer.GetCapabilities();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/PreFrameCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/PreFrameCommand.cs
new file mode 100644
index 00000000..820908f3
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/PreFrameCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct PreFrameCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.PreFrame;
+
+ public static void Run(ref PreFrameCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.PreFrame();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ReportCounterCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ReportCounterCommand.cs
new file mode 100644
index 00000000..4b0210cb
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.ReportCounter;
+ private TableRef _event;
+ private CounterType _type;
+ private TableRef> _resultHandler;
+ private bool _hostReserved;
+
+ public void Set(TableRef evt, CounterType type, TableRef> 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ResetCounterCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ResetCounterCommand.cs
new file mode 100644
index 00000000..3d796041
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/ResetCounterCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct ResetCounterCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/UpdateCountersCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/UpdateCountersCommand.cs
new file mode 100644
index 00000000..c7076c0e
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/UpdateCountersCommand.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
+{
+ struct UpdateCountersCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.UpdateCounters;
+
+ public static void Run(ref UpdateCountersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.UpdateCounters();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Sampler/SamplerDisposeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Sampler/SamplerDisposeCommand.cs
new file mode 100644
index 00000000..9485e9a1
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SamplerDispose;
+ private TableRef _sampler;
+
+ public void Set(TableRef sampler)
+ {
+ _sampler = sampler;
+ }
+
+ public static void Run(ref SamplerDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ command._sampler.Get(threaded).Base.Dispose();
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetAlphaTestCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetAlphaTestCommand.cs
new file mode 100644
index 00000000..a96879ff
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetAlphaTestCommand.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetAlphaTestCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateAdvancedCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateAdvancedCommand.cs
new file mode 100644
index 00000000..2ec10a50
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateAdvancedCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetBlendStateAdvancedCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetBlendStateAdvanced;
+ private AdvancedBlendDescriptor _blend;
+
+ public void Set(AdvancedBlendDescriptor blend)
+ {
+ _blend = blend;
+ }
+
+ public static void Run(ref SetBlendStateAdvancedCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetBlendState(command._blend);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateCommand.cs
new file mode 100644
index 00000000..68e48da5
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetBlendStateCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetBlendStateCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthBiasCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthBiasCommand.cs
new file mode 100644
index 00000000..eb8d4a72
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthBiasCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetDepthBiasCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthClampCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthClampCommand.cs
new file mode 100644
index 00000000..15159cb4
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthClampCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetDepthClampCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthModeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthModeCommand.cs
new file mode 100644
index 00000000..3e169164
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthModeCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetDepthModeCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthTestCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthTestCommand.cs
new file mode 100644
index 00000000..2abaeb78
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetDepthTestCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetDepthTestCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs
new file mode 100644
index 00000000..54311e95
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetFaceCullingCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFrontFaceCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFrontFaceCommand.cs
new file mode 100644
index 00000000..e4d7b814
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFrontFaceCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetFrontFaceCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs
new file mode 100644
index 00000000..7836acd7
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetImage;
+ private int _binding;
+ private TableRef _texture;
+ private Format _imageFormat;
+
+ public void Set(int binding, TableRef 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(threaded)?.Base, command._imageFormat);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetIndexBufferCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetIndexBufferCommand.cs
new file mode 100644
index 00000000..ded44c55
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetIndexBufferCommand.cs
@@ -0,0 +1,21 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetIndexBufferCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLineParametersCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLineParametersCommand.cs
new file mode 100644
index 00000000..68331932
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLineParametersCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetLineParametersCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLogicOpStateCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLogicOpStateCommand.cs
new file mode 100644
index 00000000..2d7fc169
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetLogicOpStateCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetLogicOpStateCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetMultisampleStateCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetMultisampleStateCommand.cs
new file mode 100644
index 00000000..f7b4969a
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetMultisampleStateCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetMultisampleStateCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetMultisampleState;
+ private MultisampleDescriptor _multisample;
+
+ public void Set(MultisampleDescriptor multisample)
+ {
+ _multisample = multisample;
+ }
+
+ public static void Run(ref SetMultisampleStateCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetMultisampleState(command._multisample);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPatchParametersCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPatchParametersCommand.cs
new file mode 100644
index 00000000..815bc3c2
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPatchParametersCommand.cs
@@ -0,0 +1,25 @@
+using Ryujinx.Common.Memory;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetPatchParametersCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetPatchParameters;
+ private int _vertices;
+ private Array4 _defaultOuterLevel;
+ private Array2 _defaultInnerLevel;
+
+ public void Set(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel)
+ {
+ _vertices = vertices;
+ defaultOuterLevel.CopyTo(_defaultOuterLevel.AsSpan());
+ defaultInnerLevel.CopyTo(_defaultInnerLevel.AsSpan());
+ }
+
+ public static void Run(ref SetPatchParametersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetPatchParameters(command._vertices, command._defaultOuterLevel.AsSpan(), command._defaultInnerLevel.AsSpan());
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPointParametersCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPointParametersCommand.cs
new file mode 100644
index 00000000..e3fad0f8
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPointParametersCommand.cs
@@ -0,0 +1,24 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetPointParametersCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPolygonModeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPolygonModeCommand.cs
new file mode 100644
index 00000000..ea2f838b
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPolygonModeCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetPolygonModeCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetPolygonMode;
+ private PolygonMode _frontMode;
+ private PolygonMode _backMode;
+
+ public void Set(PolygonMode frontMode, PolygonMode backMode)
+ {
+ _frontMode = frontMode;
+ _backMode = backMode;
+ }
+
+ public static void Run(ref SetPolygonModeCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetPolygonMode(command._frontMode, command._backMode);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveRestartCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveRestartCommand.cs
new file mode 100644
index 00000000..26b88b01
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveRestartCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetPrimitiveRestartCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveTopologyCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveTopologyCommand.cs
new file mode 100644
index 00000000..062c4e57
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetPrimitiveTopologyCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetPrimitiveTopologyCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetProgramCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetProgramCommand.cs
new file mode 100644
index 00000000..fa2e9a8a
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetProgram;
+ private TableRef _program;
+
+ public void Set(TableRef program)
+ {
+ _program = program;
+ }
+
+ public static void Run(ref SetProgramCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ThreadedProgram program = command._program.GetAs(threaded);
+
+ threaded.Programs.WaitForProgram(program);
+
+ renderer.Pipeline.SetProgram(program.Base);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRasterizerDiscardCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRasterizerDiscardCommand.cs
new file mode 100644
index 00000000..d2095a4f
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRasterizerDiscardCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetRasterizerDiscardCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetColorMasksCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetColorMasksCommand.cs
new file mode 100644
index 00000000..c247ff3a
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetRenderTargetColorMasks;
+ private SpanRef _componentMask;
+
+ public void Set(SpanRef componentMask)
+ {
+ _componentMask = componentMask;
+ }
+
+ public static void Run(ref SetRenderTargetColorMasksCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ ReadOnlySpan componentMask = command._componentMask.Get(threaded);
+ renderer.Pipeline.SetRenderTargetColorMasks(componentMask);
+ command._componentMask.Dispose(threaded);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetScaleCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetScaleCommand.cs
new file mode 100644
index 00000000..7cb5ec11
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetScaleCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetRenderTargetScaleCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetsCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetRenderTargetsCommand.cs
new file mode 100644
index 00000000..0b175a72
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetRenderTargets;
+ private TableRef _colors;
+ private TableRef _depthStencil;
+
+ public void Set(TableRef colors, TableRef 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(threaded)?.Base);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetScissorsCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetScissorsCommand.cs
new file mode 100644
index 00000000..985d775e
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetScissorsCommand.cs
@@ -0,0 +1,22 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetScissorsCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetScissor;
+ private SpanRef> _scissors;
+
+ public void Set(SpanRef> scissors)
+ {
+ _scissors = scissors;
+ }
+
+ public static void Run(ref SetScissorsCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetScissors(command._scissors.Get(threaded));
+
+ command._scissors.Dispose(threaded);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStencilTestCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStencilTestCommand.cs
new file mode 100644
index 00000000..41bff97e
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStencilTestCommand.cs
@@ -0,0 +1,18 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetStencilTestCommand : IGALCommand, 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/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs
new file mode 100644
index 00000000..6ecb0989
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetStorageBuffersCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetStorageBuffers;
+ private SpanRef _buffers;
+
+ public void Set(SpanRef buffers)
+ {
+ _buffers = buffers;
+ }
+
+ public static void Run(ref SetStorageBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ Span buffers = command._buffers.Get(threaded);
+ renderer.Pipeline.SetStorageBuffers(threaded.Buffers.MapBufferRanges(buffers));
+ command._buffers.Dispose(threaded);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTextureAndSamplerCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTextureAndSamplerCommand.cs
new file mode 100644
index 00000000..5e8e0854
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTextureAndSamplerCommand.cs
@@ -0,0 +1,28 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using Ryujinx.Graphics.GAL.Multithreading.Resources;
+using Ryujinx.Graphics.Shader;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetTextureAndSamplerCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetTextureAndSampler;
+ private ShaderStage _stage;
+ private int _binding;
+ private TableRef _texture;
+ private TableRef _sampler;
+
+ public void Set(ShaderStage stage, int binding, TableRef texture, TableRef sampler)
+ {
+ _stage = stage;
+ _binding = binding;
+ _texture = texture;
+ _sampler = sampler;
+ }
+
+ public static void Run(ref SetTextureAndSamplerCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ renderer.Pipeline.SetTextureAndSampler(command._stage, command._binding, command._texture.GetAs(threaded)?.Base, command._sampler.GetAs(threaded)?.Base);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTransformFeedbackBuffersCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetTransformFeedbackBuffersCommand.cs
new file mode 100644
index 00000000..e0d4ef2d
--- /dev/null
+++ b/src/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, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetTransformFeedbackBuffers;
+ private SpanRef _buffers;
+
+ public void Set(SpanRef buffers)
+ {
+ _buffers = buffers;
+ }
+
+ public static void Run(ref SetTransformFeedbackBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ Span buffers = command._buffers.Get(threaded);
+ renderer.Pipeline.SetTransformFeedbackBuffers(threaded.Buffers.MapBufferRanges(buffers));
+ command._buffers.Dispose(threaded);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs
new file mode 100644
index 00000000..9e93db9e
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs
@@ -0,0 +1,23 @@
+using Ryujinx.Graphics.GAL.Multithreading.Model;
+using System;
+
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetUniformBuffersCommand : IGALCommand, IGALCommand
+ {
+ public CommandType CommandType => CommandType.SetUniformBuffers;
+ private SpanRef _buffers;
+
+ public void Set(SpanRef buffers)
+ {
+ _buffers = buffers;
+ }
+
+ public static void Run(ref SetUniformBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer)
+ {
+ Span buffers = command._buffers.Get(threaded);
+ renderer.Pipeline.SetUniformBuffers(threaded.Buffers.MapBufferRanges(buffers));
+ command._buffers.Dispose(threaded);
+ }
+ }
+}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUserClipDistanceCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUserClipDistanceCommand.cs
new file mode 100644
index 00000000..4336ce49
--- /dev/null
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUserClipDistanceCommand.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.Graphics.GAL.Multithreading.Commands
+{
+ struct SetUserClipDistanceCommand : IGALCommand, IGALCommand