Metal: skip waitUntilCompleted when the command buffer is already Completed (#709)

Tiny write-back batches often finish before the wait; checking status avoids redundant ordered-queue round-trips.
This commit is contained in:
kuba
2026-07-31 11:08:56 +02:00
committed by GitHub
parent ec65419c0a
commit 79aa764d03
2 changed files with 27 additions and 3 deletions
@@ -253,7 +253,7 @@ internal static partial class MetalVideoPresenter
if (writeBackBuffers.Count > 0)
{
var committed = FlushBatchedGuestCommands();
MetalNative.SendVoid(committed, MetalNative.Selector("waitUntilCompleted"));
WaitForCommittedCommandBuffer(committed);
WriteBuffersBackToGuest(writeBackBuffers);
}
@@ -580,7 +580,7 @@ internal static partial class MetalVideoPresenter
if (writeBackBuffers.Count > 0)
{
var committed = FlushBatchedGuestCommands();
MetalNative.SendVoid(committed, MetalNative.Selector("waitUntilCompleted"));
WaitForCommittedCommandBuffer(committed);
WriteBuffersBackToGuest(writeBackBuffers);
}
@@ -668,7 +668,7 @@ internal static partial class MetalVideoPresenter
TagSnapshotResources(commandBuffer);
if (writeBackBuffers.Count > 0)
{
MetalNative.SendVoid(commandBuffer, MetalNative.Selector("waitUntilCompleted"));
WaitForCommittedCommandBuffer(commandBuffer);
WriteBuffersBackToGuest(writeBackBuffers);
}
@@ -2082,6 +2082,30 @@ internal static partial class MetalVideoPresenter
}
}
/// <summary>
/// Blocks until a committed command buffer finishes. Skips the ObjC wait
/// when status is already Completed (common for tiny label/writeback
/// batches), avoiding redundant waitUntilCompleted round-trips on the
/// ordered queue.
/// </summary>
private static void WaitForCommittedCommandBuffer(nint commandBuffer)
{
if (commandBuffer == 0)
{
return;
}
// MTLCommandBufferStatusCompleted = 4.
const nint completed = 4;
if (MetalNative.Send(commandBuffer, MetalNative.Selector("status")) >= completed)
{
return;
}
MetalNative.SendVoid(commandBuffer, MetalNative.Selector("waitUntilCompleted"));
}
private static void ReturnPooledGuestData(TranslatedGuestDraw draw)
{
foreach (var buffer in draw.GlobalMemoryBuffers)