|
|
|
@@ -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,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<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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|