[idd] scheduler: unblock ownership transitions

Permit retained-buffer reuse when both private queues are occupied by a
previous timing owner, even if the new owner has no pending deliveries.

Use the shared fallback when possible. Otherwise retain the fresh frame
locally and republish it instead of waiting for stale private deliveries.
This commit is contained in:
Geoffrey McRae
2026-08-06 17:00:31 +10:00
parent 3e9dadf340
commit fb1fb8447e

View File

@@ -1745,25 +1745,27 @@ bool CIndirectDeviceContext::FrameBufferAvailable(
return false; return false;
AcquireSRWLockShared(&m_framePublishLock); AcquireSRWLockShared(&m_framePublishLock);
bool deliveryAvailable; bool allowReady = false;
bool ownerBlocked = false;
// Pipeline one frame through each independent owner lane. Count the shared // Pipeline one frame through each independent owner lane. Count the shared
// fallback against the same limit so it cannot become a third delivery for // fallback against the same limit so it cannot become a third delivery for
// the same owner. Once both are occupied, a fully unreferenced buffer can // the same owner. Once both are occupied, a fully unreferenced buffer can
// still retain a newer frame for secondary delivery and later republish. // still retain a newer frame for secondary delivery and later republish.
if (schedule.clientID) if (schedule.clientID)
{ {
ownerBlocked = const bool ownerBlocked =
CountOwnerDeliveries(schedule.clientID) >= LGMP_Q_FRAME_LEN; CountOwnerDeliveries(schedule.clientID) >= LGMP_Q_FRAME_LEN;
deliveryAvailable = ownerBlocked || const bool ownerQueuesBlocked = FindAvailableOwnerQueue(0) < 0;
FindAvailableOwnerQueue(0) >= 0 || allowReady = ownerBlocked || ownerQueuesBlocked;
lgmpHostQueuePending(m_frameQueue) < LGMP_Q_FRAME_LEN; }
else if (lgmpHostQueuePending(m_frameQueue) != 0)
{
ReleaseSRWLockShared(&m_framePublishLock);
return false;
} }
else
deliveryAvailable = lgmpHostQueuePending(m_frameQueue) == 0;
const bool available = deliveryAvailable && // With no owner delivery lane available, a copy can still replace an
FindAvailableFrameBuffer(ownerBlocked) >= 0; // unreferenced retained frame and be republished when a lane clears.
const bool available = FindAvailableFrameBuffer(allowReady) >= 0;
ReleaseSRWLockShared(&m_framePublishLock); ReleaseSRWLockShared(&m_framePublishLock);
return available; return available;
} }
@@ -1859,8 +1861,10 @@ CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrame
AcquireSRWLockExclusive(&m_framePublishLock); AcquireSRWLockExclusive(&m_framePublishLock);
const bool ownerBlocked = schedule.clientID && const bool ownerBlocked = schedule.clientID &&
CountOwnerDeliveries(schedule.clientID) >= LGMP_Q_FRAME_LEN; CountOwnerDeliveries(schedule.clientID) >= LGMP_Q_FRAME_LEN;
const bool allowReady = ownerBlocked ||
(schedule.clientID && FindAvailableOwnerQueue(0) < 0);
const int availableFrameIndex = const int availableFrameIndex =
FindAvailableFrameBuffer(ownerBlocked); FindAvailableFrameBuffer(allowReady);
bool expected = false; bool expected = false;
const bool acquired = availableFrameIndex >= 0 && const bool acquired = availableFrameIndex >= 0 &&
m_frameInFlight[availableFrameIndex].compare_exchange_strong( m_frameInFlight[availableFrameIndex].compare_exchange_strong(
@@ -2062,8 +2066,13 @@ bool CIndirectDeviceContext::PublishFrameBuffer(unsigned frameIndex,
const int ownerQueueIndex = FindAvailableOwnerQueue(frameIndex); const int ownerQueueIndex = FindAvailableOwnerQueue(frameIndex);
if (ownerQueueIndex < 0) if (ownerQueueIndex < 0)
{ {
published = PostSharedOwnerFrame(frameIndex, schedule); published = PostSharedOwnerFrame(frameIndex, schedule);
deliveredToOwner = published; deliveredToOwner = published;
if (!published)
{
PostSharedFrame(frameIndex, schedule.clientID, now);
published = true;
}
} }
else else
{ {