telemetry and timing updates
All checks were successful
CI / React UI Build (push) Successful in 10s
CI / Native Windows Build And Tests (push) Successful in 2m58s
CI / Windows Release Package (push) Has been skipped

This commit is contained in:
Aiden
2026-05-13 00:21:28 +10:00
parent d411453f80
commit 5c1fc2a6cf
24 changed files with 260 additions and 38 deletions

View File

@@ -37,7 +37,6 @@ std::filesystem::path WriteConfigFixture()
<< " \"autoReload\": false,\n"
<< " \"maxTemporalHistoryFrames\": 8,\n"
<< " \"previewFps\": 24,\n"
<< " \"startupSettleMs\": 2500,\n"
<< " \"enableExternalKeying\": true\n"
<< "}\n";
return path;
@@ -68,7 +67,6 @@ void TestLoadsRuntimeHostConfig()
Expect(!config.autoReload, "auto reload loads");
Expect(config.maxTemporalHistoryFrames == 8, "history length loads");
Expect(config.previewFps == 24.0, "preview fps loads");
Expect(config.startupSettle == std::chrono::milliseconds(2500), "startup settle loads");
Expect(config.deckLink.externalKeyingEnabled, "external keying loads");
std::filesystem::remove(path);

View File

@@ -27,6 +27,13 @@ SystemFrameExchangeConfig MakeConfig(std::size_t capacity = 2)
return config;
}
SystemFrameExchangeConfig MakeBoundedCompletedConfig(std::size_t capacity = 4, std::size_t maxCompletedFrames = 2)
{
SystemFrameExchangeConfig config = MakeConfig(capacity);
config.maxCompletedFrames = maxCompletedFrames;
return config;
}
void TestAcquirePublishesAndSchedules()
{
SystemFrameExchange exchange(MakeConfig(1));
@@ -82,6 +89,31 @@ void TestAcquirePreservesCompletedFrames()
Expect(metrics.acquireMisses == 1, "preserving acquire miss is counted");
}
void TestCompletedReserveIsBoundedFifo()
{
SystemFrameExchange exchange(MakeBoundedCompletedConfig(4, 2));
for (uint64_t frameIndex = 1; frameIndex <= 3; ++frameIndex)
{
SystemFrame frame;
Expect(exchange.AcquireForRender(frame), "bounded reserve frame can be acquired");
frame.frameIndex = frameIndex;
Expect(exchange.PublishCompleted(frame), "bounded reserve frame can be completed");
}
SystemFrame firstScheduled;
Expect(exchange.ConsumeCompletedForSchedule(firstScheduled), "bounded reserve oldest retained frame can be scheduled");
Expect(firstScheduled.frameIndex == 2, "bounded reserve drops oldest overflow and keeps FIFO order");
SystemFrame secondScheduled;
Expect(exchange.ConsumeCompletedForSchedule(secondScheduled), "bounded reserve second retained frame can be scheduled");
Expect(secondScheduled.frameIndex == 3, "bounded reserve schedules next retained frame");
SystemFrameExchangeMetrics metrics = exchange.Metrics();
Expect(metrics.completedDrops == 1, "bounded completed reserve records oldest overflow drop");
Expect(metrics.scheduledFrames == 2, "bounded reserve schedules retained frames");
}
void TestScheduledFramesAreNotDropped()
{
SystemFrameExchange exchange(MakeConfig(1));
@@ -177,6 +209,7 @@ int main()
{
TestAcquirePublishesAndSchedules();
TestAcquirePreservesCompletedFrames();
TestCompletedReserveIsBoundedFifo();
TestScheduledFramesAreNotDropped();
TestGenerationValidationRejectsStaleFrames();
TestPixelFormatAwareSizing();

View File

@@ -57,6 +57,12 @@ struct FakeOutputMetrics
bool actualBufferedFramesAvailable = false;
uint64_t actualBufferedFrames = 0;
double scheduleCallMilliseconds = 0.0;
bool scheduleLeadAvailable = false;
int64_t playbackStreamTime = 0;
uint64_t playbackFrameIndex = 0;
uint64_t nextScheduleFrameIndex = 0;
int64_t scheduleLeadFrames = 0;
uint64_t scheduleRealignmentCount = 0;
};
struct FakeOutput
@@ -109,6 +115,12 @@ void TestTelemetrySamplesCompletedPollMissesAndShaderCounts()
FakeOutput output;
output.metrics.actualBufferedFramesAvailable = true;
output.metrics.actualBufferedFrames = 4;
output.metrics.scheduleLeadAvailable = true;
output.metrics.playbackStreamTime = 10010;
output.metrics.playbackFrameIndex = 10;
output.metrics.nextScheduleFrameIndex = 14;
output.metrics.scheduleLeadFrames = 4;
output.metrics.scheduleRealignmentCount = 1;
FakeOutputThread outputThread;
outputThread.metrics.completedPollMisses = 12;
@@ -163,6 +175,12 @@ void TestTelemetrySamplesCompletedPollMissesAndShaderCounts()
Expect(snapshot.inputSignalPresent, "input signal present is sampled");
Expect(snapshot.deckLinkBufferedAvailable, "buffer telemetry availability is sampled");
Expect(snapshot.deckLinkBuffered == 4, "buffer depth is sampled");
Expect(snapshot.deckLinkScheduleLeadAvailable, "schedule lead availability is sampled");
Expect(snapshot.deckLinkPlaybackStreamTime == 10010, "playback stream time is sampled");
Expect(snapshot.deckLinkPlaybackFrameIndex == 10, "playback frame index is sampled");
Expect(snapshot.deckLinkNextScheduleFrameIndex == 14, "next schedule frame index is sampled");
Expect(snapshot.deckLinkScheduleLeadFrames == 4, "schedule lead frames are sampled");
Expect(snapshot.deckLinkScheduleRealignments == 1, "schedule realignment count is sampled");
}
void TestTelemetryComputesRatesFromDeltas()
@@ -234,6 +252,12 @@ void TestTelemetrySerializesToJson()
snapshot.deckLinkBufferedAvailable = true;
snapshot.deckLinkBuffered = 4;
snapshot.deckLinkScheduleCallMilliseconds = 1.25;
snapshot.deckLinkScheduleLeadAvailable = true;
snapshot.deckLinkScheduleLeadFrames = 4;
snapshot.deckLinkPlaybackFrameIndex = 10;
snapshot.deckLinkNextScheduleFrameIndex = 14;
snapshot.deckLinkPlaybackStreamTime = 10010;
snapshot.deckLinkScheduleRealignments = 1;
const std::string json = RenderCadenceCompositor::CadenceTelemetryToJson(snapshot);
const std::string expected =
@@ -259,7 +283,13 @@ void TestTelemetrySerializesToJson()
"\"inputUnsupportedFrames\":3,\"inputSubmitMisses\":4,"
"\"inputCaptureFormat\":\"UYVY8\","
"\"deckLinkBufferedAvailable\":true,\"deckLinkBuffered\":4,"
"\"scheduleCallMs\":1.25}";
"\"scheduleCallMs\":1.25,"
"\"deckLinkScheduleLeadAvailable\":true,"
"\"deckLinkScheduleLeadFrames\":4,"
"\"deckLinkPlaybackFrameIndex\":10,"
"\"deckLinkNextScheduleFrameIndex\":14,"
"\"deckLinkPlaybackStreamTime\":10010,"
"\"deckLinkScheduleRealignments\":1}";
Expect(json == expected, "telemetry snapshot serializes to stable JSON");
}