[idd] scheduler: avoid stale deadline waits

This commit is contained in:
Geoffrey McRae
2026-08-06 17:23:17 +10:00
parent bdfb1c3ce0
commit fac417c6b3

View File

@@ -313,12 +313,34 @@ void CSwapChainProcessor::PublisherThread()
if (HasReadyCandidate()) if (HasReadyCandidate())
continue; continue;
uint64_t current = CFrameScheduler::Nanotime();
uint64_t cadenceTarget = 0;
if (schedule.deliveryDeadlineSerial && periodic)
{
if (schedule.deadline <= current)
{
m_devContext->FrameMissed(schedule, current, periodic);
continue;
}
cadenceTarget = schedule.deadline;
}
if (republish && m_devContext->HasPublishedFrame()) if (republish && m_devContext->HasPublishedFrame())
{ {
if (m_devContext->RepublishFrameBuffer(schedule)) if (m_devContext->RepublishFrameBuffer(schedule))
continue; continue;
ArmPublishTimer(m_publishTimer.Get(), PUBLISH_RETRY_NS); current = CFrameScheduler::Nanotime();
if (cadenceTarget && cadenceTarget <= current)
{
m_devContext->FrameMissed(schedule, current, periodic);
continue;
}
uint64_t retryTarget = current + PUBLISH_RETRY_NS;
if (cadenceTarget)
retryTarget = min(retryTarget, cadenceTarget);
ArmPublishTimer(m_publishTimer.Get(), retryTarget - current);
if (WaitForMultipleObjects( if (WaitForMultipleObjects(
ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) == ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) ==
WAIT_OBJECT_0) WAIT_OBJECT_0)
@@ -326,27 +348,24 @@ void CSwapChainProcessor::PublisherThread()
continue; continue;
} }
const uint64_t replayNow = CFrameScheduler::Nanotime();
uint64_t cadenceTarget = 0;
if (schedule.deliveryDeadlineSerial && periodic &&
schedule.deadline <= replayNow)
{
m_devContext->FrameMissed(schedule, replayNow, periodic);
continue;
}
if (schedule.deliveryDeadlineSerial && periodic)
cadenceTarget = schedule.deadline;
uint64_t replayTarget; uint64_t replayTarget;
if (m_devContext->GetSharedFrameTarget(replayNow, replayTarget)) if (m_devContext->GetSharedFrameTarget(current, replayTarget))
{ {
bool retry = false; bool retry = false;
if (replayTarget <= replayNow) if (replayTarget <= current)
{ {
if (m_devContext->ReplaySharedFrame(replayNow, retry)) if (m_devContext->ReplaySharedFrame(current, retry))
continue; continue;
current = CFrameScheduler::Nanotime();
if (cadenceTarget && cadenceTarget <= current)
{
m_devContext->FrameMissed(schedule, current, periodic);
continue;
}
if (retry) if (retry)
replayTarget = replayNow + PUBLISH_RETRY_NS; replayTarget = current + PUBLISH_RETRY_NS;
else else
{ {
if (cadenceTarget) if (cadenceTarget)
@@ -364,12 +383,19 @@ void CSwapChainProcessor::PublisherThread()
} }
} }
if (cadenceTarget && cadenceTarget < replayTarget) if (cadenceTarget)
replayTarget = cadenceTarget; replayTarget = min(replayTarget, cadenceTarget);
const uint64_t delay = replayTarget > replayNow ? current = CFrameScheduler::Nanotime();
replayTarget - replayNow : PUBLISH_RETRY_NS; if (cadenceTarget && cadenceTarget <= current)
ArmPublishTimer(m_publishTimer.Get(), delay); {
m_devContext->FrameMissed(schedule, current, periodic);
continue;
}
if (replayTarget <= current)
continue;
ArmPublishTimer(m_publishTimer.Get(), replayTarget - current);
if (WaitForMultipleObjects( if (WaitForMultipleObjects(
ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) == ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) ==
WAIT_OBJECT_0) WAIT_OBJECT_0)
@@ -379,8 +405,14 @@ void CSwapChainProcessor::PublisherThread()
if (cadenceTarget) if (cadenceTarget)
{ {
ArmPublishTimer( current = CFrameScheduler::Nanotime();
m_publishTimer.Get(), cadenceTarget - replayNow); if (cadenceTarget <= current)
{
m_devContext->FrameMissed(schedule, current, periodic);
continue;
}
ArmPublishTimer(m_publishTimer.Get(), cadenceTarget - current);
if (WaitForMultipleObjects( if (WaitForMultipleObjects(
ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) == ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) ==
WAIT_OBJECT_0) WAIT_OBJECT_0)
@@ -397,37 +429,46 @@ void CSwapChainProcessor::PublisherThread()
continue; continue;
} }
uint64_t current = CFrameScheduler::Nanotime();
uint64_t replayTarget; uint64_t replayTarget;
if (m_devContext->GetSharedFrameTarget(now, replayTarget) && if (m_devContext->GetSharedFrameTarget(current, replayTarget) &&
replayTarget < target) replayTarget < target)
{ {
if (replayTarget <= now) if (replayTarget <= current)
{ {
m_devContext->ProcessFrameQueue(); m_devContext->ProcessFrameQueue();
current = CFrameScheduler::Nanotime();
bool retry = false; bool retry = false;
if (m_devContext->ReplaySharedFrame( if (m_devContext->ReplaySharedFrame(current, retry))
CFrameScheduler::Nanotime(), retry))
continue; continue;
current = CFrameScheduler::Nanotime();
if (retry) if (retry)
replayTarget = now + PUBLISH_RETRY_NS; replayTarget = current + PUBLISH_RETRY_NS;
else else
replayTarget = target; replayTarget = target;
} }
const uint64_t delay = replayTarget > now ? replayTarget = min(replayTarget, target);
replayTarget - now : PUBLISH_RETRY_NS; current = CFrameScheduler::Nanotime();
ArmPublishTimer(m_publishTimer.Get(), delay); if (target > current)
if (WaitForMultipleObjects(
ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) ==
WAIT_OBJECT_0)
break;
continue;
}
if (target > now)
{ {
ArmPublishTimer(m_publishTimer.Get(), target - now); if (replayTarget <= current)
continue;
ArmPublishTimer(m_publishTimer.Get(), replayTarget - current);
if (WaitForMultipleObjects(
ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) ==
WAIT_OBJECT_0)
break;
continue;
}
}
current = CFrameScheduler::Nanotime();
if (target > current)
{
ArmPublishTimer(m_publishTimer.Get(), target - current);
if (WaitForMultipleObjects( if (WaitForMultipleObjects(
ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) == ARRAYSIZE(timerHandles), timerHandles, FALSE, INFINITE) ==
WAIT_OBJECT_0) WAIT_OBJECT_0)
@@ -435,8 +476,8 @@ void CSwapChainProcessor::PublisherThread()
continue; continue;
} }
const uint64_t publishStart = CFrameScheduler::Nanotime();
m_devContext->ProcessFrameQueue(); m_devContext->ProcessFrameQueue();
const uint64_t publishStart = CFrameScheduler::Nanotime();
if (!m_devContext->FrameBufferAvailable(schedule) || if (!m_devContext->FrameBufferAvailable(schedule) ||
!PublishNewestCandidate( !PublishNewestCandidate(
schedule, periodic, publishStart)) schedule, periodic, publishStart))