Skip to content

Commit

Permalink
Create command buffers when rented rather than in advance (#31)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
riperiperi authored and GreemDev committed Dec 24, 2024
1 parent 879c93c commit 2fb3c69
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/Ryujinx.Graphics.Metal/BackgroundResources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public CommandBufferPool GetPool()
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
}

Expand Down
35 changes: 11 additions & 24 deletions src/Ryujinx.Graphics.Metal/CommandBufferPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,21 @@ private struct ReservedCommandBuffer
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);
}
}

Expand All @@ -59,12 +58,12 @@ public void Initialize(MTLCommandQueue queue, IEncoderFactory stateManager)
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];
Expand All @@ -80,7 +79,7 @@ public void Initialize(IEncoderFactory encoderFactory)

for (int i = 0; i < _totalCommandBuffers; i++)
{
_commandBuffers[i].Initialize(_queue, _defaultEncoderFactory);
_commandBuffers[i].Initialize();
WaitAndDecrementRef(i);
}
}
Expand Down Expand Up @@ -207,7 +206,7 @@ public CommandBufferScoped Rent()

if (!entry.InUse && !entry.InConsumption)
{
entry.InUse = true;
entry.Use(_queue, _defaultEncoderFactory);

_inUseCount++;

Expand Down Expand Up @@ -242,16 +241,13 @@ public void Return(CommandBufferScoped cbs)
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];

Expand All @@ -275,22 +271,13 @@ private void WaitAndDecrementRef(int cbIndex, bool refreshFence = true)
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);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Ryujinx.Graphics.Metal/MetalRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public MetalRenderer(Func<CAMetalLayer> metalLayer)
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;
Expand Down

0 comments on commit 2fb3c69

Please sign in to comment.