Browse Source

Fix D3D12 debug crash due to validation layers SDK bug (#3222)

* Fix D3D12 debug crash due to validation layers SDK bug

* Change LONG to FARPROC to be technically correct

* Make requested changes:
Move windows version checking to function in bgfx.cpp
Change windowsVersionIs to also use this technique
Use bgfx code style
Specify dwOSVersionInfoSize prior to calling rtlGetVersion

* Merge both functions into one
Use bx::dlsym instead of GetProcAddress directly
Fix major & minor comparison logic

* Fix win10 version comment

* Revert rendererCreate check back to Win 0x0602

* Clean up logic as per suggestion
Raziel Alphadios 2 years ago
parent
commit
f4a9bfc4bc
3 changed files with 42 additions and 21 deletions
  1. 30 16
      src/bgfx.cpp
  2. 1 1
      src/bgfx_p.h
  3. 11 4
      src/renderer_d3d12.cpp

+ 30 - 16
src/bgfx.cpp

@@ -2653,30 +2653,44 @@ namespace bgfx
 	};
 	};
 	BX_STATIC_ASSERT(BX_COUNTOF(s_rendererCreator) == RendererType::Count);
 	BX_STATIC_ASSERT(BX_COUNTOF(s_rendererCreator) == RendererType::Count);
 
 
-	bool windowsVersionIs(Condition::Enum _op, uint32_t _version)
+	bool windowsVersionIs(Condition::Enum _op, uint32_t _version, uint32_t _build)
 	{
 	{
 #if BX_PLATFORM_WINDOWS
 #if BX_PLATFORM_WINDOWS
-		static const uint8_t s_condition[] =
-		{
-			VER_LESS_EQUAL,
-			VER_GREATER_EQUAL,
-		};
-
-		OSVERSIONINFOEXA ovi;
-		bx::memSet(&ovi, 0, sizeof(ovi) );
+		RTL_OSVERSIONINFOW ovi;
+		bx::memSet(&ovi, 0 , sizeof(ovi));
 		ovi.dwOSVersionInfoSize = sizeof(ovi);
 		ovi.dwOSVersionInfoSize = sizeof(ovi);
+		const HMODULE hMod = GetModuleHandleW(L"ntdll.dll");
+		if (NULL != hMod)
+		{
+			FARPROC (WINAPI* rtlGetVersionPtr) (PRTL_OSVERSIONINFOW) = reinterpret_cast<FARPROC (WINAPI*)(PRTL_OSVERSIONINFOW)>(bx::dlsym(hMod, "RtlGetVersion"));
+			if (NULL != rtlGetVersionPtr)
+			{
+				rtlGetVersionPtr(&ovi);
+				if (ovi.dwMajorVersion == 0)
+				{
+					return false;
+				}
+				ovi.dwBuildNumber =  UINT32_MAX == _build ? UINT32_MAX : ovi.dwBuildNumber;
+			}
+		}
+		// _WIN32_WINNT_WIN10   0x0A00
 		// _WIN32_WINNT_WINBLUE 0x0603
 		// _WIN32_WINNT_WINBLUE 0x0603
 		// _WIN32_WINNT_WIN8    0x0602
 		// _WIN32_WINNT_WIN8    0x0602
 		// _WIN32_WINNT_WIN7    0x0601
 		// _WIN32_WINNT_WIN7    0x0601
 		// _WIN32_WINNT_VISTA   0x0600
 		// _WIN32_WINNT_VISTA   0x0600
-		ovi.dwMajorVersion = HIBYTE(_version);
-		ovi.dwMinorVersion = LOBYTE(_version);
-		DWORDLONG cond = 0;
-		VER_SET_CONDITION(cond, VER_MAJORVERSION, s_condition[_op]);
-		VER_SET_CONDITION(cond, VER_MINORVERSION, s_condition[_op]);
-		return !!VerifyVersionInfoA(&ovi, VER_MAJORVERSION | VER_MINORVERSION, cond);
+		const DWORD cMajorVersion = HIBYTE(_version);
+		const DWORD cMinorVersion = LOBYTE(_version);
+		switch (_op)
+		{
+			case Condition::LessEqual:
+				return (ovi.dwMajorVersion < cMajorVersion || (ovi.dwMajorVersion == cMajorVersion && ovi.dwMinorVersion <= cMinorVersion)) && ovi.dwBuildNumber <= _build;
+			case Condition::GreaterEqual:
+				return (ovi.dwMajorVersion > cMajorVersion || (ovi.dwMajorVersion == cMajorVersion && ovi.dwMinorVersion >= cMinorVersion)) && ovi.dwBuildNumber >= _build;
+			default:
+				return false;
+		}
 #else
 #else
-		BX_UNUSED(_op, _version);
+		BX_UNUSED(_op, _version, _build);
 		return false;
 		return false;
 #endif // BX_PLATFORM_WINDOWS
 #endif // BX_PLATFORM_WINDOWS
 	}
 	}

+ 1 - 1
src/bgfx_p.h

@@ -427,7 +427,7 @@ namespace bgfx
 		};
 		};
 	};
 	};
 
 
-	bool windowsVersionIs(Condition::Enum _op, uint32_t _version);
+	bool windowsVersionIs(Condition::Enum _op, uint32_t _version, uint32_t _build = UINT32_MAX);
 
 
 	constexpr bool isShaderType(uint32_t _magic, char _type)
 	constexpr bool isShaderType(uint32_t _magic, char _type)
 	{
 	{

+ 11 - 4
src/renderer_d3d12.cpp

@@ -844,13 +844,20 @@ namespace bgfx { namespace d3d12
 
 
 								if (SUCCEEDED(hr))
 								if (SUCCEEDED(hr))
 								{
 								{
-//									debug1->SetEnableGPUBasedValidation(true);
-
 									// https://discordapp.com/channels/590611987420020747/593519198995742733/703642988345032804
 									// https://discordapp.com/channels/590611987420020747/593519198995742733/703642988345032804
 									// D3D12 Bug Number: 26131261
 									// D3D12 Bug Number: 26131261
 									// There is a bug in the D3D12 validation that causes example-21 to fail when using UAV
 									// There is a bug in the D3D12 validation that causes example-21 to fail when using UAV
-									// Setting this function below to false avoids the bug
-									debug1->SetEnableSynchronizedCommandQueueValidation(false);
+									// Setting SetEnableSynchronizedCommandQueueValidation below to false avoids the bug
+									// It was fixed in (probably) the first windows 11 sdk, 22000
+									// However, the fix causes any dx12 context with validation to break if this is set to false, so we can't do that anymore
+									if (windowsVersionIs(Condition::GreaterEqual, 0x0A00, 22000))
+									{
+										debug1->SetEnableGPUBasedValidation(true);
+									}
+									else
+									{
+										debug1->SetEnableSynchronizedCommandQueueValidation(false);
+									}
 								}
 								}
 
 
 								DX_RELEASE(debug1, 1);
 								DX_RELEASE(debug1, 1);