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:
@@ -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)
|
||||
|
||||
@@ -31,6 +31,12 @@ public:
|
||||
// Drop the opened resources (target changed / mirror turned off).
|
||||
void reset();
|
||||
|
||||
// Read the RGBA8 pixel at (x,y) of the last copied frame into out[4]. For verification
|
||||
// (e.g. decoding the mock game's frame-number block in a capture test). Copies the
|
||||
// private texture to a CPU-readable staging texture and maps it -- not a hot path.
|
||||
// Returns false if no frame has been copied yet or the readback failed.
|
||||
bool read_pixel(std::uint32_t x, std::uint32_t y, std::uint8_t out[4]);
|
||||
|
||||
[[nodiscard]] ID3D11ShaderResourceView* srv() const
|
||||
{
|
||||
return srv_.Get();
|
||||
|
||||
Reference in New Issue
Block a user