diff --git a/Ryujinx.Graphics.GAL/BufferAssignment.cs b/Ryujinx.Graphics.GAL/BufferAssignment.cs new file mode 100644 index 000000000..9f0f56c5f --- /dev/null +++ b/Ryujinx.Graphics.GAL/BufferAssignment.cs @@ -0,0 +1,14 @@ +namespace Ryujinx.Graphics.GAL +{ + public struct BufferAssignment + { + public readonly int Binding; + public readonly BufferRange Range; + + public BufferAssignment(int binding, BufferRange range) + { + Binding = binding; + Range = range; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index 38bf54f7b..26d019eb4 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/Ryujinx.Graphics.GAL/IPipeline.cs @@ -86,12 +86,12 @@ namespace Ryujinx.Graphics.GAL void SetStencilTest(StencilTestDescriptor stencilTest); - void SetStorageBuffers(int first, ReadOnlySpan buffers); + void SetStorageBuffers(ReadOnlySpan buffers); void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler); void SetTransformFeedbackBuffers(ReadOnlySpan buffers); - void SetUniformBuffers(int first, ReadOnlySpan buffers); + void SetUniformBuffers(ReadOnlySpan buffers); void SetUserClipDistance(int index, bool enableClip); diff --git a/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs b/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs index fcf09f9f4..24b0af2d7 100644 --- a/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs +++ b/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs @@ -142,6 +142,30 @@ namespace Ryujinx.Graphics.GAL.Multithreading 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. diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs index c29633739..610603caa 100644 --- a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs +++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetStorageBuffersCommand.cs @@ -6,19 +6,17 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands struct SetStorageBuffersCommand : IGALCommand { public CommandType CommandType => CommandType.SetStorageBuffers; - private int _first; - private SpanRef _buffers; + private SpanRef _buffers; - public void Set(int first, SpanRef buffers) + public void Set(SpanRef buffers) { - _first = first; _buffers = buffers; } public static void Run(ref SetStorageBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer) { - Span buffers = command._buffers.Get(threaded); - renderer.Pipeline.SetStorageBuffers(command._first, threaded.Buffers.MapBufferRanges(buffers)); + Span buffers = command._buffers.Get(threaded); + renderer.Pipeline.SetStorageBuffers(threaded.Buffers.MapBufferRanges(buffers)); command._buffers.Dispose(threaded); } } diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs index 750d8daca..e4abb403a 100644 --- a/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs +++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/SetUniformBuffersCommand.cs @@ -6,19 +6,17 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands struct SetUniformBuffersCommand : IGALCommand { public CommandType CommandType => CommandType.SetUniformBuffers; - private int _first; - private SpanRef _buffers; + private SpanRef _buffers; - public void Set(int first, SpanRef buffers) + public void Set(SpanRef buffers) { - _first = first; _buffers = buffers; } public static void Run(ref SetUniformBuffersCommand command, ThreadedRenderer threaded, IRenderer renderer) { - Span buffers = command._buffers.Get(threaded); - renderer.Pipeline.SetUniformBuffers(command._first, threaded.Buffers.MapBufferRanges(buffers)); + Span buffers = command._buffers.Get(threaded); + renderer.Pipeline.SetUniformBuffers(threaded.Buffers.MapBufferRanges(buffers)); command._buffers.Dispose(threaded); } } diff --git a/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs b/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs index 52d699335..ba120867c 100644 --- a/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs +++ b/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs @@ -275,9 +275,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetStorageBuffers(int first, ReadOnlySpan buffers) + public void SetStorageBuffers(ReadOnlySpan buffers) { - _renderer.New().Set(first, _renderer.CopySpan(buffers)); + _renderer.New().Set(_renderer.CopySpan(buffers)); _renderer.QueueCommand(); } @@ -293,9 +293,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetUniformBuffers(int first, ReadOnlySpan buffers) + public void SetUniformBuffers(ReadOnlySpan buffers) { - _renderer.New().Set(first, _renderer.CopySpan(buffers)); + _renderer.New().Set(_renderer.CopySpan(buffers)); _renderer.QueueCommand(); } diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs index 1b67f6507..f0831e158 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs @@ -24,7 +24,7 @@ namespace Ryujinx.Graphics.Gpu.Memory private readonly VertexBuffer[] _vertexBuffers; private readonly BufferBounds[] _transformFeedbackBuffers; private readonly List _bufferTextures; - private readonly BufferRange[] _ranges; + private readonly BufferAssignment[] _ranges; /// /// Holds shader stage buffer state and binding information. @@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.Gpu.Memory _bufferTextures = new List(); - _ranges = new BufferRange[Constants.TotalGpUniformBuffers * Constants.ShaderStages]; + _ranges = new BufferAssignment[Constants.TotalGpUniformBuffers * Constants.ShaderStages]; } @@ -618,10 +618,9 @@ namespace Ryujinx.Graphics.Gpu.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] private void BindBuffers(BufferCache bufferCache, BuffersPerStage[] bindings, bool isStorage) { - int rangesFirst = 0; int rangesCount = 0; - Span ranges = _ranges; + Span ranges = _ranges; for (ShaderStage stage = ShaderStage.Vertex; stage <= ShaderStage.Fragment; stage++) { @@ -640,25 +639,14 @@ namespace Ryujinx.Graphics.Gpu.Memory ? bufferCache.GetBufferRangeTillEnd(bounds.Address, bounds.Size, isWrite) : bufferCache.GetBufferRange(bounds.Address, bounds.Size); - if (rangesCount == 0) - { - rangesFirst = bindingInfo.Binding; - } - else if (bindingInfo.Binding != rangesFirst + rangesCount) - { - SetHostBuffers(ranges, rangesFirst, rangesCount, isStorage); - rangesFirst = bindingInfo.Binding; - rangesCount = 0; - } - - ranges[rangesCount++] = range; + ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range); } } } if (rangesCount != 0) { - SetHostBuffers(ranges, rangesFirst, rangesCount, isStorage); + SetHostBuffers(ranges, rangesCount, isStorage); } } @@ -671,10 +659,9 @@ namespace Ryujinx.Graphics.Gpu.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] private void BindBuffers(BufferCache bufferCache, BuffersPerStage buffers, bool isStorage) { - int rangesFirst = 0; int rangesCount = 0; - Span ranges = _ranges; + Span ranges = _ranges; for (int index = 0; index < buffers.Count; index++) { @@ -689,24 +676,13 @@ namespace Ryujinx.Graphics.Gpu.Memory ? bufferCache.GetBufferRangeTillEnd(bounds.Address, bounds.Size, isWrite) : bufferCache.GetBufferRange(bounds.Address, bounds.Size); - if (rangesCount == 0) - { - rangesFirst = bindingInfo.Binding; - } - else if (bindingInfo.Binding != rangesFirst + rangesCount) - { - SetHostBuffers(ranges, rangesFirst, rangesCount, isStorage); - rangesFirst = bindingInfo.Binding; - rangesCount = 0; - } - - ranges[rangesCount++] = range; + ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range); } } if (rangesCount != 0) { - SetHostBuffers(ranges, rangesFirst, rangesCount, isStorage); + SetHostBuffers(ranges, rangesCount, isStorage); } } @@ -718,15 +694,15 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Number of bindings /// Indicates if the buffers are storage or uniform buffers [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SetHostBuffers(ReadOnlySpan ranges, int first, int count, bool isStorage) + private void SetHostBuffers(ReadOnlySpan ranges, int count, bool isStorage) { if (isStorage) { - _context.Renderer.Pipeline.SetStorageBuffers(first, ranges.Slice(0, count)); + _context.Renderer.Pipeline.SetStorageBuffers(ranges.Slice(0, count)); } else { - _context.Renderer.Pipeline.SetUniformBuffers(first, ranges.Slice(0, count)); + _context.Renderer.Pipeline.SetUniformBuffers(ranges.Slice(0, count)); } } diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 3b234eb08..8bcaf4c77 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -1296,9 +1296,9 @@ namespace Ryujinx.Graphics.OpenGL _stencilFrontMask = stencilTest.FrontMask; } - public void SetStorageBuffers(int first, ReadOnlySpan buffers) + public void SetStorageBuffers(ReadOnlySpan buffers) { - SetBuffers(first, buffers, isStorage: true); + SetBuffers(buffers, isStorage: true); } public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler) @@ -1366,9 +1366,9 @@ namespace Ryujinx.Graphics.OpenGL } } - public void SetUniformBuffers(int first, ReadOnlySpan buffers) + public void SetUniformBuffers(ReadOnlySpan buffers) { - SetBuffers(first, buffers, isStorage: false); + SetBuffers(buffers, isStorage: false); } public void SetUserClipDistance(int index, bool enableClip) @@ -1460,21 +1460,22 @@ namespace Ryujinx.Graphics.OpenGL GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit); } - private void SetBuffers(int first, ReadOnlySpan buffers, bool isStorage) + private void SetBuffers(ReadOnlySpan buffers, bool isStorage) { BufferRangeTarget target = isStorage ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer; for (int index = 0; index < buffers.Length; index++) { - BufferRange buffer = buffers[index]; + BufferAssignment assignment = buffers[index]; + BufferRange buffer = assignment.Range; if (buffer.Handle == BufferHandle.Null) { - GL.BindBufferRange(target, first + index, 0, IntPtr.Zero, 0); + GL.BindBufferRange(target, assignment.Binding, 0, IntPtr.Zero, 0); continue; } - GL.BindBufferRange(target, first + index, buffer.Handle.ToInt32(), (IntPtr)buffer.Offset, buffer.Size); + GL.BindBufferRange(target, assignment.Binding, buffer.Handle.ToInt32(), (IntPtr)buffer.Offset, buffer.Size); } } diff --git a/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs index 8479bcf78..4cf9ce877 100644 --- a/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs +++ b/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs @@ -163,12 +163,13 @@ namespace Ryujinx.Graphics.Vulkan SignalDirty(DirtyFlags.Image); } - public void SetStorageBuffers(CommandBuffer commandBuffer, int first, ReadOnlySpan buffers) + public void SetStorageBuffers(CommandBuffer commandBuffer, ReadOnlySpan buffers) { for (int i = 0; i < buffers.Length; i++) { - var buffer = buffers[i]; - int index = first + i; + var assignment = buffers[i]; + var buffer = assignment.Range; + int index = assignment.Binding; Auto vkBuffer = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false); ref Auto currentVkBuffer = ref _storageBufferRefs[index]; @@ -243,12 +244,13 @@ namespace Ryujinx.Graphics.Vulkan SignalDirty(DirtyFlags.Texture); } - public void SetUniformBuffers(CommandBuffer commandBuffer, int first, ReadOnlySpan buffers) + public void SetUniformBuffers(CommandBuffer commandBuffer, ReadOnlySpan buffers) { for (int i = 0; i < buffers.Length; i++) { - var buffer = buffers[i]; - int index = first + i; + var assignment = buffers[i]; + var buffer = assignment.Range; + int index = assignment.Binding; Auto vkBuffer = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false); ref Auto currentVkBuffer = ref _uniformBufferRefs[index]; diff --git a/Ryujinx.Graphics.Vulkan/HelperShader.cs b/Ryujinx.Graphics.Vulkan/HelperShader.cs index 1ef22dc29..076a3baab 100644 --- a/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -177,7 +177,7 @@ namespace Ryujinx.Graphics.Vulkan gd.BufferManager.SetData(bufferHandle, 0, region); - _pipeline.SetUniformBuffers(1, stackalloc[] { new BufferRange(bufferHandle, 0, RegionBufferSize) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) }); Span viewports = stackalloc GAL.Viewport[1]; @@ -240,7 +240,7 @@ namespace Ryujinx.Graphics.Vulkan gd.BufferManager.SetData(bufferHandle, 0, clearColor); - _pipeline.SetUniformBuffers(1, stackalloc[] { new BufferRange(bufferHandle, 0, ClearColorBufferSize) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, ClearColorBufferSize)) }); Span viewports = stackalloc GAL.Viewport[1]; @@ -302,7 +302,7 @@ namespace Ryujinx.Graphics.Vulkan gd.BufferManager.SetData(bufferHandle, 0, region); - pipeline.SetUniformBuffers(1, stackalloc[] { new BufferRange(bufferHandle, 0, RegionBufferSize) }); + pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) }); Span viewports = stackalloc GAL.Viewport[1]; @@ -380,7 +380,7 @@ namespace Ryujinx.Graphics.Vulkan _pipeline.SetCommandBuffer(cbs); - _pipeline.SetUniformBuffers(0, stackalloc[] { new BufferRange(bufferHandle, 0, ParamsBufferSize) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); Span> sbRanges = new Auto[2]; @@ -571,7 +571,7 @@ namespace Ryujinx.Graphics.Vulkan int conversionType = srcIsMs ? src.Info.BytesPerPixel : -src.Info.BytesPerPixel; _pipeline.Specialize(conversionType); - _pipeline.SetUniformBuffers(0, stackalloc[] { new BufferRange(bufferHandle, 0, ParamsBufferSize) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); if (src.Info.Target == Target.Texture2DMultisampleArray || dst.Info.Target == Target.Texture2DMultisampleArray) @@ -776,7 +776,7 @@ namespace Ryujinx.Graphics.Vulkan srcIndirectBufferOffset, indirectDataSize); - _pipeline.SetUniformBuffers(0, stackalloc[] { drawCountBufferAligned }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, drawCountBufferAligned) }); _pipeline.SetStorageBuffers(1, new[] { srcIndirectBuffer.GetBuffer(), dstIndirectBuffer.GetBuffer(), patternBuffer.GetBuffer() }); _pipeline.SetProgram(_programConvertIndirectData); @@ -804,7 +804,7 @@ namespace Ryujinx.Graphics.Vulkan 0, convertedCount * outputIndexSize); - _pipeline.SetUniformBuffers(0, stackalloc[] { new BufferRange(patternBufferHandle, 0, ParamsBufferSize) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(patternBufferHandle, 0, ParamsBufferSize)) }); _pipeline.SetStorageBuffers(1, new[] { srcIndexBuffer.GetBuffer(), dstIndexBuffer.GetBuffer() }); _pipeline.SetProgram(_programConvertIndexBuffer); diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 5d2263aa2..87155a0d5 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -973,9 +973,9 @@ namespace Ryujinx.Graphics.Vulkan SignalStateChange(); } - public void SetStorageBuffers(int first, ReadOnlySpan buffers) + public void SetStorageBuffers(ReadOnlySpan buffers) { - _descriptorSetUpdater.SetStorageBuffers(CommandBuffer, first, buffers); + _descriptorSetUpdater.SetStorageBuffers(CommandBuffer, buffers); } public void SetStorageBuffers(int first, ReadOnlySpan> buffers) @@ -1013,9 +1013,9 @@ namespace Ryujinx.Graphics.Vulkan } } - public void SetUniformBuffers(int first, ReadOnlySpan buffers) + public void SetUniformBuffers(ReadOnlySpan buffers) { - _descriptorSetUpdater.SetUniformBuffers(CommandBuffer, first, buffers); + _descriptorSetUpdater.SetUniformBuffers(CommandBuffer, buffers); } public void SetUserClipDistance(int index, bool enableClip)