From efdfe83418b832128fc90ac63d902372e027b66f Mon Sep 17 00:00:00 2001 From: LotP1 <68976644+LotP1@users.noreply.github.com> Date: Sun, 26 Oct 2025 15:08:23 +0100 Subject: [PATCH] pointer based commands removes unnecessary allocations of graphics commands --- .../Resources/ThreadedCounterEvent.cs | 4 +- .../Resources/ThreadedImageArray.cs | 8 +- .../Resources/ThreadedProgram.cs | 12 +- .../Resources/ThreadedSampler.cs | 4 +- .../Resources/ThreadedTexture.cs | 48 ++-- .../Resources/ThreadedTextureArray.cs | 12 +- .../Multithreading/ThreadedPipeline.cs | 222 +++++++++--------- .../Multithreading/ThreadedRenderer.cs | 81 +++---- .../Multithreading/ThreadedWindow.cs | 4 +- 9 files changed, 198 insertions(+), 197 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedCounterEvent.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedCounterEvent.cs index 15db2b9fa..557c2ae04 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedCounterEvent.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedCounterEvent.cs @@ -29,9 +29,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources return new TableRef(_renderer, reference); } - public void Dispose() + public unsafe void Dispose() { - _renderer.New().Set(Ref(this)); + _renderer.New()->Set(Ref(this)); _renderer.QueueCommand(); } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs index 82587c189..a415dbbf0 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs @@ -21,15 +21,15 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources return new TableRef(_renderer, reference); } - public void Dispose() + public unsafe void Dispose() { - _renderer.New().Set(Ref(this)); + _renderer.New()->Set(Ref(this)); _renderer.QueueCommand(); } - public void SetImages(int index, ITexture[] images) + public unsafe void SetImages(int index, ITexture[] images) { - _renderer.New().Set(Ref(this), index, Ref(images)); + _renderer.New()->Set(Ref(this), index, Ref(images)); _renderer.QueueCommand(); } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedProgram.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedProgram.cs index d5a22f669..9573bbaac 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedProgram.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedProgram.cs @@ -21,25 +21,25 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources return new TableRef(_renderer, reference); } - public void Dispose() + public unsafe void Dispose() { - _renderer.New().Set(Ref(this)); + _renderer.New()->Set(Ref(this)); _renderer.QueueCommand(); } - public byte[] GetBinary() + public unsafe byte[] GetBinary() { ResultBox box = new(); - _renderer.New().Set(Ref(this), Ref(box)); + _renderer.New()->Set(Ref(this), Ref(box)); _renderer.InvokeCommand(); return box.Result; } - public ProgramLinkStatus CheckProgramLink(bool blocking) + public unsafe ProgramLinkStatus CheckProgramLink(bool blocking) { ResultBox box = new(); - _renderer.New().Set(Ref(this), blocking, Ref(box)); + _renderer.New()->Set(Ref(this), blocking, Ref(box)); _renderer.InvokeCommand(); return box.Result; diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedSampler.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedSampler.cs index ae3d993a3..8dc9647ab 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedSampler.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedSampler.cs @@ -13,9 +13,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources _renderer = renderer; } - public void Dispose() + public unsafe void Dispose() { - _renderer.New().Set(new TableRef(_renderer, this)); + _renderer.New()->Set(new TableRef(_renderer, this)); _renderer.QueueCommand(); } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs index fa71d20b3..e33b58745 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs @@ -28,25 +28,25 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources return new TableRef(_renderer, reference); } - public void CopyTo(ITexture destination, int firstLayer, int firstLevel) + public unsafe void CopyTo(ITexture destination, int firstLayer, int firstLevel) { - _renderer.New().Set(Ref(this), Ref((ThreadedTexture)destination), firstLayer, firstLevel); + _renderer.New()->Set(Ref(this), Ref((ThreadedTexture)destination), firstLayer, firstLevel); _renderer.QueueCommand(); } - public void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel) + public unsafe void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel) { - _renderer.New().Set(Ref(this), Ref((ThreadedTexture)destination), srcLayer, dstLayer, srcLevel, dstLevel); + _renderer.New()->Set(Ref(this), Ref((ThreadedTexture)destination), srcLayer, dstLayer, srcLevel, dstLevel); _renderer.QueueCommand(); } - public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter) + public unsafe void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter) { ThreadedTexture dest = (ThreadedTexture)destination; if (_renderer.IsGpuThread()) { - _renderer.New().Set(Ref(this), Ref(dest), srcRegion, dstRegion, linearFilter); + _renderer.New()->Set(Ref(this), Ref(dest), srcRegion, dstRegion, linearFilter); _renderer.QueueCommand(); } else @@ -59,21 +59,21 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources } } - public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) + public unsafe ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) { ThreadedTexture newTex = new(_renderer, info); - _renderer.New().Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel); + _renderer.New()->Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel); _renderer.QueueCommand(); return newTex; } - public PinnedSpan GetData() + public unsafe PinnedSpan GetData() { if (_renderer.IsGpuThread()) { ResultBox> box = new(); - _renderer.New().Set(Ref(this), Ref(box)); + _renderer.New()->Set(Ref(this), Ref(box)); _renderer.InvokeCommand(); return box.Result; @@ -86,12 +86,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources } } - public PinnedSpan GetData(int layer, int level) + public unsafe PinnedSpan GetData(int layer, int level) { if (_renderer.IsGpuThread()) { ResultBox> box = new(); - _renderer.New().Set(Ref(this), Ref(box), layer, level); + _renderer.New()->Set(Ref(this), Ref(box), layer, level); _renderer.InvokeCommand(); return box.Result; @@ -104,42 +104,42 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources } } - public void CopyTo(BufferRange range, int layer, int level, int stride) + public unsafe void CopyTo(BufferRange range, int layer, int level, int stride) { - _renderer.New().Set(Ref(this), range, layer, level, stride); + _renderer.New()->Set(Ref(this), range, layer, level, stride); _renderer.QueueCommand(); } /// - public void SetData(MemoryOwner data) + public unsafe void SetData(MemoryOwner data) { - _renderer.New().Set(Ref(this), Ref(data)); + _renderer.New()->Set(Ref(this), Ref(data)); _renderer.QueueCommand(); } /// - public void SetData(MemoryOwner data, int layer, int level) + public unsafe void SetData(MemoryOwner data, int layer, int level) { - _renderer.New().Set(Ref(this), Ref(data), layer, level); + _renderer.New()->Set(Ref(this), Ref(data), layer, level); _renderer.QueueCommand(); } /// - public void SetData(MemoryOwner data, int layer, int level, Rectangle region) + public unsafe void SetData(MemoryOwner data, int layer, int level, Rectangle region) { - _renderer.New().Set(Ref(this), Ref(data), layer, level, region); + _renderer.New()->Set(Ref(this), Ref(data), layer, level, region); _renderer.QueueCommand(); } - public void SetStorage(BufferRange buffer) + public unsafe void SetStorage(BufferRange buffer) { - _renderer.New().Set(Ref(this), buffer); + _renderer.New()->Set(Ref(this), buffer); _renderer.QueueCommand(); } - public void Release() + public unsafe void Release() { - _renderer.New().Set(Ref(this)); + _renderer.New()->Set(Ref(this)); _renderer.QueueCommand(); } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTextureArray.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTextureArray.cs index 4334c7048..56b0e0d34 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTextureArray.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTextureArray.cs @@ -22,21 +22,21 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources return new TableRef(_renderer, reference); } - public void Dispose() + public unsafe void Dispose() { - _renderer.New().Set(Ref(this)); + _renderer.New()->Set(Ref(this)); _renderer.QueueCommand(); } - public void SetSamplers(int index, ISampler[] samplers) + public unsafe void SetSamplers(int index, ISampler[] samplers) { - _renderer.New().Set(Ref(this), index, Ref(samplers.ToArray())); + _renderer.New()->Set(Ref(this), index, Ref(samplers.ToArray())); _renderer.QueueCommand(); } - public void SetTextures(int index, ITexture[] textures) + public unsafe void SetTextures(int index, ITexture[] textures) { - _renderer.New().Set(Ref(this), index, Ref(textures.ToArray())); + _renderer.New()->Set(Ref(this), index, Ref(textures.ToArray())); _renderer.QueueCommand(); } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs index c999ad789..c0fb6361e 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs @@ -21,343 +21,343 @@ namespace Ryujinx.Graphics.GAL.Multithreading return new TableRef(_renderer, reference); } - public void Barrier() + public unsafe void Barrier() { _renderer.New(); _renderer.QueueCommand(); } - public void BeginTransformFeedback(PrimitiveTopology topology) + public unsafe void BeginTransformFeedback(PrimitiveTopology topology) { - _renderer.New().Set(topology); + _renderer.New()->Set(topology); _renderer.QueueCommand(); } - public void ClearBuffer(BufferHandle destination, int offset, int size, uint value) + public unsafe void ClearBuffer(BufferHandle destination, int offset, int size, uint value) { - _renderer.New().Set(destination, offset, size, value); + _renderer.New()->Set(destination, offset, size, value); _renderer.QueueCommand(); } - public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) + public unsafe void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) { - _renderer.New().Set(index, layer, layerCount, componentMask, color); + _renderer.New()->Set(index, layer, layerCount, componentMask, color); _renderer.QueueCommand(); } - public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) + public unsafe void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) { - _renderer.New().Set(layer, layerCount, depthValue, depthMask, stencilValue, stencilMask); + _renderer.New()->Set(layer, layerCount, depthValue, depthMask, stencilValue, stencilMask); _renderer.QueueCommand(); } - public void CommandBufferBarrier() + public unsafe void CommandBufferBarrier() { _renderer.New(); _renderer.QueueCommand(); } - public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) + public unsafe void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) { - _renderer.New().Set(source, destination, srcOffset, dstOffset, size); + _renderer.New()->Set(source, destination, srcOffset, dstOffset, size); _renderer.QueueCommand(); } - public void DispatchCompute(int groupsX, int groupsY, int groupsZ) + public unsafe void DispatchCompute(int groupsX, int groupsY, int groupsZ) { - _renderer.New().Set(groupsX, groupsY, groupsZ); + _renderer.New()->Set(groupsX, groupsY, groupsZ); _renderer.QueueCommand(); } - public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) + public unsafe void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) { - _renderer.New().Set(vertexCount, instanceCount, firstVertex, firstInstance); + _renderer.New()->Set(vertexCount, instanceCount, firstVertex, firstInstance); _renderer.QueueCommand(); } - public void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance) + public unsafe void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance) { - _renderer.New().Set(indexCount, instanceCount, firstIndex, firstVertex, firstInstance); + _renderer.New()->Set(indexCount, instanceCount, firstIndex, firstVertex, firstInstance); _renderer.QueueCommand(); } - public void DrawIndexedIndirect(BufferRange indirectBuffer) + public unsafe void DrawIndexedIndirect(BufferRange indirectBuffer) { - _renderer.New().Set(indirectBuffer); + _renderer.New()->Set(indirectBuffer); _renderer.QueueCommand(); } - public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) + public unsafe void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) { - _renderer.New().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride); + _renderer.New()->Set(indirectBuffer, parameterBuffer, maxDrawCount, stride); _renderer.QueueCommand(); } - public void DrawIndirect(BufferRange indirectBuffer) + public unsafe void DrawIndirect(BufferRange indirectBuffer) { - _renderer.New().Set(indirectBuffer); + _renderer.New()->Set(indirectBuffer); _renderer.QueueCommand(); } - public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) + public unsafe void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) { - _renderer.New().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride); + _renderer.New()->Set(indirectBuffer, parameterBuffer, maxDrawCount, stride); _renderer.QueueCommand(); } - public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion) + public unsafe void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion) { - _renderer.New().Set(Ref(texture), Ref(sampler), srcRegion, dstRegion); + _renderer.New()->Set(Ref(texture), Ref(sampler), srcRegion, dstRegion); _renderer.QueueCommand(); } - public void EndHostConditionalRendering() + public unsafe void EndHostConditionalRendering() { _renderer.New(); _renderer.QueueCommand(); } - public void EndTransformFeedback() + public unsafe void EndTransformFeedback() { _renderer.New(); _renderer.QueueCommand(); } - public void SetAlphaTest(bool enable, float reference, CompareOp op) + public unsafe void SetAlphaTest(bool enable, float reference, CompareOp op) { - _renderer.New().Set(enable, reference, op); + _renderer.New()->Set(enable, reference, op); _renderer.QueueCommand(); } - public void SetBlendState(AdvancedBlendDescriptor blend) + public unsafe void SetBlendState(AdvancedBlendDescriptor blend) { - _renderer.New().Set(blend); + _renderer.New()->Set(blend); _renderer.QueueCommand(); } - public void SetBlendState(int index, BlendDescriptor blend) + public unsafe void SetBlendState(int index, BlendDescriptor blend) { - _renderer.New().Set(index, blend); + _renderer.New()->Set(index, blend); _renderer.QueueCommand(); } - public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) + public unsafe void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { - _renderer.New().Set(enables, factor, units, clamp); + _renderer.New()->Set(enables, factor, units, clamp); _renderer.QueueCommand(); } - public void SetDepthClamp(bool clamp) + public unsafe void SetDepthClamp(bool clamp) { - _renderer.New().Set(clamp); + _renderer.New()->Set(clamp); _renderer.QueueCommand(); } - public void SetDepthMode(DepthMode mode) + public unsafe void SetDepthMode(DepthMode mode) { - _renderer.New().Set(mode); + _renderer.New()->Set(mode); _renderer.QueueCommand(); } - public void SetDepthTest(DepthTestDescriptor depthTest) + public unsafe void SetDepthTest(DepthTestDescriptor depthTest) { - _renderer.New().Set(depthTest); + _renderer.New()->Set(depthTest); _renderer.QueueCommand(); } - public void SetFaceCulling(bool enable, Face face) + public unsafe void SetFaceCulling(bool enable, Face face) { - _renderer.New().Set(enable, face); + _renderer.New()->Set(enable, face); _renderer.QueueCommand(); } - public void SetFrontFace(FrontFace frontFace) + public unsafe void SetFrontFace(FrontFace frontFace) { - _renderer.New().Set(frontFace); + _renderer.New()->Set(frontFace); _renderer.QueueCommand(); } - public void SetImage(ShaderStage stage, int binding, ITexture texture) + public unsafe void SetImage(ShaderStage stage, int binding, ITexture texture) { - _renderer.New().Set(stage, binding, Ref(texture)); + _renderer.New()->Set(stage, binding, Ref(texture)); _renderer.QueueCommand(); } - public void SetImageArray(ShaderStage stage, int binding, IImageArray array) + public unsafe void SetImageArray(ShaderStage stage, int binding, IImageArray array) { - _renderer.New().Set(stage, binding, Ref(array)); + _renderer.New()->Set(stage, binding, Ref(array)); _renderer.QueueCommand(); } - public void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array) + public unsafe void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array) { - _renderer.New().Set(stage, setIndex, Ref(array)); + _renderer.New()->Set(stage, setIndex, Ref(array)); _renderer.QueueCommand(); } - public void SetIndexBuffer(BufferRange buffer, IndexType type) + public unsafe void SetIndexBuffer(BufferRange buffer, IndexType type) { - _renderer.New().Set(buffer, type); + _renderer.New()->Set(buffer, type); _renderer.QueueCommand(); } - public void SetLineParameters(float width, bool smooth) + public unsafe void SetLineParameters(float width, bool smooth) { - _renderer.New().Set(width, smooth); + _renderer.New()->Set(width, smooth); _renderer.QueueCommand(); } - public void SetLogicOpState(bool enable, LogicalOp op) + public unsafe void SetLogicOpState(bool enable, LogicalOp op) { - _renderer.New().Set(enable, op); + _renderer.New()->Set(enable, op); _renderer.QueueCommand(); } - public void SetMultisampleState(MultisampleDescriptor multisample) + public unsafe void SetMultisampleState(MultisampleDescriptor multisample) { - _renderer.New().Set(multisample); + _renderer.New()->Set(multisample); _renderer.QueueCommand(); } - public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) + public unsafe void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - _renderer.New().Set(vertices, defaultOuterLevel, defaultInnerLevel); + _renderer.New()->Set(vertices, defaultOuterLevel, defaultInnerLevel); _renderer.QueueCommand(); } - public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin) + public unsafe void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin) { - _renderer.New().Set(size, isProgramPointSize, enablePointSprite, origin); + _renderer.New()->Set(size, isProgramPointSize, enablePointSprite, origin); _renderer.QueueCommand(); } - public void SetPolygonMode(PolygonMode frontMode, PolygonMode backMode) + public unsafe void SetPolygonMode(PolygonMode frontMode, PolygonMode backMode) { - _renderer.New().Set(frontMode, backMode); + _renderer.New()->Set(frontMode, backMode); _renderer.QueueCommand(); } - public void SetPrimitiveRestart(bool enable, int index) + public unsafe void SetPrimitiveRestart(bool enable, int index) { - _renderer.New().Set(enable, index); + _renderer.New()->Set(enable, index); _renderer.QueueCommand(); } - public void SetPrimitiveTopology(PrimitiveTopology topology) + public unsafe void SetPrimitiveTopology(PrimitiveTopology topology) { - _renderer.New().Set(topology); + _renderer.New()->Set(topology); _renderer.QueueCommand(); } - public void SetProgram(IProgram program) + public unsafe void SetProgram(IProgram program) { - _renderer.New().Set(Ref(program)); + _renderer.New()->Set(Ref(program)); _renderer.QueueCommand(); } - public void SetRasterizerDiscard(bool discard) + public unsafe void SetRasterizerDiscard(bool discard) { - _renderer.New().Set(discard); + _renderer.New()->Set(discard); _renderer.QueueCommand(); } - public void SetRenderTargetColorMasks(ReadOnlySpan componentMask) + public unsafe void SetRenderTargetColorMasks(ReadOnlySpan componentMask) { - _renderer.New().Set(_renderer.CopySpan(componentMask)); + _renderer.New()->Set(_renderer.CopySpan(componentMask)); _renderer.QueueCommand(); } - public void SetRenderTargets(ITexture[] colors, ITexture depthStencil) + public unsafe void SetRenderTargets(ITexture[] colors, ITexture depthStencil) { - _renderer.New().Set(Ref(colors.ToArray()), Ref(depthStencil)); + _renderer.New()->Set(Ref(colors.ToArray()), Ref(depthStencil)); _renderer.QueueCommand(); } - public void SetScissors(ReadOnlySpan> scissors) + public unsafe void SetScissors(ReadOnlySpan> scissors) { - _renderer.New().Set(_renderer.CopySpan(scissors)); + _renderer.New()->Set(_renderer.CopySpan(scissors)); _renderer.QueueCommand(); } - public void SetStencilTest(StencilTestDescriptor stencilTest) + public unsafe void SetStencilTest(StencilTestDescriptor stencilTest) { - _renderer.New().Set(stencilTest); + _renderer.New()->Set(stencilTest); _renderer.QueueCommand(); } - public void SetStorageBuffers(ReadOnlySpan buffers) + public unsafe void SetStorageBuffers(ReadOnlySpan buffers) { - _renderer.New().Set(_renderer.CopySpan(buffers)); + _renderer.New()->Set(_renderer.CopySpan(buffers)); _renderer.QueueCommand(); } - public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler) + public unsafe void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler) { - _renderer.New().Set(stage, binding, Ref(texture), Ref(sampler)); + _renderer.New()->Set(stage, binding, Ref(texture), Ref(sampler)); _renderer.QueueCommand(); } - public void SetTextureArray(ShaderStage stage, int binding, ITextureArray array) + public unsafe void SetTextureArray(ShaderStage stage, int binding, ITextureArray array) { - _renderer.New().Set(stage, binding, Ref(array)); + _renderer.New()->Set(stage, binding, Ref(array)); _renderer.QueueCommand(); } - public void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array) + public unsafe void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array) { - _renderer.New().Set(stage, setIndex, Ref(array)); + _renderer.New()->Set(stage, setIndex, Ref(array)); _renderer.QueueCommand(); } - public void SetTransformFeedbackBuffers(ReadOnlySpan buffers) + public unsafe void SetTransformFeedbackBuffers(ReadOnlySpan buffers) { - _renderer.New().Set(_renderer.CopySpan(buffers)); + _renderer.New()->Set(_renderer.CopySpan(buffers)); _renderer.QueueCommand(); } - public void SetUniformBuffers(ReadOnlySpan buffers) + public unsafe void SetUniformBuffers(ReadOnlySpan buffers) { - _renderer.New().Set(_renderer.CopySpan(buffers)); + _renderer.New()->Set(_renderer.CopySpan(buffers)); _renderer.QueueCommand(); } - public void SetUserClipDistance(int index, bool enableClip) + public unsafe void SetUserClipDistance(int index, bool enableClip) { - _renderer.New().Set(index, enableClip); + _renderer.New()->Set(index, enableClip); _renderer.QueueCommand(); } - public void SetVertexAttribs(ReadOnlySpan vertexAttribs) + public unsafe void SetVertexAttribs(ReadOnlySpan vertexAttribs) { - _renderer.New().Set(_renderer.CopySpan(vertexAttribs)); + _renderer.New()->Set(_renderer.CopySpan(vertexAttribs)); _renderer.QueueCommand(); } - public void SetVertexBuffers(ReadOnlySpan vertexBuffers) + public unsafe void SetVertexBuffers(ReadOnlySpan vertexBuffers) { - _renderer.New().Set(_renderer.CopySpan(vertexBuffers)); + _renderer.New()->Set(_renderer.CopySpan(vertexBuffers)); _renderer.QueueCommand(); } - public void SetViewports(ReadOnlySpan viewports) + public unsafe void SetViewports(ReadOnlySpan viewports) { - _renderer.New().Set(_renderer.CopySpan(viewports)); + _renderer.New()->Set(_renderer.CopySpan(viewports)); _renderer.QueueCommand(); } - public void TextureBarrier() + public unsafe void TextureBarrier() { _renderer.New(); _renderer.QueueCommand(); } - public void TextureBarrierTiled() + public unsafe void TextureBarrierTiled() { _renderer.New(); _renderer.QueueCommand(); } - public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual) + public unsafe bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual) { ThreadedCounterEvent evt = value as ThreadedCounterEvent; if (evt != null) @@ -369,20 +369,20 @@ namespace Ryujinx.Graphics.GAL.Multithreading return false; } - _renderer.New().Set(Ref(evt), compare, isEqual); + _renderer.New()->Set(Ref(evt), compare, isEqual); _renderer.QueueCommand(); return true; } } - _renderer.New().Set(Ref(evt), Ref(null), isEqual); + _renderer.New()->Set(Ref(evt), Ref(null), isEqual); _renderer.QueueCommand(); return false; } - public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual) + public unsafe bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual) { - _renderer.New().Set(Ref(value as ThreadedCounterEvent), Ref(compare as ThreadedCounterEvent), isEqual); + _renderer.New()->Set(Ref(value as ThreadedCounterEvent), Ref(compare as ThreadedCounterEvent), isEqual); _renderer.QueueCommand(); return false; } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs index 74a345ffa..3c179da36 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs @@ -167,7 +167,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading return new TableRef(this, reference); } - internal ref T New() where T : struct + internal unsafe T* New() where T : unmanaged, IGALCommand { while (_producerPtr == (Volatile.Read(ref _consumerPtr) + QueueCount - 1) % QueueCount) { @@ -183,11 +183,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading _producerPtr = (_producerPtr + 1) % QueueCount; Span memory = new(_commandQueue, taken * _elementSize, _elementSize); - ref T result = ref Unsafe.As(ref MemoryMarshal.GetReference(memory)); + T* result = (T*)Unsafe.AsPointer(ref memory.GetPinnableReference()); + // ref T result = ref Unsafe.As(ref MemoryMarshal.GetReference(memory)); - memory[^1] = (byte)((IGALCommand)result).CommandType; + memory[^1] = (byte)(result)->CommandType; - return ref result; + return result; } internal int AddTableRef(object obj) @@ -251,12 +252,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading return Thread.CurrentThread == _gpuThread; } - public void BackgroundContextAction(Action action, bool alwaysBackground = false) + public unsafe void BackgroundContextAction(Action action, bool alwaysBackground = false) { if (IsGpuThread() && !alwaysBackground) { // The action must be performed on the render thread. - New().Set(Ref(action)); + New()->Set(Ref(action)); InvokeCommand(); } else @@ -265,43 +266,43 @@ namespace Ryujinx.Graphics.GAL.Multithreading } } - public BufferHandle CreateBuffer(int size, BufferAccess access) + public unsafe BufferHandle CreateBuffer(int size, BufferAccess access) { BufferHandle handle = Buffers.CreateBufferHandle(); - New().Set(handle, size, access); + New()->Set(handle, size, access); QueueCommand(); return handle; } - public BufferHandle CreateBuffer(nint pointer, int size) + public unsafe BufferHandle CreateBuffer(nint pointer, int size) { BufferHandle handle = Buffers.CreateBufferHandle(); - New().Set(handle, pointer, size); + New()->Set(handle, pointer, size); QueueCommand(); return handle; } - public BufferHandle CreateBufferSparse(ReadOnlySpan storageBuffers) + public unsafe BufferHandle CreateBufferSparse(ReadOnlySpan storageBuffers) { BufferHandle handle = Buffers.CreateBufferHandle(); - New().Set(handle, CopySpan(storageBuffers)); + New()->Set(handle, CopySpan(storageBuffers)); QueueCommand(); return handle; } - public IImageArray CreateImageArray(int size, bool isBuffer) + public unsafe IImageArray CreateImageArray(int size, bool isBuffer) { ThreadedImageArray imageArray = new(this); - New().Set(Ref(imageArray), size, isBuffer); + New()->Set(Ref(imageArray), size, isBuffer); QueueCommand(); return imageArray; } - public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info) + public unsafe IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info) { ThreadedProgram program = new(this); @@ -311,34 +312,34 @@ namespace Ryujinx.Graphics.GAL.Multithreading ProgramCount++; - New().Set(Ref((IProgramRequest)request)); + New()->Set(Ref((IProgramRequest)request)); QueueCommand(); return program; } - public ISampler CreateSampler(SamplerCreateInfo info) + public unsafe ISampler CreateSampler(SamplerCreateInfo info) { ThreadedSampler sampler = new(this); - New().Set(Ref(sampler), info); + New()->Set(Ref(sampler), info); QueueCommand(); return sampler; } - public void CreateSync(ulong id, bool strict) + public unsafe void CreateSync(ulong id, bool strict) { Sync.CreateSyncHandle(id); - New().Set(id, strict); + New()->Set(id, strict); QueueCommand(); } - public ITexture CreateTexture(TextureCreateInfo info) + public unsafe ITexture CreateTexture(TextureCreateInfo info) { if (IsGpuThread()) { ThreadedTexture texture = new(this, info); - New().Set(Ref(texture), info); + New()->Set(Ref(texture), info); QueueCommand(); return texture; @@ -353,27 +354,27 @@ namespace Ryujinx.Graphics.GAL.Multithreading return texture; } } - public ITextureArray CreateTextureArray(int size, bool isBuffer) + public unsafe ITextureArray CreateTextureArray(int size, bool isBuffer) { ThreadedTextureArray textureArray = new(this); - New().Set(Ref(textureArray), size, isBuffer); + New()->Set(Ref(textureArray), size, isBuffer); QueueCommand(); return textureArray; } - public void DeleteBuffer(BufferHandle buffer) + public unsafe void DeleteBuffer(BufferHandle buffer) { - New().Set(buffer); + New()->Set(buffer); QueueCommand(); } - public PinnedSpan GetBufferData(BufferHandle buffer, int offset, int size) + public unsafe PinnedSpan GetBufferData(BufferHandle buffer, int offset, int size) { if (IsGpuThread()) { ResultBox> box = new(); - New().Set(buffer, offset, size, Ref(box)); + New()->Set(buffer, offset, size, Ref(box)); InvokeCommand(); return box.Result; @@ -384,10 +385,10 @@ namespace Ryujinx.Graphics.GAL.Multithreading } } - public Capabilities GetCapabilities() + public unsafe Capabilities GetCapabilities() { ResultBox box = new(); - New().Set(Ref(box)); + New()->Set(Ref(box)); InvokeCommand(); return box.Result; @@ -412,29 +413,29 @@ namespace Ryujinx.Graphics.GAL.Multithreading _baseRenderer.Initialize(logLevel); } - public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info) + public unsafe IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info) { ThreadedProgram program = new(this); BinaryProgramRequest request = new(program, programBinary, hasFragmentShader, info); Programs.Add(request); - New().Set(Ref((IProgramRequest)request)); + New()->Set(Ref((IProgramRequest)request)); QueueCommand(); return program; } - public void PreFrame() + public unsafe void PreFrame() { New(); QueueCommand(); } - public ICounterEvent ReportCounter(CounterType type, EventHandler resultHandler, float divisor, bool hostReserved) + public unsafe ICounterEvent ReportCounter(CounterType type, EventHandler resultHandler, float divisor, bool hostReserved) { ThreadedCounterEvent evt = new(this, type, _lastSampleCounterClear); - New().Set(Ref(evt), type, Ref(resultHandler), divisor, hostReserved); + New()->Set(Ref(evt), type, Ref(resultHandler), divisor, hostReserved); QueueCommand(); if (type == CounterType.SamplesPassed) @@ -445,9 +446,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading return evt; } - public void ResetCounter(CounterType type) + public unsafe void ResetCounter(CounterType type) { - New().Set(type); + New()->Set(type); QueueCommand(); _lastSampleCounterClear = true; } @@ -457,13 +458,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading _baseRenderer.Screenshot(); } - public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan data) + public unsafe void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan data) { - New().Set(buffer, offset, CopySpan(data)); + New()->Set(buffer, offset, CopySpan(data)); QueueCommand(); } - public void UpdateCounters() + public unsafe void UpdateCounters() { New(); QueueCommand(); diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs index 7a4836982..78c39c493 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs @@ -17,13 +17,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading _impl = impl; } - public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback) + public unsafe void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback) { // If there's already a frame in the pipeline, wait for it to be presented first. // This is a multithread rate limit - we can't be more than one frame behind the command queue. _renderer.WaitForFrame(); - _renderer.New().Set(new TableRef(_renderer, texture as ThreadedTexture), crop, new TableRef(_renderer, swapBuffersCallback)); + _renderer.New()->Set(new TableRef(_renderer, texture as ThreadedTexture), crop, new TableRef(_renderer, swapBuffersCallback)); _renderer.QueueCommand(); }