Frame timing
All checks were successful
CI / React UI Build (push) Successful in 10s
CI / Native Windows Build And Tests (push) Successful in 2m53s
CI / Windows Release Package (push) Successful in 3m6s

This commit is contained in:
Aiden
2026-05-12 01:08:32 +10:00
parent ac729dc2b9
commit f1f4e3421b
6 changed files with 141 additions and 39 deletions

View File

@@ -359,6 +359,12 @@ void VideoBackend::StartOutputProducerWorker()
if (mOutputProducerWorkerRunning)
return;
const double frameBudgetMilliseconds = State().frameBudgetMilliseconds;
const auto frameDuration = frameBudgetMilliseconds > 0.0
? std::chrono::duration_cast<RenderCadenceController::Duration>(
std::chrono::duration<double, std::milli>(frameBudgetMilliseconds))
: std::chrono::milliseconds(16);
mRenderCadenceController.Configure(frameDuration, std::chrono::steady_clock::now());
mLastOutputProductionCompletion = VideoIOCompletion();
mLastOutputProductionTime = std::chrono::steady_clock::time_point();
mOutputProducerWorkerStopping = false;
@@ -433,11 +439,16 @@ void VideoBackend::OutputProducerWorkerMain()
const RenderOutputQueueMetrics metrics = mReadyOutputQueue.GetMetrics();
RecordReadyQueueDepthSample(metrics);
const OutputProductionDecision decision = mOutputProductionController.Decide(BuildOutputProductionPressure(metrics));
if (decision.action != OutputProductionAction::Produce || decision.requestedFrames == 0)
const auto now = std::chrono::steady_clock::now();
RenderCadenceDecision cadenceDecision = mRenderCadenceController.Tick(now);
if (cadenceDecision.action == RenderCadenceAction::Wait)
{
const auto waitDuration = (std::min)(
std::chrono::duration_cast<std::chrono::milliseconds>(cadenceDecision.waitDuration),
OutputProducerWakeInterval());
std::unique_lock<std::mutex> lock(mOutputProducerMutex);
mOutputProducerCondition.wait_for(lock, OutputProducerWakeInterval());
mOutputProducerCondition.wait_for(lock, waitDuration);
if (mOutputProducerWorkerStopping)
{
mOutputProducerWorkerRunning = false;
@@ -454,16 +465,7 @@ void VideoBackend::OutputProducerWorkerMain()
completion = mLastOutputProductionCompletion;
}
const bool belowTargetDepth = metrics.depth < decision.targetReadyFrames;
const auto now = std::chrono::steady_clock::now();
if (!belowTargetDepth &&
mLastOutputProductionTime != std::chrono::steady_clock::time_point() &&
now - mLastOutputProductionTime < OutputProducerWakeInterval())
{
continue;
}
const std::size_t producedFrames = ProduceReadyOutputFrames(completion, decision.requestedFrames);
const std::size_t producedFrames = ProduceReadyOutputFrames(completion, 1);
if (producedFrames > 0)
{
mLastOutputProductionTime = std::chrono::steady_clock::now();
@@ -600,10 +602,6 @@ std::size_t VideoBackend::ProduceReadyOutputFrames(const VideoIOCompletion& comp
std::size_t producedFrames = 0;
while (producedFrames < maxFrames)
{
const OutputProductionDecision decision = mOutputProductionController.Decide(BuildOutputProductionPressure(metrics));
if (decision.action != OutputProductionAction::Produce)
break;
if (!RenderReadyOutputFrame(mVideoIODevice->State(), completion))
break;
++producedFrames;
@@ -634,7 +632,10 @@ bool VideoBackend::RenderReadyOutputFrame(const VideoIOState& state, const Video
VideoIOOutputFrame outputFrame;
const auto acquireStart = std::chrono::steady_clock::now();
if (!mSystemOutputFramePool.AcquireFreeSlot(outputSlot))
return false;
{
if (!mReadyOutputQueue.DropOldestFrame() || !mSystemOutputFramePool.AcquireFreeSlot(outputSlot))
return false;
}
outputFrame = outputSlot.frame;
const auto acquireEnd = std::chrono::steady_clock::now();