提交 3b5a30ce 编写于 作者: J jp9000

win-capture: Capture all D3D12 backbuffers

D3D12 capture does not take in to account when multiple backbuffers are
in used.  With previous versions of Direct3D there was no need to do
this, but with D3D12 you must explicitly capture each specific
backbuffer currently in use.
上级 fb60a5f1
......@@ -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;
......
......@@ -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;
......
......@@ -5,7 +5,7 @@
#include <d3d11on12.h>
#include <d3d12.h>
#include <dxgi1_2.h>
#include <dxgi1_4.h>
#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,21 +62,36 @@ 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,
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);
(void**)&data.backbuffer11[i]);
if (FAILED(hr)) {
hlog_hr("create_d3d12_tex: failed to create backbuffer11",
hr);
hlog_hr("create_d3d12_tex: failed to create "
"backbuffer11", hr);
return false;
}
}
D3D11_TEXTURE2D_DESC desc11 = {};
desc11.Width = data.cx;
......@@ -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<IDXGISwapChain3*>(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);
}
}
......
......@@ -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();
}
}
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册