Reland "Reland "Improve DX compiler library loading""

This is a reland of commit e579b628e5d5276086b6a2eaefa1718586bc7e18

Add dawn_force_system_component_load for projects (like Skia) which
require that Dawn load all compiler DLL from System32. Best security
is to leave the default value which (now) loads compiler DLLs from the
same directory as Dawn code.

On Chromium builds (such as x86) which do not build DXC, place the
DLLs from the SDK into the build folder to appease infra tools that
copy the DLLs unconditionally.

Improve DAWN_USE_BUILT_DXC to use the #define to skip loading the DLLs
altogether.

Original change's description:
> Reland "Improve DX compiler library loading"
>
> This is a reland of commit e4d4669d79501b1acdd2bf017ba491b611d741da
>
> Remove build_with_chromium statements in test GN files that copy
> DLLs. Rely on copies instructions which already exist with the D3D12
> files.
>
> To appease Skia builds which do not depend on the Windows SDK,
> fallback to system FXC if the local directory version is not found.
>
> Original change's description:
> > Improve DX compiler library loading
> >
> > Previously, DX compiler DLLs were loaded using LoadLibrary with no path.
> > D3D12 compiler DLLs were further sourced from the local user's SDK
> > directory as a fallback.
> >
> > For better security, load DX compiler DLLs using full paths, with
> > SEARCH_DLL_LOAD_DIR | SEARCH_DEFAULT_DIRS for better security. Scenarios
> > such as Skia and x86 builds where we need dawn_use_built_dxc will
> > fallback to FXC. No fallbacks to local user SDK directories.
> >
> > Bug:356665092
> > Change-Id: Ib4148f9b89da694e3868b4f3c3c329a4b06ce922
> > Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/229754
> > Reviewed-by: Corentin Wallez <cwallez@chromium.org>
> > Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>
> > Reviewed-by: Antonio Maiorano <amaiorano@google.com>
>
> Bug: 356665092
> Change-Id: Ic05d20c47c5db3021f9e38b724bf527bfba52a5e
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/233216
> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
> Reviewed-by: Antonio Maiorano <amaiorano@google.com>
> Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>

Bug: 356665092
Change-Id: I83db06312db28123f9d5aee29617a8746768bb3d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/234919
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index baca383..8dc8c3c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,6 +88,7 @@
 set(BUILD_SAMPLES OFF)
 set(BUILD_TESTS OFF)
 set(TARGET_MACOS OFF)
+set(DAWN_FORCE_SYSTEM_COMPONENT_LOAD OFF)
 if (EMSCRIPTEN)
   # Only the samples are supported for Emscripten at the moment.
   # TODO(crbug.com/42240181): Make dawn_end2end_tests work too.
@@ -150,6 +151,7 @@
 option(DAWN_ENABLE_OPENGLES "Enable compilation of the OpenGL ES backend" ${ENABLE_OPENGLES})
 option(DAWN_ENABLE_VULKAN "Enable compilation of the Vulkan backend" ${ENABLE_VULKAN})
 option(DAWN_ENABLE_SPIRV_VALIDATION "Enable validation of SPIR-V" ${ENABLE_SPIRV_VALIDATION})
+option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ${DAWN_FORCE_SYSTEM_COMPONENT_LOAD})
 
 message(STATUS "Dawn building using Emscripten toolchain: ${EMSCRIPTEN}")
 message(STATUS "Dawn build D3D11 backend: ${DAWN_ENABLE_D3D11}")
@@ -167,6 +169,7 @@
 message(STATUS "Dawn build with MSAN: ${DAWN_ENABLE_MSAN}")
 message(STATUS "Dawn build with UBSAN: ${DAWN_ENABLE_UBSAN}")
 message(STATUS "Dawn enable install: ${DAWN_ENABLE_INSTALL}")
+message(STATUS "Dawn allow system component fallback: ${DAWN_FORCE_SYSTEM_COMPONENT_LOAD}")
 message(STATUS "")
 
 option(DAWN_ALWAYS_ASSERT "Enable assertions on all build types" OFF)
@@ -431,6 +434,9 @@
 if (WIN32)
     target_compile_definitions(dawn_internal_config INTERFACE "NOMINMAX" "WIN32_LEAN_AND_MEAN")
 endif()
+if (DAWN_FORCE_SYSTEM_COMPONENT_LOAD)
+    target_compile_definitions(dawn_internal_config INTERFACE "DAWN_FORCE_SYSTEM_COMPONENT_LOAD")
+endif()
 
 ################################################################################
 # Tint
diff --git a/scripts/dawn_features.gni b/scripts/dawn_features.gni
index 873d516..f4f375f 100644
--- a/scripts/dawn_features.gni
+++ b/scripts/dawn_features.gni
@@ -59,6 +59,10 @@
   # See crbug.com/tint/1753.
   dawn_use_built_dxc = is_win && target_cpu != "x86"
 
+  # Force Dawn to load components like d3dcompiler_47.dll and vulkan-1.dll from
+  # system directories instead of local directories.
+  dawn_force_system_component_load = false
+
   # Whether to build Dawn's NodeJS bindings
   dawn_build_node_bindings = false
 }
