Skip to content
2 changes: 1 addition & 1 deletion include/dxc/Support/dxcapi.extval.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class DxcDllExtValidationLoader : public DllLoader {
// DxCompilerSupport manages the
// lifetime of dxcompiler.dll, while DxilExtValSupport
// manages the lifetime of dxil.dll
dxc::SpecificDllLoader DxCompilerSupport;
dxc::DxCompilerDllLoader DxCompilerSupport;
dxc::SpecificDllLoader DxilExtValSupport;
std::string DxilDllPath;

Expand Down
3 changes: 3 additions & 0 deletions include/dxc/Test/DxcTestUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "dxc/Support/WinIncludes.h"

#include "dxc/Support/dxcapi.extval.h"
#include "dxc/Support/dxcapi.use.h"
#include "dxc/dxcapi.h"
#include "llvm/ADT/ArrayRef.h"
Expand Down Expand Up @@ -199,6 +200,8 @@ void GetDxilPart(dxc::DllLoader &dllSupport, IDxcBlob *pProgram,
IDxcBlob **pDxilPart);
std::string DisassembleProgram(dxc::DxCompilerDllLoader &dllSupport,
IDxcBlob *pProgram);
std::string DisassembleProgram(dxc::DxcDllExtValidationLoader &dllSupport,
IDxcBlob *pProgram);
void SplitPassList(LPWSTR pPassesBuffer, std::vector<LPCWSTR> &passes);
void MultiByteStringToBlob(dxc::DllLoader &dllSupport, const std::string &val,
UINT32 codePoint, IDxcBlob **ppBlob);
Expand Down
78 changes: 77 additions & 1 deletion tools/clang/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,84 @@ add_lit_testsuites(CLANG ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${CLANG_TEST_DEPS}
FOLDER "Clang tests/Suites"
)
# -------------------------------------------------------------------------
# DXIL Backward Compatibility Section
# -------------------------------------------------------------------------

# Define DXC releases as (NAME VERSION) pairs
set(DXC_RELEASES
dxc_2025_07_14 v1.8.2505.1
dxc_2025_05_24 v1.8.2505
dxc_2025_02_20 v1.8.2502
dxc_2023_08_14 v1.7.2308
dxc_2021_12_08 v1.6.2112
)

# Download a DXC release
function(add_released_dxc name version)
ExternalProject_Add(${name}
URL https://github.com/microsoft/DirectXShaderCompiler/releases/download/${version}/${name}.zip
DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/tools/clang/test/dxc_releases
SOURCE_DIR ${CMAKE_BINARY_DIR}/tools/clang/test/dxc_releases/${version}/${name}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
endfunction()

# Iterate over releases
list(LENGTH DXC_RELEASES DXC_RELEASES_LENGTH)
math(EXPR num_pairs "${DXC_RELEASES_LENGTH} / 2")
math(EXPR loop_end "${num_pairs} - 1")
foreach(i RANGE 0 ${loop_end})
math(EXPR idx_name "${i}*2")
math(EXPR idx_version "${i}*2 + 1")

list(GET DXC_RELEASES ${idx_name} name)
list(GET DXC_RELEASES ${idx_version} version)

add_released_dxc(${name} ${version})

if(WIN32)
# Determine target architecture for DXC binaries
if(CMAKE_GENERATOR MATCHES "Visual Studio")
# Multi-config generators (VS/Xcode)
if(NOT DEFINED CMAKE_GENERATOR_PLATFORM)
message(FATAL_ERROR "CMAKE_GENERATOR_PLATFORM not set for multi-config generator")
endif()
set(TARGET_ARCH ${CMAKE_GENERATOR_PLATFORM})
else()
# Single-config generators (Ninja, Makefiles)
# Use pointer size to guess x86 vs x64
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does ARM fit into this?

set(TARGET_ARCH x64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(TARGET_ARCH x86)
else()
message(FATAL_ERROR "Unknown pointer size: ${CMAKE_SIZEOF_VOID_P}")
endif()
endif()

message("TARGET_ARCH IS ${TARGET_ARCH}")

# Path to dxil.dll for this release
set(DXC_PATH ${CMAKE_BINARY_DIR}/tools/clang/test/dxc_releases/${version}/${name}/bin/${TARGET_ARCH}/dxil.dll)

# Create a lit target for this release
add_lit_target("check-clang-${name}" "Running clang regression tests with ${name}\n"
${CMAKE_CURRENT_SOURCE_DIR}
PARAMS ${CLANG_TEST_PARAMS} DXC_DXIL_DLL_PATH=${DXC_PATH}
DEPENDS ${CLANG_TEST_DEPS} ${name}
ARGS ${CLANG_TEST_EXTRA_ARGS}
)

# Manually generate targets that we need to expose in visual studio builds.
# Hook into check-all
if (WIN32 AND TARGET check-all)
add_dependencies(check-all "check-clang-${name}")
endif()
endif()
endforeach()
# -------------------------------------------------------------------------

# The code below here _ONLY_ executes when building with Visual Studio or Xcode.
if (NOT CMAKE_CONFIGURATION_TYPES)
Expand Down
3 changes: 3 additions & 0 deletions tools/clang/test/LitDXILValidation/Environment.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# REQUIRES: dxc_dxil_dll_path
# RUN: python -c "import os; print(os.environ['DXC_DXIL_DLL_PATH'])" | FileCheck %s
# CHECK: dxil.dll
9 changes: 9 additions & 0 deletions tools/clang/test/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import lit.util
# name: The name of this test suite.
config.name = 'Clang'

print("PARAMS seen in top level config:", lit_config.params)


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this left-over debugging code, or do you think this should be here long term?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left-over.

# Tweak PATH for Win32
if platform.system() == 'Windows':
# Seek sane tools in directories and set to $PATH.
Expand Down Expand Up @@ -94,6 +97,12 @@ for name in possibly_dangerous_env_vars:
if name in config.environment:
del config.environment[name]

dxc_dll_path = lit_config.params.get('DXC_DXIL_DLL_PATH', None)
if dxc_dll_path and os.path.exists(dxc_dll_path):
lit_config.note("Setting DXC_DXIL_DLL_PATH environment variable")
config.environment.update({'DXC_DXIL_DLL_PATH' : dxc_dll_path})
config.available_features.add("dxc_dxil_dll_path")

# Tweak the PATH to include the tools dir and the scripts dir.
if clang_obj_root is not None:
clang_tools_dir = getattr(config, 'clang_tools_dir', None)
Expand Down
15 changes: 13 additions & 2 deletions tools/clang/unittests/HLSL/ValidationTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#include "dxc/Support/Global.h"

#include "dxc/DXIL/DxilShaderModel.h"
#include "dxc/Support/dxcapi.extval.h"
#include "dxc/Test/DxcTestUtils.h"
#include "dxc/Test/HlslTestUtils.h"

Expand Down Expand Up @@ -327,11 +326,12 @@ class ValidationTest : public ::testing::Test {
TEST_METHOD(PSVContentValidationMS)
TEST_METHOD(PSVContentValidationAS)
TEST_METHOD(UnitTestExtValidationSupport)
TEST_METHOD(UnitTestValidationBackCompatibility)
TEST_METHOD(WrongPSVSize)
TEST_METHOD(WrongPSVSizeOnZeros)
TEST_METHOD(WrongPSVVersion)

dxc::DxCompilerDllLoader m_dllSupport;
dxc::DxcDllExtValidationLoader m_dllSupport;
VersionSupportInfo m_ver;

void TestCheck(LPCWSTR name) {
Expand Down Expand Up @@ -4302,6 +4302,17 @@ TEST_F(ValidationTest, UnitTestExtValidationSupport) {
}
#endif

// Building on the above test, this test uses the DxcDllExtValidationLoader
// class to instantiate loader objects using previously released
// dxcompiler.dll's. The environment will also be set up so that the previous
// dxil.dll's will also be loaded (to be used for external validation).
TEST_F(ValidationTest, UnitTestValidationBackCompatibility) {
dxc::DxcDllExtValidationLoader ExtSupport;
ExtSupport.Initialize();
std::string dllPath = ExtSupport.GetDxilDllPath();
VERIFY_IS_TRUE(dllPath.empty());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean that dllPath is empty? I'm trying to understand what this test is testing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is going to be out of scope for now. I'm going to focus on getting check-clang to work with older external validators.
But the point was, this test would be run when an older validator was set in the env var, and so we expect initialization to pull the env var's value and the loader object should have a stored dll path (it shouldn't be empty since it was read from the env var). It would only be empty if the env var was never set, thus proving that the infrastructure correctly set the environment.
This shouldn't be tested quite yet since it seems like a whole separate ordeal to add taef-based tests. We'll probably need to adjust the standard taef-test filter so that the original check-clang-taef_exec target runs on .ll / .hlsl / .test, AND .cpp files that are NOT the back-compat validation tests, otherwise they would fail since the environment wasn't set up.
It's a separate problem for now.

}

TEST_F(ValidationTest, ValidatePreviewBypassHash) {
if (m_ver.SkipDxilVersion(1, ShaderModel::kHighestMinor))
return;
Expand Down
2 changes: 0 additions & 2 deletions tools/clang/unittests/HLSLExec/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ find_package(D3D12 REQUIRED) # Used for ExecutionTest.cpp.

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")

set(DXCSUPPORT_DIR "${CMAKE_SOURCE_DIR}/lib/DxcSupport")

add_clang_library(ExecHLSLTests SHARED
ExecutionTest.cpp
ShaderOpTest.cpp
Expand Down
14 changes: 14 additions & 0 deletions tools/clang/unittests/HLSLTestLib/DxcTestUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,20 @@ std::string DisassembleProgram(dxc::DxCompilerDllLoader &dllSupport,
return BlobToUtf8(pDisassembly);
}

std::string DisassembleProgram(dxc::DxcDllExtValidationLoader &dllSupport,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having trouble connecting the dots here as to why the changes involving DisassembleProgram are related to the rest of these changes?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this was when I had thought I could do taef tests and modify the loaders all in one PR, I do think this will be needed, but later :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep this in this change or should it be pulled out to the later one?

IDxcBlob *pProgram) {
CComPtr<IDxcCompiler> pCompiler;
CComPtr<IDxcBlobEncoding> pDisassembly;

if (!dllSupport.IsEnabled()) {
VERIFY_SUCCEEDED(dllSupport.Initialize());
}

VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
return BlobToUtf8(pDisassembly);
}

void AssembleToContainer(dxc::DllLoader &dllSupport, IDxcBlob *pModule,
IDxcBlob **pContainer) {
CComPtr<IDxcAssembler> pAssembler;
Expand Down