summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorKacper Michajłow <kasper93@gmail.com>2023-05-01 03:11:15 +0200
committerKacper Michajłow <kasper93@gmail.com>2024-04-19 03:32:29 +0200
commit19a9164e246c197c77ec2d0c0f1f462e42bb4817 (patch)
treee041bb7a86c00e47163ff3820241170161da67e6 /video
parent56b3bcaaf2594e38e35f0d115d84ee0e1aeac7ee (diff)
downloadmpv-19a9164e246c197c77ec2d0c0f1f462e42bb4817.tar.bz2
mpv-19a9164e246c197c77ec2d0c0f1f462e42bb4817.tar.xz
d3d11: use IDXGIInfoQueue instead ID3D11InfoQueue
DXGI debug interface encapsulate multiple message queues, which allows to get validation not only for D3D11 calls, but also DXGI ones. Also this makes leak detector not report self debug interface as alive like it was before. And same as with validation, it has ability to detect more alive objects, not being limited to D3D11.
Diffstat (limited to 'video')
-rw-r--r--video/out/d3d11/ra_d3d11.c77
-rw-r--r--video/out/gpu/d3d11_helpers.c42
-rw-r--r--video/out/gpu/d3d11_helpers.h8
3 files changed, 77 insertions, 50 deletions
diff --git a/video/out/d3d11/ra_d3d11.c b/video/out/d3d11/ra_d3d11.c
index 84fd004adc..2b9c1aa11e 100644
--- a/video/out/d3d11/ra_d3d11.c
+++ b/video/out/d3d11/ra_d3d11.c
@@ -13,6 +13,7 @@
#include "osdep/windows_utils.h"
#include "video/out/gpu/spirv.h"
#include "video/out/gpu/utils.h"
+#include "video/out/gpu/d3d11_helpers.h"
#include "ra_d3d11.h"
@@ -44,8 +45,8 @@ struct ra_d3d11 {
struct dll_version d3d_compiler_ver;
// Debug interfaces (--gpu-debug)
- ID3D11Debug *debug;
- ID3D11InfoQueue *iqueue;
+ IDXGIDebug *debug;
+ IDXGIInfoQueue *iqueue;
// Device capabilities
D3D_FEATURE_LEVEL fl;
@@ -2094,24 +2095,24 @@ static uint64_t timer_stop(struct ra *ra, ra_timer *ratimer)
return timer->result;
}
-static int map_msg_severity(D3D11_MESSAGE_SEVERITY sev)
+static int map_msg_severity(DXGI_INFO_QUEUE_MESSAGE_SEVERITY sev)
{
switch (sev) {
- case D3D11_MESSAGE_SEVERITY_CORRUPTION:
+ case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION:
return MSGL_FATAL;
- case D3D11_MESSAGE_SEVERITY_ERROR:
+ case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR:
return MSGL_ERR;
- case D3D11_MESSAGE_SEVERITY_WARNING:
+ case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING:
return MSGL_WARN;
default:
- case D3D11_MESSAGE_SEVERITY_INFO:
- case D3D11_MESSAGE_SEVERITY_MESSAGE:
+ case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO:
+ case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE:
return MSGL_DEBUG;
}
}
static int map_msg_severity_by_id(D3D11_MESSAGE_ID id,
- D3D11_MESSAGE_SEVERITY sev)
+ DXGI_INFO_QUEUE_MESSAGE_SEVERITY sev)
{
switch (id) {
// These are normal. The RA timer queue habitually reuses timer objects
@@ -2180,31 +2181,35 @@ static void debug_marker(struct ra *ra, const char *msg)
// Copy debug-layer messages to mpv's log output
bool printed_header = false;
- uint64_t messages = ID3D11InfoQueue_GetNumStoredMessages(p->iqueue);
+ uint64_t messages = IDXGIInfoQueue_GetNumStoredMessages(p->iqueue,
+ DXGI_DEBUG_ALL);
for (uint64_t i = 0; i < messages; i++) {
SIZE_T len;
- hr = ID3D11InfoQueue_GetMessage(p->iqueue, i, NULL, &len);
+ hr = IDXGIInfoQueue_GetMessage(p->iqueue, DXGI_DEBUG_ALL, i, NULL, &len);
if (FAILED(hr) || !len)
goto done;
- D3D11_MESSAGE *d3dmsg = talloc_size(talloc_ctx, len);
- hr = ID3D11InfoQueue_GetMessage(p->iqueue, i, d3dmsg, &len);
+ DXGI_INFO_QUEUE_MESSAGE *dxgimsg = talloc_size(talloc_ctx, len);
+ hr = IDXGIInfoQueue_GetMessage(p->iqueue, DXGI_DEBUG_ALL, i, dxgimsg, &len);
if (FAILED(hr))
goto done;
- int msgl = map_msg_severity_by_id(d3dmsg->ID, d3dmsg->Severity);
+ int msgl = IsEqualGUID(&dxgimsg->Producer, &DXGI_DEBUG_D3D11)
+ ? map_msg_severity_by_id(dxgimsg->ID, dxgimsg->Severity)
+ : map_msg_severity(dxgimsg->Severity);
+
if (mp_msg_test(ra->log, msgl)) {
if (!printed_header)
MP_INFO(ra, "%s:\n", msg);
printed_header = true;
- MP_MSG(ra, msgl, "%d: %.*s\n", (int)d3dmsg->ID,
- (int)d3dmsg->DescriptionByteLength, d3dmsg->pDescription);
- talloc_free(d3dmsg);
+ MP_MSG(ra, msgl, "%d: %.*s\n", (int)dxgimsg->ID,
+ (int)dxgimsg->DescriptionByteLength, dxgimsg->pDescription);
+ talloc_free(dxgimsg);
}
}
- ID3D11InfoQueue_ClearStoredMessages(p->iqueue);
+ IDXGIInfoQueue_ClearStoredMessages(p->iqueue, DXGI_DEBUG_ALL);
done:
talloc_free(talloc_ctx);
}
@@ -2240,9 +2245,9 @@ static void destroy(struct ra *ra)
if (p->debug) {
// Report any leaked objects
debug_marker(ra, "after destroy");
- ID3D11Debug_ReportLiveDeviceObjects(p->debug, D3D11_RLDO_DETAIL);
+ IDXGIDebug_ReportLiveObjects(p->debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_DETAIL);
debug_marker(ra, "after leak check");
- ID3D11Debug_ReportLiveDeviceObjects(p->debug, D3D11_RLDO_SUMMARY);
+ IDXGIDebug_ReportLiveObjects(p->debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_SUMMARY);
debug_marker(ra, "after leak summary");
}
SAFE_RELEASE(p->debug);
@@ -2280,34 +2285,6 @@ void ra_d3d11_flush(struct ra *ra)
ID3D11DeviceContext_Flush(p->ctx);
}
-static void init_debug_layer(struct ra *ra)
-{
- struct ra_d3d11 *p = ra->priv;
- HRESULT hr;
-
- hr = ID3D11Device_QueryInterface(p->dev, &IID_ID3D11Debug,
- (void**)&p->debug);
- if (FAILED(hr)) {
- MP_ERR(ra, "Failed to get debug device: %s\n", mp_HRESULT_to_str(hr));
- return;
- }
-
- hr = ID3D11Device_QueryInterface(p->dev, &IID_ID3D11InfoQueue,
- (void**)&p->iqueue);
- if (FAILED(hr)) {
- MP_ERR(ra, "Failed to get info queue: %s\n", mp_HRESULT_to_str(hr));
- return;
- }
-
- // Store an unlimited amount of messages in the buffer. This is fine
- // because we flush stored messages regularly (in debug_marker.)
- ID3D11InfoQueue_SetMessageCountLimit(p->iqueue, -1);
-
- // Push empty filter to get everything
- D3D11_INFO_QUEUE_FILTER filter = {0};
- ID3D11InfoQueue_PushStorageFilter(p->iqueue, &filter);
-}
-
static struct dll_version get_dll_version(HMODULE dll)
{
void *ctx = talloc_new(NULL);
@@ -2467,7 +2444,7 @@ struct ra *ra_d3d11_create(ID3D11Device *dev, struct mp_log *log,
}
if (ID3D11Device_GetCreationFlags(p->dev) & D3D11_CREATE_DEVICE_DEBUG)
- init_debug_layer(ra);
+ mp_d3d11_get_debug_interfaces(ra->log, &p->debug, &p->iqueue);
// Some level 9_x devices don't have timestamp queries
hr = ID3D11Device_CreateQuery(p->dev,
@@ -2483,7 +2460,7 @@ struct ra *ra_d3d11_create(ID3D11Device *dev, struct mp_log *log,
// Ignore any messages during find_max_texture_dimension
if (p->iqueue)
- ID3D11InfoQueue_ClearStoredMessages(p->iqueue);
+ IDXGIInfoQueue_ClearStoredMessages(p->iqueue, DXGI_DEBUG_ALL);
MP_VERBOSE(ra, "Maximum Texture2D size: %dx%d\n", ra->max_texture_wh,
ra->max_texture_wh);
diff --git a/video/out/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c
index d45c038553..358a7deb8b 100644
--- a/video/out/gpu/d3d11_helpers.c
+++ b/video/out/gpu/d3d11_helpers.c
@@ -32,14 +32,17 @@
// Windows 8 enum value, not present in mingw-w64 headers
#define DXGI_ADAPTER_FLAG_SOFTWARE (2)
typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
+typedef HRESULT(WINAPI *PFN_DXGI_GET_DEBUG_INTERFACE)(REFIID riid, void **ppDebug);
static mp_once d3d11_once = MP_STATIC_ONCE_INITIALIZER;
static PFN_D3D11_CREATE_DEVICE pD3D11CreateDevice = NULL;
static PFN_CREATE_DXGI_FACTORY pCreateDXGIFactory1 = NULL;
+static PFN_DXGI_GET_DEBUG_INTERFACE pDXGIGetDebugInterface = NULL;
static void d3d11_load(void)
{
HMODULE d3d11 = LoadLibraryW(L"d3d11.dll");
HMODULE dxgilib = LoadLibraryW(L"dxgi.dll");
+ HMODULE dxgidebuglib = LoadLibraryW(L"dxgidebug.dll");
if (!d3d11 || !dxgilib)
return;
@@ -47,6 +50,10 @@ static void d3d11_load(void)
GetProcAddress(d3d11, "D3D11CreateDevice");
pCreateDXGIFactory1 = (PFN_CREATE_DXGI_FACTORY)
GetProcAddress(dxgilib, "CreateDXGIFactory1");
+ if (dxgidebuglib) {
+ pDXGIGetDebugInterface = (PFN_DXGI_GET_DEBUG_INTERFACE)
+ GetProcAddress(dxgidebuglib, "DXGIGetDebugInterface");
+ }
}
static bool load_d3d11_functions(struct mp_log *log)
@@ -995,3 +1002,38 @@ done:
SAFE_RELEASE(output6);
return ret;
}
+
+void mp_d3d11_get_debug_interfaces(struct mp_log *log, IDXGIDebug **debug,
+ IDXGIInfoQueue **iqueue)
+{
+ load_d3d11_functions(log);
+
+ *iqueue = NULL;
+ *debug = NULL;
+
+ if (!pDXGIGetDebugInterface)
+ return;
+
+ HRESULT hr;
+
+ hr = pDXGIGetDebugInterface(&IID_IDXGIInfoQueue, (void **) iqueue);
+ if (FAILED(hr)) {
+ mp_fatal(log, "Failed to get info queue: %s\n", mp_HRESULT_to_str(hr));
+ return;
+ }
+
+ // Store an unlimited amount of messages in the buffer. This is fine
+ // because we flush stored messages regularly (in debug_marker.)
+ IDXGIInfoQueue_SetMessageCountLimit(*iqueue, DXGI_DEBUG_D3D11, -1);
+ IDXGIInfoQueue_SetMessageCountLimit(*iqueue, DXGI_DEBUG_DXGI, -1);
+
+ // Push empty filter to get everything
+ DXGI_INFO_QUEUE_FILTER filter = {0};
+ IDXGIInfoQueue_PushStorageFilter(*iqueue, DXGI_DEBUG_ALL, &filter);
+
+ hr = pDXGIGetDebugInterface(&IID_IDXGIDebug, (void **) debug);
+ if (FAILED(hr)) {
+ mp_fatal(log, "Failed to get debug device: %s\n", mp_HRESULT_to_str(hr));
+ return;
+ }
+}
diff --git a/video/out/gpu/d3d11_helpers.h b/video/out/gpu/d3d11_helpers.h
index 6cc6818064..166d451933 100644
--- a/video/out/gpu/d3d11_helpers.h
+++ b/video/out/gpu/d3d11_helpers.h
@@ -23,6 +23,7 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#include <dxgi1_6.h>
+#include <dxgidebug.h>
#include "video/mp_image.h"
@@ -35,6 +36,10 @@
#define DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 ((DXGI_COLOR_SPACE_TYPE)23)
#define DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 ((DXGI_COLOR_SPACE_TYPE)24)
+#if !HAVE_DXGI_DEBUG_D3D11
+DEFINE_GUID(DXGI_DEBUG_D3D11, 0x4b99317b, 0xac39, 0x4aa6, 0xbb, 0xb, 0xba, 0xa0, 0x47, 0x84, 0x79, 0x8f);
+#endif
+
struct d3d11_device_opts {
// Enable the debug layer (D3D11_CREATE_DEVICE_DEBUG)
bool debug;
@@ -109,4 +114,7 @@ bool mp_d3d11_create_swapchain(ID3D11Device *dev, struct mp_log *log,
struct d3d11_swapchain_opts *opts,
IDXGISwapChain **swapchain_out);
+void mp_d3d11_get_debug_interfaces(struct mp_log *log, IDXGIDebug **debug,
+ IDXGIInfoQueue **iqueue);
+
#endif