Browse Source

libobs-d3d11: Check if device can perform fast clear on init

NVIDIA GPUs in multi-GPU setups cannot safely perform a fast clear until
driver 527.37. Implement a check against the Vendor ID and driver
version of the adapter to determine if the adapter can safely perform a
fast clear.

Co-authored-by: derrod <[email protected]>
Ryan Foster 2 years ago
parent
commit
a8f770fdfc
2 changed files with 24 additions and 0 deletions
  1. 23 0
      libobs-d3d11/d3d11-subsystem.cpp
  2. 1 0
      libobs-d3d11/d3d11-subsystem.hpp

+ 23 - 0
libobs-d3d11/d3d11-subsystem.cpp

@@ -641,11 +641,28 @@ static bool CheckFormat(ID3D11Device *device, DXGI_FORMAT format)
 	       ((support & required) == required);
 }
 
+static bool FastClearSupported(UINT vendorId, uint64_t version)
+{
+	/* Always true for non-NVIDIA GPUs */
+	if (vendorId != 0x10de)
+		return true;
+
+	const uint16_t aa = (version >> 48) & 0xffff;
+	const uint16_t bb = (version >> 32) & 0xffff;
+	const uint16_t ccccc = (version >> 16) & 0xffff;
+	const uint16_t ddddd = version & 0xffff;
+
+	/* Check for NVIDIA driver version >= 31.0.15.2737 */
+	return aa >= 31 && bb >= 0 && ccccc >= 15 && ddddd >= 2737;
+}
+
 void gs_device::InitDevice(uint32_t adapterIdx)
 {
 	wstring adapterName;
 	DXGI_ADAPTER_DESC desc;
 	D3D_FEATURE_LEVEL levelUsed = D3D_FEATURE_LEVEL_10_0;
+	LARGE_INTEGER umd;
+	uint64_t driverVersion = 0;
 	HRESULT hr = 0;
 
 	adpIdx = adapterIdx;
@@ -663,6 +680,10 @@ void gs_device::InitDevice(uint32_t adapterIdx)
 	blog(LOG_INFO, "Loading up D3D11 on adapter %s (%" PRIu32 ")",
 	     adapterNameUTF8.Get(), adapterIdx);
 
+	hr = adapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &umd);
+	if (SUCCEEDED(hr))
+		driverVersion = umd.QuadPart;
+
 	hr = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL,
 			       createFlags, featureLevels,
 			       sizeof(featureLevels) /
@@ -725,6 +746,8 @@ void gs_device::InitDevice(uint32_t adapterIdx)
 	nv12Supported = CheckFormat(device, DXGI_FORMAT_NV12) &&
 			!HasBadNV12Output();
 	p010Supported = nv12Supported && CheckFormat(device, DXGI_FORMAT_P010);
+
+	fastClearSupported = FastClearSupported(desc.VendorId, driverVersion);
 }
 
 static inline void ConvertStencilSide(D3D11_DEPTH_STENCILOP_DESC &desc,

+ 1 - 0
libobs-d3d11/d3d11-subsystem.hpp

@@ -1022,6 +1022,7 @@ struct gs_device {
 	uint32_t adpIdx = 0;
 	bool nv12Supported = false;
 	bool p010Supported = false;
+	bool fastClearSupported = false;
 
 	gs_texture_2d *curRenderTarget = nullptr;
 	gs_zstencil_buffer *curZStencilBuffer = nullptr;