From 6f6ccb7898b68ae85cb1b4c40d1b97d08484cbbb Mon Sep 17 00:00:00 2001 From: riperiperi Date: Sun, 30 Jun 2024 19:04:28 +0100 Subject: [PATCH] Create command buffers when rented rather than in advance (#31) * Make it less likely to freeze, but the creation of the command buffer should probably be moved * Create command buffers as they're rented rather than in advance --- .../BackgroundResources.cs | 2 +- .../CommandBufferPool.cs | 35 ++++++------------- src/Ryujinx.Graphics.Metal/MetalRenderer.cs | 2 +- 3 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/Ryujinx.Graphics.Metal/BackgroundResources.cs b/src/Ryujinx.Graphics.Metal/BackgroundResources.cs index ea49ac6ec..c06a6747b 100644 --- a/src/Ryujinx.Graphics.Metal/BackgroundResources.cs +++ b/src/Ryujinx.Graphics.Metal/BackgroundResources.cs @@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.Metal if (_pool == null) { MTLCommandQueue queue = _renderer.BackgroundQueue; - _pool = new CommandBufferPool(queue); + _pool = new CommandBufferPool(queue, true); _pool.Initialize(null); // TODO: Proper encoder factory for background render/compute } diff --git a/src/Ryujinx.Graphics.Metal/CommandBufferPool.cs b/src/Ryujinx.Graphics.Metal/CommandBufferPool.cs index 9c9e452fb..050f93efc 100644 --- a/src/Ryujinx.Graphics.Metal/CommandBufferPool.cs +++ b/src/Ryujinx.Graphics.Metal/CommandBufferPool.cs @@ -33,22 +33,21 @@ namespace Ryujinx.Graphics.Metal public List Dependants; public List Waitables; - public void Reinitialize(MTLCommandQueue queue, IEncoderFactory stateManager) + public void Use(MTLCommandQueue queue, IEncoderFactory stateManager) { CommandBuffer = queue.CommandBuffer(); + Fence = new FenceHolder(CommandBuffer); Encoders.Initialize(CommandBuffer, stateManager); + + InUse = true; } - public void Initialize(MTLCommandQueue queue, IEncoderFactory stateManager) + public void Initialize() { - CommandBuffer = queue.CommandBuffer(); - Dependants = new List(); Waitables = new List(); Encoders = new CommandBufferEncoder(); - - Encoders.Initialize(CommandBuffer, stateManager); } } @@ -59,12 +58,12 @@ namespace Ryujinx.Graphics.Metal private int _queuedCount; private int _inUseCount; - public CommandBufferPool(MTLCommandQueue queue) + public CommandBufferPool(MTLCommandQueue queue, bool isLight = false) { _queue = queue; _owner = Thread.CurrentThread; - _totalCommandBuffers = MaxCommandBuffers; + _totalCommandBuffers = isLight ? 2 : MaxCommandBuffers; _totalCommandBuffersMask = _totalCommandBuffers - 1; _commandBuffers = new ReservedCommandBuffer[_totalCommandBuffers]; @@ -80,7 +79,7 @@ namespace Ryujinx.Graphics.Metal for (int i = 0; i < _totalCommandBuffers; i++) { - _commandBuffers[i].Initialize(_queue, _defaultEncoderFactory); + _commandBuffers[i].Initialize(); WaitAndDecrementRef(i); } } @@ -207,7 +206,7 @@ namespace Ryujinx.Graphics.Metal if (!entry.InUse && !entry.InConsumption) { - entry.InUse = true; + entry.Use(_queue, _defaultEncoderFactory); _inUseCount++; @@ -242,16 +241,13 @@ namespace Ryujinx.Graphics.Metal var commandBuffer = entry.CommandBuffer; commandBuffer.Commit(); - // Replace entry with new MTLCommandBuffer - entry.Reinitialize(_queue, _defaultEncoderFactory); - int ptr = (_queuedIndexesPtr + _queuedCount) % _totalCommandBuffers; _queuedIndexes[ptr] = cbIndex; _queuedCount++; } } - private void WaitAndDecrementRef(int cbIndex, bool refreshFence = true) + private void WaitAndDecrementRef(int cbIndex) { ref var entry = ref _commandBuffers[cbIndex]; @@ -275,22 +271,13 @@ namespace Ryujinx.Graphics.Metal entry.Dependants.Clear(); entry.Waitables.Clear(); entry.Fence?.Dispose(); - - if (refreshFence) - { - entry.Fence = new FenceHolder(entry.CommandBuffer); - } - else - { - entry.Fence = null; - } } public void Dispose() { for (int i = 0; i < _totalCommandBuffers; i++) { - WaitAndDecrementRef(i, refreshFence: false); + WaitAndDecrementRef(i); } } } diff --git a/src/Ryujinx.Graphics.Metal/MetalRenderer.cs b/src/Ryujinx.Graphics.Metal/MetalRenderer.cs index 1edd91c56..d9ac0118c 100644 --- a/src/Ryujinx.Graphics.Metal/MetalRenderer.cs +++ b/src/Ryujinx.Graphics.Metal/MetalRenderer.cs @@ -41,7 +41,7 @@ namespace Ryujinx.Graphics.Metal throw new NotSupportedException("Metal backend requires Tier 2 Argument Buffer support."); } - _queue = _device.NewCommandQueue(CommandBufferPool.MaxCommandBuffers); + _queue = _device.NewCommandQueue(CommandBufferPool.MaxCommandBuffers + 1); BackgroundQueue = _device.NewCommandQueue(CommandBufferPool.MaxCommandBuffers); _getMetalLayer = metalLayer;