Skip to content

Add a test target to run exec tests with latest warp from nuget #7101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jan 31, 2025
4 changes: 4 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ stages:
call utils\hct\hctstart.cmd %HLSL_SRC_DIR% %HLSL_BLD_DIR%
call utils\hct\hcttest.cmd -$(configuration) noexec
displayName: 'DXIL Tests'
- script: |
call utils\hct\hctstart.cmd %HLSL_SRC_DIR% %HLSL_BLD_DIR%
call utils\hct\hcttest.cmd -$(configuration) exec-warp
displayName: 'DXIL Execution Tests (Nuget WARP)'

- job: Nix
timeoutInMinutes: 90
Expand Down
233 changes: 233 additions & 0 deletions cmake/modules/Nuget.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
include_guard(GLOBAL)

if(NOT DEFINED BINARY_DIR)
message(SEND_ERROR "Callers must provide BINARY_DIR")
endif()

if(NOT DEFINED BUILD_TYPE)
message(SEND_ERROR "Callers must provide BUILD_TYPE")
endif()

if(NOT DEFINED ENV{USE_WARP_FROM_NUGET})
message(SEND_ERROR "Callers must set a string value for the environement variable USE_WARP_FROM_NUGET value."
"Either 'LATEST_RELEASE' or 'LATEST_PREVIEW'")
endif()

set(USE_WARP_FROM_NUGET $ENV{USE_WARP_FROM_NUGET})

# Downloads nuget.exe to the given path if it doesn't exist yet.
function(EnsureNugetExists target_path)
# Download the latest nuget.exe to the given path.
if(NOT EXISTS ${target_path})
message(STATUS "Installing nuget.exe to ${target_path}...")
file(DOWNLOAD
https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
${target_path}
)
endif()
endfunction()

# Downloads nuget.exe to the given path if it doesn't exist yet.
function(GetNuGetPackageLatestVersion)
set(params NAME ID SOURCE OUTPUT_DIR OUTPUT_VARIABLE PREVIEW)
cmake_parse_arguments(PARSE_ARGV 0 ARG "" "${params}" "")

if(NOT ARG_OUTPUT_DIR)
set(ARG_OUTPUT_DIR )
endif()

set(nuget_exe_path "${ARG_OUTPUT_DIR}\\nuget.exe install")
EnsureNugetExists(${nuget_exe_path})

