From f4a9bfc4bce9dd6c1762492a1fd599ecff0e9fb2 Mon Sep 17 00:00:00 2001 From: Raziel Alphadios <64050682+RazielXYZ@users.noreply.github.com> Date: Thu, 14 Dec 2023 05:20:07 +0200 Subject: [PATCH] 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 --- src/bgfx.cpp | 46 +++++++++++++++++++++++++++--------------- src/bgfx_p.h | 2 +- src/renderer_d3d12.cpp | 15 ++++++++++---- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/bgfx.cpp b/src/bgfx.cpp index d11152c54..e6f72d336 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -2653,30 +2653,44 @@ namespace bgfx }; 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 - 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); + const HMODULE hMod = GetModuleHandleW(L"ntdll.dll"); + if (NULL != hMod) + { + FARPROC (WINAPI* rtlGetVersionPtr) (PRTL_OSVERSIONINFOW) = reinterpret_cast(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_WIN8 0x0602 // _WIN32_WINNT_WIN7 0x0601 // _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 - BX_UNUSED(_op, _version); + BX_UNUSED(_op, _version, _build); return false; #endif // BX_PLATFORM_WINDOWS } diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 1084f6987..098be7ee3 100644 --- a/src/bgfx_p.h +++ b/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) { diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index 62b8f12d7..42ec0963f 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -844,13 +844,20 @@ namespace bgfx { namespace d3d12 if (SUCCEEDED(hr)) { -// debug1->SetEnableGPUBasedValidation(true); - // https://discordapp.com/channels/590611987420020747/593519198995742733/703642988345032804 // D3D12 Bug Number: 26131261 // 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);