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
This commit is contained in:
riperiperi 2024-06-30 19:04:28 +01:00 committed by Isaac Marovitz
parent e3dd174f28
commit 117c5c1645
No known key found for this signature in database
GPG Key ID: 97250B2B09A132E1
3 changed files with 13 additions and 26 deletions

View File

@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.Metal
if (_pool == null) if (_pool == null)
{ {
MTLCommandQueue queue = _renderer.BackgroundQueue; MTLCommandQueue queue = _renderer.BackgroundQueue;
_pool = new CommandBufferPool(queue); _pool = new CommandBufferPool(queue, true);
_pool.Initialize(null); // TODO: Proper encoder factory for background render/compute _pool.Initialize(null); // TODO: Proper encoder factory for background render/compute
} }

View File

@ -33,22 +33,21 @@ namespace Ryujinx.Graphics.Metal
public List<IAuto> Dependants; public List<IAuto> Dependants;
public List<MultiFenceHolder> Waitables; public List<MultiFenceHolder> Waitables;
public void Reinitialize(MTLCommandQueue queue, IEncoderFactory stateManager) public void Use(MTLCommandQueue queue, IEncoderFactory stateManager)
{ {
CommandBuffer = queue.CommandBuffer(); CommandBuffer = queue.CommandBuffer();
Fence = new FenceHolder(CommandBuffer);
Encoders.Initialize(CommandBuffer, stateManager); Encoders.Initialize(CommandBuffer, stateManager);
InUse = true;
} }
public void Initialize(MTLCommandQueue queue, IEncoderFactory stateManager) public void Initialize()
{ {
CommandBuffer = queue.CommandBuffer();
Dependants = new List<IAuto>(); Dependants = new List<IAuto>();
Waitables = new List<MultiFenceHolder>(); Waitables = new List<MultiFenceHolder>();
Encoders = new CommandBufferEncoder(); Encoders = new CommandBufferEncoder();
Encoders.Initialize(CommandBuffer, stateManager);
} }
} }
@ -59,12 +58,12 @@ namespace Ryujinx.Graphics.Metal
private int _queuedCount; private int _queuedCount;
private int _inUseCount; private int _inUseCount;
public CommandBufferPool(MTLCommandQueue queue) public CommandBufferPool(MTLCommandQueue queue, bool isLight = false)
{ {
_queue = queue; _queue = queue;
_owner = Thread.CurrentThread; _owner = Thread.CurrentThread;
_totalCommandBuffers = MaxCommandBuffers; _totalCommandBuffers = isLight ? 2 : MaxCommandBuffers;
_totalCommandBuffersMask = _totalCommandBuffers - 1; _totalCommandBuffersMask = _totalCommandBuffers - 1;
_commandBuffers = new ReservedCommandBuffer[_totalCommandBuffers]; _commandBuffers = new ReservedCommandBuffer[_totalCommandBuffers];
@ -80,7 +79,7 @@ namespace Ryujinx.Graphics.Metal
for (int i = 0; i < _totalCommandBuffers; i++) for (int i = 0; i < _totalCommandBuffers; i++)
{ {
_commandBuffers[i].Initialize(_queue, _defaultEncoderFactory); _commandBuffers[i].Initialize();
WaitAndDecrementRef(i); WaitAndDecrementRef(i);
} }
} }
@ -207,7 +206,7 @@ namespace Ryujinx.Graphics.Metal
if (!entry.InUse && !entry.InConsumption) if (!entry.InUse && !entry.InConsumption)
{ {
entry.InUse = true; entry.Use(_queue, _defaultEncoderFactory);
_inUseCount++; _inUseCount++;
@ -242,16 +241,13 @@ namespace Ryujinx.Graphics.Metal
var commandBuffer = entry.CommandBuffer; var commandBuffer = entry.CommandBuffer;
commandBuffer.Commit(); commandBuffer.Commit();
// Replace entry with new MTLCommandBuffer
entry.Reinitialize(_queue, _defaultEncoderFactory);
int ptr = (_queuedIndexesPtr + _queuedCount) % _totalCommandBuffers; int ptr = (_queuedIndexesPtr + _queuedCount) % _totalCommandBuffers;
_queuedIndexes[ptr] = cbIndex; _queuedIndexes[ptr] = cbIndex;
_queuedCount++; _queuedCount++;
} }
} }
private void WaitAndDecrementRef(int cbIndex, bool refreshFence = true) private void WaitAndDecrementRef(int cbIndex)
{ {
ref var entry = ref _commandBuffers[cbIndex]; ref var entry = ref _commandBuffers[cbIndex];
@ -275,22 +271,13 @@ namespace Ryujinx.Graphics.Metal
entry.Dependants.Clear(); entry.Dependants.Clear();
entry.Waitables.Clear(); entry.Waitables.Clear();
entry.Fence?.Dispose(); entry.Fence?.Dispose();
if (refreshFence)
{
entry.Fence = new FenceHolder(entry.CommandBuffer);
}
else
{
entry.Fence = null;
}
} }
public void Dispose() public void Dispose()
{ {
for (int i = 0; i < _totalCommandBuffers; i++) for (int i = 0; i < _totalCommandBuffers; i++)
{ {
WaitAndDecrementRef(i, refreshFence: false); WaitAndDecrementRef(i);
} }
} }
} }

View File

@ -41,7 +41,7 @@ namespace Ryujinx.Graphics.Metal
throw new NotSupportedException("Metal backend requires Tier 2 Argument Buffer support."); 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); BackgroundQueue = _device.NewCommandQueue(CommandBufferPool.MaxCommandBuffers);
_getMetalLayer = metalLayer; _getMetalLayer = metalLayer;