if (${ARG_ID}_LATEST_VERSION)
set(${ARG_OUTPUT_VARIABLE} ${${ARG_ID}_LATEST_VERSION} PARENT_SCOPE)
else()
if(NOT ARG_SOURCE)
set(ARG_SOURCE https://api.nuget.org/v3/index.json)
endif()

if(NOT ARG_PREVIEW)
set(ARG_PREVIEW OFF)
endif()

if(ARG_PREVIEW)
# Note that '-Prerelease' options will only return a prerelease package if that is also the latest.
# If you want a prerelease package with an older version number than the latest release package then you
# need to pass a specific version number.
message("Will add '-Prelease' to nuget list command")
set(prerelease "-Prerelease")
endif()

execute_process(
COMMAND ${nuget_exe_path}
list ${ARG_ID}
-Source ${ARG_SOURCE}
${prerelease}
RESULT_VARIABLE result
OUTPUT_VARIABLE nuget_list_output
OUTPUT_STRIP_TRAILING_WHITESPACE
)

if(NOT ${result} STREQUAL "0")
message(FATAL_ERROR "NuGet failed to find latest version of package ${ARG_ID} with exit code ${result}.")
endif()

# Get last line of running nuget.exe list <ID>.
string(REPLACE "\n" ";" nuget_list_output ${nuget_list_output})
list(POP_BACK nuget_list_output nuget_list_last_line)
if(nuget_list_last_line STREQUAL "No packages found.")
message(FATAL_ERROR "NuGet failed to find latest version of package ${ARG_ID}.")
endif()

# The last line should have the format <ID> <VERSION>
string(REPLACE " " ";" nuget_list_last_line ${nuget_list_last_line})
list(POP_BACK nuget_list_last_line nuget_version)

if(NOT nuget_version)
message(FATAL_ERROR "NuGet failed to find latest version of package ${ARG_ID}.")
endif()

message("Nuget found version:${nuget_version} for ${ARG_ID}")

# Save output variable and cache the result so subsequent calls to the version-unspecified package
# are faster.
set(${ARG_OUTPUT_VARIABLE} ${nuget_version} PARENT_SCOPE)
set(${ARG_ID}_LATEST_VERSION ${nuget_version} CACHE INTERNAL "")
endif()
endfunction()

# Installs a NuGet package under OUTPUT_DIR.
#
# FetchNuGetPackage(
# ID Microsoft.Direct3D.WARP
# VERSION 1.0.13
# SOURCE https://api.nuget.org/v3/index.json
# )
#
# This functions sets a variable <name>_SOURCE_DIR (e.g. Microsoft.Direct3D.WARP_SOURCE_DIR in above example) to the
# extract NuGet package contents.
function(FetchNuGetPackage)
set(params NAME ID VERSION SOURCE OUTPUT_DIR RELEASE_TYPE)
cmake_parse_arguments(PARSE_ARGV 0 ARG "" "${params}" "")

# The NAME parameter is optional: if it's not set then the package ID is used as the name. The
# reason for having a separate NAME is to allow a consistent identifier for packages whose ID
# changes with each release (e.g. GDK).
if(NOT ARG_NAME)
set(ARG_NAME ${ARG_ID})
endif()

if(NOT ARG_OUTPUT_DIR)
set(ARG_OUTPUT_DIR ${BINARY_DIR}/temp)
endif()

set(nuget_exe_path ${ARG_OUTPUT_DIR}/nuget.exe)

if(NOT ARG_SOURCE)
set(ARG_SOURCE https://api.nuget.org/v3/index.json)
endif()

if(NOT ARG_RELEASE_TYPE)
set(ARG_RELEASE_TYPE "LATEST_RELEASE")
endif()

set(PREVIEW OFF)

if(${ARG_RELEASE_TYPE} STREQUAL "LATEST_PREVIEW")
set(PREVIEW ON)
endif()

# Default to latest version
if(NOT ARG_VERSION)
GetNuGetPackageLatestVersion(
ID ${ARG_ID}
SOURCE ${ARG_SOURCE}
PREVIEW ${PREVIEW}
OUTPUT_DIR ${ARG_OUTPUT_DIR}
OUTPUT_VARIABLE ARG_VERSION
)
endif()

set(nupkg_path ${ARG_OUTPUT_DIR}/${ARG_ID}.${ARG_VERSION}/${ARG_ID}.${ARG_VERSION}.nupkg)

if(NOT EXISTS ${nupkg_path})
message(STATUS "NuGet: adding package ${ARG_ID}.${ARG_VERSION}")

EnsureNugetExists(${nuget_exe_path})

set(retry_count 0)
set(max_retries 10)
set(retry_delay 10)
set(result 1)

# Run NuGet CLI to download the package.
while(NOT ${result} STREQUAL "0" AND ${retry_count} LESS ${max_retries})
message(STATUS "'${nuget_exe_path}' install '${ARG_ID}' -Version '${ARG_VERSION}' -Source '${ARG_SOURCE}' -OutputDirectory '${ARG_OUTPUT_DIR}' -DependencyVersion Ignore -Verbosity quiet")
execute_process(
COMMAND
${nuget_exe_path}
install ${ARG_ID}
-Version ${ARG_VERSION}
-Source ${ARG_SOURCE}
-OutputDirectory ${ARG_OUTPUT_DIR}
-DependencyVersion Ignore
-Verbosity quiet
RESULT_VARIABLE result
)
if(NOT ${result} STREQUAL "0")
math(EXPR retry_count "${retry_count} + 1")

message(STATUS "Nuget failed: '${result}'. Retrying in ${retry_delay} seconds...")
execute_process(
COMMAND
${CMAKE_COMMAND} -E sleep ${retry_delay}
)
endif()
endwhile()

if(NOT ${result} STREQUAL "0")
message(FATAL_ERROR "NuGet failed: '${result}' Package '${ARG_NAME}' (${ARG_ID}.${ARG_VERSION})")
endif()
endif()

# Set output variable. The NAME parameter is optional: if it's not set then the package ID is used as the
# name. The reason for having a separate NAME is for packages whose IDs change (e.g. GDK) so that callers
# can use a fixed name in dependents. Example, targets can reference gdk_SOURCE_DIR with the snippet below
# instead of having to reference Microsoft.GDK.PC.230300_SOURCE_DIR.
#
# FetchNuGetPackage(
# NAME gdk
# ID Microsoft.GDK.PC.220300
# VERSION 10.0.22621.3049
# )
set(${ARG_NAME}_SOURCE_DIR ${ARG_OUTPUT_DIR}/${ARG_ID}.${ARG_VERSION} PARENT_SCOPE)
endfunction()

# Begin the 'main' logic of this file. Previous code is all defintions.
message("USE_WARP_FROM_NUGET: ${USE_WARP_FROM_NUGET}")
if(${USE_WARP_FROM_NUGET} STREQUAL "LATEST_RELEASE" OR ${USE_WARP_FROM_NUGET} STREQUAL "LATEST_PREVIEW")

message("Fetching warp from nuget")

FetchNuGetPackage(ID Microsoft.Direct3D.WARP OUTPUT_DIR ${BINARY_DIR}/temp RELEASE_TYPE ${USE_WARP_FROM_NUGET})

if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
set(ARCH "x64")
endif()
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "X86")
set(ARCH "win32")
endif()
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ARM64")
set(ARCH "arm64")
endif()

set(WARP_SOURCE_PATH "${Microsoft.Direct3D.WARP_SOURCE_DIR}/build/native/bin/${ARCH}")
set(WARP_DEST_PATH "${BINARY_DIR}/${BUILD_TYPE}/bin/")
message("Copying d3d10warp.dll and d3d10warp.pdb \n"
" from: ${WARP_SOURCE_PATH}\n"
" to: ${WARP_DEST_PATH}")
file(COPY "${WARP_SOURCE_PATH}/d3d10warp.dll"
DESTINATION "${WARP_DEST_PATH}")
file(COPY "${WARP_SOURCE_PATH}/d3d10warp.pdb"
DESTINATION "${WARP_DEST_PATH}")
endif()
17 changes: 17 additions & 0 deletions tools/clang/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,29 @@ if (WIN32)
)
set(TAEF_EXEC_ADAPTER "" CACHE STRING "adapter for taef exec test")

