summaryrefslogtreecommitdiffstats
path: root/video/out/gpu/d3d11_helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/gpu/d3d11_helpers.c')
-rw-r--r--video/out/gpu/d3d11_helpers.c210
1 files changed, 155 insertions, 55 deletions
diff --git a/video/out/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c
index 33d01e0861..fa37d5ef30 100644
--- a/video/out/gpu/d3d11_helpers.c
+++ b/video/out/gpu/d3d11_helpers.c
@@ -19,12 +19,12 @@
#include <d3d11.h>
#include <dxgi1_6.h>
#include <versionhelpers.h>
-#include <pthread.h>
#include "common/common.h"
#include "common/msg.h"
#include "misc/bstr.h"
#include "osdep/io.h"
+#include "osdep/threads.h"
#include "osdep/windows_utils.h"
#include "d3d11_helpers.h"
@@ -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 pthread_once_t d3d11_once = PTHREAD_ONCE_INIT;
+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,11 +50,15 @@ 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)
{
- pthread_once(&d3d11_once, d3d11_load);
+ mp_exec_once(&d3d11_once, d3d11_load);
if (!pD3D11CreateDevice || !pCreateDXGIFactory1) {
mp_fatal(log, "Failed to load base d3d11 functionality: "
"CreateDevice: %s, CreateDXGIFactory1: %s\n",
@@ -228,9 +235,9 @@ static const char *d3d11_get_csp_name(DXGI_COLOR_SPACE_TYPE csp)
}
static bool d3d11_get_mp_csp(DXGI_COLOR_SPACE_TYPE csp,
- struct mp_colorspace *mp_csp)
+ struct pl_color_space *pl_color_system)
{
- if (!mp_csp)
+ if (!pl_color_system)
return false;
// Colorspaces utilizing gamma 2.2 (G22) are set to
@@ -243,27 +250,27 @@ static bool d3d11_get_mp_csp(DXGI_COLOR_SPACE_TYPE csp,
// regarding not doing conversion from BT.601 to BT.709.
switch (csp) {
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709:
- *mp_csp = (struct mp_colorspace){
- .gamma = MP_CSP_TRC_AUTO,
- .primaries = MP_CSP_PRIM_AUTO,
+ *pl_color_system = (struct pl_color_space){
+ .transfer = PL_COLOR_TRC_UNKNOWN,
+ .primaries = PL_COLOR_PRIM_UNKNOWN,
};
break;
case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709:
- *mp_csp = (struct mp_colorspace) {
- .gamma = MP_CSP_TRC_LINEAR,
- .primaries = MP_CSP_PRIM_AUTO,
+ *pl_color_system = (struct pl_color_space) {
+ .transfer = PL_COLOR_TRC_LINEAR,
+ .primaries = PL_COLOR_PRIM_UNKNOWN,
};
break;
case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020:
- *mp_csp = (struct mp_colorspace) {
- .gamma = MP_CSP_TRC_PQ,
- .primaries = MP_CSP_PRIM_BT_2020,
+ *pl_color_system = (struct pl_color_space) {
+ .transfer = PL_COLOR_TRC_PQ,
+ .primaries = PL_COLOR_PRIM_BT_2020,
};
break;
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020:
- *mp_csp = (struct mp_colorspace) {
- .gamma = MP_CSP_TRC_AUTO,
- .primaries = MP_CSP_PRIM_BT_2020,
+ *pl_color_system = (struct pl_color_space) {
+ .transfer = PL_COLOR_TRC_UNKNOWN,
+ .primaries = PL_COLOR_PRIM_BT_2020,
};
break;
default:
@@ -287,28 +294,8 @@ static bool query_output_format_and_colorspace(struct mp_log *log,
if (!out_fmt || !out_cspace)
return false;
- HRESULT hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
- if (FAILED(hr)) {
- mp_err(log, "Failed to get swap chain's containing output: %s!\n",
- mp_HRESULT_to_str(hr));
- goto done;
- }
-
- hr = IDXGIOutput_QueryInterface(output, &IID_IDXGIOutput6,
- (void**)&output6);
- if (FAILED(hr)) {
- // point where systems older than Windows 10 would fail,
- // thus utilizing error log level only with windows 10+
- mp_msg(log, IsWindows10OrGreater() ? MSGL_ERR : MSGL_V,
- "Failed to create a DXGI 1.6 output interface: %s\n",
- mp_HRESULT_to_str(hr));
- goto done;
- }
-
- hr = IDXGIOutput6_GetDesc1(output6, &desc);
- if (FAILED(hr)) {
- mp_err(log, "Failed to query swap chain's output information: %s\n",
- mp_HRESULT_to_str(hr));
+ if (!mp_get_dxgi_output_desc(swapchain, &desc)) {
+ mp_err(log, "Failed to query swap chain's output information\n");
goto done;
}
@@ -371,9 +358,9 @@ static int get_feature_levels(int max_fl, int min_fl,
return len;
}
-static IDXGIAdapter1 *get_d3d11_adapter(struct mp_log *log,
- struct bstr requested_adapter_name,
- struct bstr *listing)
+IDXGIAdapter1 *mp_get_dxgi_adapter(struct mp_log *log,
+ bstr requested_adapter_name,
+ bstr *listing)
{
HRESULT hr = S_OK;
IDXGIFactory1 *factory;
@@ -437,6 +424,37 @@ static IDXGIAdapter1 *get_d3d11_adapter(struct mp_log *log,
return picked_adapter;
}
+int mp_dxgi_validate_adapter(struct mp_log *log,
+ const struct m_option *opt,
+ struct bstr name, const char **value)
+{
+ struct bstr param = bstr0(*value);
+ bool help = bstr_equals0(param, "help");
+ bool adapter_matched = false;
+ struct bstr listing = { 0 };
+
+ if (bstr_equals0(param, "")) {
+ return 0;
+ }
+
+ adapter_matched = mp_dxgi_list_or_verify_adapters(log,
+ help ? bstr0(NULL) : param,
+ help ? &listing : NULL);
+
+ if (help) {
+ mp_info(log, "Available DXGI adapters:\n%.*s",
+ BSTR_P(listing));
+ talloc_free(listing.start);
+ return M_OPT_EXIT;
+ }
+
+ if (!adapter_matched) {
+ mp_err(log, "No adapter matching '%.*s'!\n", BSTR_P(param));
+ }
+
+ return adapter_matched ? 0 : M_OPT_INVALID;
+}
+
static HRESULT create_device(struct mp_log *log, IDXGIAdapter1 *adapter,
bool warp, bool debug, int max_fl, int min_fl,
ID3D11Device **dev)
@@ -455,9 +473,9 @@ static HRESULT create_device(struct mp_log *log, IDXGIAdapter1 *adapter,
NULL, flags, levels, levels_len, D3D11_SDK_VERSION, dev, NULL, NULL);
}
-bool mp_d3d11_list_or_verify_adapters(struct mp_log *log,
- bstr adapter_name,
- bstr *listing)
+bool mp_dxgi_list_or_verify_adapters(struct mp_log *log,
+ bstr adapter_name,
+ bstr *listing)
{
IDXGIAdapter1 *picked_adapter = NULL;
@@ -465,7 +483,7 @@ bool mp_d3d11_list_or_verify_adapters(struct mp_log *log,
return false;
}
- if ((picked_adapter = get_d3d11_adapter(log, adapter_name, listing))) {
+ if ((picked_adapter = mp_get_dxgi_adapter(log, adapter_name, listing))) {
SAFE_RELEASE(picked_adapter);
return true;
}
@@ -480,6 +498,7 @@ bool mp_d3d11_create_present_device(struct mp_log *log,
struct d3d11_device_opts *opts,
ID3D11Device **dev_out)
{
+ bool debug = opts->debug;
bool warp = opts->force_warp;
int max_fl = opts->max_feature_level;
int min_fl = opts->min_feature_level;
@@ -496,7 +515,7 @@ bool mp_d3d11_create_present_device(struct mp_log *log,
goto done;
}
- adapter = get_d3d11_adapter(log, bstr0(adapter_name), NULL);
+ adapter = mp_get_dxgi_adapter(log, bstr0(adapter_name), NULL);
if (adapter_name && !adapter) {
mp_warn(log, "Adapter matching '%s' was not found in the system! "
@@ -510,7 +529,15 @@ bool mp_d3d11_create_present_device(struct mp_log *log,
max_fl = max_fl ? max_fl : D3D_FEATURE_LEVEL_11_0;
min_fl = min_fl ? min_fl : D3D_FEATURE_LEVEL_9_1;
- hr = create_device(log, adapter, warp, opts->debug, max_fl, min_fl, &dev);
+ hr = create_device(log, adapter, warp, debug, max_fl, min_fl, &dev);
+
+ // Retry without debug, if SDK is not available
+ if (debug && hr == DXGI_ERROR_SDK_COMPONENT_MISSING) {
+ mp_warn(log, "gpu-debug disabled due to error: %s\n", mp_HRESULT_to_str(hr));
+ debug = false;
+ continue;
+ }
+
if (SUCCEEDED(hr))
break;
@@ -630,7 +657,21 @@ static HRESULT create_swapchain_1_2(ID3D11Device *dev, IDXGIFactory2 *factory,
};
if (flip) {
- desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ // UNORDERED_ACCESS with FLIP_SEQUENTIAL seems to be buggy with
+ // Windows 7 drivers
+ if ((desc.BufferUsage & DXGI_USAGE_UNORDERED_ACCESS) &&
+ !IsWindows8OrGreater())
+ {
+ mp_verbose(log, "Disabling UNORDERED_ACCESS for flip-model "
+ "swapchain backbuffers in Windows 7\n");
+ desc.BufferUsage &= ~DXGI_USAGE_UNORDERED_ACCESS;
+ }
+
+ if (IsWindows10OrGreater()) {
+ desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ } else {
+ desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ }
desc.BufferCount = opts->length;
} else {
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
@@ -770,7 +811,7 @@ static bool configure_created_swapchain(struct mp_log *log,
IDXGISwapChain *swapchain,
DXGI_FORMAT requested_format,
DXGI_COLOR_SPACE_TYPE requested_csp,
- struct mp_colorspace *configured_csp)
+ struct pl_color_space *configured_csp)
{
DXGI_FORMAT probed_format = DXGI_FORMAT_UNKNOWN;
DXGI_FORMAT selected_format = DXGI_FORMAT_UNKNOWN;
@@ -778,7 +819,7 @@ static bool configure_created_swapchain(struct mp_log *log,
DXGI_COLOR_SPACE_TYPE selected_colorspace;
const char *format_name = NULL;
const char *csp_name = NULL;
- struct mp_colorspace mp_csp = { 0 };
+ struct pl_color_space pl_color_system = { 0 };
bool mp_csp_mapped = false;
query_output_format_and_colorspace(log, swapchain,
@@ -794,7 +835,7 @@ static bool configure_created_swapchain(struct mp_log *log,
requested_csp : probed_colorspace;
format_name = d3d11_get_format_name(selected_format);
csp_name = d3d11_get_csp_name(selected_colorspace);
- mp_csp_mapped = d3d11_get_mp_csp(selected_colorspace, &mp_csp);
+ mp_csp_mapped = d3d11_get_mp_csp(selected_colorspace, &pl_color_system);
mp_verbose(log, "Selected swapchain format %s (%d), attempting "
"to utilize it.\n",
@@ -825,7 +866,7 @@ static bool configure_created_swapchain(struct mp_log *log,
"mapping! Overriding to standard sRGB!\n",
csp_name, selected_colorspace);
selected_colorspace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
- d3d11_get_mp_csp(selected_colorspace, &mp_csp);
+ d3d11_get_mp_csp(selected_colorspace, &pl_color_system);
}
mp_verbose(log, "Selected swapchain color space %s (%d), attempting to "
@@ -837,7 +878,7 @@ static bool configure_created_swapchain(struct mp_log *log,
}
if (configured_csp) {
- *configured_csp = mp_csp;
+ *configured_csp = pl_color_system;
}
return true;
@@ -921,7 +962,9 @@ bool mp_d3d11_create_swapchain(ID3D11Device *dev, struct mp_log *log,
DXGI_SWAP_CHAIN_DESC scd = {0};
IDXGISwapChain_GetDesc(swapchain, &scd);
- if (scd.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
+ if (scd.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ||
+ scd.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
+ {
mp_verbose(log, "Using flip-model presentation\n");
} else {
mp_verbose(log, "Using bitblt-model presentation\n");
@@ -939,3 +982,60 @@ done:
SAFE_RELEASE(dxgi_dev);
return success;
}
+
+bool mp_get_dxgi_output_desc(IDXGISwapChain *swapchain, DXGI_OUTPUT_DESC1 *desc)
+{
+ bool ret = false;
+ IDXGIOutput *output = NULL;
+ IDXGIOutput6 *output6 = NULL;
+
+ if (FAILED(IDXGISwapChain_GetContainingOutput(swapchain, &output)))
+ goto done;
+
+ if (FAILED(IDXGIOutput_QueryInterface(output, &IID_IDXGIOutput6, (void**)&output6)))
+ goto done;
+
+ ret = SUCCEEDED(IDXGIOutput6_GetDesc1(output6, desc));
+
+done:
+ SAFE_RELEASE(output);
+ SAFE_RELEASE(output6);
+ return ret;
+}
+
+#if HAVE_DXGI_DEBUG
+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;
+ }
+}
+#endif