From b6e141afb88a42a8ea822f29367332ec10d69cd3 Mon Sep 17 00:00:00 2001 From: Jiawei Shao Date: Fri, 20 Nov 2020 08:27:29 +0000 Subject: [PATCH] D3D12: Search the default path of Windows SDK for DXC DLLs This patch adds another way to get DXC DLLs (dxcompiler.dll and dxil.dll) by searching the default installation path of Windows x64 SDK (C:\Program Files (x86)\Windows Kits\10\\bin\10.0.[version].0\x64) so that now Dawn can find these two DLLs when Windows SDK is correctly installed at the default location. This patch also forces enabling the "use_dxc" toggle when Dawn can find DXC DLLs and the device is created with "ShaderFloat16" extension enabled because currently the HLSL shaders with float16_t can only be compiled with DXC DLLs. BUG=dawn:402 Change-Id: I410195d9e079f54faebbca71fff77a71f489f08e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/33180 Commit-Queue: Corentin Wallez Reviewed-by: Corentin Wallez Reviewed-by: Austin Eng --- src/dawn_native/Device.cpp | 2 +- src/dawn_native/d3d12/DeviceD3D12.cpp | 3 + src/dawn_native/d3d12/PlatformFunctions.cpp | 132 ++++++++++++++++++-- src/dawn_native/d3d12/PlatformFunctions.h | 5 +- 4 files changed, 129 insertions(+), 13 deletions(-) diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp index 5214564874..0c493b6f1c 100644 --- a/src/dawn_native/Device.cpp +++ b/src/dawn_native/Device.cpp @@ -1115,7 +1115,7 @@ namespace dawn_native { void DeviceBase::ForceSetToggle(Toggle toggle, bool isEnabled) { if (!mOverridenToggles.Has(toggle) && mEnabledToggles.Has(toggle) != isEnabled) { dawn::WarningLog() << "Forcing toggle \"" << ToggleEnumToName(toggle) << "\" to " - << isEnabled << "when it was overriden to be " << !isEnabled; + << isEnabled << " when it was overriden to be " << !isEnabled; } mEnabledToggles.Set(toggle, isEnabled); } diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp index a261143d25..4db2133531 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.cpp +++ b/src/dawn_native/d3d12/DeviceD3D12.cpp @@ -195,6 +195,9 @@ namespace dawn_native { namespace d3d12 { void Device::ApplyUseDxcToggle() { if (!ToBackend(GetAdapter())->GetBackend()->GetFunctions()->IsDXCAvailable()) { ForceSetToggle(Toggle::UseDXC, false); + } else if (IsExtensionEnabled(Extension::ShaderFloat16)) { + // Currently we can only use DXC to compile HLSL shaders using float16. + ForceSetToggle(Toggle::UseDXC, true); } } diff --git a/src/dawn_native/d3d12/PlatformFunctions.cpp b/src/dawn_native/d3d12/PlatformFunctions.cpp index 467e8d79ef..960d172e5c 100644 --- a/src/dawn_native/d3d12/PlatformFunctions.cpp +++ b/src/dawn_native/d3d12/PlatformFunctions.cpp @@ -16,7 +16,89 @@ #include "common/DynamicLib.h" +#include +#include +#include + namespace dawn_native { namespace d3d12 { + namespace { + // Extract Version from "10.0.{Version}.0" if possible, otherwise return 0. + uint32_t GetWindowsSDKVersionFromDirectoryName(const char* directoryName) { + constexpr char kPrefix[] = "10.0."; + constexpr char kPostfix[] = ".0"; + + constexpr uint32_t kPrefixLen = sizeof(kPrefix) - 1; + constexpr uint32_t kPostfixLen = sizeof(kPostfix) - 1; + const uint32_t directoryNameLen = strlen(directoryName); + + if (directoryNameLen < kPrefixLen + kPostfixLen + 1) { + return 0; + } + + // Check if directoryName starts with "10.0.". + if (strncmp(directoryName, kPrefix, kPrefixLen) != 0) { + return 0; + } + + // Check if directoryName ends with ".0". + if (strncmp(directoryName + (directoryNameLen - kPostfixLen), kPostfix, kPostfixLen) != + 0) { + return 0; + } + + // Extract Version from "10.0.{Version}.0" and convert Version into an integer. + return atoi(directoryName + kPrefixLen); + } + + class ScopedFileHandle final { + public: + explicit ScopedFileHandle(HANDLE handle) : mHandle(handle) { + } + ~ScopedFileHandle() { + if (mHandle != INVALID_HANDLE_VALUE) { + ASSERT(FindClose(mHandle)); + } + } + HANDLE GetHandle() const { + return mHandle; + } + + private: + HANDLE mHandle; + }; + + std::string GetWindowsSDKBasePath() { + const char* kDefaultWindowsSDKPath = + "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\*"; + WIN32_FIND_DATAA fileData; + ScopedFileHandle handle(FindFirstFileA(kDefaultWindowsSDKPath, &fileData)); + if (handle.GetHandle() == INVALID_HANDLE_VALUE) { + return ""; + } + + uint32_t highestWindowsSDKVersion = 0; + do { + if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + continue; + } + + highestWindowsSDKVersion = + std::max(highestWindowsSDKVersion, + GetWindowsSDKVersionFromDirectoryName(fileData.cFileName)); + } while (FindNextFileA(handle.GetHandle(), &fileData)); + + if (highestWindowsSDKVersion == 0) { + return ""; + } + + // Currently we only support using DXC on x64. + std::ostringstream ostream; + ostream << "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0." + << highestWindowsSDKVersion << ".0\\x64\\"; + + return ostream.str(); + } + } // anonymous namespace PlatformFunctions::PlatformFunctions() { } @@ -26,8 +108,7 @@ namespace dawn_native { namespace d3d12 { MaybeError PlatformFunctions::LoadFunctions() { DAWN_TRY(LoadD3D12()); DAWN_TRY(LoadDXGI()); - LoadDXIL(); - LoadDXCompiler(); + LoadDXCLibraries(); DAWN_TRY(LoadFXCompiler()); DAWN_TRY(LoadD3D11()); LoadPIXRuntime(); @@ -74,17 +155,48 @@ namespace dawn_native { namespace d3d12 { return {}; } - void PlatformFunctions::LoadDXIL() { - if (!mDXILLib.Open("dxil.dll", nullptr)) { - mDXILLib.Close(); - } + void PlatformFunctions::LoadDXCLibraries() { + const std::string& windowsSDKBasePath = GetWindowsSDKBasePath(); + + LoadDXIL(windowsSDKBasePath); + LoadDXCompiler(windowsSDKBasePath); } - void PlatformFunctions::LoadDXCompiler() { + void PlatformFunctions::LoadDXIL(const std::string& baseWindowsSDKPath) { + const char* dxilDLLName = "dxil.dll"; + const std::array kDxilDLLPaths = { + {dxilDLLName, baseWindowsSDKPath + dxilDLLName}}; + + for (const std::string& dxilDLLPath : kDxilDLLPaths) { + if (mDXILLib.Open(dxilDLLPath, nullptr)) { + return; + } + } + ASSERT(!mDXILLib.Valid()); + } + + void PlatformFunctions::LoadDXCompiler(const std::string& baseWindowsSDKPath) { // DXIL must be loaded before DXC, otherwise shader signing is unavailable - if (!mDXCompilerLib.Open("dxcompiler.dll", nullptr) || - !mDXCompilerLib.GetProc(&dxcCreateInstance, "DxcCreateInstance", nullptr)) { - mDXCompilerLib.Close(); + if (!mDXILLib.Valid()) { + return; + } + + const char* dxCompilerDLLName = "dxcompiler.dll"; + const std::array kDxCompilerDLLPaths = { + {dxCompilerDLLName, baseWindowsSDKPath + dxCompilerDLLName}}; + + DynamicLib dxCompilerLib; + for (const std::string& dxCompilerDLLName : kDxCompilerDLLPaths) { + if (dxCompilerLib.Open(dxCompilerDLLName, nullptr)) { + break; + } + } + + if (dxCompilerLib.Valid() && + dxCompilerLib.GetProc(&dxcCreateInstance, "DxcCreateInstance", nullptr)) { + mDXCompilerLib = std::move(dxCompilerLib); + } else { + mDXILLib.Close(); } } diff --git a/src/dawn_native/d3d12/PlatformFunctions.h b/src/dawn_native/d3d12/PlatformFunctions.h index 7b2851b2d9..123519e38c 100644 --- a/src/dawn_native/d3d12/PlatformFunctions.h +++ b/src/dawn_native/d3d12/PlatformFunctions.h @@ -91,8 +91,9 @@ namespace dawn_native { namespace d3d12 { MaybeError LoadD3D12(); MaybeError LoadD3D11(); MaybeError LoadDXGI(); - void LoadDXIL(); - void LoadDXCompiler(); + void LoadDXCLibraries(); + void LoadDXIL(const std::string& baseWindowsSDKPath); + void LoadDXCompiler(const std::string& baseWindowsSDKPath); MaybeError LoadFXCompiler(); void LoadPIXRuntime();