Add mock-game capture/audio/hook stress test

mock_game_test launches coop_mock_game (DX11/DX12, frame-numbered A/V), injects
coop_hook.dll, opens the hook's shared video texture, and decodes the frame
number from the captured pixels to assert a monotonic, advancing mirror for
both backends (catches dropped/stale/out-of-order frames). Then it runs an
A/V + hook/unhook stress pass and confirms no crash + capture resumes. Adds a
read_pixel() readback to the shipping SharedTextureSource for the decode.
Robust to repeated/CI runs (kills stray games, retries inject). Trim the
roadmap (the mock-game item is done) and document the test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 05:22:20 +02:00
parent e2562ac63c
commit e608c6fb38
5 changed files with 518 additions and 11 deletions

View File

@@ -92,6 +92,44 @@ bool SharedTextureSource::reopen(unsigned long pid, const VideoShareView& share)
return true;
}
bool SharedTextureSource::read_pixel(std::uint32_t x, std::uint32_t y, std::uint8_t out[4])
{
if (private_ == nullptr || ctx_ == nullptr || device_ == nullptr)
{
return false;
}
D3D11_TEXTURE2D_DESC desc{};
private_->GetDesc(&desc);
if (x >= desc.Width || y >= desc.Height)
{
return false;
}
D3D11_TEXTURE2D_DESC staging_desc = desc;
staging_desc.Usage = D3D11_USAGE_STAGING;
staging_desc.BindFlags = 0;
staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
staging_desc.MiscFlags = 0;
Microsoft::WRL::ComPtr<ID3D11Texture2D> staging;
if (FAILED(device_->CreateTexture2D(&staging_desc, nullptr, &staging)))
{
return false;
}
ctx_->CopyResource(staging.Get(), private_.Get());
D3D11_MAPPED_SUBRESOURCE map{};
if (FAILED(ctx_->Map(staging.Get(), 0, D3D11_MAP_READ, 0, &map)))
{
return false;
}
const auto* px = static_cast<const std::uint8_t*>(map.pData) + static_cast<std::size_t>(y) * map.RowPitch +
static_cast<std::size_t>(x) * 4; // R8G8B8A8_UNORM
out[0] = px[0];
out[1] = px[1];
out[2] = px[2];
out[3] = px[3];
ctx_->Unmap(staging.Get(), 0);
return true;
}
bool SharedTextureSource::update(const VideoShareView& share, unsigned long pid)
{
if (device_ == nullptr || pid == 0)