Skip to content

Commit 4fb6998

Browse files
committed
wip - proof of concept
1 parent 48d23cd commit 4fb6998

File tree

4 files changed

+210
-89
lines changed

4 files changed

+210
-89
lines changed

tools/clang/unittests/HLSLExec/ExecutionTest.cpp

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ class ExecutionTest {
464464

465465
dxc::DxCompilerDllLoader m_support;
466466

467+
std::optional<D3D12SDK> D3D12SDK;
467468
bool m_D3DInitCompleted = false;
468469
bool m_ExperimentalModeEnabled = false;
469470
bool m_AgilitySDKEnabled = false;
@@ -475,46 +476,21 @@ class ExecutionTest {
475476
if (!m_D3DInitCompleted) {
476477
m_D3DInitCompleted = true;
477478

478-
HMODULE hRuntime = LoadLibraryW(L"d3d12.dll");
479-
if (hRuntime == NULL)
479+
D3D12SDK = D3D12SDK::create();
480+
if (!D3D12SDK)
480481
return false;
481-
// Do not: FreeLibrary(hRuntime);
482-
// If we actually free the library, it defeats the purpose of
483-
// enableAgilitySDK and enableExperimentalMode.
484-
485-
HRESULT hr;
486-
hr = enableAgilitySDK(hRuntime);
487-
if (FAILED(hr)) {
488-
LogCommentFmt(L"Unable to enable Agility SDK - 0x%08x.", hr);
489-
} else if (hr == S_FALSE) {
490-
LogCommentFmt(L"Agility SDK not enabled.");
491-
} else {
492-
LogCommentFmt(L"Agility SDK enabled.");
493-
}
494-
495-
hr = enableExperimentalMode(hRuntime);
496-
if (FAILED(hr)) {
497-
LogCommentFmt(L"Unable to enable shader experimental mode - 0x%08x.",
498-
hr);
499-
} else if (hr == S_FALSE) {
500-
LogCommentFmt(L"Experimental mode not enabled.");
501-
} else {
502-
LogCommentFmt(L"Experimental mode enabled.");
503-
}
504-
505-
hr = enableDebugLayer();
506-
if (FAILED(hr)) {
507-
LogCommentFmt(L"Unable to enable debug layer - 0x%08x.", hr);
508-
} else if (hr == S_FALSE) {
509-
LogCommentFmt(L"Debug layer not enabled.");
510-
} else {
511-
LogCommentFmt(L"Debug layer enabled.");
512-
}
513482
}
514483

515484
return true;
516485
}
517486

487+
bool createDevice(ID3D12Device **D3DDevice,
488+
ExecTestUtils::D3D_SHADER_MODEL TestModel =
489+
ExecTestUtils::D3D_SHADER_MODEL_6_0,
490+
bool SkipUnsupported = true) {
491+
return D3D12SDK->createDevice(D3DDevice, TestModel, SkipUnsupported);
492+
}
493+
518494
std::wstring DxcBlobToWide(IDxcBlob *pBlob) {
519495
if (!pBlob)
520496
return std::wstring();
@@ -12527,7 +12503,9 @@ static void WriteReadBackDump(st::ShaderOp *pShaderOp, st::ShaderOpTest *pTest,
1252712503
// It's exclusive with the use of the DLL as a TAEF target.
1252812504
extern "C" {
1252912505
__declspec(dllexport) HRESULT WINAPI
12530-
InitializeOpTests(void *pStrCtx, st::OutputStringFn pOutputStrFn) {
12506+
InitializeOpTests([[maybe_unused]] void *pStrCtx,
12507+
[[maybe_unused]] st::OutputStringFn pOutputStrFn) {
12508+
#ifdef _FORCE_EXPERIMENTAL_SHADERS
1253112509
HMODULE Runtime = LoadLibraryW(L"d3d12.dll");
1253212510

1253312511
if (Runtime == NULL)
@@ -12538,13 +12516,14 @@ __declspec(dllexport) HRESULT WINAPI
1253812516
if (FAILED(hr)) {
1253912517
pOutputStrFn(pStrCtx, L"Unable to enable experimental shader models.\r\n.");
1254012518
}
12519+
#endif
1254112520
return S_OK;
1254212521
}
1254312522

1254412523
__declspec(dllexport) HRESULT WINAPI
12545-
RunOpTest(void *pStrCtx, st::OutputStringFn pOutputStrFn, LPCSTR pText,
12546-
ID3D12Device *pDevice, ID3D12CommandQueue *pCommandQueue,
12547-
ID3D12Resource *pRenderTarget, char **pReadBackDump) {
12524+
RunOpTest(void *pStrCtx, st::OutputStringFn pOutputStrFn, LPCSTR pText,
12525+
ID3D12Device *pDevice, ID3D12CommandQueue *pCommandQueue,
12526+
ID3D12Resource *pRenderTarget, char **pReadBackDump) {
1254812527

1254912528
HRESULT hr;
1255012529
if (pReadBackDump)

tools/clang/unittests/HLSLExec/HlslExecTestUtils.cpp

Lines changed: 169 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <atlcomcli.h>
99
#include <d3d12.h>
1010
#include <dxgi1_4.h>
11+
#include <optional>
1112

1213
static bool useDebugIfaces() { return true; }
1314

@@ -319,6 +320,7 @@ enableExperimentalShaderModels(UUID AdditionalFeatures[] = nullptr,
319320
}
320321

321322
HRESULT enableAgilitySDK(HMODULE Runtime) {
323+
322324
// D3D12SDKVersion > 1 will use provided version, otherwise, auto-detect.
323325
// D3D12SDKVersion == 1 means fail if we can't auto-detect.
324326
UINT SDKVersion = 0;
@@ -390,17 +392,173 @@ HRESULT enableExperimentalMode(HMODULE Runtime) {
390392
return HR;
391393
}
392394

393-
HRESULT enableDebugLayer() {
394-
// The debug layer does net yet validate DXIL programs that require
395-
// rewriting, but basic logging should work properly.
396-
HRESULT HR = S_FALSE;
397-
if (useDebugIfaces()) {
398-
CComPtr<ID3D12Debug> DebugController;
399-
HR = D3D12GetDebugInterface(IID_PPV_ARGS(&DebugController));
400-
if (SUCCEEDED(HR)) {
401-
DebugController->EnableDebugLayer();
402-
HR = S_OK;
395+
static bool enableDebugLayer() {
396+
using namespace hlsl_test;
397+
398+
CComPtr<ID3D12Debug> DebugController;
399+
HRESULT HR;
400+
if (FAILED(HR = D3D12GetDebugInterface(IID_PPV_ARGS(&DebugController)))) {
401+
LogErrorFmt(L"Failed to get ID3D12Debug: 0x%08x", HR);
402+
return false;
403+
}
404+
405+
DebugController->EnableDebugLayer();
406+
return true;
407+
}
408+
409+
struct AgilitySDKConfiguration {
410+
WEX::Common::String SDKPath;
411+
UINT SDKVersion = 0;
412+
bool MustFind = false;
413+
};
414+
415+
static std::optional<AgilitySDKConfiguration> getAgilitySDKConfiguration() {
416+
using hlsl_test::LogErrorFmt;
417+
using WEX::TestExecution::RuntimeParameters;
418+
419+
AgilitySDKConfiguration C;
420+
421+
// For global configuration, D3D12SDKPath must be relative path from .exe,
422+
// which means relative to TE.exe location, and must start with ".\\", such as
423+
// with the default: ".\\D3D12\\".
424+
//
425+
// For ID3D12DeviceFactory-style configuration, D3D12SDKPath can be an
426+
// absolute path.
427+
if (SUCCEEDED(RuntimeParameters::TryGetValue(L"D3D12SDKPath", C.SDKPath))) {
428+
// Make sure path ends in backslash
429+
if (!C.SDKPath.IsEmpty() && C.SDKPath.Right(1) != "\\")
430+
C.SDKPath.Append("\\");
431+
}
432+
433+
if (C.SDKPath.IsEmpty())
434+
C.SDKPath = L".\\D3D12\\";
435+
436+
// D3D12SDKVersion > 1 will use provided version, otherwise, auto-detect.
437+
// D3D12SDKVersion == 1 means fail if we can't auto-detect.
438+
RuntimeParameters::TryGetValue(L"D3D12SDKVersion", C.SDKVersion);
439+
440+
C.MustFind = C.SDKVersion >= 1;
441+
442+
if (C.SDKVersion <= 1) {
443+
// Use the version supported by the SDK in the path.
444+
C.SDKVersion = getD3D12SDKVersion(std::wstring(C.SDKPath));
445+
if (C.SDKVersion == 0) {
446+
if (C.MustFind) {
447+
LogErrorFmt(L"Agility SDK not found in relative path: %s",
448+
static_cast<const wchar_t *>(C.SDKPath));
449+
return std::nullopt;
450+
}
451+
452+
// No AgilitySDK found, caller indicated that they just want to use the
453+
// inbox D3D12 in this case.
454+
return AgilitySDKConfiguration{};
403455
}
404456
}
405-
return HR;
457+
458+
return C;
459+
}
460+
461+
static bool enableGlobalAgilitySDK() {
462+
using namespace hlsl_test;
463+
464+
std::optional<AgilitySDKConfiguration> C = getAgilitySDKConfiguration();
465+
if (!C)
466+
return false;
467+
468+
if (C->SDKVersion == 0)
469+
return true;
470+
471+
CComPtr<ID3D12SDKConfiguration> SDKConfig;
472+
HRESULT HR;
473+
if (FAILED(HR = D3D12GetInterface(CLSID_D3D12SDKConfiguration,
474+
IID_PPV_ARGS(&SDKConfig)))) {
475+
LogErrorFmt(L"Failed to get ID3D12SDKConfiguration instance: 0x%08x", HR);
476+
return !C->MustFind;
477+
}
478+
479+
if (FAILED(HR = SDKConfig->SetSDKVersion(C->SDKVersion, CW2A(C->SDKPath)))) {
480+
LogErrorFmt(L"SetSDKVersion(%d, %s) failed: 0x%08x", C->SDKVersion,
481+
static_cast<const wchar_t *>(C->SDKPath), HR);
482+
return !C->MustFind;
483+
}
484+
485+
// Currently, it appears that the SetSDKVersion will succeed even when
486+
// D3D12Core is not found, or its version doesn't match. When that's the
487+
// case, will cause a failure in the very next thing that actually requires
488+
// D3D12Core.dll to be loaded instead. So, we attempt to clear experimental
489+
// features next, which is a valid use case and a no-op at this point. This
490+
// requires D3D12Core to be loaded. If this fails, we know the AgilitySDK
491+
// setting actually failed.
492+
if (FAILED(
493+
HR = D3D12EnableExperimentalFeatures(0, nullptr, nullptr, nullptr))) {
494+
LogErrorFmt(L"D3D12EnableExperimentalFeatures(0...) failed: 0x%08x", HR);
495+
return !C->MustFind;
496+
}
497+
498+
return true;
406499
}
500+
501+
static bool enableGlobalExperimentalMode() {
502+
using namespace hlsl_test;
503+
504+
const bool ExperimentalShaders = GetTestParamBool(L"ExperimentalShaders");
505+
506+
if (!ExperimentalShaders)
507+
return false;
508+
509+
HRESULT HR;
510+
if (FAILED(HR = D3D12EnableExperimentalFeatures(
511+
1, &D3D12ExperimentalShaderModels, nullptr, nullptr))) {
512+
LogErrorFmt(L"D3D12EnableExperimentalFeatures("
513+
L"D3D12ExperimentalShaderModels) failed: 0x%08x",
514+
HR);
515+
return false;
516+
}
517+
518+
return true;
519+
}
520+
521+
static void setGlobalConfiguration() {
522+
using namespace hlsl_test;
523+
524+
if (enableGlobalAgilitySDK())
525+
LogCommentFmt(L"Agility SDK enabled.");
526+
else
527+
LogCommentFmt(L"Agility SDK not enabled.");
528+
529+
if (enableGlobalExperimentalMode())
530+
LogCommentFmt(L"Experimental mode enabled.");
531+
else
532+
LogCommentFmt(L"Experimental mode not enabled.");
533+
}
534+
535+
std::optional<D3D12SDK> D3D12SDK::create() {
536+
using namespace hlsl_test;
537+
538+
if (enableDebugLayer())
539+
LogCommentFmt(L"Debug layer enabled");
540+
else
541+
LogCommentFmt(L"Debug layer not enabled");
542+
543+
// CComPtr<ID3D12SDKConfiguration1> Config1;
544+
// if (FAILED(D3D12GetInterface(CLSID_D3D12SDKConfiguration,
545+
// IID_PPV_ARGS(&Config1))))
546+
{ return D3D12SDK(nullptr); }
547+
548+
CComPtr<ID3D12DeviceFactory> DeviceFactory;
549+
550+
// ...
551+
552+
return D3D12SDK(DeviceFactory);
553+
}
554+
555+
D3D12SDK::D3D12SDK(CComPtr<ID3D12DeviceFactory> DeviceFactory)
556+
: DeviceFactory(std::move(DeviceFactory)) {}
557+
558+
D3D12SDK::~D3D12SDK() = default;
559+
560+
bool D3D12SDK::createDevice(ID3D12Device **D3DDevice,
561+
ExecTestUtils::D3D_SHADER_MODEL TestModel,
562+
bool SkipUnsupported) {
563+
return ::createDevice(D3DDevice, TestModel, SkipUnsupported);
564+
}

tools/clang/unittests/HLSLExec/HlslExecTestUtils.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#ifndef HLSLEXECTESTUTILS_H
22
#define HLSLEXECTESTUTILS_H
33

4+
#include <atlcomcli.h>
45
#include <d3d12.h>
6+
#include <optional>
57
#include <windows.h>
68

79
#include "dxc/Support/dxcapi.use.h"
@@ -26,13 +28,22 @@ typedef enum D3D_SHADER_MODEL {
2628
} // namespace ExecTestUtils
2729

2830
bool useDxbc();
29-
HRESULT enableDebugLayer();
30-
HRESULT enableExperimentalMode(HMODULE Runtime);
31-
HRESULT enableAgilitySDK(HMODULE Runtime);
32-
bool createDevice(ID3D12Device **D3DDevice,
33-
ExecTestUtils::D3D_SHADER_MODEL TestModel =
34-
ExecTestUtils::D3D_SHADER_MODEL_6_0,
35-
bool SkipUnsupported = true);
31+
32+
class D3D12SDK {
33+
CComPtr<ID3D12DeviceFactory> DeviceFactory;
34+
35+
public:
36+
static std::optional<D3D12SDK> create();
37+
~D3D12SDK();
38+
39+
bool createDevice(ID3D12Device **D3DDevice,
40+
ExecTestUtils::D3D_SHADER_MODEL TestModel =
41+
ExecTestUtils::D3D_SHADER_MODEL_6_0,
42+
bool SkipUnsupported = true);
43+
44+
private:
45+
D3D12SDK(CComPtr<ID3D12DeviceFactory> DeviceFactory);
46+
};
3647

3748
void readHlslDataIntoNewStream(LPCWSTR RelativePath, IStream **Stream,
3849
dxc::SpecificDllLoader &Support);

0 commit comments

Comments
 (0)