# Use a custom target so we can depend on it and re-run the cmake logic which downloads warp
# from nuget if requested.
add_custom_target(WarpFromNuget
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}
-DBUILD_TYPE=${CMAKE_BUILD_TYPE}
-DBINARY_DIR=${CMAKE_BINARY_DIR}
-P "${CMAKE_SOURCE_DIR}/cmake/modules/nuget.cmake")

add_lit_target("check-clang-taef-exec" "Running lit suite hlsl execution test"
${CMAKE_CURRENT_SOURCE_DIR}/taef_exec
PARAMS ${CLANG_TEST_PARAMS}
adapter=${TAEF_EXEC_ADAPTER}
DEPENDS ExecHLSLTests dxexp
ARGS ${CLANG_TEST_EXTRA_ARGS}
)

add_lit_target("check-clang-taef-exec-warp" "Running lit suite hlsl execution test with D3D WARP from nuget"
${CMAKE_CURRENT_SOURCE_DIR}/taef_exec
PARAMS ${CLANG_TEST_PARAMS}
adapter=${TAEF_EXEC_ADAPTER}
DEPENDS ExecHLSLTests dxexp WarpFromNuget
ARGS ${CLANG_TEST_EXTRA_ARGS}
)
endif()
# HLSL Change End
2 changes: 1 addition & 1 deletion tools/clang/unittests/HLSLExec/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ endif()
# Add a .user file with settings for te.exe.
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" DOS_STYLE_SOURCE_DIR)
file(TO_NATIVE_PATH "${TAEF_BIN_DIR}" DOS_TAEF_BIN_DIR)
configure_file(ExecHLSLTests.vcxproj.user.txt ExecHLSLTests.vcxproj.user)
configure_file(ExecHLSLTests.vcxproj.user.txt ExecHLSLTests.vcxproj.user)
9 changes: 9 additions & 0 deletions tools/clang/unittests/HLSLExec/ExecutionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,15 @@ class ExecutionTest {

return false;
}

