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 2511bf1e4c
commit 6f6ccb7898
3 changed files with 13 additions and 26 deletions

View file

@ -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
}

View file

@ -33,22 +33,21 @@ namespace Ryujinx.Graphics.Metal
public List<IAuto> Dependants;
public List<MultiFenceHolder> 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<IAuto>();
Waitables = new List<MultiFenceHolder>();
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);
}
}
}

View file

@ -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;