Give the mock-game backends one source of truth for the test pattern
The animated pattern math (background sweep, moving 24px bar, frame- counter block) was copy-pasted across all five clear-based backends (dx9/dx10/dx11/dx12/gl). The backends MUST render an identical image -- the capture test decodes the same frame-counter block from each -- so a drift between copies would be a silent test hazard. Factor it into one frame_pattern() helper (plus kBarWidth) in render_backend.hpp; each backend now consumes the computed bg/bar_x/code values with its own API's clear/fill. mock_game_test still decodes every backend correctly.
This commit is contained in:
@@ -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.
|
// Size (px) of the top-left frame-counter block the test samples.
|
||||||
inline constexpr std::uint32_t kFrameBlock = 64;
|
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<std::uint8_t>((frame * 2) % 256);
|
||||||
|
p.bg_g = static_cast<std::uint8_t>((frame * 3) % 256);
|
||||||
|
p.bg_b = static_cast<std::uint8_t>((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
|
class RenderBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -75,23 +75,18 @@ public:
|
|||||||
|
|
||||||
void render_and_present(std::uint32_t frame) override
|
void render_and_present(std::uint32_t frame) override
|
||||||
{
|
{
|
||||||
const D3DCOLOR bg = opaque(static_cast<std::uint8_t>((frame * 2) % 256),
|
const FramePattern p = frame_pattern(frame, width_);
|
||||||
static_cast<std::uint8_t>((frame * 3) % 256),
|
dev_->Clear(0, nullptr, D3DCLEAR_TARGET, opaque(p.bg_r, p.bg_g, p.bg_b), 1.0f, 0);
|
||||||
static_cast<std::uint8_t>((frame * 5) % 256));
|
|
||||||
dev_->Clear(0, nullptr, D3DCLEAR_TARGET, bg, 1.0f, 0);
|
|
||||||
|
|
||||||
ComPtr<IDirect3DSurface9> back;
|
ComPtr<IDirect3DSurface9> back;
|
||||||
if (SUCCEEDED(dev_->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, back.GetAddressOf())))
|
if (SUCCEEDED(dev_->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, back.GetAddressOf())))
|
||||||
{
|
{
|
||||||
const LONG span = width_ > 24 ? static_cast<LONG>(width_ - 24) : 1;
|
const LONG bx = static_cast<LONG>(p.bar_x);
|
||||||
const LONG bx = static_cast<LONG>((frame * 4) % static_cast<std::uint32_t>(span));
|
RECT bar = {bx, 0, bx + static_cast<LONG>(kBarWidth), static_cast<LONG>(height_)}; // moving vertical bar
|
||||||
RECT bar = {bx, 0, bx + 24, static_cast<LONG>(height_)}; // moving vertical bar
|
|
||||||
dev_->ColorFill(back.Get(), &bar, opaque(255, 255, 255));
|
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<LONG>(kFrameBlock), static_cast<LONG>(kFrameBlock)};
|
RECT block = {0, 0, static_cast<LONG>(kFrameBlock), static_cast<LONG>(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);
|
dev_->Present(nullptr, nullptr, nullptr, nullptr);
|
||||||
|
|||||||
@@ -69,23 +69,19 @@ public:
|
|||||||
|
|
||||||
void render_and_present(std::uint32_t frame) override
|
void render_and_present(std::uint32_t frame) override
|
||||||
{
|
{
|
||||||
const std::uint32_t bg = pack(static_cast<std::uint8_t>((frame * 2) % 256),
|
const FramePattern p = frame_pattern(frame, width_);
|
||||||
static_cast<std::uint8_t>((frame * 3) % 256),
|
const std::uint32_t bg = pack(p.bg_r, p.bg_g, p.bg_b);
|
||||||
static_cast<std::uint8_t>((frame * 5) % 256));
|
|
||||||
const std::uint32_t whitepx = pack(255, 255, 255);
|
const std::uint32_t whitepx = pack(255, 255, 255);
|
||||||
std::uint8_t fr = 0, fg = 0, fb = 0;
|
const std::uint32_t code = pack(p.code_r, p.code_g, p.code_b);
|
||||||
frame_to_rgb(frame, fr, fg, fb);
|
|
||||||
const std::uint32_t code = pack(fr, fg, fb);
|
|
||||||
|
|
||||||
const std::uint32_t span = width_ > 24 ? width_ - 24 : 1;
|
const std::uint32_t bx = p.bar_x; // moving vertical bar
|
||||||
const std::uint32_t bx = (frame * 4) % span; // moving vertical bar
|
|
||||||
for (std::uint32_t y = 0; y < height_; ++y)
|
for (std::uint32_t y = 0; y < height_; ++y)
|
||||||
{
|
{
|
||||||
std::uint32_t* row = px_.data() + static_cast<std::size_t>(y) * width_;
|
std::uint32_t* row = px_.data() + static_cast<std::size_t>(y) * width_;
|
||||||
for (std::uint32_t x = 0; x < width_; ++x)
|
for (std::uint32_t x = 0; x < width_; ++x)
|
||||||
{
|
{
|
||||||
std::uint32_t c = bg;
|
std::uint32_t c = bg;
|
||||||
if (x >= bx && x < bx + 24)
|
if (x >= bx && x < bx + kBarWidth)
|
||||||
{
|
{
|
||||||
c = whitepx;
|
c = whitepx;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,23 +81,17 @@ public:
|
|||||||
|
|
||||||
void render_and_present(std::uint32_t frame) override
|
void render_and_present(std::uint32_t frame) override
|
||||||
{
|
{
|
||||||
// Animated background: each channel sweeps at a different rate -> constant motion.
|
const FramePattern p = frame_pattern(frame, width_);
|
||||||
const float bg[4] = {static_cast<float>((frame * 2) % 256) / 255.0f,
|
|
||||||
static_cast<float>((frame * 3) % 256) / 255.0f,
|
const float bg[4] = {p.bg_r / 255.0f, p.bg_g / 255.0f, p.bg_b / 255.0f, 1.0f};
|
||||||
static_cast<float>((frame * 5) % 256) / 255.0f, 1.0f};
|
|
||||||
ctx_->ClearRenderTargetView(rtv_.Get(), bg);
|
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 float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
const LONG span = width_ > 24 ? static_cast<LONG>(width_ - 24) : 1;
|
const LONG bx = static_cast<LONG>(p.bar_x);
|
||||||
const LONG bx = static_cast<LONG>((frame * 4) % static_cast<std::uint32_t>(span));
|
const D3D11_RECT bar = {bx, 0, bx + static_cast<LONG>(kBarWidth), static_cast<LONG>(height_)};
|
||||||
const D3D11_RECT bar = {bx, 0, bx + 24, static_cast<LONG>(height_)};
|
|
||||||
ctx_->ClearView(rtv_.Get(), white, &bar, 1);
|
ctx_->ClearView(rtv_.Get(), white, &bar, 1);
|
||||||
|
|
||||||
// Frame-counter block (top-left): RGB encodes the exact frame number for the test.
|
const float code[4] = {p.code_r / 255.0f, p.code_g / 255.0f, p.code_b / 255.0f, 1.0f};
|
||||||
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 D3D11_RECT block = {0, 0, static_cast<LONG>(kFrameBlock), static_cast<LONG>(kFrameBlock)};
|
const D3D11_RECT block = {0, 0, static_cast<LONG>(kFrameBlock), static_cast<LONG>(kFrameBlock)};
|
||||||
ctx_->ClearView(rtv_.Get(), code, &block, 1);
|
ctx_->ClearView(rtv_.Get(), code, &block, 1);
|
||||||
|
|
||||||
|
|||||||
@@ -115,23 +115,17 @@ public:
|
|||||||
|
|
||||||
transition(targets_[idx].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
transition(targets_[idx].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||||
|
|
||||||
// Animated background (full RT clear).
|
const FramePattern p = frame_pattern(frame, width_);
|
||||||
const float bg[4] = {static_cast<float>((frame * 2) % 256) / 255.0f,
|
|
||||||
static_cast<float>((frame * 3) % 256) / 255.0f,
|
const float bg[4] = {p.bg_r / 255.0f, p.bg_g / 255.0f, p.bg_b / 255.0f, 1.0f};
|
||||||
static_cast<float>((frame * 5) % 256) / 255.0f, 1.0f};
|
|
||||||
list_->ClearRenderTargetView(rtv_handles_[idx], bg, 0, nullptr);
|
list_->ClearRenderTargetView(rtv_handles_[idx], bg, 0, nullptr);
|
||||||
|
|
||||||
// Moving vertical bar.
|
|
||||||
const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
const LONG span = width_ > 24 ? static_cast<LONG>(width_ - 24) : 1;
|
const LONG bx = static_cast<LONG>(p.bar_x);
|
||||||
const LONG bx = static_cast<LONG>((frame * 4) % static_cast<std::uint32_t>(span));
|
const D3D12_RECT bar = {bx, 0, bx + static_cast<LONG>(kBarWidth), static_cast<LONG>(height_)};
|
||||||
const D3D12_RECT bar = {bx, 0, bx + 24, static_cast<LONG>(height_)};
|
|
||||||
list_->ClearRenderTargetView(rtv_handles_[idx], white, 1, &bar);
|
list_->ClearRenderTargetView(rtv_handles_[idx], white, 1, &bar);
|
||||||
|
|
||||||
// Frame-counter block (top-left).
|
const float code[4] = {p.code_r / 255.0f, p.code_g / 255.0f, p.code_b / 255.0f, 1.0f};
|
||||||
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 D3D12_RECT block = {0, 0, static_cast<LONG>(kFrameBlock), static_cast<LONG>(kFrameBlock)};
|
const D3D12_RECT block = {0, 0, static_cast<LONG>(kFrameBlock), static_cast<LONG>(kFrameBlock)};
|
||||||
list_->ClearRenderTargetView(rtv_handles_[idx], code, 1, &block);
|
list_->ClearRenderTargetView(rtv_handles_[idx], code, 1, &block);
|
||||||
|
|
||||||
|
|||||||
@@ -63,27 +63,24 @@ public:
|
|||||||
const GLsizei h = static_cast<GLsizei>(height_);
|
const GLsizei h = static_cast<GLsizei>(height_);
|
||||||
glViewport(0, 0, w, h);
|
glViewport(0, 0, w, h);
|
||||||
|
|
||||||
|
const FramePattern p = frame_pattern(frame, width_);
|
||||||
|
|
||||||
// Animated background (whole framebuffer).
|
// Animated background (whole framebuffer).
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
glClearColor(static_cast<float>((frame * 2) % 256) / 255.0f, static_cast<float>((frame * 3) % 256) / 255.0f,
|
glClearColor(p.bg_r / 255.0f, p.bg_g / 255.0f, p.bg_b / 255.0f, 1.0f);
|
||||||
static_cast<float>((frame * 5) % 256) / 255.0f, 1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
// Moving vertical bar (full height).
|
// Moving vertical bar (full height).
|
||||||
const std::uint32_t span = width_ > 24 ? width_ - 24 : 1;
|
glScissor(static_cast<GLint>(p.bar_x), 0, static_cast<GLsizei>(kBarWidth), h);
|
||||||
const GLint bx = static_cast<GLint>((frame * 4) % span);
|
|
||||||
glScissor(bx, 0, 24, h);
|
|
||||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// Frame-counter block at the GL top-left (y = h - block) so it lands top-left after the
|
// Frame-counter block at the GL top-left (y = h - block) so it lands top-left after the
|
||||||
// capture's vertical flip.
|
// 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<GLint>(kFrameBlock), static_cast<GLsizei>(kFrameBlock),
|
glScissor(0, h - static_cast<GLint>(kFrameBlock), static_cast<GLsizei>(kFrameBlock),
|
||||||
static_cast<GLsizei>(kFrameBlock));
|
static_cast<GLsizei>(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);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user