diff --git a/plugins/win-capture/graphics-hook/d3d10-capture.cpp b/plugins/win-capture/graphics-hook/d3d10-capture.cpp index e7a3e0a2a6c0e48bc955b63742266e2c5662643b..9f62ff9e1d9ce5f8b1f2ac751aee75c844551733 100644 --- a/plugins/win-capture/graphics-hook/d3d10-capture.cpp +++ b/plugins/win-capture/graphics-hook/d3d10-capture.cpp @@ -771,7 +771,7 @@ static inline void d3d10_shmem_capture(ID3D10Resource *backbuffer) data.cur_tex = next_tex; } -void d3d10_capture(void *swap_ptr, void *backbuffer_ptr) +void d3d10_capture(void *swap_ptr, void *backbuffer_ptr, bool) { IDXGIResource *dxgi_backbuffer = (IDXGIResource*)backbuffer_ptr; IDXGISwapChain *swap = (IDXGISwapChain*)swap_ptr; diff --git a/plugins/win-capture/graphics-hook/d3d11-capture.cpp b/plugins/win-capture/graphics-hook/d3d11-capture.cpp index 7ebe3a5584b4bd13bedfeda7ee8d952ac3782f49..ee0d7e162453be761f6a333892f1ee0987ad98bf 100644 --- a/plugins/win-capture/graphics-hook/d3d11-capture.cpp +++ b/plugins/win-capture/graphics-hook/d3d11-capture.cpp @@ -813,7 +813,7 @@ static inline void d3d11_shmem_capture(ID3D11Resource *backbuffer) data.cur_tex = next_tex; } -void d3d11_capture(void *swap_ptr, void *backbuffer_ptr) +void d3d11_capture(void *swap_ptr, void *backbuffer_ptr, bool) { IDXGIResource *dxgi_backbuffer = (IDXGIResource*)backbuffer_ptr; IDXGISwapChain *swap = (IDXGISwapChain*)swap_ptr; diff --git a/plugins/win-capture/graphics-hook/d3d12-capture.cpp b/plugins/win-capture/graphics-hook/d3d12-capture.cpp index 6999b3ec4971ec665cb94c48c91f820fa6b8e17b..01c31b32f0c6018a53a11e1ac7aeaf3865a9833e 100644 --- a/plugins/win-capture/graphics-hook/d3d12-capture.cpp +++ b/plugins/win-capture/graphics-hook/d3d12-capture.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include "dxgi-helpers.hpp" #include "../funchook.h" @@ -20,6 +20,7 @@ struct d3d12_data { bool using_shtex : 1; bool using_scale : 1; bool multisampled : 1; + bool dxgi_1_4 : 1; ID3D11Device *device11; ID3D11DeviceContext *context11; @@ -28,7 +29,9 @@ struct d3d12_data { union { struct { struct shtex_data *shtex_info; - ID3D11Resource *backbuffer11; + ID3D11Resource *backbuffer11[3]; + UINT backbuffer_count; + UINT cur_backbuffer; ID3D11Texture2D *copy_tex; HANDLE handle; }; @@ -41,8 +44,10 @@ void d3d12_free(void) { if (data.copy_tex) data.copy_tex->Release(); - if (data.backbuffer11) - data.backbuffer11->Release(); + for (size_t i = 0; i < data.backbuffer_count; i++) { + if (data.backbuffer11[i]) + data.backbuffer11[i]->Release(); + } if (data.device11) data.device11->Release(); if (data.context11) @@ -57,20 +62,35 @@ void d3d12_free(void) hlog("----------------- d3d12 capture freed ----------------"); } -static bool create_d3d12_tex(ID3D12Resource *backbuffer) +static bool create_d3d12_tex(ID3D12Resource *backbuffer[3], UINT count) { D3D11_RESOURCE_FLAGS rf11 = {}; HRESULT hr; - hr = data.device11on12->CreateWrappedResource(backbuffer, &rf11, - D3D12_RESOURCE_STATE_COPY_SOURCE, - D3D12_RESOURCE_STATE_PRESENT, - __uuidof(ID3D11Resource), - (void**)&data.backbuffer11); - if (FAILED(hr)) { - hlog_hr("create_d3d12_tex: failed to create backbuffer11", - hr); + if (!count) return false; + + if (count > 3) { + hlog("Somehow it's using more than 3 backbuffers. " + "Not sure why anyone would do that."); + count = 3; + } + + data.backbuffer_count = count; + + for (UINT i = 0; i < count; i++) { + hr = data.device11on12->CreateWrappedResource( + backbuffer[i], + &rf11, + D3D12_RESOURCE_STATE_COPY_SOURCE, + D3D12_RESOURCE_STATE_PRESENT, + __uuidof(ID3D11Resource), + (void**)&data.backbuffer11[i]); + if (FAILED(hr)) { + hlog_hr("create_d3d12_tex: failed to create " + "backbuffer11", hr); + return false; + } } D3D11_TEXTURE2D_DESC desc11 = {}; @@ -90,7 +110,10 @@ static bool create_d3d12_tex(ID3D12Resource *backbuffer) return false; } - data.device11on12->ReleaseWrappedResources(&data.backbuffer11, 1); + for (UINT i = 0; i < count; i++) { + data.device11on12->ReleaseWrappedResources( + &data.backbuffer11[i], 1); + } IDXGIResource *dxgi_res; hr = data.copy_tex->QueryInterface(__uuidof(IDXGIResource), @@ -174,12 +197,13 @@ static bool d3d12_init_11on12(void) return true; } -static bool d3d12_shtex_init(HWND window, ID3D12Resource *backbuffer) +static bool d3d12_shtex_init(HWND window, ID3D12Resource *backbuffer[3], + UINT count) { if (!d3d12_init_11on12()) { return false; } - if (!create_d3d12_tex(backbuffer)) { + if (!create_d3d12_tex(backbuffer, count)) { return false; } if (!capture_init_shtex(&data.shtex_info, window, @@ -192,10 +216,13 @@ static bool d3d12_shtex_init(HWND window, ID3D12Resource *backbuffer) return true; } -static inline bool d3d12_init_format(IDXGISwapChain *swap, HWND &window) +static inline bool d3d12_init_format(IDXGISwapChain *swap, HWND &window, + ID3D12Resource *backbuffer[3], UINT *p_count) { DXGI_SWAP_CHAIN_DESC desc; + IDXGISwapChain3 *swap3; HRESULT hr; + UINT count; hr = swap->GetDesc(&desc); if (FAILED(hr)) { @@ -209,6 +236,31 @@ static inline bool d3d12_init_format(IDXGISwapChain *swap, HWND &window) data.base_cx = desc.BufferDesc.Width; data.base_cy = desc.BufferDesc.Height; + hr = swap->QueryInterface(__uuidof(IDXGISwapChain3), (void**)&swap3); + if (SUCCEEDED(hr)) { + data.dxgi_1_4 = true; + hlog("We're DXGI1.4 boys!"); + swap3->Release(); + } + + count = desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD + ? 1 : desc.BufferCount; + + for (UINT i = 0; i < count; i++) { + hr = swap->GetBuffer(i, __uuidof(ID3D12Resource), + (void**)&backbuffer[i]); + if (FAILED(hr)) { + if (i > 0) { + for (UINT j = 0; j < i; j++) { + backbuffer[j]->Release(); + } + } + return false; + } + } + + *p_count = count; + if (data.using_scale) { data.cx = global_hook_info->cx; data.cy = global_hook_info->cy; @@ -219,11 +271,13 @@ static inline bool d3d12_init_format(IDXGISwapChain *swap, HWND &window) return true; } -static void d3d12_init(IDXGISwapChain *swap, ID3D12Resource *backbuffer) +static void d3d12_init(IDXGISwapChain *swap) { + ID3D12Resource *backbuffer[3]; bool success = true; HWND window; HRESULT hr; + UINT count; data.using_scale = global_hook_info->use_scale; @@ -235,7 +289,7 @@ static void d3d12_init(IDXGISwapChain *swap, ID3D12Resource *backbuffer) data.device->Release(); - if (!d3d12_init_format(swap, window)) { + if (!d3d12_init_format(swap, window, backbuffer, &count)) { return; } if (data.using_scale) { @@ -247,7 +301,7 @@ static void d3d12_init(IDXGISwapChain *swap, ID3D12Resource *backbuffer) "unsupported; ignoring"); } - success = d3d12_shtex_init(window, backbuffer); + success = d3d12_shtex_init(window, backbuffer, count); } if (!success) @@ -263,37 +317,49 @@ static inline void d3d12_copy_texture(ID3D11Resource *dst, ID3D11Resource *src) } } -static inline void d3d12_shtex_capture() +static inline void d3d12_shtex_capture(IDXGISwapChain *swap, + bool capture_overlay) { - data.device11on12->AcquireWrappedResources(&data.backbuffer11, 1); - d3d12_copy_texture(data.copy_tex, data.backbuffer11); - data.device11on12->ReleaseWrappedResources(&data.backbuffer11, 1); + bool dxgi_1_4 = data.dxgi_1_4; + UINT cur_idx; + + if (dxgi_1_4) { + IDXGISwapChain3 *swap3 = + reinterpret_cast(swap); + cur_idx = swap3->GetCurrentBackBufferIndex(); + if (!capture_overlay) { + if (++cur_idx >= data.backbuffer_count) + cur_idx = 0; + } + } else { + cur_idx = data.cur_backbuffer; + } + + ID3D11Resource *backbuffer = data.backbuffer11[cur_idx]; + + data.device11on12->AcquireWrappedResources(&backbuffer, 1); + d3d12_copy_texture(data.copy_tex, backbuffer); + data.device11on12->ReleaseWrappedResources(&backbuffer, 1); data.context11->Flush(); + + if (!dxgi_1_4) { + if (++data.cur_backbuffer >= data.backbuffer_count) + data.cur_backbuffer = 0; + } } -void d3d12_capture(void *swap_ptr, void *backbuffer_ptr) +void d3d12_capture(void *swap_ptr, void*, bool capture_overlay) { - IUnknown *unk_backbuffer = (IUnknown*)backbuffer_ptr; IDXGISwapChain *swap = (IDXGISwapChain*)swap_ptr; - ID3D12Resource *backbuffer; - HRESULT hr; if (capture_should_stop()) { d3d12_free(); } if (capture_should_init()) { - hr = unk_backbuffer->QueryInterface(__uuidof(ID3D12Resource), - (void**)&backbuffer); - if (FAILED(hr)) { - hlog_hr("d3d12_capture: failed to get backbuffer", hr); - return; - } - - d3d12_init(swap, backbuffer); - backbuffer->Release(); + d3d12_init(swap); } if (capture_ready()) { - d3d12_shtex_capture(); + d3d12_shtex_capture(swap, capture_overlay); } } diff --git a/plugins/win-capture/graphics-hook/dxgi-capture.cpp b/plugins/win-capture/graphics-hook/dxgi-capture.cpp index c9891a56cabacb475ee00dd95229edf45122fe66..9cdea1b8231f3ad0ed2338db6daccc9158ca0f4d 100644 --- a/plugins/win-capture/graphics-hook/dxgi-capture.cpp +++ b/plugins/win-capture/graphics-hook/dxgi-capture.cpp @@ -20,7 +20,7 @@ static struct func_hook present; struct dxgi_swap_data { IDXGISwapChain *swap; - void (*capture)(void*, void*); + void (*capture)(void*, void*, bool); void (*free)(void); }; @@ -131,7 +131,7 @@ static HRESULT STDMETHODCALLTYPE hook_present(IDXGISwapChain *swap, backbuffer = get_dxgi_backbuffer(swap); if (!!backbuffer) { - data.capture(swap, backbuffer); + data.capture(swap, backbuffer, capture_overlay); backbuffer->Release(); } } @@ -155,7 +155,7 @@ static HRESULT STDMETHODCALLTYPE hook_present(IDXGISwapChain *swap, backbuffer = get_dxgi_backbuffer(swap); if (!!backbuffer) { - data.capture(swap, backbuffer); + data.capture(swap, backbuffer, capture_overlay); backbuffer->Release(); } } diff --git a/plugins/win-capture/graphics-hook/graphics-hook.h b/plugins/win-capture/graphics-hook/graphics-hook.h index c9cd6c6d4dcc0499c523dadf51f28524ea0a1ac8..8baa762492c496c28e4b89f1d1efa900197e385e 100644 --- a/plugins/win-capture/graphics-hook/graphics-hook.h +++ b/plugins/win-capture/graphics-hook/graphics-hook.h @@ -43,13 +43,13 @@ extern bool hook_d3d9(void); extern bool hook_dxgi(void); extern bool hook_gl(void); -extern void d3d10_capture(void *swap, void *backbuffer); +extern void d3d10_capture(void *swap, void *backbuffer, bool capture_overlay); extern void d3d10_free(void); -extern void d3d11_capture(void *swap, void *backbuffer); +extern void d3d11_capture(void *swap, void *backbuffer, bool capture_overlay); extern void d3d11_free(void); #if COMPILE_D3D12_HOOK -extern void d3d12_capture(void *swap, void *backbuffer); +extern void d3d12_capture(void *swap, void *backbuffer, bool capture_overlay); extern void d3d12_free(void); #endif