diff --git a/tools/mock_game/render_backend.hpp b/tools/mock_game/render_backend.hpp index e8f50c6..5d7237b 100644 --- a/tools/mock_game/render_backend.hpp +++ b/tools/mock_game/render_backend.hpp @@ -37,6 +37,32 @@ inline std::uint32_t rgb_to_frame(std::uint8_t r, std::uint8_t g, std::uint8_t b // Size (px) of the top-left frame-counter block the test samples. inline constexpr std::uint32_t kFrameBlock = 64; +// Width (px) of the moving vertical bar. +inline constexpr std::uint32_t kBarWidth = 24; + +// The animated pattern the mock renders for one frame, computed once so every backend draws the +// IDENTICAL image (the capture test compares backends). Each backend consumes these values with its +// own API's clear/fill calls: an animated full-screen background, a kBarWidth-wide full-height white +// bar at bar_x, and the top-left kFrameBlock-square frame-counter block whose colour encodes `frame`. +struct FramePattern +{ + std::uint8_t bg_r, bg_g, bg_b; // background; each channel sweeps at a different rate -> motion + std::uint32_t bar_x; // left edge of the moving bar + std::uint8_t code_r, code_g, code_b; // frame-counter block colour (frame_to_rgb) +}; + +inline FramePattern frame_pattern(std::uint32_t frame, std::uint32_t width) +{ + FramePattern p{}; + p.bg_r = static_cast((frame * 2) % 256); + p.bg_g = static_cast((frame * 3) % 256); + p.bg_b = static_cast((frame * 5) % 256); + const std::uint32_t span = width > kBarWidth ? width - kBarWidth : 1; + p.bar_x = (frame * 4) % span; + frame_to_rgb(frame, p.code_r, p.code_g, p.code_b); + return p; +} + class RenderBackend { public: diff --git a/tools/mock_game/render_dx09.cpp b/tools/mock_game/render_dx09.cpp index ec3744e..aa18f4d 100644 --- a/tools/mock_game/render_dx09.cpp +++ b/tools/mock_game/render_dx09.cpp @@ -75,23 +75,18 @@ public: void render_and_present(std::uint32_t frame) override { - const D3DCOLOR bg = opaque(static_cast((frame * 2) % 256), - static_cast((frame * 3) % 256), - static_cast((frame * 5) % 256)); - dev_->Clear(0, nullptr, D3DCLEAR_TARGET, bg, 1.0f, 0); + const FramePattern p = frame_pattern(frame, width_); + dev_->Clear(0, nullptr, D3DCLEAR_TARGET, opaque(p.bg_r, p.bg_g, p.bg_b), 1.0f, 0); ComPtr back; if (SUCCEEDED(dev_->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, back.GetAddressOf()))) { - const LONG span = width_ > 24 ? static_cast(width_ - 24) : 1; - const LONG bx = static_cast((frame * 4) % static_cast(span)); - RECT bar = {bx, 0, bx + 24, static_cast(height_)}; // moving vertical bar + const LONG bx = static_cast(p.bar_x); + RECT bar = {bx, 0, bx + static_cast(kBarWidth), static_cast(height_)}; // moving vertical bar dev_->ColorFill(back.Get(), &bar, opaque(255, 255, 255)); - std::uint8_t r = 0, g = 0, b = 0; - frame_to_rgb(frame, r, g, b); RECT block = {0, 0, static_cast(kFrameBlock), static_cast(kFrameBlock)}; - dev_->ColorFill(back.Get(), &block, opaque(r, g, b)); // top-left frame-counter block + dev_->ColorFill(back.Get(), &block, opaque(p.code_r, p.code_g, p.code_b)); // top-left frame block } dev_->Present(nullptr, nullptr, nullptr, nullptr); diff --git a/tools/mock_game/render_dx10.cpp b/tools/mock_game/render_dx10.cpp index 46a5840..0d31679 100644 --- a/tools/mock_game/render_dx10.cpp +++ b/tools/mock_game/render_dx10.cpp @@ -69,23 +69,19 @@ public: void render_and_present(std::uint32_t frame) override { - const std::uint32_t bg = pack(static_cast((frame * 2) % 256), - static_cast((frame * 3) % 256), - static_cast((frame * 5) % 256)); + const FramePattern p = frame_pattern(frame, width_); + const std::uint32_t bg = pack(p.bg_r, p.bg_g, p.bg_b); const std::uint32_t whitepx = pack(255, 255, 255); - std::uint8_t fr = 0, fg = 0, fb = 0; - frame_to_rgb(frame, fr, fg, fb); - const std::uint32_t code = pack(fr, fg, fb); + const std::uint32_t code = pack(p.code_r, p.code_g, p.code_b); - const std::uint32_t span = width_ > 24 ? width_ - 24 : 1; - const std::uint32_t bx = (frame * 4) % span; // moving vertical bar + const std::uint32_t bx = p.bar_x; // moving vertical bar for (std::uint32_t y = 0; y < height_; ++y) { std::uint32_t* row = px_.data() + static_cast(y) * width_; for (std::uint32_t x = 0; x < width_; ++x) { std::uint32_t c = bg; - if (x >= bx && x < bx + 24) + if (x >= bx && x < bx + kBarWidth) { c = whitepx; } diff --git a/tools/mock_game/render_dx11.cpp b/tools/mock_game/render_dx11.cpp index 762c84d..593ab2a 100644 --- a/tools/mock_game/render_dx11.cpp +++ b/tools/mock_game/render_dx11.cpp @@ -81,23 +81,17 @@ public: void render_and_present(std::uint32_t frame) override { - // Animated background: each channel sweeps at a different rate -> constant motion. - const float bg[4] = {static_cast((frame * 2) % 256) / 255.0f, - static_cast((frame * 3) % 256) / 255.0f, - static_cast((frame * 5) % 256) / 255.0f, 1.0f}; + const FramePattern p = frame_pattern(frame, width_); + + const float bg[4] = {p.bg_r / 255.0f, p.bg_g / 255.0f, p.bg_b / 255.0f, 1.0f}; ctx_->ClearRenderTargetView(rtv_.Get(), bg); - // Moving vertical bar (obvious motion; a dropped frame makes it jump). const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - const LONG span = width_ > 24 ? static_cast(width_ - 24) : 1; - const LONG bx = static_cast((frame * 4) % static_cast(span)); - const D3D11_RECT bar = {bx, 0, bx + 24, static_cast(height_)}; + const LONG bx = static_cast(p.bar_x); + const D3D11_RECT bar = {bx, 0, bx + static_cast(kBarWidth), static_cast(height_)}; ctx_->ClearView(rtv_.Get(), white, &bar, 1); - // Frame-counter block (top-left): RGB encodes the exact frame number for the test. - std::uint8_t r = 0, g = 0, b = 0; - frame_to_rgb(frame, r, g, b); - const float code[4] = {r / 255.0f, g / 255.0f, b / 255.0f, 1.0f}; + const float code[4] = {p.code_r / 255.0f, p.code_g / 255.0f, p.code_b / 255.0f, 1.0f}; const D3D11_RECT block = {0, 0, static_cast(kFrameBlock), static_cast(kFrameBlock)}; ctx_->ClearView(rtv_.Get(), code, &block, 1); diff --git a/tools/mock_game/render_dx12.cpp b/tools/mock_game/render_dx12.cpp index 53d1a28..819146f 100644 --- a/tools/mock_game/render_dx12.cpp +++ b/tools/mock_game/render_dx12.cpp @@ -115,23 +115,17 @@ public: transition(targets_[idx].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); - // Animated background (full RT clear). - const float bg[4] = {static_cast((frame * 2) % 256) / 255.0f, - static_cast((frame * 3) % 256) / 255.0f, - static_cast((frame * 5) % 256) / 255.0f, 1.0f}; + const FramePattern p = frame_pattern(frame, width_); + + const float bg[4] = {p.bg_r / 255.0f, p.bg_g / 255.0f, p.bg_b / 255.0f, 1.0f}; list_->ClearRenderTargetView(rtv_handles_[idx], bg, 0, nullptr); - // Moving vertical bar. const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - const LONG span = width_ > 24 ? static_cast(width_ - 24) : 1; - const LONG bx = static_cast((frame * 4) % static_cast(span)); - const D3D12_RECT bar = {bx, 0, bx + 24, static_cast(height_)}; + const LONG bx = static_cast(p.bar_x); + const D3D12_RECT bar = {bx, 0, bx + static_cast(kBarWidth), static_cast(height_)}; list_->ClearRenderTargetView(rtv_handles_[idx], white, 1, &bar); - // Frame-counter block (top-left). - std::uint8_t r = 0, g = 0, b = 0; - frame_to_rgb(frame, r, g, b); - const float code[4] = {r / 255.0f, g / 255.0f, b / 255.0f, 1.0f}; + const float code[4] = {p.code_r / 255.0f, p.code_g / 255.0f, p.code_b / 255.0f, 1.0f}; const D3D12_RECT block = {0, 0, static_cast(kFrameBlock), static_cast(kFrameBlock)}; list_->ClearRenderTargetView(rtv_handles_[idx], code, 1, &block); diff --git a/tools/mock_game/render_gl.cpp b/tools/mock_game/render_gl.cpp index b53144d..534fa75 100644 --- a/tools/mock_game/render_gl.cpp +++ b/tools/mock_game/render_gl.cpp @@ -63,27 +63,24 @@ public: const GLsizei h = static_cast(height_); glViewport(0, 0, w, h); + const FramePattern p = frame_pattern(frame, width_); + // Animated background (whole framebuffer). glDisable(GL_SCISSOR_TEST); - glClearColor(static_cast((frame * 2) % 256) / 255.0f, static_cast((frame * 3) % 256) / 255.0f, - static_cast((frame * 5) % 256) / 255.0f, 1.0f); + glClearColor(p.bg_r / 255.0f, p.bg_g / 255.0f, p.bg_b / 255.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_SCISSOR_TEST); // Moving vertical bar (full height). - const std::uint32_t span = width_ > 24 ? width_ - 24 : 1; - const GLint bx = static_cast((frame * 4) % span); - glScissor(bx, 0, 24, h); + glScissor(static_cast(p.bar_x), 0, static_cast(kBarWidth), h); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // Frame-counter block at the GL top-left (y = h - block) so it lands top-left after the // capture's vertical flip. - std::uint8_t r = 0, g = 0, b = 0; - frame_to_rgb(frame, r, g, b); glScissor(0, h - static_cast(kFrameBlock), static_cast(kFrameBlock), static_cast(kFrameBlock)); - glClearColor(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f); + glClearColor(p.code_r / 255.0f, p.code_g / 255.0f, p.code_b / 255.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_SCISSOR_TEST);