graphics-hook: Try multiple D3D12 queues

Keep trying queues until one of them passes D3D11On12CreateDevice.
This commit is contained in:
jpark37 2021-05-16 01:09:30 -07:00 committed by Jim
parent 5290326b77
commit c6cee82c92
2 changed files with 78 additions and 32 deletions

View File

@ -46,7 +46,8 @@ struct d3d12_data {
static struct d3d12_data data = {};
extern thread_local bool dxgi_presenting;
extern ID3D12CommandQueue *dxgi_possible_swap_queue;
extern ID3D12CommandQueue *dxgi_possible_swap_queues[8];
extern size_t dxgi_possible_swap_queue_count;
extern bool dxgi_present_attempted;
void d3d12_free(void)
@ -149,7 +150,6 @@ static bool d3d12_init_11on12(ID3D12Device *device)
static PFN_D3D11ON12_CREATE_DEVICE create_11_on_12 = nullptr;
static bool initialized_11 = false;
static bool initialized_func = false;
HRESULT hr;
if (!initialized_11 && !d3d11) {
d3d11 = load_system_library("d3d11.dll");
@ -178,29 +178,47 @@ static bool d3d12_init_11on12(ID3D12Device *device)
return false;
}
IUnknown *queue = nullptr;
IUnknown *const *queues = nullptr;
UINT num_queues = 0;
bool created = false;
if (global_hook_info->d3d12_use_swap_queue) {
hlog("d3d12_init_11on12: creating 11 device with swap queue: 0x%" PRIX64,
(uint64_t)(uintptr_t)dxgi_possible_swap_queue);
queue = dxgi_possible_swap_queue;
queues = &queue;
num_queues = 1;
for (size_t i = 0; i < dxgi_possible_swap_queue_count; ++i) {
hlog("d3d12_init_11on12: creating 11 device with swap queue: 0x%" PRIX64,
(uint64_t)(uintptr_t)dxgi_possible_swap_queues[i]);
IUnknown *const queue = dxgi_possible_swap_queues[i];
const HRESULT hr = create_11_on_12(
device, 0, nullptr, 0, &queue, 1, 0,
&data.device11, &data.context11, nullptr);
created = SUCCEEDED(hr);
if (created) {
break;
}
hlog_hr("d3d12_init_11on12: failed to create 11 device",
hr);
}
} else {
hlog("d3d12_init_11on12: creating 11 device without swap queue");
const HRESULT hr = create_11_on_12(device, 0, nullptr, 0,
nullptr, 0, 0,
&data.device11,
&data.context11, nullptr);
created = SUCCEEDED(hr);
if (!created) {
hlog_hr("d3d12_init_11on12: failed to create 11 device",
hr);
}
}
hr = create_11_on_12(device, 0, nullptr, 0, queues, num_queues, 0,
&data.device11, &data.context11, nullptr);
if (FAILED(hr)) {
hlog_hr("d3d12_init_11on12: failed to create 11 device", hr);
if (!created) {
return false;
}
data.device11->QueryInterface(__uuidof(ID3D11On12Device),
(void **)&data.device11on12);
memset(dxgi_possible_swap_queues, 0, sizeof(dxgi_possible_swap_queues));
dxgi_possible_swap_queue_count = 0;
dxgi_present_attempted = false;
const HRESULT hr =
data.device11->QueryInterface(IID_PPV_ARGS(&data.device11on12));
if (FAILED(hr)) {
hlog_hr("d3d12_init_11on12: failed to query 11on12 device", hr);
return false;
@ -363,6 +381,18 @@ void d3d12_capture(void *swap_ptr, void *, bool capture_overlay)
}
}
static bool try_append_queue_if_unique(ID3D12CommandQueue *queue)
{
for (size_t i = 0; i < dxgi_possible_swap_queue_count; ++i) {
if (dxgi_possible_swap_queues[i] == queue)
return false;
}
dxgi_possible_swap_queues[dxgi_possible_swap_queue_count] = queue;
++dxgi_possible_swap_queue_count;
return true;
}
static HRESULT STDMETHODCALLTYPE
hook_execute_command_lists(ID3D12CommandQueue *queue, UINT NumCommandLists,
ID3D12CommandList *const *ppCommandLists)
@ -370,17 +400,24 @@ hook_execute_command_lists(ID3D12CommandQueue *queue, UINT NumCommandLists,
hlog_verbose("ExecuteCommandLists callback: queue=0x%" PRIX64,
(uint64_t)(uintptr_t)queue);
if (!dxgi_possible_swap_queue) {
if (dxgi_presenting) {
hlog("Remembering D3D12 queue from present");
dxgi_possible_swap_queue = queue;
if (dxgi_possible_swap_queue_count <
_countof(dxgi_possible_swap_queues)) {
if (dxgi_presenting &&
(queue->GetDesc().Type == D3D12_COMMAND_LIST_TYPE_DIRECT)) {
if (try_append_queue_if_unique(queue)) {
hlog("Remembering D3D12 queue from present: queue=0x%" PRIX64,
(uint64_t)(uintptr_t)queue);
}
} else if (dxgi_present_attempted &&
(queue->GetDesc().Type ==
D3D12_COMMAND_LIST_TYPE_DIRECT)) {
hlog("Remembering D3D12 queue from first direct submit after present");
dxgi_possible_swap_queue = queue;
if (try_append_queue_if_unique(queue)) {
hlog("Remembering D3D12 queue from first direct submit after present: queue=0x%" PRIX64,
(uint64_t)(uintptr_t)queue);
}
} else {
hlog_verbose("Ignoring D3D12 queue");
hlog_verbose("Ignoring D3D12 queue=0x%" PRIX64,
(uint64_t)(uintptr_t)queue);
}
}

View File

@ -25,7 +25,8 @@ static struct func_hook present;
static struct func_hook present1;
thread_local bool dxgi_presenting = false;
struct ID3D12CommandQueue *dxgi_possible_swap_queue = nullptr;
struct ID3D12CommandQueue *dxgi_possible_swap_queues[8]{};
size_t dxgi_possible_swap_queue_count;
bool dxgi_present_attempted = false;
struct dxgi_swap_data {
@ -89,13 +90,16 @@ static bool setup_dxgi(IDXGISwapChain *swap)
device->Release();
hlog("Found D3D12 device on swap chain: swap=0x%" PRIX64
", device=0x%" PRIX64 ", use_queue=%d, queue=0x%" PRIX64,
", device=0x%" PRIX64 ", use_queue=%d",
(uint64_t)(uintptr_t)swap, (uint64_t)(uintptr_t)device,
(int)global_hook_info->d3d12_use_swap_queue,
(uint64_t)(uintptr_t)dxgi_possible_swap_queue);
(int)global_hook_info->d3d12_use_swap_queue);
for (size_t i = 0; i < dxgi_possible_swap_queue_count; ++i) {
hlog("\tqueue=0x%" PRIX64,
(uint64_t)(uintptr_t)dxgi_possible_swap_queues[i]);
}
if (!global_hook_info->d3d12_use_swap_queue ||
dxgi_possible_swap_queue) {
(dxgi_possible_swap_queue_count > 0)) {
data.swap = swap;
data.capture = d3d12_capture;
data.free = d3d12_free;
@ -121,7 +125,9 @@ static ULONG STDMETHODCALLTYPE hook_release(IUnknown *unknown)
data.swap = nullptr;
data.capture = nullptr;
dxgi_possible_swap_queue = nullptr;
memset(dxgi_possible_swap_queues, 0,
sizeof(dxgi_possible_swap_queues));
dxgi_possible_swap_queue_count = 0;
dxgi_present_attempted = false;
data.free();
@ -143,7 +149,8 @@ static HRESULT STDMETHODCALLTYPE hook_resize_buffers(IDXGISwapChain *swap,
data.swap = nullptr;
data.capture = nullptr;
dxgi_possible_swap_queue = nullptr;
memset(dxgi_possible_swap_queues, 0, sizeof(dxgi_possible_swap_queues));
dxgi_possible_swap_queue_count = 0;
dxgi_present_attempted = false;
if (data.free)
@ -182,7 +189,9 @@ static void update_mismatch_count(bool match)
if (swap_chain_mismatch_count == swap_chain_mismtach_limit) {
data.swap = nullptr;
data.capture = nullptr;
dxgi_possible_swap_queue = nullptr;
memset(dxgi_possible_swap_queues, 0,
sizeof(dxgi_possible_swap_queues));
dxgi_possible_swap_queue_count = 0;
dxgi_present_attempted = false;
data.free();