#include "RenderCommandQueue.h" #include namespace { int gFailures = 0; void Expect(bool condition, const char* message) { if (condition) return; std::cerr << "FAIL: " << message << "\n"; ++gFailures; } void TestPreviewRequestUsesLatestValue() { RenderCommandQueue queue; queue.RequestPreviewPresent({ 1920, 1080 }); queue.RequestPreviewPresent({ 1280, 720 }); const RenderCommandQueueMetrics metrics = queue.GetMetrics(); Expect(metrics.depth == 1, "preview requests coalesce to one pending command"); Expect(metrics.enqueuedCount == 1, "first preview request is counted as enqueued"); Expect(metrics.coalescedCount == 1, "second preview request is counted as coalesced"); RenderPreviewPresentRequest request; Expect(queue.TryTakePreviewPresent(request), "preview request can be consumed"); Expect(request.outputFrameWidth == 1280 && request.outputFrameHeight == 720, "latest preview request wins"); Expect(!queue.TryTakePreviewPresent(request), "preview request is removed after consume"); Expect(queue.GetMetrics().depth == 0, "preview consume empties queue depth"); } void TestScreenshotRequestUsesLatestValue() { RenderCommandQueue queue; queue.RequestScreenshotCapture({ 640, 360 }); queue.RequestScreenshotCapture({ 3840, 2160 }); RenderScreenshotCaptureRequest request; Expect(queue.TryTakeScreenshotCapture(request), "screenshot request can be consumed"); Expect(request.width == 3840 && request.height == 2160, "latest screenshot request wins"); Expect(!queue.TryTakeScreenshotCapture(request), "screenshot request is removed after consume"); } void TestRenderResetScopesCoalesceToStrongestRequest() { RenderCommandQueue queue; queue.RequestRenderReset(RenderCommandResetScope::TemporalHistoryOnly); queue.RequestRenderReset(RenderCommandResetScope::ShaderFeedbackOnly); RenderCommandResetScope scope = RenderCommandResetScope::None; Expect(queue.TryTakeRenderReset(scope), "render reset request can be consumed"); Expect(scope == RenderCommandResetScope::TemporalHistoryAndFeedback, "temporal and feedback reset requests merge"); Expect(!queue.TryTakeRenderReset(scope), "render reset request is removed after consume"); queue.RequestRenderReset(RenderCommandResetScope::None); Expect(queue.GetMetrics().depth == 0, "none reset request is ignored"); } void TestInputUploadRequestUsesLatestValue() { int firstPixel = 1; int secondPixel = 2; RenderCommandQueue queue; RenderInputUploadRequest firstRequest; firstRequest.inputFrame.bytes = &firstPixel; firstRequest.inputFrame.width = 1920; firstRequest.videoState.captureTextureWidth = 1920; firstRequest.ownedBytes = { 1, 2, 3, 4 }; queue.RequestInputUpload(firstRequest); RenderInputUploadRequest secondRequest; secondRequest.inputFrame.bytes = &secondPixel; secondRequest.inputFrame.width = 1280; secondRequest.videoState.captureTextureWidth = 1280; secondRequest.ownedBytes = { 5, 6 }; queue.RequestInputUpload(secondRequest); const RenderCommandQueueMetrics metrics = queue.GetMetrics(); Expect(metrics.depth == 1, "input upload requests coalesce to one pending command"); Expect(metrics.enqueuedCount == 1, "first input upload request is counted as enqueued"); Expect(metrics.coalescedCount == 1, "second input upload request is counted as coalesced"); RenderInputUploadRequest request; Expect(queue.TryTakeInputUpload(request), "input upload request can be consumed"); Expect(request.inputFrame.bytes == &secondPixel, "latest input upload bytes pointer wins"); Expect(request.inputFrame.width == 1280, "latest input upload frame wins"); Expect(request.videoState.captureTextureWidth == 1280, "latest input upload state wins"); Expect(request.ownedBytes.size() == 2 && request.ownedBytes[0] == 5 && request.ownedBytes[1] == 6, "latest input upload owned bytes win"); Expect(!queue.TryTakeInputUpload(request), "input upload request is removed after consume"); } void TestOutputFrameRequestsAreFifo() { RenderCommandQueue queue; RenderOutputFrameRequest firstRequest; firstRequest.videoState.outputFrameSize.width = 1920; firstRequest.completion.result = VideoIOCompletionResult::Completed; queue.RequestOutputFrame(firstRequest); RenderOutputFrameRequest secondRequest; secondRequest.videoState.outputFrameSize.width = 1280; secondRequest.completion.result = VideoIOCompletionResult::Dropped; queue.RequestOutputFrame(secondRequest); Expect(queue.GetMetrics().depth == 2, "output frame requests are queued independently"); RenderOutputFrameRequest request; Expect(queue.TryTakeOutputFrame(request), "first output request can be consumed"); Expect(request.videoState.outputFrameSize.width == 1920, "first output request is consumed first"); Expect(request.completion.result == VideoIOCompletionResult::Completed, "first output completion is preserved"); Expect(queue.TryTakeOutputFrame(request), "second output request can be consumed"); Expect(request.videoState.outputFrameSize.width == 1280, "second output request is consumed second"); Expect(request.completion.result == VideoIOCompletionResult::Dropped, "second output completion is preserved"); Expect(!queue.TryTakeOutputFrame(request), "output queue is empty after consuming all requests"); } void TestIndependentCommandKindsShareDepth() { RenderCommandQueue queue; queue.RequestPreviewPresent({ 1, 2 }); queue.RequestScreenshotCapture({ 3, 4 }); queue.RequestInputUpload({}); queue.RequestOutputFrame({}); queue.RequestRenderReset(RenderCommandResetScope::TemporalHistoryOnly); Expect(queue.GetMetrics().depth == 5, "independent command kinds each contribute to depth"); } } int main() { TestPreviewRequestUsesLatestValue(); TestScreenshotRequestUsesLatestValue(); TestRenderResetScopesCoalesceToStrongestRequest(); TestInputUploadRequestUsesLatestValue(); TestOutputFrameRequestsAreFifo(); TestIndependentCommandKindsShareDepth(); if (gFailures != 0) { std::cerr << gFailures << " RenderCommandQueue test failure(s).\n"; return 1; } std::cout << "RenderCommandQueue tests passed.\n"; return 0; }