diff --git a/hook/src/present_hook.cpp b/hook/src/present_hook.cpp index 1d30e07..407bf5c 100644 --- a/hook/src/present_hook.cpp +++ b/hook/src/present_hook.cpp @@ -424,6 +424,16 @@ void capture_backbuffer_d3d12(IDXGISwapChain* sc) std::scoped_lock lock(g_tex_mutex); if (ensure_on12_locked(dev)) { + // DX12 capture is pricier than DX11/OpenGL (measured ~0.38 ms vs ~0.05/0.09 ms of + // present-thread overhead) because it goes through the D3D11On12 bridge. The cost is NOT + // CreateWrappedResource (measured ~0.012 ms) -- it's the CopyResource issued on the 11On12 + // immediate context (~0.13 ms) plus the mandatory Flush to make the shared copy visible to + // the host (~0.06 ms), neither of which the native-D3D11 path pays. Eliminating it needs a + // native-D3D12 copy-queue path into a D3D12-shared texture, but the host consumes the + // shared surface via an IDXGIKeyedMutex (a D3D11 concept), so that also means switching the + // DX12 producer<->host sync to a shared ID3D12Fence -- a cross-API rewrite. Deferred: the + // overhead is ~5% of a 144 Hz frame and the capture is correct; the bridge stays for now. + // // Order our copy after the game's frame without burdening the game's queue: the // game queue signals the fence (cheap), our copy queue waits on it. Skipped if the // queue isn't captured yet or the fence is missing (one possibly-early frame).