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
This commit is contained in:
Raziel Alphadios 2023-12-14 05:20:07 +02:00 committed by GitHub
parent e2631c1a56
commit f4a9bfc4bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 21 deletions

View File

@ -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[] = RTL_OSVERSIONINFOW ovi;
{ bx::memSet(&ovi, 0 , sizeof(ovi));
VER_LESS_EQUAL,
VER_GREATER_EQUAL,
};
OSVERSIONINFOEXA 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); const DWORD cMajorVersion = HIBYTE(_version);
ovi.dwMinorVersion = LOBYTE(_version); const DWORD cMinorVersion = LOBYTE(_version);
DWORDLONG cond = 0; switch (_op)
VER_SET_CONDITION(cond, VER_MAJORVERSION, s_condition[_op]); {
VER_SET_CONDITION(cond, VER_MINORVERSION, s_condition[_op]); case Condition::LessEqual:
return !!VerifyVersionInfoA(&ovi, VER_MAJORVERSION | VER_MINORVERSION, cond); 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
} }

View File

@ -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)
{ {

View File

@ -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 // Setting SetEnableSynchronizedCommandQueueValidation below to false avoids the bug
debug1->SetEnableSynchronizedCommandQueueValidation(false); // 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);