Execution Tests: Clean up - Factor out createWARPDevice and createHardwareDevice#7987
Execution Tests: Clean up - Factor out createWARPDevice and createHardwareDevice#7987alsepkow wants to merge 15 commits intomicrosoft:mainfrom
Conversation
You can test this locally with the following command:git-clang-format --diff ba86cc068a61dc890c244bd8a710e704cebf327b b2531d6c2cacda27d13882e2e8ed9852d80676b5 -- tools/clang/unittests/HLSLExec/HlslExecTestUtils.cppView the diff from clang-format here.diff --git a/tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp b/tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp
index 0af439a0..095524ff 100644
--- a/tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp
+++ b/tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp
@@ -83,7 +83,7 @@ static void createWarpDevice(
CreateDeviceFn,
ID3D12Device **D3DDevice, bool SkipUnsupported) {
- if (*D3DDevice)
+ if (*D3DDevice)
LogWarningFmt(L"createDevice called with non-null *D3DDevice - "
L"this will likely leak the previous device");
*D3DDevice = nullptr;
@@ -152,7 +152,7 @@ static void createHardwareDevice(
CreateDeviceFn,
ID3D12Device **D3DDevice) {
- if (*D3DDevice)
+ if (*D3DDevice)
LogWarningFmt(L"createDevice called with non-null *D3DDevice - "
L"this will likely leak the previous device");
*D3DDevice = nullptr;
|
|
The previous version had comments explaining the strategy around loading the right DLL etc, it's shame these have all been lost in this refactor. |
|
I'll add the comments back in.
…________________________________
From: Damyan Pepper ***@***.***>
Sent: Monday, December 8, 2025 12:51 PM
To: microsoft/DirectXShaderCompiler ***@***.***>
Cc: Alex Sepkowski ***@***.***>; Author ***@***.***>
Subject: Re: [microsoft/DirectXShaderCompiler] Execution Tests: Clean up - Factor out createWARPDevice and add RAII wrapper for WARP dll. (PR #7987)
[https://avatars.githubusercontent.com/u/8118402?s=20&v=4]damyanp left a comment (microsoft/DirectXShaderCompiler#7987)<#7987 (comment)>
The previous version had comments explaining the strategy around loading the right DLL etc, it's shame these have all been lost in this refactor.
—
Reply to this email directly, view it on GitHub<#7987 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/ABK4EW7BWBVND3G6WDHHTBT4AXQFRAVCNFSM6AAAAACOGT2BFOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTMMRYHE2TGOBXGE>.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
| createWarpDevice(DXGIFactory, CreateDeviceFn, &D3DDeviceCom, | ||
| SkipUnsupported); | ||
| } else { | ||
| CComPtr<IDXGIAdapter1> HardwareAdapter; |
There was a problem hiding this comment.
Paraphrazing:
if (UseWrap)
callSingleFunctionThatDoesTheUseWarpThing();
else {
// many lines of code for doing the hardware device thing
}
See "single level of abstraction principle".
There was a problem hiding this comment.
This change does muddy that a bit. But on the other hand, I felt that a 100 line function for creating a d3d device was getting overly complicated and felt difficult to follow.
Maybe it would be better to move the DLL loader back to a class. It can handle the logging/logic for that.
And we could have shared logic to call CreateDeviceFn. The branching logic based on SW/HW can just select the appropriate IDXGIAdapter before calling.
Or I can leave it all alone. This function has just been eating at me for a while.
There was a problem hiding this comment.
My suggestion would have been to add a createHardwareDevice() that's at the same level of abstraction os createWarpDevice().
| // Log the actual version of WARP that's loaded | ||
| if (GetModuleHandleW(L"d3d10warp.dll") != NULL) { | ||
| WCHAR FullModuleFilePath[MAX_PATH] = L""; | ||
| GetModuleFileNameW(GetModuleHandleW(L"d3d10warp.dll"), FullModuleFilePath, | ||
| sizeof(FullModuleFilePath)); | ||
| LogCommentFmt(L"WARP driver loaded from: %ls", FullModuleFilePath); | ||
| } |
There was a problem hiding this comment.
This behaves differently than it did previously. The old version very carefully made sure to free the library it had loaded, so make sure that the path it gets from GetModuleHandle refers to the module that's being kept loaded by the device. This has been lost in this change.
There was a problem hiding this comment.
I've reverted to identical inline logic.
| // Load WARP DLL if specified | ||
| WarpDllLoader warpLoader; | ||
| warpLoader.LoadWarpDll(); |
There was a problem hiding this comment.
FWIW, I think it was clearer and simpler and less lines of code to have this little one-use RAII helper inline here.
damyanp
left a comment
There was a problem hiding this comment.
LGTM, although I think this would be improved by having a createHardwareDevice thing as mentioned in my comment.
| if (SkipUnsupported) | ||
| WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped); | ||
|
|
||
| D3DDevice = nullptr; |
There was a problem hiding this comment.
It would be customary to set this to nullptr at the beginning of the function. But also, shouldn't it be *D3DDevice = nullptr;? Otherwise, what's the point?
Also, if you're trying to clear a potentially initialized D3DDevice, I don't think that should be the case when it fails the create, so I don't think you should need to clear it here.
There was a problem hiding this comment.
Agreed. Changing this logic to instead use a local CComPtr and detach from that to assign a valid value to the output when it succeeds.
| IDXGIFactory4 *DXGIFactory, | ||
| std::function<HRESULT(IUnknown *, D3D_FEATURE_LEVEL, REFIID, void **)> | ||
| CreateDeviceFn, | ||
| ID3D12Device **D3DDevice) { |
There was a problem hiding this comment.
Should we clear device on entry here too (*D3DDevice = nullptr)?
Strange, this seems to imply that |
This PR just cleans up the createDevice function by factoring out the logic for creating a WARP device. And I also included a suggestion from co-pilot to add a small RAII wrapper for managing the lifetime of the Warp DLL.