diff --git a/src/dawn/common/BUILD.gn b/src/dawn/common/BUILD.gn
index a79e7a2..e3ef4ca 100644
--- a/src/dawn/common/BUILD.gn
+++ b/src/dawn/common/BUILD.gn
@@ -121,6 +121,10 @@
     defines += [ "DAWN_ENABLE_ERROR_INJECTION" ]
   }
 
+  if (dawn_force_system_component_load) {
+    defines += [ "DAWN_FORCE_SYSTEM_COMPONENT_LOAD" ]
+  }
+
   # Only internal Dawn targets can use this config, this means only targets in
   # this BUILD.gn file and related subdirs.
   visibility = [
diff --git a/src/dawn/common/DynamicLib.cpp b/src/dawn/common/DynamicLib.cpp
index c1457df..f7db34c 100644
--- a/src/dawn/common/DynamicLib.cpp
+++ b/src/dawn/common/DynamicLib.cpp
@@ -78,7 +78,14 @@
 #if DAWN_PLATFORM_IS(WINUWP)
     mHandle = LoadPackagedLibrary(UTF8ToWStr(filename.c_str()).c_str(), 0);
 #else
-    mHandle = LoadLibraryA(filename.c_str());
+#if defined(DAWN_FORCE_SYSTEM_COMPONENT_LOAD)
+    const DWORD loadLibraryFlags = LOAD_LIBRARY_SEARCH_SYSTEM32;
+#else
+    // Use SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS to avoid DLL search path attacks.
+    const DWORD loadLibraryFlags =
+        LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;
+#endif
+    mHandle = LoadLibraryExA(filename.c_str(), nullptr, loadLibraryFlags);
 #endif
     if (mHandle == nullptr && error != nullptr) {
         *error =
diff --git a/src/dawn/native/d3d/D3DCompilationRequest.h b/src/dawn/native/d3d/D3DCompilationRequest.h
index 1e3bcd0..5080eb0 100644
--- a/src/dawn/native/d3d/D3DCompilationRequest.h
+++ b/src/dawn/native/d3d/D3DCompilationRequest.h
@@ -68,7 +68,6 @@
     X(uint32_t, shaderModel)                                                         \
     X(uint32_t, compileFlags)                                                        \
     X(Compiler, compiler)                                                            \
-    X(uint64_t, compilerVersion)                                                     \
     X(std::wstring_view, dxcShaderProfile)                                           \
     X(std::string_view, fxcShaderProfile)                                            \
     X(uint32_t, firstIndexOffsetShaderRegister)                                      \
@@ -85,7 +84,6 @@
     X(bool, hasShaderF16Feature)                         \
     X(uint32_t, compileFlags)                            \
     X(Compiler, compiler)                                \
-    X(uint64_t, compilerVersion)                         \
     X(std::wstring_view, dxcShaderProfile)               \
     X(std::string_view, fxcShaderProfile)                \
     X(UnsafeUnserializedValue<pD3DCompile>, d3dCompile)  \
diff --git a/src/dawn/native/d3d/PlatformFunctions.cpp b/src/dawn/native/d3d/PlatformFunctions.cpp
index cd51833..b7ce6cc 100644
--- a/src/dawn/native/d3d/PlatformFunctions.cpp
+++ b/src/dawn/native/d3d/PlatformFunctions.cpp
@@ -32,6 +32,8 @@
 
 #include <vector>
 
+#include "dawn/common/SystemUtils.h"
+
 namespace dawn::native::d3d {
 
 namespace {
@@ -96,8 +98,20 @@
     d3dDisassemble = &D3DDisassemble;
 #else
     std::string error;
-    if (!mFXCompilerLib.Open("d3dcompiler_47.dll", &error) ||
-        !mFXCompilerLib.GetProc(&d3dCompile, "D3DCompile", &error) ||
+#if defined(DAWN_FORCE_SYSTEM_COMPONENT_LOAD)
+    // https://crbug.com/399358291. Since Skia's build system is not able to locate the Windows
+    // SDK tools, d3dcompiler_47.dll is not copied into the build location. Tests fail when we
+    // prepend the module directory to the path. To address this, we fallback to the compiler
+    // that comes with the OS. The OS compiler contains functionality and heap corruption bugs
+    // on older Windows versions so care must be taken to always ship with the latest SDK
+    // compiler.
+    const bool loadSuccess = mFXCompilerLib.OpenSystemLibrary(L"d3dcompiler_47.dll", &error);
+#else
+    const auto modulePath = GetModuleDirectory();
+    const std::string& pathToPrepend = modulePath.value_or("");
+    const bool loadSuccess = mFXCompilerLib.Open(pathToPrepend + "d3dcompiler_47.dll", &error);
+#endif
+    if (!loadSuccess || !mFXCompilerLib.GetProc(&d3dCompile, "D3DCompile", &error) ||
         !mFXCompilerLib.GetProc(&d3dDisassemble, "D3DDisassemble", &error)) {
         return DAWN_INTERNAL_ERROR(error.c_str());
     }
diff --git a/src/dawn/native/d3d11/ShaderModuleD3D11.cpp b/src/dawn/native/d3d11/ShaderModuleD3D11.cpp
index 8ef732d..49677a5 100644
--- a/src/dawn/native/d3d11/ShaderModuleD3D11.cpp
+++ b/src/dawn/native/d3d11/ShaderModuleD3D11.cpp
@@ -101,7 +101,6 @@
     req.bytecode.compiler = d3d::Compiler::FXC;
     req.bytecode.d3dCompile =
         UnsafeUnserializedValue(pD3DCompile{device->GetFunctions()->d3dCompile});
-    req.bytecode.compilerVersion = D3D_COMPILER_VERSION;
     DAWN_ASSERT(device->GetDeviceInfo().shaderModel == 50);
     switch (stage) {
         case SingleShaderStage::Vertex:
diff --git a/src/dawn/native/d3d12/BackendD3D12.cpp b/src/dawn/native/d3d12/BackendD3D12.cpp
index a94fb13..92636be 100644
--- a/src/dawn/native/d3d12/BackendD3D12.cpp
+++ b/src/dawn/native/d3d12/BackendD3D12.cpp
@@ -40,14 +40,6 @@
 
 namespace dawn::native::d3d12 {
 
-namespace {
-
-uint64_t MakeDXCVersion(uint64_t majorVersion, uint64_t minorVersion) {
-    return (majorVersion << 32) + minorVersion;
-}
-
-}  // anonymous namespace
-
 Backend::Backend(InstanceBase* instance) : Base(instance, wgpu::BackendType::D3D12) {}
 
 MaybeError Backend::Initialize() {
@@ -60,50 +52,11 @@
         DAWN_TRY(Base::Initialize(std::move(functions)));
     }
 
-    // Check if DXC is available and cache DXC version information
-    if (!GetFunctions()->IsDXCBinaryAvailable()) {
-        // DXC version information is not available if DXC binaries are not available.
-        mDxcVersionInfo = DxcUnavailable{"DXC binary is not available"};
-    } else {
-        // Check the DXC version information and validate them being not lower than pre-defined
-        // minimum version.
-        AcquireDxcVersionInformation();
-
-        // Check that DXC version information is acquired successfully.
-        if (std::holds_alternative<DxcVersionInfo>(mDxcVersionInfo)) {
-            const DxcVersionInfo& dxcVersionInfo = std::get<DxcVersionInfo>(mDxcVersionInfo);
-
-            // The required minimum version for DXC compiler and validator.
-            // Notes about requirement consideration:
-            //   * DXC version 1.4 has some known issues when compiling Tint generated HLSL program,
-            //   please
-            //     refer to crbug.com/tint/1719
-            //   * Windows SDK 20348 provides DXC compiler and validator version 1.6
-            // Here the minimum version requirement for DXC compiler and validator are both set
-            // to 1.6.
-            constexpr uint64_t minimumCompilerMajorVersion = 1;
-            constexpr uint64_t minimumCompilerMinorVersion = 6;
-            constexpr uint64_t minimumValidatorMajorVersion = 1;
-            constexpr uint64_t minimumValidatorMinorVersion = 6;
-
-            // Check that DXC compiler and validator version are not lower than minimum.
-            if (dxcVersionInfo.DxcCompilerVersion <
-                    MakeDXCVersion(minimumCompilerMajorVersion, minimumCompilerMinorVersion) ||
-                dxcVersionInfo.DxcValidatorVersion <
-                    MakeDXCVersion(minimumValidatorMajorVersion, minimumValidatorMinorVersion)) {
-                // If DXC version is lower than required minimum, set mDxcVersionInfo to
-                // DxcUnavailable to indicate that DXC is not available.
-                std::ostringstream ss;
-                ss << "DXC version too low: dxil.dll required version 1.6, actual version "
-                   << (dxcVersionInfo.DxcValidatorVersion >> 32) << "."
-                   << (dxcVersionInfo.DxcValidatorVersion & ((uint64_t(1) << 32) - 1))
-                   << ", dxcompiler.dll required version 1.6, actual version "
-                   << (dxcVersionInfo.DxcCompilerVersion >> 32) << "."
-                   << (dxcVersionInfo.DxcCompilerVersion & ((uint64_t(1) << 32) - 1));
-                mDxcVersionInfo = DxcUnavailable{ss.str()};
-            }
-        }
-    }
+    // Initialize the DXC validator and compiler if we build them.
+#if defined(DAWN_USE_BUILT_DXC)
+    DAWN_TRY(EnsureDxcValidator());
+    DAWN_TRY(EnsureDxcCompiler());
+#endif
 
     // Enable the debug layer (requires the Graphics Tools "optional feature").
     const auto instance = GetInstance();
@@ -126,10 +79,6 @@
         }
     }
 
-#ifdef DAWN_USE_BUILT_DXC
-    DAWN_INVALID_IF(!IsDXCAvailable(), "DXC dlls were built, but are not available");
-#endif
-
     return {};
 }
 
@@ -182,85 +131,6 @@
     return mDxcValidator;
 }
 
-void Backend::AcquireDxcVersionInformation() {
-    DAWN_ASSERT(std::holds_alternative<DxcUnavailable>(mDxcVersionInfo));
-
-    auto tryAcquireDxcVersionInfo = [this]() -> ResultOrError<DxcVersionInfo> {
-        DAWN_TRY(EnsureDxcValidator());
-        DAWN_TRY(EnsureDxcCompiler());
-
-        ComPtr<IDxcVersionInfo> compilerVersionInfo;
-
-        DAWN_TRY(CheckHRESULT(mDxcCompiler.As(&compilerVersionInfo),
-                              "D3D12 QueryInterface IDxcCompiler3 to IDxcVersionInfo"));
-        uint32_t compilerMajor, compilerMinor;
-        DAWN_TRY(CheckHRESULT(compilerVersionInfo->GetVersion(&compilerMajor, &compilerMinor),
-                              "IDxcVersionInfo::GetVersion"));
-
-        ComPtr<IDxcVersionInfo> validatorVersionInfo;
-
-        DAWN_TRY(CheckHRESULT(mDxcValidator.As(&validatorVersionInfo),
-                              "D3D12 QueryInterface IDxcValidator to IDxcVersionInfo"));
-        uint32_t validatorMajor, validatorMinor;
-        DAWN_TRY(CheckHRESULT(validatorVersionInfo->GetVersion(&validatorMajor, &validatorMinor),
-                              "IDxcVersionInfo::GetVersion"));
-
-        // Pack major and minor version number into a single version number.
-        uint64_t compilerVersion = MakeDXCVersion(compilerMajor, compilerMinor);
-        uint64_t validatorVersion = MakeDXCVersion(validatorMajor, validatorMinor);
-        return DxcVersionInfo{compilerVersion, validatorVersion};
-    };
-
-    auto dxcVersionInfoOrError = tryAcquireDxcVersionInfo();
-
-    if (dxcVersionInfoOrError.IsSuccess()) {
-        // Cache the DXC version information.
-        mDxcVersionInfo = dxcVersionInfoOrError.AcquireSuccess();
-    } else {
-        // Error occurs when acquiring DXC version information, set the cache to unavailable and
-        // record the error message.
-        std::string errorMessage = dxcVersionInfoOrError.AcquireError()->GetFormattedMessage();
-        dawn::ErrorLog() << errorMessage;
-        mDxcVersionInfo = DxcUnavailable{errorMessage};
-    }
-}
-
-// Return both DXC compiler and DXC validator version, assert that DXC version information is
-// acquired successfully.
-DxcVersionInfo Backend::GetDxcVersion() const {
-    DAWN_ASSERT(std::holds_alternative<DxcVersionInfo>(mDxcVersionInfo));
-    return DxcVersionInfo(std::get<DxcVersionInfo>(mDxcVersionInfo));
-}
-
-// Return true if and only if DXC binary is available, and the DXC version is validated to
-// be no older than a pre-defined minimum version.
-bool Backend::IsDXCAvailable() const {
-    // mDxcVersionInfo hold DxcVersionInfo instead of DxcUnavailable if and only if DXC binaries and
-    // version are validated in `Initialize`.
-    return std::holds_alternative<DxcVersionInfo>(mDxcVersionInfo);
-}
-
-// Return true if and only if IsDXCAvailable() return true, and the DXC compiler and validator
-// version are validated to be no older than the minimum version given in parameter.
-bool Backend::IsDXCAvailableAndVersionAtLeast(uint64_t minimumCompilerMajorVersion,
-                                              uint64_t minimumCompilerMinorVersion,
-                                              uint64_t minimumValidatorMajorVersion,
-                                              uint64_t minimumValidatorMinorVersion) const {
-    // mDxcVersionInfo hold DxcVersionInfo instead of DxcUnavailable if and only if DXC binaries and
-    // version are validated in `Initialize`.
-    if (std::holds_alternative<DxcVersionInfo>(mDxcVersionInfo)) {
-        const DxcVersionInfo& dxcVersionInfo = std::get<DxcVersionInfo>(mDxcVersionInfo);
-        // Check that DXC compiler and validator version are not lower than given requirements.
-        if (dxcVersionInfo.DxcCompilerVersion >=
-                MakeDXCVersion(minimumCompilerMajorVersion, minimumCompilerMinorVersion) &&
-            dxcVersionInfo.DxcValidatorVersion >=
-                MakeDXCVersion(minimumValidatorMajorVersion, minimumValidatorMinorVersion)) {
-            return true;
-        }
-    }
-    return false;
-}
-
 ResultOrError<Ref<PhysicalDeviceBase>> Backend::CreatePhysicalDeviceFromIDXGIAdapter(
     ComPtr<IDXGIAdapter> dxgiAdapter) {
     ComPtr<IDXGIAdapter3> dxgiAdapter3;
diff --git a/src/dawn/native/d3d12/BackendD3D12.h b/src/dawn/native/d3d12/BackendD3D12.h
index 57dd2e5..edfa645 100644
--- a/src/dawn/native/d3d12/BackendD3D12.h
+++ b/src/dawn/native/d3d12/BackendD3D12.h
@@ -41,14 +41,6 @@
 
 class PlatformFunctions;
 
-// DxcVersionInfo holds both DXC compiler (dxcompiler.dll) version and DXC validator (dxil.dll)
-// version, which are not necessarily identical. Both are in uint64_t type, as the result of
-// MakeDXCVersion.
-struct DxcVersionInfo {
-    uint64_t DxcCompilerVersion;
-    uint64_t DxcValidatorVersion;
-};
-
 // If DXC version information is not available due to no DXC binary or error occurs when acquiring
 // version, DxcUnavailable indicates the version information being unavailable and holds the
 // detailed error information.
@@ -68,21 +60,6 @@
     ComPtr<IDxcCompiler3> GetDxcCompiler() const;
     ComPtr<IDxcValidator> GetDxcValidator() const;
 
-    // Return true if and only if DXC binary is available, and the DXC compiler and validator
-    // version are validated to be no older than a specific minimum version, currently 1.6.
-    bool IsDXCAvailable() const;
-
-    // Return true if and only if mIsDXCAvailable is true, and the DXC compiler and validator
-    // version are validated to be no older than the minimum version given in parameter.
-    bool IsDXCAvailableAndVersionAtLeast(uint64_t minimumCompilerMajorVersion,
-                                         uint64_t minimumCompilerMinorVersion,
-                                         uint64_t minimumValidatorMajorVersion,
-                                         uint64_t minimumValidatorMinorVersion) const;
-
-    // Return the DXC version information cached in mDxcVersionInformation, assert that the version
-    // information is valid. Must be called after ensuring `IsDXCAvailable()` return true.
-    DxcVersionInfo GetDxcVersion() const;
-
     const PlatformFunctions* GetFunctions() const;
 
   protected:
@@ -90,24 +67,10 @@
         ComPtr<IDXGIAdapter> dxgiAdapter) override;
 
   private:
-    // Acquiring DXC version information and store the result in mDxcVersionInfo. This function
-    // should be called only once, during startup in `Initialize`.
-    void AcquireDxcVersionInformation();
-
     ComPtr<IDxcLibrary> mDxcLibrary;
     ComPtr<IDxcCompiler3> mDxcCompiler;
     ComPtr<IDxcValidator> mDxcValidator;
 
-    // DXC binaries and DXC version information are checked when start up in `Initialize`. There are
-    // two possible states:
-    //   1. The DXC binary is not available, or error occurs when checking the version information
-    //      and therefore no DXC version information available, or the DXC version is lower than
-    //      requested minimum and therefore DXC is not available, represented by DxcUnavailable
-    //      in which a error message is held;
-    //   3. The DXC version information is acquired successfully and validated not lower than
-    //      requested minimum, stored in DxcVersionInfo.
-    std::variant<DxcUnavailable, DxcVersionInfo> mDxcVersionInfo;
-
     using Base = d3d::Backend;
 };
 
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp
index 2247e3c..21aaf5e 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -272,7 +272,6 @@
 // Ensure DXC if use_dxc toggles are set and validated.
 MaybeError Device::EnsureDXCIfRequired() {
     if (IsToggleEnabled(Toggle::UseDXC)) {
-        DAWN_ASSERT(ToBackend(GetPhysicalDevice())->GetBackend()->IsDXCAvailable());
         DAWN_TRY(ToBackend(GetPhysicalDevice())->GetBackend()->EnsureDxcCompiler());
         DAWN_TRY(ToBackend(GetPhysicalDevice())->GetBackend()->EnsureDxcLibrary());
         DAWN_TRY(ToBackend(GetPhysicalDevice())->GetBackend()->EnsureDxcValidator());
diff --git a/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp b/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
index f9083d9..02c3792 100644
--- a/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
@@ -175,10 +175,10 @@
         EnableFeature(Feature::ChromiumExperimentalTimestampQueryInsidePasses);
     }
 
+#if defined(DAWN_USE_BUILT_DXC)
     // ShaderF16 features require DXC version being 1.4 or higher, shader model supporting 6.2 or
     // higher, and native supporting F16 shader ops.
-    if (GetBackend()->IsDXCAvailableAndVersionAtLeast(1, 4, 1, 4) &&
-        mDeviceInfo.highestSupportedShaderModel >= 62 && mDeviceInfo.supportsNative16BitShaderOps) {
+    if (mDeviceInfo.highestSupportedShaderModel >= 62 && mDeviceInfo.supportsNative16BitShaderOps) {
         EnableFeature(Feature::ShaderF16);
     }
 
@@ -186,9 +186,10 @@
     // See crbug.com/391680973
     const bool kForceDisableSubgroups = gpu_info::IsIntelGen9(GetVendorId(), GetDeviceId());
     // Subgroups feature requires SM >= 6.0 and capabilities flags.
-    if (!kForceDisableSubgroups && GetBackend()->IsDXCAvailable() && mDeviceInfo.supportsWaveOps) {
+    if (!kForceDisableSubgroups && mDeviceInfo.supportsWaveOps) {
         EnableFeature(Feature::Subgroups);
     }
+#endif
 
     D3D12_FEATURE_DATA_FORMAT_SUPPORT bgra8unormFormatInfo = {};
     bgra8unormFormatInfo.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
@@ -550,25 +551,20 @@
 
 void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
                                                 TogglesState* adapterToggles) const {
-    // Check for use_dxc toggle
 #ifdef DAWN_USE_BUILT_DXC
-    // Default to using DXC. If shader model < 6.0, though, we must use FXC.
     if (GetDeviceInfo().highestSupportedShaderModel < 60) {
+        // If shader model < 6.0, though, we must use FXC.
         adapterToggles->ForceSet(Toggle::UseDXC, false);
     }
-
-    bool useDxc = platform->IsFeatureEnabled(dawn::platform::Features::kWebGPUUseDXC);
+    const bool useDxc = platform->IsFeatureEnabled(dawn::platform::Features::kWebGPUUseDXC);
     adapterToggles->Default(Toggle::UseDXC, useDxc);
 #else
-    // Default to using FXC
-    if (!GetBackend()->IsDXCAvailable()) {
-        adapterToggles->ForceSet(Toggle::UseDXC, false);
-    }
+    adapterToggles->ForceSet(Toggle::UseDXC, false);
     adapterToggles->Default(Toggle::UseDXC, false);
 #endif
 
-    uint32_t deviceId = GetDeviceId();
-    uint32_t vendorId = GetVendorId();
+    const uint32_t deviceId = GetDeviceId();
+    const uint32_t vendorId = GetVendorId();
 
     // On Intel Gen12 D3D driver < 32.0.101.5762, using shader model 6.6 will cause unexpected
     // result when adding/subtracting I32/U32 vector/scalar with vector/scalar in constant
@@ -608,6 +604,12 @@
 
 void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
                                                TogglesState* deviceToggles) const {
+#ifdef DAWN_USE_BUILT_DXC
+    const bool dxcAvailable = true;
+#else
+    const bool dxcAvailable = false;
+#endif
+
     const bool useResourceHeapTier2 = (GetDeviceInfo().resourceHeapTier >= 2);
     deviceToggles->Default(Toggle::UseD3D12ResourceHeapTier2, useResourceHeapTier2);
     deviceToggles->Default(Toggle::UseD3D12RenderPass, GetDeviceInfo().supportsRenderPass);
@@ -670,16 +672,14 @@
     // Native support of packed 4x8 integer dot product required shader model 6.4 or higher, and
     // DXC 1.4 or higher.
     if (!(GetAppliedShaderModelUnderToggles(*deviceToggles) >= 64) ||
-        !deviceToggles->IsEnabled(Toggle::UseDXC) ||
-        !GetBackend()->IsDXCAvailableAndVersionAtLeast(1, 4, 1, 4)) {
+        !deviceToggles->IsEnabled(Toggle::UseDXC) || !dxcAvailable) {
         deviceToggles->ForceSet(Toggle::PolyFillPacked4x8DotProduct, true);
     }
 
     // Native support of pack/unpack 4x8 intrinsics required shader model 6.6 or higher, and
     // DXC 1.4 or higher.
     if (!(GetAppliedShaderModelUnderToggles(*deviceToggles) >= 66) ||
-        !deviceToggles->IsEnabled(Toggle::UseDXC) ||
-        !GetBackend()->IsDXCAvailableAndVersionAtLeast(1, 6, 1, 6)) {
+        !deviceToggles->IsEnabled(Toggle::UseDXC) || !dxcAvailable) {
         deviceToggles->ForceSet(Toggle::D3D12PolyFillPackUnpack4x8, true);
     }
 
diff --git a/src/dawn/native/d3d12/PlatformFunctionsD3D12.cpp b/src/dawn/native/d3d12/PlatformFunctionsD3D12.cpp
index c84c8e4..f135ccf 100644
--- a/src/dawn/native/d3d12/PlatformFunctionsD3D12.cpp
+++ b/src/dawn/native/d3d12/PlatformFunctionsD3D12.cpp
@@ -32,92 +32,25 @@
 #include <string>
 #include <utility>
 
+#include "dawn/common/SystemUtils.h"
+
 namespace dawn::native::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) {
-            DAWN_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() = default;
 PlatformFunctions::~PlatformFunctions() = default;
 
 MaybeError PlatformFunctions::LoadFunctions() {
     DAWN_TRY(Base::LoadFunctions());
-    LoadDXCLibraries();
+
+    const auto modulePath = GetModuleDirectory();
+    const std::string& pathToPrepend = modulePath.value_or("");
+
+#if DAWN_USE_BUILT_DXC
+    LoadDXCLibraries(pathToPrepend);
+#endif
     DAWN_TRY(LoadD3D12());
     DAWN_TRY(LoadD3D11());
-    LoadPIXRuntime();
+    LoadPIXRuntime(pathToPrepend);
     return {};
 }
 
@@ -166,13 +99,13 @@
     return mPIXEventRuntimeLib.Valid();
 }
 
-void PlatformFunctions::LoadPIXRuntime() {
+void PlatformFunctions::LoadPIXRuntime(const std::string& pathToPrepend) {
     // TODO(dawn:766):
     // In UWP PIX should be statically linked WinPixEventRuntime_UAP.lib
     // So maybe we should put WinPixEventRuntime as a third party package
     // Currently PIX is not going to be loaded in UWP since the following
     // mPIXEventRuntimeLib.Open will fail.
-    if (!mPIXEventRuntimeLib.Open("WinPixEventRuntime.dll") ||
+    if (!mPIXEventRuntimeLib.Open(pathToPrepend + "WinPixEventRuntime.dll") ||
         !mPIXEventRuntimeLib.GetProc(&pixBeginEventOnCommandList, "PIXBeginEventOnCommandList") ||
         !mPIXEventRuntimeLib.GetProc(&pixEndEventOnCommandList, "PIXEndEventOnCommandList") ||
         !mPIXEventRuntimeLib.GetProc(&pixSetMarkerOnCommandList, "PIXSetMarkerOnCommandList")) {
@@ -180,72 +113,27 @@
     }
 }
 
-void PlatformFunctions::LoadDXCLibraries() {
+void PlatformFunctions::LoadDXCLibraries(const std::string& pathToPrepend) {
     // TODO(dawn:766)
     // Statically linked with dxcompiler.lib in UWP
     // currently linked with dxcompiler.lib making CoreApp unable to activate
     // LoadDXIL and LoadDXCompiler will fail in UWP, but LoadFunctions() can still be
     // successfully executed.
 
-    const std::string& windowsSDKBasePath = GetWindowsSDKBasePath();
-
-    LoadDXIL(windowsSDKBasePath);
-    LoadDXCompiler(windowsSDKBasePath);
-}
-
-void PlatformFunctions::LoadDXIL(const std::string& baseWindowsSDKPath) {
-    constexpr char kDxilDLLName[] = "dxil.dll";
-    const std::array kDxilDLLPaths{
-#ifdef DAWN_USE_BUILT_DXC
-        std::string{kDxilDLLName},
-#else
-        std::string{kDxilDLLName},
-        baseWindowsSDKPath + kDxilDLLName,
-#endif
-    };
-
-    for (const std::string& dxilDLLPath : kDxilDLLPaths) {
-        if (mDXILLib.Open(dxilDLLPath, nullptr)) {
-            return;
-        }
-    }
-    DAWN_ASSERT(!mDXILLib.Valid());
-}
-
-void PlatformFunctions::LoadDXCompiler(const std::string& baseWindowsSDKPath) {
+    DynamicLib dxilLib;
     // DXIL must be loaded before DXC, otherwise shader signing is unavailable
-    if (!mDXILLib.Valid()) {
+    if (!dxilLib.Open(pathToPrepend + "dxil.dll")) {
         return;
     }
 
-    constexpr char kDxCompilerDLLName[] = "dxcompiler.dll";
-    const std::array kDxCompilerDLLPaths{
-#ifdef DAWN_USE_BUILT_DXC
-        std::string{kDxCompilerDLLName},
-#else
-        std::string{kDxCompilerDLLName}, baseWindowsSDKPath + kDxCompilerDLLName
-#endif
-    };
-
     DynamicLib dxCompilerLib;
-    for (const std::string& dllName : kDxCompilerDLLPaths) {
-        if (dxCompilerLib.Open(dllName, nullptr)) {
-            break;
-        }
+    if (!dxCompilerLib.Open(pathToPrepend + "dxcompiler.dll") ||
+        !dxCompilerLib.GetProc(&dxcCreateInstance, "DxcCreateInstance", nullptr)) {
+        return;
     }
 
-    if (dxCompilerLib.Valid() &&
-        dxCompilerLib.GetProc(&dxcCreateInstance, "DxcCreateInstance", nullptr)) {
-        mDXCompilerLib = std::move(dxCompilerLib);
-    } else {
-        mDXILLib.Close();
-    }
-}
-
-// Use Backend::IsDXCAvailable if possible, which also check the DXC is no older than a given
-// version
-bool PlatformFunctions::IsDXCBinaryAvailable() const {
-    return mDXILLib.Valid() && mDXCompilerLib.Valid();
+    mDXCompilerLib = std::move(dxCompilerLib);
+    mDXILLib = std::move(dxilLib);
 }
 
 }  // namespace dawn::native::d3d12
diff --git a/src/dawn/native/d3d12/PlatformFunctionsD3D12.h b/src/dawn/native/d3d12/PlatformFunctionsD3D12.h
index b242dee..0f06a69 100644
--- a/src/dawn/native/d3d12/PlatformFunctionsD3D12.h
+++ b/src/dawn/native/d3d12/PlatformFunctionsD3D12.h
@@ -43,7 +43,6 @@
     ~PlatformFunctions() override;
 
     MaybeError LoadFunctions();
-    bool IsDXCBinaryAvailable() const;
     bool IsPIXEventRuntimeLoaded() const;
 
     // Functions from d3d12.dll
@@ -87,10 +86,8 @@
 
     MaybeError LoadD3D12();
     MaybeError LoadD3D11();
-    void LoadPIXRuntime();
-    void LoadDXCLibraries();
-    void LoadDXIL(const std::string& baseWindowsSDKPath);
-    void LoadDXCompiler(const std::string& baseWindowsSDKPath);
+    void LoadPIXRuntime(const std::string& pathToPrepend);
+    void LoadDXCLibraries(const std::string& pathToPrepend);
 
     DynamicLib mD3D12Lib;
     DynamicLib mD3D11Lib;
diff --git a/src/dawn/native/d3d12/ShaderModuleD3D12.cpp b/src/dawn/native/d3d12/ShaderModuleD3D12.cpp
index 9a9eac2..c2dd378 100644
--- a/src/dawn/native/d3d12/ShaderModuleD3D12.cpp
+++ b/src/dawn/native/d3d12/ShaderModuleD3D12.cpp
@@ -141,23 +141,14 @@
     req.bytecode.compileFlags = compileFlags;
 
     if (device->IsToggleEnabled(Toggle::UseDXC)) {
-        // If UseDXC toggle are not forced to be disable, DXC should have been validated to be
-        // available.
-        DAWN_ASSERT(ToBackend(device->GetPhysicalDevice())->GetBackend()->IsDXCAvailable());
-        // We can get the DXC version information since IsDXCAvailable() is true.
-        d3d12::DxcVersionInfo dxcVersionInfo =
-            ToBackend(device->GetPhysicalDevice())->GetBackend()->GetDxcVersion();
-
         req.bytecode.compiler = d3d::Compiler::DXC;
         req.bytecode.dxcLibrary = UnsafeUnserializedValue(device->GetDxcLibrary().Get());
         req.bytecode.dxcCompiler = UnsafeUnserializedValue(device->GetDxcCompiler().Get());
-        req.bytecode.compilerVersion = dxcVersionInfo.DxcCompilerVersion;
         req.bytecode.dxcShaderProfile = device->GetDxcShaderProfiles()[stage];
     } else {
         req.bytecode.compiler = d3d::Compiler::FXC;
         req.bytecode.d3dCompile =
             UnsafeUnserializedValue(pD3DCompile{device->GetFunctions()->d3dCompile});
-        req.bytecode.compilerVersion = D3D_COMPILER_VERSION;
         switch (stage) {
             case SingleShaderStage::Vertex:
                 req.bytecode.fxcShaderProfile = "vs_5_1";
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index 76206b8..b8ec2a2 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -142,12 +142,10 @@
 # Copy target for DXC
 ###############################################################################
 
-# When building with chromium under Windows, we need to copy the DXC from
-# Windows SDK into build folder, in order to ensure a DXC of version 1.6 is
-# available when running end-to-end tests in Chromium. Note that currently DXC
-# only provided for x86 and x64 in Windows SDK 20348.
-if (!dawn_use_built_dxc && build_with_chromium && is_win &&
-    (target_cpu == "x64" || target_cpu == "x86")) {
+# Chromium archive scripts are not able to determine whether dawn_built_dxc
+# is defined. Hence, we need to copy the DXC DLLs from the Windows SDK so the
+# scripts always have something to pick up.
+if (!dawn_use_built_dxc && build_with_chromium && is_win) {
   # The windows_sdk_path is acquired in visual_studio_version.gni.
   import("//build/config/win/visual_studio_version.gni")
 
@@ -162,7 +160,6 @@
   # end-to-end test in Chromium.
   copy("copy_dxc_binary") {
     sources = [
-      "$windows_sdk_path/bin/$windows_sdk_version/$target_cpu/dxc.exe",
       "$windows_sdk_path/bin/$windows_sdk_version/$target_cpu/dxcompiler.dll",
       "$windows_sdk_path/bin/$windows_sdk_version/$target_cpu/dxil.dll",
     ]
@@ -196,15 +193,13 @@
 
     # Running Dawn tests within Chromium in Windows may require DXC, copy DXC
     # binary from Windows SDK.
-    if (build_with_chromium && is_win &&
-        (target_cpu == "x64" || target_cpu == "x86")) {
+    if (build_with_chromium && is_win) {
       if (dawn_use_built_dxc) {
         if (!defined(deps)) {
           deps = []
         }
         deps += [
           "$dawn_root/third_party/gn/dxc:copy_dxil_dll",
-          "$dawn_root/third_party/gn/dxc:dxc",
           "$dawn_root/third_party/gn/dxc:dxcompiler",
         ]
       } else {