-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix D3D12 debug crash due to validation layers SDK bug #3222
Conversation
Can you use Lines 2656 to 2682 in e2631c1
|
Not really because the dwMajorVersion and dwMinorVersion for all builds of windows 10 and 11 are the same (major = 10 and minor = 0) so it doesn't get us the specific enough version/build that we need. |
src/renderer_d3d12.cpp
Outdated
if (hMod) { | ||
FARPROC (WINAPI* rtlGetVersionPtr) (PRTL_OSVERSIONINFOW) = reinterpret_cast<FARPROC (WINAPI*)(PRTL_OSVERSIONINFOW)>(::GetProcAddress(hMod, "RtlGetVersion")); | ||
if (rtlGetVersionPtr != nullptr) { | ||
rtlGetVersionPtr(&osver); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before you call rtlGetVersion(&osver)
you need to specify dwOSVersionInfoSize
size.
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlgetversion#parameters
src/renderer_d3d12.cpp
Outdated
RTL_OSVERSIONINFOW osver; | ||
bx::memSet(&osver, 0 , sizeof(RTL_OSVERSIONINFOW)); | ||
const HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll"); | ||
if (hMod) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use bgfx code style... braces next line...
src/renderer_d3d12.cpp
Outdated
@@ -844,13 +844,31 @@ namespace bgfx { namespace d3d12 | |||
|
|||
if (SUCCEEDED(hr)) | |||
{ | |||
// debug1->SetEnableGPUBasedValidation(true); | |||
//This is the least ugly way to get the windows build that still works past win10 without deprecation warnings or needing app manifests | |||
RTL_OSVERSIONINFOW osver; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this into function, make content of function #if BX_PLATFORM_WINDOWS
because D3D1x compiles on Linux too.
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
Looks like BX_PLATFORM_WINDOWS and BX_PLATFORM_EMSCRIPTEN are both defined at the same time for emscripten builds - that doesn't seem good (and it breaks the emscripten build due to it trying to compile GetProcAddress) |
Use bx::dlsym instead of GetProcAddress directly Fix major & minor comparison logic
{ | ||
return false; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you could do:
ovi.dwBuildNumber = UINT32_MAX == _build ? UINT32_MAX : ovi.dwBuildNumber;
And then remove those if/else blocks below since test will succeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea!
Platform, edition and version independencyCreating dependencies to kernel-mode and/or windows-driver functions within an user-app is not a good idea per se, even if Windows calls a particular function indirectly from user-mode. WDM (windows-driver): https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlgetversion Win32 (user-mode): https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexa There always may be runtimes or editions restricting kernel-mode or driver-mode access from an user-app. You are doing better using the user-mode function GetVersion or GetVersionEx, even it may return the targeted version (manifest or compaitbility version - a proper app needs a manifest anyway!) and the compiler eventually tells you using VerifyVersionInfo in preference. Alternatively, though with bigger overhead, WMI methods could be used. |
I agree in theory. However, I don't see us adding manifests to every example (but maybe we could through example-common entry since that instantiates the window/app), nor do I see users/devs adding manifests to their app (at least not from the get go), which means even with proper usage of VerifyVersionInfo we would get wrong results and the crash would be back - and users unfamiliar with the issue or with the need for manifests would be confused. GetVersion or GetVersionEx are out of the question because they're deprecated: per your link "GetVersionExA may be altered or unavailable for releases after Windows 8.1."; trying to use it issues deprecated warning, which examples treat as error. Even if they weren't, they have the same behavior as VerifyVersionInfo wherein they need manifests to be correct. Alternatively, windows build string could be found in the registry or in the file info of windows dlls and other files. However, I don't really think those methods are any less prone to random restrictions or changes in the future, nor are they cleaner. |
You are right, GetVersionEx causes a depreciation compiler message, which takes the same risk failing in future Windows versions than using Rtl* functions. A suggested way using VerifyVersionInfo, when passing a value of 20000 or greater to _build, to query for Windows 11 and later:
|
Am I correct in assuming that doesn't see/report the build number correctly unless a manifest is present? 😅 |
Right, your solution is the 'smallest bitter pill', unless a manifest is used. https://learn.microsoft.com/en-us/windows/win32/sysinfo/targeting-your-application-at-windows-8-1 |
° Suggestion - adding a proper manifest. Add a generic manifest to the toolchains for all Windows executables and revert the VerifyVersionInfoA as shown above, by: One standalone manifest to all exes and dlls are sufficient.
2a) Add the manifest file to VS-solution files, either embedded or standalone. 2b) Other IDE's or toolchains define a standalone manifest-file, and copy scripts/generic.bgfx.manifest into the exe's or dll's folder. |
I don't oppose idea of adding manifest... Can you research what's minimal viable manifest? Like remove all windows OS before 10. We don't care about any of those. Does
We want embedded. |
I fully agree on dropping implicit support of older Windows versions than 10, when Win10 gets 10 y/o already.
That's not a problem for the demo exes, not at all if the manifest is embedded. I can provide the needed VS-C compiler command line options tomorrow, after double checking on the minimum requirements. |
Yeah, if you could add this to GENie script that would be the best. |
Disregarding how this is going to work on mingw or such, we'll also have to make it clear to users that dx12 debug is broken unless they add a similar manifest to their own application. Not sure where the best place to do that would be. |
@RazielXYZ Btw, embedding manifests can be done by a resource as well. @bkaradzic I am waiting for you coming up with a solution for mingw, before proceeding on it (prolly after Xmas). In any way, we should go with the easiest, but proper, solution for it - I don't want to over-complicate it. |
@Chris1AA I am not into mingw either 😅 not sure who would be familiar with it that we could ask |
* 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 fixes #3176 and the other intermittent questions about this problem.
This way of runtime checking the windows build is the least ugly/hacky that I could find (and yet, it's still awful).
I only tested on win11 build 22621. If we think tests on other versions or builds are necessary I can try to make some VMs.