if (GetModuleHandle("d3d10warp.dll") != NULL) {
CHAR szFullModuleFilePath[MAX_PATH] = "";
GetModuleFileName(GetModuleHandle("d3d10warp.dll"), szModuleFilePath,
sizeof(szModuleFilePath));
WEX::Logging::Log::Comment(WEX::Common::String().Format(
L"WARP driver loaded from: %S", szModuleFilePath));
}

} else {
CComPtr<IDXGIAdapter1> hardwareAdapter;
WEX::Common::String AdapterValue;
Expand Down
13 changes: 9 additions & 4 deletions utils/hct/hctbuild.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ set WINSDK_MIN_VERSION=10.0.17763.0
set INSTALL_DIR=
set DEFAULT_EXEC_ADAPTER=-DTAEF_EXEC_ADAPTER=
set LIT_ARGS=
set FRESH=

:parse_args
if "%1"=="" (
Expand Down Expand Up @@ -208,6 +209,10 @@ if "%1"=="-sanitizer" (
set CMAKE_OPTS=%CMAKE_OPTS% -DLLVM_USE_SANITIZER:STRING=Address
shift /1 & goto :parse_args
)
if "%1"=="-fresh" (
set FRESH="--fresh"
shift /1 & goto :parse_args
)


rem Begin SPIRV change
Expand Down Expand Up @@ -468,13 +473,13 @@ cd /d %3
if "%DO_SETUP%"=="1" (
echo Creating solution files for %2, logging to %3\cmake-log.txt
if "%BUILD_GENERATOR%"=="Ninja" (
echo Running "%CMAKE_PATH%" -DCMAKE_BUILD_TYPE:STRING=%1 %CMAKE_OPTS% -G %4 %HLSL_SRC_DIR% > %3\cmake-log.txt
"%CMAKE_PATH%" -DCMAKE_BUILD_TYPE:STRING=%1 %CMAKE_OPTS% -G %4 %HLSL_SRC_DIR% >> %3\cmake-log.txt 2>&1
echo Running "%CMAKE_PATH%" %FRESH% -DCMAKE_BUILD_TYPE:STRING=%1 %CMAKE_OPTS% -G %4 %HLSL_SRC_DIR% > %3\cmake-log.txt
"%CMAKE_PATH%" %FRESH% -DCMAKE_BUILD_TYPE:STRING=%1 %CMAKE_OPTS% -G %4 %HLSL_SRC_DIR% >> %3\cmake-log.txt 2>&1
) else (
rem BUILD_TYPE is mostly ignored in this path as VS generates multiple targets
rem it is still needed to satisfy cmake file expectations
echo Running "%CMAKE_PATH%" -DCMAKE_BUILD_TYPE:STRING=%1 %CMAKE_OPTS% -G %4 %5 %HLSL_SRC_DIR% > %3\cmake-log.txt
"%CMAKE_PATH%" -DCMAKE_BUILD_TYPE:STRING=%1 %CMAKE_OPTS% -G %4 %5 %HLSL_SRC_DIR% >> %3\cmake-log.txt 2>&1
echo Running "%CMAKE_PATH%" %FRESH% -DCMAKE_BUILD_TYPE:STRING=%1 %CMAKE_OPTS% -G %4 %5 %HLSL_SRC_DIR% > %3\cmake-log.txt
"%CMAKE_PATH%" %FRESH% -DCMAKE_BUILD_TYPE:STRING=%1 %CMAKE_OPTS% -G %4 %5 %HLSL_SRC_DIR% >> %3\cmake-log.txt 2>&1
)
if %SHOW_CMAKE_LOG%==1 (
echo ------- Start of %3\cmake-log.txt -------
Expand Down
20 changes: 19 additions & 1 deletion utils/hct/hcttest.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ set TEST_MANUAL_FILE_CHECK=0
set SINGLE_FILE_CHECK_NAME=0
set CUSTOM_BIN_SET=
set USE_AGILITY_SDK=
set USE_WARP_FROM_NUGET=
set EXEC_TEST_TARGET="check-clang-taef-exec"

rem Begin SPIRV change
set TEST_SPIRV=0
Expand Down Expand Up @@ -132,6 +134,22 @@ if "%1"=="-clean" (
set TEST_ALL=0
set TEST_EXEC=1
set TEST_EXEC_REQUIRED=1
) else if "%1"=="exec-warp" (
rem If exec-warp is explicitly supplied, hcttest will fail if machine is not configured
rem to run execution tests, otherwise, execution tests would be skipped.
set TEST_ALL=0
set TEST_EXEC=1
set USE_WARP_FROM_NUGET=LATEST_RELEASE
set TEST_EXEC_REQUIRED=1
set EXEC_TEST_TARGET="check-clang-taef-exec-warp"
) else if "%1"=="exec-warp-preview" (
rem If exec-warp-preview is explicitly supplied, hcttest will fail if machine is not configured
rem to run execution tests, otherwise, execution tests would be skipped.
set TEST_ALL=0
set TEST_EXEC=1
set USE_WARP_FROM_NUGET=LATEST_PREVIEW
set TEST_EXEC_REQUIRED=1
set EXEC_TEST_TARGET="check-clang-taef-exec-warp"
) else if "%1"=="exec-filter" (
set TEST_ALL=0
set TEST_EXEC=1
Expand Down Expand Up @@ -333,7 +351,7 @@ if "%TEST_USE_LIT%"=="1" (
if defined EXEC_ADAPTER (
py %HLSL_SRC_DIR%/utils/lit/lit.py -v --no-progress-bar --param build_mode=%BUILD_CONFIG% --param clang_site_config=%HLSL_BLD_DIR%/tools/clang/test/lit.site.cfg --param clang_taef_exec_site_config=%HLSL_BLD_DIR%/tools/clang/test/taef_exec/lit.site.cfg %EXEC_ADAPTER% %HLSL_SRC_DIR%/tools/clang/test/taef_exec
) else (
cmake --build %HLSL_BLD_DIR% --config %BUILD_CONFIG% --target check-clang-taef-exec
cmake --build %HLSL_BLD_DIR% --config %BUILD_CONFIG% --target %EXEC_TEST_TARGET%
)
set RES_EXEC=!ERRORLEVEL!
)
Expand Down
Loading