#include "CadenceTelemetry.h" #include #include #include #include namespace { int gFailures = 0; void Expect(bool condition, const char* message) { if (condition) return; std::cerr << "FAIL: " << message << "\n"; ++gFailures; } struct FakeExchangeMetrics { std::size_t freeCount = 0; std::size_t completedCount = 0; std::size_t scheduledCount = 0; uint64_t completedFrames = 0; uint64_t scheduledFrames = 0; }; struct FakeExchange { FakeExchangeMetrics metrics; FakeExchangeMetrics Metrics() const { return metrics; } }; struct FakeOutputThreadMetrics { uint64_t completedPollMisses = 0; uint64_t scheduleFailures = 0; }; struct FakeOutputThread { FakeOutputThreadMetrics metrics; FakeOutputThreadMetrics Metrics() const { return metrics; } }; struct FakeOutputMetrics { uint64_t completions = 0; uint64_t displayedLate = 0; uint64_t dropped = 0; uint64_t scheduleFailures = 0; bool actualBufferedFramesAvailable = false; uint64_t actualBufferedFrames = 0; double scheduleCallMilliseconds = 0.0; }; struct FakeOutput { FakeOutputMetrics metrics; FakeOutputMetrics Metrics() const { return metrics; } }; struct FakeRenderThreadMetrics { uint64_t shaderBuildsCommitted = 0; uint64_t shaderBuildFailures = 0; }; struct FakeRenderThread { FakeRenderThreadMetrics metrics; FakeRenderThreadMetrics GetMetrics() const { return metrics; } }; void TestTelemetrySamplesCompletedPollMissesAndShaderCounts() { RenderCadenceCompositor::CadenceTelemetry telemetry; FakeExchange exchange; exchange.metrics.freeCount = 7; exchange.metrics.completedCount = 1; exchange.metrics.scheduledCount = 4; exchange.metrics.completedFrames = 100; exchange.metrics.scheduledFrames = 96; FakeOutput output; output.metrics.actualBufferedFramesAvailable = true; output.metrics.actualBufferedFrames = 4; FakeOutputThread outputThread; outputThread.metrics.completedPollMisses = 12; outputThread.metrics.scheduleFailures = 0; FakeRenderThread renderThread; renderThread.metrics.shaderBuildsCommitted = 1; renderThread.metrics.shaderBuildFailures = 0; const auto snapshot = telemetry.Sample(exchange, output, outputThread, renderThread); Expect(snapshot.freeFrames == 7, "free frame count is sampled"); Expect(snapshot.completedFrames == 1, "completed frame count is sampled"); Expect(snapshot.scheduledFrames == 4, "scheduled frame count is sampled"); Expect(snapshot.completedPollMisses == 12, "completed poll misses are sampled"); Expect(snapshot.shaderBuildsCommitted == 1, "shader committed count is sampled"); Expect(snapshot.shaderBuildFailures == 0, "shader failure count is sampled"); Expect(snapshot.deckLinkBufferedAvailable, "buffer telemetry availability is sampled"); Expect(snapshot.deckLinkBuffered == 4, "buffer depth is sampled"); } void TestTelemetryComputesRatesFromDeltas() { RenderCadenceCompositor::CadenceTelemetry telemetry; FakeExchange exchange; FakeOutput output; FakeOutputThread outputThread; FakeRenderThread renderThread; exchange.metrics.completedFrames = 10; exchange.metrics.scheduledFrames = 10; (void)telemetry.Sample(exchange, output, outputThread, renderThread); std::this_thread::sleep_for(std::chrono::milliseconds(5)); exchange.metrics.completedFrames = 20; exchange.metrics.scheduledFrames = 19; const auto snapshot = telemetry.Sample(exchange, output, outputThread, renderThread); Expect(snapshot.sampleSeconds > 0.0, "second telemetry sample has elapsed time"); Expect(snapshot.renderFps > 0.0, "render fps is computed from completed frame delta"); Expect(snapshot.scheduleFps > 0.0, "schedule fps is computed from scheduled frame delta"); } } int main() { TestTelemetrySamplesCompletedPollMissesAndShaderCounts(); TestTelemetryComputesRatesFromDeltas(); if (gFailures != 0) { std::cerr << gFailures << " telemetry test failure(s).\n"; return 1; } std::cout << "RenderCadenceCompositor telemetry tests passed.\n"; return 0; }