Phase 7.5 timing logs
Some checks failed
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m45s
CI / Windows Release Package (push) Has been cancelled

This commit is contained in:
Aiden
2026-05-11 21:32:40 +10:00
parent 0a7954e879
commit f8adbbe0fe
8 changed files with 457 additions and 4 deletions

View File

@@ -6,6 +6,7 @@
#include "RenderEngine.h"
#include "RuntimeEventDispatcher.h"
#include <algorithm>
#include <chrono>
#include <cstring>
#include <windows.h>
@@ -294,6 +295,13 @@ void VideoBackend::StartOutputCompletionWorker()
mPendingOutputCompletions.clear();
mReadyOutputQueue.Clear();
mNextReadyOutputFrameIndex = 0;
mHasReadyQueueDepthBaseline = false;
mMinReadyQueueDepth = 0;
mMaxReadyQueueDepth = 0;
mReadyQueueZeroDepthCount = 0;
mOutputRenderMilliseconds = 0.0;
mSmoothedOutputRenderMilliseconds = 0.0;
mMaxOutputRenderMilliseconds = 0.0;
mOutputCompletionWorkerStopping = false;
mOutputCompletionWorkerRunning = true;
mOutputCompletionWorker = std::thread(&VideoBackend::OutputCompletionWorkerMain, this);
@@ -347,7 +355,9 @@ void VideoBackend::ProcessOutputFrameCompletion(const VideoIOCompletion& complet
{
RecordFramePacing(completion.result);
PublishOutputFrameCompleted(completion);
const VideoPlayoutRecoveryDecision recoveryDecision = AccountForCompletionResult(completion.result, mReadyOutputQueue.GetMetrics().depth);
const RenderOutputQueueMetrics initialQueueMetrics = mReadyOutputQueue.GetMetrics();
RecordReadyQueueDepthSample(initialQueueMetrics);
const VideoPlayoutRecoveryDecision recoveryDecision = AccountForCompletionResult(completion.result, initialQueueMetrics.depth);
FillReadyOutputQueue(completion);
if (!ScheduleReadyOutputFrame())
@@ -364,9 +374,15 @@ void VideoBackend::RecordBackendPlayoutHealth(VideoIOCompletionResult result, co
queueMetrics.depth,
queueMetrics.capacity,
queueMetrics.pushedCount,
mMinReadyQueueDepth,
mMaxReadyQueueDepth,
mReadyQueueZeroDepthCount,
queueMetrics.poppedCount,
queueMetrics.droppedCount,
queueMetrics.underrunCount,
mOutputRenderMilliseconds,
mSmoothedOutputRenderMilliseconds,
mMaxOutputRenderMilliseconds,
recoveryDecision.completedFrameIndex,
recoveryDecision.scheduledFrameIndex,
recoveryDecision.scheduledLeadFrames,
@@ -391,12 +407,14 @@ bool VideoBackend::FillReadyOutputQueue(const VideoIOCompletion& completion)
return filledAny;
filledAny = true;
metrics = mReadyOutputQueue.GetMetrics();
RecordReadyQueueDepthSample(metrics);
}
return true;
}
bool VideoBackend::RenderReadyOutputFrame(const VideoIOState& state, const VideoIOCompletion& completion)
{
const auto renderStart = std::chrono::steady_clock::now();
VideoIOOutputFrame outputFrame;
if (!BeginOutputFrame(outputFrame))
return false;
@@ -409,9 +427,16 @@ bool VideoBackend::RenderReadyOutputFrame(const VideoIOState& state, const Video
if (!rendered)
{
ApplyLifecycleTransition(VideoBackendLifecycleState::Degraded, "Output frame render request failed; skipping schedule for this frame.");
const double renderMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
std::chrono::steady_clock::now() - renderStart).count();
RecordOutputRenderDuration(renderMilliseconds);
return false;
}
const double renderMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
std::chrono::steady_clock::now() - renderStart).count();
RecordOutputRenderDuration(renderMilliseconds);
RenderOutputFrame readyFrame;
readyFrame.frame = outputFrame;
readyFrame.frameIndex = ++mNextReadyOutputFrameIndex;
@@ -423,6 +448,7 @@ bool VideoBackend::ScheduleReadyOutputFrame()
RenderOutputFrame readyFrame;
if (!mReadyOutputQueue.TryPop(readyFrame))
return false;
RecordReadyQueueDepthSample(mReadyOutputQueue.GetMetrics());
if (!ScheduleOutputFrame(readyFrame.frame))
return false;
@@ -488,6 +514,37 @@ void VideoBackend::RecordFramePacing(VideoIOCompletionResult completionResult)
PublishTimingSample("VideoBackend", "smoothedCompletionInterval", mSmoothedCompletionIntervalMilliseconds, "ms");
}
void VideoBackend::RecordReadyQueueDepthSample(const RenderOutputQueueMetrics& metrics)
{
if (!mHasReadyQueueDepthBaseline)
{
mHasReadyQueueDepthBaseline = true;
mMinReadyQueueDepth = metrics.depth;
mMaxReadyQueueDepth = metrics.depth;
}
else
{
mMinReadyQueueDepth = (std::min)(mMinReadyQueueDepth, metrics.depth);
mMaxReadyQueueDepth = (std::max)(mMaxReadyQueueDepth, metrics.depth);
}
if (metrics.depth == 0)
++mReadyQueueZeroDepthCount;
}
void VideoBackend::RecordOutputRenderDuration(double renderMilliseconds)
{
mOutputRenderMilliseconds = (std::max)(renderMilliseconds, 0.0);
if (mSmoothedOutputRenderMilliseconds <= 0.0)
mSmoothedOutputRenderMilliseconds = mOutputRenderMilliseconds;
else
mSmoothedOutputRenderMilliseconds = mSmoothedOutputRenderMilliseconds * 0.9 + mOutputRenderMilliseconds * 0.1;
mMaxOutputRenderMilliseconds = (std::max)(mMaxOutputRenderMilliseconds, mOutputRenderMilliseconds);
PublishTimingSample("VideoBackend", "outputRender", mOutputRenderMilliseconds, "ms");
PublishTimingSample("VideoBackend", "smoothedOutputRender", mSmoothedOutputRenderMilliseconds, "ms");
}
bool VideoBackend::ApplyLifecycleTransition(VideoBackendLifecycleState state, const std::string& message)
{
const VideoBackendLifecycleTransition transition = mLifecycle.TransitionTo(state, message);