Clear windows branch; preserve previous contents in win-old

This commit is contained in:
ayo committed 2026-10-16 05:20:08 -04:00
1 parent f0c881985b
commit 73994d4634
311 files changed
-57018

No files matched your search

-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra \
"$ROOT/tools/bench_dlss_kernel.cpp" -ldl \
-o "$ROOT/build/bench_dlss_kernel"
printf 'Built %s\n' "$ROOT/build/bench_dlss_kernel"
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
"$ROOT/scripts/build_d4r_nvngx_shim.sh"
"$MINGW_CXX" -std=c++20 -O2 -Wall -Wextra -I"$ROOT/build/vulkan-include" -static -static-libgcc -static-libstdc++ \
"$ROOT/tools/d3d12_dlss_harness.cpp" "$ROOT/tools/d4r_ngx_param_host.cpp" "$ROOT/build/d4r_ngx_param_msvc.obj" \
-o "$ROOT/build/d3d12_dlss_harness.exe"
printf 'Built %s\n' "$ROOT/build/d3d12_dlss_harness.exe"
-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
VULKAN_INCLUDE="${VULKAN_INCLUDE:-/usr/include}"
# Only the Vulkan headers from the host include tree, not its libc headers.
mkdir -p "$ROOT/build/vulkan-include"
ln -sfn "$VULKAN_INCLUDE/vulkan" "$ROOT/build/vulkan-include/vulkan"
ln -sfn "$VULKAN_INCLUDE/vk_video" "$ROOT/build/vulkan-include/vk_video"
"$MINGW_CXX" -I"$ROOT/build/vulkan-include" -std=c++20 -O2 -Wall -Wextra -Wno-missing-field-initializers -static -static-libgcc -static-libstdc++ \
"$ROOT/tools/d3d12_hip_interop_probe.cpp" -ld3d12 -o "$ROOT/build/d3d12_hip_interop_probe.exe"
printf 'Built %s\n' "$ROOT/build/d3d12_hip_interop_probe.exe"
-30
View File
@@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Build d4r-owned motion processing kernels and embed them in the Wine bridge.
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
OUT="${1:-$ROOT/build/wine-nvcuda/generated}"
ROCM="${D4R_ROCM_DIR:-/opt/rocm}"
CLANG="$ROCM/lib/llvm/bin/clang++"
[[ -x "$CLANG" ]] || { echo "motion kernels need ROCm clang (D4R_ROCM_DIR)" >&2; exit 2; }
mkdir -p "$OUT"
for arch in gfx1100 gfx1101 gfx1102 gfx1103 gfx1200 gfx1201; do
"$CLANG" -x hip -nogpuinc -nogpulib --offload-device-only --offload-arch="$arch" \
--no-gpu-bundle-output -O3 -mno-wavefrontsize64 -o "$OUT/$arch.hsaco" \
"$ROOT/kernels/support/motion_dilate.hip"
done
python3 - "$OUT" <<'PY'
from pathlib import Path
import sys
root = Path(sys.argv[1])
lines = ['/* Generated from d4r-owned HIP source; do not edit. */', '#include <string.h>']
for p in sorted(root.glob('gfx*.hsaco')):
data = p.read_bytes()
lines.append(f'static const unsigned char motion_{p.stem}[] __attribute__((aligned(64))) = {{')
lines.extend(','.join(f'0x{x:02x}' for x in data[i:i+24]) + ',' for i in range(0,len(data),24))
lines.append('};')
lines.append('static const void* d4r_motion_image(const char* arch) {')
for p in sorted(root.glob('gfx*.hsaco')):
lines.append(f' if (strcmp(arch, "{p.stem}") == 0) return motion_{p.stem};')
lines.append(' return NULL;\n}')
(root/'d4r_motion_kernels.h').write_text('\n'.join(lines)+'\n')
PY
-9
View File
@@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CC="${MINGW_CC:-x86_64-w64-mingw32-gcc}"
mkdir -p "$ROOT/build"
"$CC" -std=c11 -O2 -Wall -Wextra -shared -static-libgcc \
"$ROOT/tools/d4r_nvapi_identity.c" -o "$ROOT/build/nvapi64.dll"
printf 'Built %s\n' "$ROOT/build/nvapi64.dll"
-23
View File
@@ -1,23 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Builds build/d4r_nvngx.dll, the D3D12-to-CUDA NGX core shim loaded by
# OptiScaler through its NvngxPath setting.
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
CLANG_CL="${CLANG_CL:-clang-cl}"
VULKAN_INCLUDE="${VULKAN_INCLUDE:-/usr/include}"
mkdir -p "$ROOT/build"
# Only the Vulkan headers from the host include tree, not its libc headers.
mkdir -p "$ROOT/build/vulkan-include"
ln -sfn "$VULKAN_INCLUDE/vulkan" "$ROOT/build/vulkan-include/vulkan"
ln -sfn "$VULKAN_INCLUDE/vk_video" "$ROOT/build/vulkan-include/vk_video"
PARAM_OBJECT="$ROOT/build/d4r_ngx_param_msvc.obj"
"$CLANG_CL" --target=x86_64-pc-windows-msvc /nologo /std:c++20 /O2 /c /GS- /GR- /EHs-c- /Zl \
"/Fo$PARAM_OBJECT" -- "$ROOT/tools/d4r_ngx_param_msvc.cpp"
"$MINGW_CXX" -std=c++20 -O2 -Wall -Wextra -Wno-missing-field-initializers -I"$ROOT/build/vulkan-include" -shared -static -static-libgcc -static-libstdc++ \
"$ROOT/tools/d4r_nvngx_shim.cpp" "$ROOT/tools/d4r_ngx_param_host.cpp" "$PARAM_OBJECT" \
-o "$ROOT/build/d4r_nvngx.dll"
printf 'Built %s\n' "$ROOT/build/d4r_nvngx.dll"
-20
View File
@@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
ROCM_ROOT="${ROCM_ROOT:-/opt/rocm}"
if [[ ! -f "$ROCM_ROOT/include/hip/hip_runtime_api.h" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ROCM_ROOT to a ROCm installation containing HIP headers and libamdhip64.so\n' >&2
exit 2
fi
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra -D__HIP_PLATFORM_AMD__=1 \
-I"$ROCM_ROOT/include" \
"$ROOT/tools/hip_vk_interop_probe.cpp" \
-L"$ROCM_ROOT/lib" -lamdhip64 -lvulkan \
-Wl,-rpath,"$ROCM_ROOT/lib" \
-o "$ROOT/build/hip_vk_interop_probe"
printf 'Built %s\n' "$ROOT/build/hip_vk_interop_probe"
-21
View File
@@ -1,21 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
CLANG_CL="${CLANG_CL:-clang-cl}"
if [[ -z "${NVSDK_NGX_INCLUDE:-}" || ! -f "$NVSDK_NGX_INCLUDE/nvsdk_ngx.h" ]]; then
printf '%s\n' "Set NVSDK_NGX_INCLUDE to a directory containing NVIDIA's nvsdk_ngx.h and nvsdk_ngx_defs.h" >&2
exit 2
fi
mkdir -p "$ROOT/build"
ABI_OBJECT="$ROOT/build/ngx_param_abi_probe_msvc.obj"
"$CLANG_CL" --target=x86_64-pc-windows-msvc /nologo /std:c++20 /O2 /c /GS- /GR- /EHs-c- /Zl \
"/Fo$ABI_OBJECT" "$ROOT/tools/ngx_param_abi_probe_msvc.cpp"
"$MINGW_CXX" -std=c++20 -O2 -Wall -Wextra -static -static-libgcc -static-libstdc++ \
-I"$NVSDK_NGX_INCLUDE" \
"$ROOT/tools/ngx_cuda_probe.cpp" "$ABI_OBJECT" \
-o "$ROOT/build/ngx_cuda_probe.exe"
printf 'Built %s\n' "$ROOT/build/ngx_cuda_probe.exe"
-17
View File
@@ -1,17 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
if [[ -z "${NVSDK_NGX_INCLUDE:-}" || ! -f "$NVSDK_NGX_INCLUDE/nvsdk_ngx.h" ]]; then
printf '%s\n' "Set NVSDK_NGX_INCLUDE to a directory containing NVIDIA's nvsdk_ngx.h and nvsdk_ngx_defs.h" >&2
exit 2
fi
mkdir -p "$ROOT/build"
"$MINGW_CXX" -std=c++20 -O2 -Wall -Wextra -static -static-libgcc -static-libstdc++ \
-I"$NVSDK_NGX_INCLUDE" \
"$ROOT/tools/ngx_d3d12_probe.cpp" \
-o "$ROOT/build/ngx_d3d12_probe.exe"
printf 'Built %s\n' "$ROOT/build/ngx_d3d12_probe.exe"
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
mkdir -p "$ROOT/build"
"$MINGW_CXX" -std=c++20 -O2 -Wall -Wextra -Werror \
"$ROOT/tools/ngx_load_probe.cpp" \
-o "$ROOT/build/ngx_load_probe.exe"
printf 'Built %s\n' "$ROOT/build/ngx_load_probe.exe"
-23
View File
@@ -1,23 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
if [[ -z "${NVSDK_NGX_INCLUDE:-}" || ! -f "$NVSDK_NGX_INCLUDE/nvsdk_ngx_vk.h" ]]; then
printf '%s\n' "Set NVSDK_NGX_INCLUDE to a directory containing NVIDIA's nvsdk_ngx_vk.h and nvsdk_ngx_defs.h" >&2
exit 2
fi
VULKAN_INCLUDE="${VULKAN_INCLUDE:-$(dirname "$NVSDK_NGX_INCLUDE")/vulkan/include}"
if [[ ! -f "$VULKAN_INCLUDE/vulkan/vulkan.h" ]]; then
printf '%s\n' "Set VULKAN_INCLUDE to a Windows-target Vulkan-Headers include root" >&2
exit 2
fi
mkdir -p "$ROOT/build"
"$MINGW_CXX" -std=c++20 -O2 -Wall -Wextra -static -static-libgcc -static-libstdc++ \
-I"$NVSDK_NGX_INCLUDE" -I"$VULKAN_INCLUDE" \
"$ROOT/tools/ngx_vulkan_probe.cpp" \
-o "$ROOT/build/ngx_vulkan_probe.exe"
printf 'Built %s\n' "$ROOT/build/ngx_vulkan_probe.exe"
-111
View File
@@ -1,111 +0,0 @@
#!/usr/bin/env bash
# Run inside packaging/build/Dockerfile.glibc241 with a recent official Rust toolchain and ROCm mounted.
# Supply isolated, patched ZLUDA/vkd3d checkouts and the usual package_release.sh inputs.
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
: "${D4R_RELEASE_BUILD_ROOT:?set the build output directory}"
: "${D4R_ZLUDA_SRC:?set a build-local ZLUDA checkout with patches 0002-0007 applied}"
: "${D4R_VKD3D_SRC:?set a build-local vkd3d-proton checkout with patches 0001 and 0002 applied}"
: "${D4R_ROCM_DIR:?set ROCm with clang and device libraries}"
BUILD="$(realpath -m "$D4R_RELEASE_BUILD_ROOT")"
[[ "$(getconf GNU_LIBC_VERSION)" == 'glibc 2.41' ]] || {
echo "This release build requires GLIBC 2.41; use the pinned Debian build image" >&2; exit 2;
}
# Helper generation modifies its source checkout. Refuse the external source-cache directory.
case "$(realpath "$D4R_ZLUDA_SRC")" in "$BUILD"/*) ;; *) echo "ZLUDA source must be inside $BUILD" >&2; exit 2 ;; esac
case "$(realpath "$D4R_VKD3D_SRC")" in "$BUILD"/*) ;; *) echo "vkd3d source must be inside $BUILD" >&2; exit 2 ;; esac
mkdir -p "$BUILD/logs"
for source in "$D4R_ZLUDA_SRC/ext/llvm-project/llvm/CMakeLists.txt" "$D4R_ZLUDA_SRC/ext/HiGHS/CMakeLists.txt"; do
[[ -f "$source" ]] || { echo "missing pinned source submodule: $source" >&2; exit 2; }
done
export CARGO_TARGET_DIR="$BUILD/zluda-target"
export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-8}"
export CMAKE_BUILD_PARALLEL_LEVEL="$CARGO_BUILD_JOBS"
export LIBRARY_PATH="$D4R_ROCM_DIR/lib${D4R_ROCM_LINK_STUBS:+:$D4R_ROCM_LINK_STUBS}"
export LD_LIBRARY_PATH="$D4R_ROCM_DIR/lib"
export HIP_PATH="$D4R_ROCM_DIR"
export ROCM_PATH="$D4R_ROCM_DIR"
export HIP_CLANG_PATH="$D4R_ROCM_DIR/lib/llvm/bin"
{
getconf GNU_LIBC_VERSION
rustc --version
cargo --version
gcc --version | head -1
winegcc --version | head -1
"$D4R_ROCM_DIR/lib/llvm/bin/clang++" --version | head -1
} > "$BUILD/toolchain.txt"
ZLUDA_SOURCE_ROOT="$D4R_ZLUDA_SRC" ROCM_ROOT="$D4R_ROCM_DIR" \
D4R_ZLUDA_PTX_HELPER_WORK="$BUILD/helpers" "$ROOT/scripts/build_zluda_ptx_helpers.sh" \
> "$BUILD/logs/helpers.log" 2>&1
echo 'Device helpers rebuilt'
(cd "$D4R_ZLUDA_SRC" && cargo build --offline --locked --release -p zluda \
&& cargo build --offline --locked --release -p ptx --example d4r_emit) \
> "$BUILD/logs/zluda.log" 2>&1
export D4R_ZLUDA_DIR="$CARGO_TARGET_DIR/release"
export D4R_ZLUDA_EMIT="$D4R_ZLUDA_DIR/examples/d4r_emit"
"$ROOT/scripts/check_glibc_compat.sh" 2.41 "$D4R_ZLUDA_DIR/libnvcuda.so"
echo 'ZLUDA and the offline emitter rebuilt; GLIBC check passed'
# A minimal ROCm compiler extraction may omit lld. Use the matching LLVM built above so
# all GPU targets link with the same AMDGPU/ELF support, inside the compatible environment.
for llvm_build in "$CARGO_TARGET_DIR"/release/build/llvm_zluda-*/out/build; do
[[ -f "$llvm_build/build.ninja" ]] || continue
ninja -j "$CARGO_BUILD_JOBS" -C "$llvm_build" lld > "$BUILD/logs/lld.log" 2>&1
export PATH="$llvm_build/bin:$PATH"
break
done
command -v lld >/dev/null || { echo 'missing AMDGPU linker' >&2; exit 2; }
"$ROOT/scripts/build_d4r_nvngx_shim.sh" > "$BUILD/logs/shim.log" 2>&1
"$ROOT/scripts/build_wine_nvcuda_bridge.sh" > "$BUILD/logs/bridge.log" 2>&1
"$ROOT/scripts/check_glibc_compat.sh" 2.41 "$ROOT/build/wine-nvcuda/x86_64-unix/nvcuda.dll.so"
if [[ ! -f "$BUILD/vkd3d-build/build.ninja" ]]; then
meson setup --cross-file "$D4R_VKD3D_SRC/build-win64.txt" --buildtype release \
-Denable_tests=false "$BUILD/vkd3d-build" "$D4R_VKD3D_SRC" > "$BUILD/logs/vkd3d.log" 2>&1
fi
ninja -j "$CARGO_BUILD_JOBS" -C "$BUILD/vkd3d-build" >> "$BUILD/logs/vkd3d.log" 2>&1
export D4R_VKD3D_DIR="$BUILD/vkd3d"
mkdir -p "$D4R_VKD3D_DIR"
x86_64-w64-mingw32-strip -o "$D4R_VKD3D_DIR/d3d12.dll" "$BUILD/vkd3d-build/libs/d3d12/d3d12.dll"
x86_64-w64-mingw32-strip -o "$D4R_VKD3D_DIR/d3d12core.dll" "$BUILD/vkd3d-build/libs/d3d12core/d3d12core.dll"
echo 'Shim, bridge and vkd3d-proton rebuilt'
export D4R_BUNDLE_TEX="$BUILD/kernels"
export D4R_DLSS_PTX_DIR="$BUILD/ptx"
python3 "$ROOT/kernels/tools/extract_dlss_ptx.py" "$D4R_BUNDLE_DLSS" "$D4R_DLSS_PTX_DIR" > "$BUILD/logs/extract.log"
build_textures() {
local arch="$1" folder fp8 accuracy out
folders=("$arch")
[[ "$arch" == gfx12* ]] && folders+=("$arch-fp8")
for folder in "${folders[@]}"; do
fp8=0
[[ "$folder" == *-fp8 ]] && fp8=1
for accuracy in 0 1; do
out="$D4R_BUNDLE_TEX/$folder"
[[ "$accuracy" == 1 ]] && out="$D4R_BUNDLE_TEX/accuracy/$folder"
D4R_PREFER_ACCURACY="$accuracy" D4R_GPU_ARCH="$arch" D4R_NATIVE_FP8="$fp8" \
D4R_DLSS_DLL="$D4R_BUNDLE_DLSS" "$ROOT/kernels/build.sh" tex "$out" \
> "$BUILD/logs/tex-$folder-$accuracy.log" 2>&1
echo "Texture kernels rebuilt: $folder accuracy=$accuracy"
done
done
}
pending=()
failed=0
for arch in ${D4R_GPU_ARCHS:-gfx1100 gfx1101 gfx1102 gfx1103 gfx1200 gfx1201}; do
build_textures "$arch" &
pending+=("$!")
if (( ${#pending[@]} >= 4 )); then
wait "${pending[0]}" || failed=1
pending=("${pending[@]:1}")
fi
done
for pid in "${pending[@]}"; do wait "$pid" || failed=1; done
[[ "$failed" == 0 ]] || { echo 'Texture target build failed' >&2; exit 1; }
python3 -m unittest discover -s "$ROOT/tests" -v > "$BUILD/logs/tests.log" 2>&1
export D4R_SKIP_BUILD=1
export D4R_MAX_GLIBC=2.41
export D4R_BUILD_INFO="$BUILD/toolchain.txt"
export D4R_PACKAGE_KERNEL_JOBS=4
"$ROOT/scripts/package_release.sh" "$BUILD/dist" > "$BUILD/logs/package.log" 2>&1
echo "Release packaged in $BUILD/dist"
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra \
"$ROOT/tools/replay_dlss_fp8_ops.cpp" -ldl \
-o "$ROOT/build/replay_dlss_fp8_ops"
printf 'Built %s\n' "$ROOT/build/replay_dlss_fp8_ops"
-18
View File
@@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
ROCM_ROOT="${ROCM_ROOT:-/opt/rocm}"
if [[ ! -f "$ROCM_ROOT/include/hip/hip_runtime_api.h" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ROCM_ROOT to a ROCm installation containing HIP headers and libamdhip64.so\n' >&2
exit 2
fi
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra -D__HIP_PLATFORM_AMD__=1 \
-I"$ROCM_ROOT/include" \
"$ROOT/tools/replay_dlss_histogram.cpp" -L"$ROCM_ROOT/lib" -lamdhip64 -ldl \
-Wl,-rpath,"$ROCM_ROOT/lib" \
-o "$ROOT/build/replay_dlss_histogram"
printf 'Built %s\n' "$ROOT/build/replay_dlss_histogram"
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra \
"$ROOT/tools/replay_dlss_kernel.cpp" -ldl \
-o "$ROOT/build/replay_dlss_kernel"
printf 'Built %s\n' "$ROOT/build/replay_dlss_kernel"
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra \
"$ROOT/tools/replay_dlss_layer.cpp" -ldl \
-o "$ROOT/build/replay_dlss_layer"
printf 'Built %s\n' "$ROOT/build/replay_dlss_layer"
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra \
"$ROOT/tools/replay_dlss_surface_half_store.cpp" -ldl \
-o "$ROOT/build/replay_dlss_surface_half_store"
printf 'Built %s\n' "$ROOT/build/replay_dlss_surface_half_store"
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra \
"$ROOT/tools/replay_dlss_surface_store.cpp" -ldl \
-o "$ROOT/build/replay_dlss_surface_store"
printf 'Built %s\n' "$ROOT/build/replay_dlss_surface_store"
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CXX="${CXX:-g++}"
mkdir -p "$ROOT/build"
"$CXX" -std=c++20 -O2 -Wall -Wextra \
"$ROOT/tools/replay_dlss_texture_sample.cpp" -ldl \
-o "$ROOT/build/replay_dlss_texture_sample"
printf 'Built %s\n' "$ROOT/build/replay_dlss_texture_sample"
-30
View File
@@ -1,30 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Builds vkd3d-proton with patches/vkd3d-proton/ applied (split command lists
# for the shim's same-frame DLSS, D4R_SHIM_SPLIT_FRAME) into OUT_DIR, which
# the game launcher takes as D4R_VKD3D_DIR.
# usage: build_vkd3d_proton_d4r.sh OUT_DIR
# Env: VKD3D_PROTON_SRC (clone, default ~/.cache/d4r-vkd3d-proton),
# VKD3D_PROTON_COMMIT (default 3dfc6f07, the base GE-Proton11-3 ships).
if [[ $# -ne 1 ]]; then
printf 'usage: %s OUT_DIR\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
OUT="$(realpath -m "$1")"
SRC="${VKD3D_PROTON_SRC:-$HOME/.cache/d4r-vkd3d-proton}"
COMMIT="${VKD3D_PROTON_COMMIT:-3dfc6f07}"
BUILD="$SRC-build"
[[ -d "$SRC/.git" ]] || git clone https://github.com/HansKristian-Work/vkd3d-proton.git "$SRC"
# -f: the clone is a build cache; the patch is reapplied below.
git -C "$SRC" checkout -q -f -B d4r-split "$COMMIT"
git -C "$SRC" submodule update --init --recursive -q
git -C "$SRC" apply "$ROOT"/patches/vkd3d-proton/*.patch
[[ -d "$BUILD" ]] || meson setup --cross-file "$SRC/build-win64.txt" --buildtype release -Denable_tests=false "$BUILD" "$SRC"
ninja -C "$BUILD"
mkdir -p "$OUT"
x86_64-w64-mingw32-strip -o "$OUT/d3d12.dll" "$BUILD/libs/d3d12/d3d12.dll"
x86_64-w64-mingw32-strip -o "$OUT/d3d12core.dll" "$BUILD/libs/d3d12core/d3d12core.dll"
printf 'Built %s/d3d12.dll and d3d12core.dll\n' "$OUT"
-21
View File
@@ -1,21 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WINEGCC="${WINEGCC:-winegcc}"
WINEBUILD="${WINEBUILD:-winebuild}"
BRIDGE_ROOT="$ROOT/build/wine-nvcuda"
mkdir -p "$BRIDGE_ROOT/x86_64-unix" "$BRIDGE_ROOT/x86_64-windows"
MOTION_FLAGS=()
if [[ -x "${D4R_ROCM_DIR:-/opt/rocm}/lib/llvm/bin/clang++" ]]; then
"$ROOT/scripts/build_d4r_motion_kernels.sh" "$BRIDGE_ROOT/generated"
MOTION_FLAGS=(-DD4R_MOTION_KERNELS -I"$BRIDGE_ROOT/generated")
fi
"$WINEGCC" -m64 -shared -o "$BRIDGE_ROOT/x86_64-unix/nvcuda.dll" \
"${MOTION_FLAGS[@]}" \
"$ROOT/tools/wine_nvcuda_bridge.c" \
-Wb,--export="$ROOT/tools/wine_nvcuda_bridge.spec" -ldl -lpthread
"$WINEBUILD" --dll --fake-module -E "$ROOT/tools/wine_nvcuda_bridge.spec" \
-F nvcuda.dll -b x86_64-windows -o "$BRIDGE_ROOT/x86_64-windows/nvcuda.dll"
printf 'Built Wine nvcuda bridge in %s\n' "$BRIDGE_ROOT"
-64
View File
@@ -1,64 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ZLUDA_SOURCE_ROOT="${ZLUDA_SOURCE_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-/opt/rocm}"
HIPCC="${HIPCC:-$ROCM_ROOT/bin/hipcc}"
LLVM_DIS="${LLVM_DIS:-$ROCM_ROOT/lib/llvm/bin/llvm-dis}"
LLVM_AS="${LLVM_AS:-$ROCM_ROOT/lib/llvm/bin/llvm-as}"
OCML="${OCML:-$ROCM_ROOT/amdgcn/bitcode/ocml.bc}"
WORK_ROOT="${D4R_ZLUDA_PTX_HELPER_WORK:-${TMPDIR:-/tmp}/d4r-zluda-ptx-helpers}"
# D4R_ZLUDA_HELPER_FLAGS: extra compiler flags, e.g. -DD4R_WMMA12_SHIM for the gfx12-layout test build (never
# ship it: its gfx12 helpers use gfx11 WMMAs)
read -r -a EXTRA_FLAGS <<< "${D4R_ZLUDA_HELPER_FLAGS:-}"
if [[ -z "$ZLUDA_SOURCE_ROOT" || ! -f "$ZLUDA_SOURCE_ROOT/ptx/lib/zluda_ptx_impl.cpp" ]]; then
printf 'Set ZLUDA_SOURCE_ROOT to a ZLUDA source checkout\n' >&2
exit 2
fi
for dependency in "$HIPCC" "$LLVM_DIS" "$LLVM_AS" "$OCML"; do
if [[ ! -e "$dependency" ]]; then
printf 'Required ROCm/LLVM helper is missing: %s\n' "$dependency" >&2
exit 2
fi
done
mkdir -p "$WORK_ROOT"
SOURCE="$ZLUDA_SOURCE_ROOT/ptx/lib/zluda_ptx_impl.cpp"
PTX_LIB="$ZLUDA_SOURCE_ROOT/ptx/lib"
COMMON_FLAGS=(-DHIP_ENABLE_WARP_SYNC_BUILTINS -std=c++20 -Xclang -fdenormal-fp-math=dynamic
--rocm-path="$ROCM_ROOT" -I"$ROCM_ROOT/include"
-Wall -Wextra -Wsign-compare -Wconversion -x hip "$SOURCE" -nogpulib -O3
-mno-wavefrontsize64 --offload-device-only --offload-arch=gfx1030 -emit-llvm -c
-Xclang -mlink-bitcode-file -Xclang "$OCML" "${EXTRA_FLAGS[@]}")
build_one() {
local suffix="$1"
shift
local raw="$WORK_ROOT/zluda_ptx_impl${suffix}.raw.bc"
local clean="$WORK_ROOT/zluda_ptx_impl${suffix}.clean.bc"
local ll="$WORK_ROOT/zluda_ptx_impl${suffix}.ll"
local output="$PTX_LIB/zluda_ptx_impl${suffix}.bc"
"$HIPCC" "${COMMON_FLAGS[@]}" "$@" -o "$raw"
"$LLVM_DIS" "$raw" -o "$ll"
sed -E \
-e '/@llvm.used/d' \
-e '/wchar_size/d' \
-e '/llvm.module.flags/d' \
-e '/__hip_cuid/d' \
-e 's/optnone//g' \
-e 's/define hidden/define linkonce_odr/g' \
-e 's/"target-cpu"="gfx1030"//g' \
-e 's/"target-features"="[^"]+"//g' "$ll" |
"$LLVM_AS" -o "$clean" -
mv "$clean" "$output"
printf 'Wrote %s (%s bytes)\n' "$output" "$(stat -c '%s' "$output")"
}
build_one ""
build_one "_constrained" -ffp-model=strict -ffp-exception-behavior=ignore
# wave64 helpers (D4R_ZLUDA_WAVE64: two CUDA warps per wave; see d4r_warp_base in zluda_ptx_impl.cpp)
build_one "_w64" -mwavefrontsize64 -DD4R_WAVE64
build_one "_constrained_w64" -ffp-model=strict -ffp-exception-behavior=ignore -mwavefrontsize64 -DD4R_WAVE64
-59
View File
@@ -1,59 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
section() {
printf '\n## %s\n' "$1"
}
show_if_available() {
local tool="$1"
shift
if command -v "$tool" >/dev/null 2>&1; then
"$tool" "$@" 2>&1 || true
else
printf '%s: not found\n' "$tool"
fi
}
section 'Operating system'
uname -a
section 'Display adapters and kernel drivers'
show_if_available lspci -nnk | rg -A4 -i 'vga|3d|display' || true
section 'ROCm / HIP'
show_if_available rocminfo | head -80 || true
show_if_available hipcc --version | head -20 || true
if command -v rocm-smi >/dev/null 2>&1; then
rocm-smi --showproductname --showdriverversion 2>&1 | head -50 || true
elif [[ -x /opt/rocm/bin/rocm-smi ]]; then
/opt/rocm/bin/rocm-smi --showproductname --showdriverversion 2>&1 | head -50 || true
fi
section 'Vulkan'
if command -v vulkaninfo >/dev/null 2>&1; then
vulkaninfo --summary 2>&1 | rg -i 'VULKANINFO|Instance Version|GPU[0-9]|apiVersion|driverVersion|vendorID|deviceID|deviceName|driverID|driverName|driverInfo' || true
else
printf 'vulkaninfo: not found\n'
fi
section 'Wine / Proton'
show_if_available wine --version
show_if_available protontricks --version
find "$HOME/.local/share/Steam/compatibilitytools.d" -maxdepth 3 -type f -name proton -print 2>/dev/null | head -20 || true
section 'Build and PE inspection tools'
for tool in x86_64-w64-mingw32-g++ cmake ninja llvm-objdump llvm-readobj objdump strings; do
if command -v "$tool" >/dev/null 2>&1; then
printf '%-28s %s\n' "$tool" "$(command -v "$tool")"
else
printf '%-28s %s\n' "$tool" 'not found'
fi
done
section 'Installed relevant Arch packages'
if command -v pacman >/dev/null 2>&1; then
pacman -Q 2>/dev/null | rg -i '(^| )(rocm|hip|vulkan|wine|mingw|clang|mesa)(-| )' || true
else
printf 'pacman: not found\n'
fi
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/env bash
# Reject Linux release libraries that need a newer GLIBC than the target runtime.
# Usage: check_glibc_compat.sh MAX_GLIBC LIBRARY [LIBRARY ...]
set -euo pipefail
if [[ $# -lt 2 || ! "$1" =~ ^[0-9]+\.[0-9]+$ ]]; then
printf 'usage: %s MAX_GLIBC LIBRARY [LIBRARY ...]\n' "$0" >&2
exit 2
fi
max="GLIBC_$1"
shift
command -v readelf >/dev/null || { echo 'readelf is required to check GLIBC compatibility' >&2; exit 2; }
failed=0
for library in "$@"; do
if [[ ! -f "$library" ]]; then
printf 'missing library: %s\n' "$library" >&2
failed=1
continue
fi
if ! versions="$(readelf -W --version-info "$library" 2>&1)"; then
printf 'cannot inspect %s: %s\n' "$library" "$versions" >&2
failed=1
continue
fi
required="$(printf '%s\n' "$versions" | grep -Eo 'GLIBC_[0-9]+\.[0-9]+' | sort -Vu | tail -1 || true)"
if [[ -n "$required" && "$(printf '%s\n%s\n' "$max" "$required" | sort -Vu | tail -1)" != "$max" ]]; then
printf '%s requires %s (target: at most %s)\n' "$library" "$required" "$max" >&2
failed=1
fi
done
exit "$failed"
-210
View File
@@ -1,210 +0,0 @@
#!/usr/bin/env python3
"""Translate d4r.ini (see config/d4r.ini.default) into shell exports for the game launcher.
usage: d4r_config.py [--config PATH] [--print | --launch]
Prints "export VAR=value" lines for every setting the INI decides, skipping variables that are
already set in the environment (explicit environment always wins). --print lists the resulting
settings for humans instead. Without --config: $D4R_CONFIG, else ~/.config/d4r/d4r.ini, which is
created from config/d4r.ini.default on first use.
"""
import configparser
import os
import shlex
import shutil
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
DEFAULT_TEMPLATE = ROOT / "config" / "d4r.ini.default"
PRESETS = {"A": 1, "B": 2, "C": 3, "D": 4, "E": 5, "F": 6, "G": 7, "J": 10, "K": 11, "L": 12, "M": 13}
# friendly names for [DLSS] Model
MODEL_ALIASES = {"CNN": "E", "DLSS3": "E", "DLSS4": "K", "DLSS4.5": "M", "TRANSFORMER": "K"}
def fail(message):
print(f"d4r config: {message}", file=sys.stderr)
sys.exit(2)
def config_path(argv):
if "--config" in argv:
return Path(argv[argv.index("--config") + 1]).expanduser()
if os.environ.get("D4R_CONFIG"):
return Path(os.environ["D4R_CONFIG"]).expanduser()
path = Path.home() / ".config" / "d4r" / "d4r.ini"
if not path.exists() and DEFAULT_TEMPLATE.exists():
path.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(DEFAULT_TEMPLATE, path)
print(f"d4r config: created {path} from the default template; edit it to change settings",
file=sys.stderr)
return path
def main(argv):
path = config_path(argv)
ini = configparser.ConfigParser(inline_comment_prefixes=(";", "#"), interpolation=None)
ini.optionxform = str # keep [Env] variable names as written
if path.exists():
ini.read(path)
def get(section, key):
value = ini.get(section, key, fallback="").strip()
return None if value == "" or value.lower() == "auto" else value
def flag(section, key):
value = get(section, key)
if value is None:
return None
if value.lower() in ("1", "true", "yes", "on"):
return True
if value.lower() in ("0", "false", "no", "off"):
return False
fail(f"[{section}] {key} must be true or false, not {value!r}")
def path_value(section, key):
value = get(section, key)
return os.path.expanduser(value) if value else None
if "--launch" in argv:
# PROTON_DIR, COMPAT_DATA_DIR and GAME_EXE for scripts/d4r_play.sh, one per line
values = [path_value("Launch", key) for key in ("ProtonDir", "CompatDataDir", "GameExe")]
missing = [key for key, value in zip(("ProtonDir", "CompatDataDir", "GameExe"), values) if not value]
if missing:
fail(f"set [Launch] {', '.join(missing)} in {path}")
print("\n".join(values))
return
env = {}
env["D4R_PREFER_ACCURACY"] = "1" if flag("Kernels", "PreferAccuracy") else "0"
model = get("DLSS", "Model")
if model is not None:
if model.isdigit():
env["D4R_DLSS_PRESET"] = model
elif model.upper() in PRESETS or model.upper() in MODEL_ALIASES:
env["D4R_DLSS_PRESET"] = str(PRESETS[MODEL_ALIASES.get(model.upper(), model.upper())])
else:
fail(f"[DLSS] Model {model!r}: use one of {', '.join(list(PRESETS) + list(MODEL_ALIASES))} or a preset number")
age = get("Latency", "FrameAge")
if age is not None:
if age not in ("0", "1", "2", "3"):
fail(f"[Latency] FrameAge must be 0-3, not {age!r}")
if age == "0":
# same-frame results: the game's command list is split around DLSS (patched vkd3d-proton)
env["D4R_SHIM_SPLIT_FRAME"] = "1"
else:
env["D4R_SHIM_SPLIT_FRAME"] = "0"
env["D4R_SHIM_MAX_IN_FLIGHT"] = age
for key, var in (("RuntimeDir", "D4R_RUNTIME_DIR"), ("ZludaDir", "D4R_ZLUDA_DIR"), ("RocmDir", "D4R_ROCM_DIR"),
("VkD3DDir", "D4R_VKD3D_DIR")):
value = path_value("Paths", key)
if value:
env[var] = value
# JIT caches (ZLUDA's compiled kernels among them): a directory, or per-zluda for the one the test
# runs warm for each ZLUDA build (~/.cache/d4r-perf-game-jit-<ZludaDir name>)
jit = get("Paths", "JitCacheDir")
if jit is not None:
if jit.lower() == "per-zluda":
zluda = env.get("D4R_ZLUDA_DIR") or os.environ.get("D4R_ZLUDA_DIR")
if not zluda:
fail("[Paths] JitCacheDir = per-zluda needs [Paths] ZludaDir")
jit = f"~/.cache/d4r-perf-game-jit-{Path(zluda).name}"
env["XDG_CACHE_HOME"] = os.path.expanduser(jit)
if age == "0" and "D4R_VKD3D_DIR" not in env and not os.environ.get("D4R_VKD3D_DIR"):
print("d4r config: FrameAge = 0 needs [Paths] VkD3DDir (the d4r-patched vkd3d-proton); without it the "
"shim falls back to older frames", file=sys.stderr)
mode = (get("Kernels", "NativeKernels") or "off").lower()
if mode not in ("fast", "exact", "off"):
fail(f"[Kernels] NativeKernels must be fast, exact or off, not {mode!r}")
if mode != "off":
directory = path_value("Paths", "NativeKernelDirFast" if mode == "fast" else "NativeKernelDirExact")
if not directory:
fail(f"[Kernels] NativeKernels = {mode} needs [Paths] NativeKernelDir{mode.capitalize()}")
if not Path(directory).is_dir():
fail(f"native kernel directory {directory} does not exist")
env["D4R_ZLUDA_NATIVE_DIR"] = directory
for key, var in (("Fp8Wmma", "D4R_ZLUDA_WMMA_FP8"), ("IgnoreDenormals", "D4R_ZLUDA_IGNORE_DENORMAL")):
value = flag("Kernels", key)
if value is not None:
env[var] = "1" if value else "0"
# RDNA4's native FP8 WMMA (on unless set off; ZLUDA and the bridge ignore it on other GPUs)
value = flag("Kernels", "NativeFp8")
env["D4R_ZLUDA_WMMA_FP8_NATIVE"] = "0" if value is False else "1"
value = flag("Kernels", "NativeSwinEncoders")
env["D4R_NATIVE_SWIN_ENCODERS"] = "0" if value is False else "1"
value = get("Kernels", "ImplicitMaxBlock")
if value:
env["D4R_ZLUDA_IMPLICIT_MAX_BLOCK"] = value
for key, var in (("VramInterop", "D4R_SHIM_VRAM_INTEROP"), ("InputSync", "D4R_SHIM_INPUT_SYNC"),
("LinearInputs", "D4R_SHIM_LINEAR_INPUTS"),
("DirectOutput", "D4R_SHIM_OUTPUT_DIRECT"), ("ElideNgxSync", "D4R_ELIDE_NGX_SYNC"),
("EvalSync", "D4R_SHIM_EVAL_SYNC")):
value = flag("Interop", key)
if value is not None:
env[var] = "1" if value else "0"
value = get("Interop", "MarkerPollUs")
dilation = get("Interop", "MotionVectorDilation")
if dilation is not None and dilation not in ("0", "1", "2"):
fail("[Interop] MotionVectorDilation must be 0, 1 or 2")
env["D4R_MOTION_DILATION"] = dilation or "0"
if value:
if not value.isdigit():
fail(f"[Interop] MarkerPollUs must be a number of microseconds, not {value!r}")
env["D4R_SHIM_MARKER_POLL_US"] = value
engine = path_value("Game", "EngineIni")
cvars = get("Game", "Cvars")
if engine and cvars:
env["D4R_UE_ENGINE_INI"] = engine
env["D4R_UE_CVARS"] = cvars
value = flag("OptiScaler", "FpsOverlay")
if value is False:
env["D4R_OPTISCALER_FPS_OVERLAY_TYPE"] = "0"
env["D4R_OPTISCALER_SHOW_FPS"] = "false"
elif get("OptiScaler", "FpsOverlayType"):
env["D4R_OPTISCALER_FPS_OVERLAY_TYPE"] = get("OptiScaler", "FpsOverlayType")
if get("OptiScaler", "LogLevel"):
env["D4R_OPTISCALER_LOG_LEVEL"] = get("OptiScaler", "LogLevel")
extra = []
ratios = [(mode_name, get("OptiScaler", f"QualityRatio{mode_name}"))
for mode_name in ("Quality", "Balanced", "Performance", "UltraPerformance")]
if any(ratio for _, ratio in ratios):
extra.append("QualityOverrides.QualityRatioOverrideEnabled=true")
extra += [f"QualityOverrides.QualityRatio{name}={ratio}" for name, ratio in ratios if ratio]
if get("OptiScaler", "Extra"):
extra.append(get("OptiScaler", "Extra"))
if extra:
env["D4R_EXTRA_OPTISCALER_CONFIG"] = ";".join(extra)
if flag("Overlay", "MangoHud"):
env["MANGOHUD"] = "1"
if get("Overlay", "MangoHudConfig"):
env["MANGOHUD_CONFIG"] = get("Overlay", "MangoHudConfig")
if flag("Debug", "Profile"):
env["D4R_PROFILE"] = "1"
if path_value("Debug", "LogDir"):
env["D4R_GAME_LOG_DIR"] = path_value("Debug", "LogDir")
if ini.has_section("Env"):
for key, value in ini.items("Env"):
env[key] = value.strip()
final = {key: value for key, value in env.items() if key not in os.environ}
if "--print" in argv:
print(f"d4r config: {path}{'' if path.exists() else ' (missing: built-in defaults)'}")
for key in sorted(env):
note = "" if key in final else f" (environment wins: {os.environ[key]})"
print(f" {key}={env[key]}{note}")
return
for key, value in sorted(final.items()):
print(f"export {key}={shlex.quote(value)}")
if __name__ == "__main__":
main(sys.argv[1:])
-9
View File
@@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# One-command launch: runs the game configured in d4r.ini's [Launch] section with all d4r settings
# from the same file (see config/d4r.ini.default). Extra arguments go to the game.
# D4R_CONFIG=/path/to/other.ini scripts/d4r_play.sh
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
mapfile -t LAUNCH < <(python3 "$ROOT/scripts/d4r_config.py" --launch) || exit 2
[[ ${#LAUNCH[@]} -eq 3 ]] || exit 2
exec "$ROOT/scripts/run_game_d4r_optiscaler_proton.sh" "${LAUNCH[0]}" "${LAUNCH[1]}" "${LAUNCH[2]}" "$@"
-40
View File
@@ -1,40 +0,0 @@
# Source this to export the environment a Proton process needs to run
# official DLSS on AMD through d4r (ZLUDA + Wine CUDA bridge + NGX shim).
# Paths can be overridden before sourcing.
D4R_RUNTIME_DIR="${D4R_RUNTIME_DIR:-$HOME/.local/share/d4r-dlss}"
D4R_ZLUDA_DIR="${D4R_ZLUDA_DIR:-$HOME/.cache/d4r-zluda-current}"
# ROCm user-space runtime: a private copy under ~/.cache if present, otherwise the system /opt/rocm
if [[ -z "${D4R_ROCM_DIR:-}" ]]; then
D4R_ROCM_DIR="$HOME/.cache/d4r-rocm-deps/root/opt/rocm"
[[ -d "$D4R_ROCM_DIR" ]] || D4R_ROCM_DIR=/opt/rocm
fi
d4r_winpath() { printf 'Z:%s' "$(printf '%s' "$1" | tr '/' '\\')"; }
# dxvk-nvapi on a non-NVIDIA driver, reporting Ada so NGX uploads the FP8
# network weights that match the sm_89 PTX ZLUDA compiles.
export PROTON_ENABLE_NVAPI=1
export DXVK_NVAPI_ALLOW_OTHER_DRIVERS=1
export DXVK_NVAPI_GPU_ARCH=AD100
# ZLUDA and the ROCm user-cache runtime.
export LD_LIBRARY_PATH="$D4R_ZLUDA_DIR:$D4R_ROCM_DIR/lib:$D4R_ROCM_DIR/lib/llvm/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export D4R_ZLUDA_LIBCUDA="$D4R_ZLUDA_DIR/libcuda.so"
# Kernels without PTX launch bounds (DLSS's convolutions) are compiled for at
# most 256-thread blocks, as CUDA itself allows 255 registers for them; the
# default 1024 bound caps gfx11 waves at 96 VGPRs and makes them spill.
export D4R_ZLUDA_IMPLICIT_MAX_BLOCK="${D4R_ZLUDA_IMPLICIT_MAX_BLOCK:-256}"
# f16 tensor-core MMAs (DLSS's convolutions) run on gfx11/gfx12 WMMA instead of a
# dot-product fallback (patches/zluda/0003 and 0007); 0 selects the fallback.
export D4R_ZLUDA_WMMA="${D4R_ZLUDA_WMMA:-1}"
# DLSS frames in flight. The presented upscaled image is this many game frames
# old at most: 3 = highest frame rate (Townfall ~86 fps, age 2-3), 2 = age 2
# (~75 fps), 1 = age 1, the lowest possible with the CPU staging path (~53 fps).
export D4R_SHIM_MAX_IN_FLIGHT="${D4R_SHIM_MAX_IN_FLIGHT:-3}"
# 1 keeps DLSS inputs and output in VRAM (vkd3d-proton Vulkan interop, no CPU
# staging): Townfall ~141 fps at age 2-3 with 3 in flight, ~113 fps at age 1
# with D4R_SHIM_MAX_IN_FLIGHT=1. Needs vkd3d-proton; falls back automatically.
export D4R_SHIM_VRAM_INTEROP="${D4R_SHIM_VRAM_INTEROP:-0}"
# Shim configuration (Windows paths inside the prefix).
export D4R_NVCUDA_BRIDGE="$(d4r_winpath "$D4R_RUNTIME_DIR/bin/nvcuda.dll")"
export D4R_NGX_CORE="${D4R_NGX_CORE:-$(d4r_winpath "$D4R_RUNTIME_DIR/ngx/_nvngx.dll")}"
export D4R_NGX_FEATURE_DIR="$(d4r_winpath "$D4R_RUNTIME_DIR/dlss")"
export D4R_SHIM_LOG="${D4R_SHIM_LOG:-$(d4r_winpath "$D4R_RUNTIME_DIR/d4r_nvngx.log")}"
-63
View File
@@ -1,63 +0,0 @@
#!/usr/bin/env bash
# Fetches the ROCm user-space runtime the release bundles in d4r/rocm: HIP, HSA, comgr and
# rocprofiler-register from AMD's ROCm 7.2.4 packages for Ubuntu 22.04, plus the libelf and libnuma
# they need, which Steam's container runtime lacks. These builds need only glibc 2.34, so they run
# in SteamLinuxRuntime_4 on any distribution (a rolling distribution's ROCm may need a newer glibc).
#
# usage: scripts/fetch_rocm_runtime.sh [OUT_DIR] (default: ~/.cache/d4r-rocm-runtime)
# Result: OUT_DIR/lib/<soname> for each library and OUT_DIR/licenses/.
set -euo pipefail
OUT="$(realpath -m "${1:-$HOME/.cache/d4r-rocm-runtime}")"
AMD=https://repo.radeon.com/rocm/apt/7.2.4/pool/main
UBUNTU=http://archive.ubuntu.com/ubuntu/pool/main
# url sha256
PACKAGES=(
"$AMD/h/hip-runtime-amd/hip-runtime-amd_7.2.53211.70204-93~22.04_amd64.deb 2b0fc15d4456bc35370f33672b202b43f2af1aceac47a42c22d1370b2f46968f"
"$AMD/c/comgr/comgr_3.0.0.70204-93~22.04_amd64.deb 58460d117131369a248d334ba749609abea8591cd05752ac572c9a10f31ac006"
"$AMD/h/hsa-rocr/hsa-rocr_1.18.0.70204-93~22.04_amd64.deb 7fccbb91e38fadd126538f15e02c66e20db717a60eb03f2a045e47497bf67405"
"$AMD/r/rocprofiler-register/rocprofiler-register_0.6.0.70204-93~22.04_amd64.deb c2780e37a7217329b5d3d40e682ae6979481b1a59b86415a0cdf849b9c142bfd"
"$UBUNTU/e/elfutils/libelf1_0.186-1ubuntu0.1_amd64.deb 2cc781614b045b450a1e073ee3b0902f393ee58ede1d2ea4526ad805fcccf538"
"$UBUNTU/n/numactl/libnuma1_2.0.14-3ubuntu2_amd64.deb 0721c89001fbbd1ada23e89da5d60e762763c1a7b3dc814a2e9a518480a8043d"
)
# soname, the file it names inside the packages
LIBRARIES=(
"libamdhip64.so.7 opt/rocm-7.2.4/lib/libamdhip64.so.7"
"libamd_comgr.so.3 opt/rocm-7.2.4/lib/libamd_comgr.so.3"
"libhsa-runtime64.so.1 opt/rocm-7.2.4/lib/libhsa-runtime64.so.1"
"librocprofiler-register.so.0 opt/rocm-7.2.4/lib/librocprofiler-register.so.0"
"libelf.so.1 usr/lib/x86_64-linux-gnu/libelf.so.1"
"libnuma.so.1 usr/lib/x86_64-linux-gnu/libnuma.so.1"
)
LICENSES=(
"HIP-LICENSE.md opt/rocm-7.2.4/share/doc/hip/LICENSE.md"
"comgr-LICENSE.txt opt/rocm-7.2.4/share/doc/amd_comgr/LICENSE.txt"
"ROCr-LICENSE.md opt/rocm-7.2.4/share/doc/hsa-rocr/LICENSE.md"
"rocprofiler-register-LICENSE.md opt/rocm-7.2.4/share/doc/rocprofiler-register/LICENSE.md"
"libelf-copyright.txt usr/share/doc/libelf1/copyright"
"libnuma-copyright.txt usr/share/doc/libnuma1/copyright"
)
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
mkdir -p "$TMP/root"
for entry in "${PACKAGES[@]}"; do
read -r url sha <<< "$entry"
deb="$TMP/$(basename "$url")"
curl -fsSL -o "$deb" "$url"
echo "$sha $deb" | sha256sum -c --quiet
data="$(ar t "$deb" | grep '^data\.tar')"
ar p "$deb" "$data" | tar -x -C "$TMP/root" -f - --use-compress-program="$(case "$data" in *.zst) echo zstd -d ;; *.xz) echo xz -d ;; *) echo gzip -d ;; esac)"
done
rm -rf "$OUT"
mkdir -p "$OUT/lib" "$OUT/licenses"
for entry in "${LIBRARIES[@]}"; do
read -r soname path <<< "$entry"
cp -L "$TMP/root/$path" "$OUT/lib/$soname"
done
for entry in "${LICENSES[@]}"; do
read -r name path <<< "$entry"
cp "$TMP/root/$path" "$OUT/licenses/$name"
done
printf 'ROCm runtime in %s (%s)\n' "$OUT" "$(du -sh "$OUT" | cut -f1)"
-29
View File
@@ -1,29 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Stages the pieces a Proton game needs under D4R_RUNTIME_DIR
# (default ~/.local/share/d4r-dlss):
# bin/nvcuda.dll Wine CUDA bridge (ELF builtin, preloaded by path by the shim)
# bin/d4r_nvngx.dll D3D12-to-CUDA NGX core shim (OptiScaler NvngxPath target)
# ngx/_nvngx.dll official NGX core
# dlss/nvngx_dlss.dll official DLSS SR feature DLL (also copied into bin/)
# usage: install_d4r_runtime.sh PATH_TO_NGX_CORE_DLL PATH_TO_NVNGX_DLSS_DLL
if [[ $# -ne 2 ]]; then
printf 'usage: %s PATH_TO_NGX_CORE_DLL PATH_TO_NVNGX_DLSS_DLL\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
RUNTIME="${D4R_RUNTIME_DIR:-$HOME/.local/share/d4r-dlss}"
"$ROOT/scripts/build_d4r_nvngx_shim.sh"
"$ROOT/scripts/build_wine_nvcuda_bridge.sh"
mkdir -p "$RUNTIME/bin" "$RUNTIME/ngx" "$RUNTIME/dlss"
cp -f "$ROOT/build/wine-nvcuda/x86_64-unix/nvcuda.dll.so" "$RUNTIME/bin/nvcuda.dll"
cp -f "$ROOT/build/d4r_nvngx.dll" "$RUNTIME/bin/d4r_nvngx.dll"
copy_unless_same() { [[ "$(realpath "$1")" == "$(realpath -m "$2")" ]] || cp -f "$1" "$2"; }
copy_unless_same "$1" "$RUNTIME/ngx/_nvngx.dll"
copy_unless_same "$2" "$RUNTIME/dlss/nvngx_dlss.dll"
# The NGX core's CUDA init ignores the feature search paths it is given and
# scans the directory of the module that calls it, i.e. the shim's.
cp -f "$RUNTIME/dlss/nvngx_dlss.dll" "$RUNTIME/bin/nvngx_dlss.dll"
sha256sum "$RUNTIME"/ngx/_nvngx.dll "$RUNTIME"/dlss/nvngx_dlss.dll
printf 'Installed d4r runtime in %s\n' "$RUNTIME"
-252
View File
@@ -1,252 +0,0 @@
#!/usr/bin/env bash
# Builds the drag-in release: a zip whose contents are extracted into the folder that holds a game's
# main .exe, like an OptiScaler release. packaging/D4R_README.txt describes the result.
#
# usage: scripts/package_release.sh [OUT_DIR] (default: dist/)
#
# Inputs (environment):
# D4R_OPTISCALER OptiScaler release archive (.7z or .zip) or extracted folder (required; 0.9.4 tested)
# D4R_DLSS_DLLS colon-separated nvngx_dlss.dll files whose kernel code the native kernels accept
# (required; only hashes of their PTX go into the release)
# D4R_ZLUDA_DIR ZLUDA build with patches/zluda applied (libnvcuda.so) default ~/.cache/d4r-zluda-current
# D4R_VKD3D_DIR d4r-patched vkd3d-proton (d3d12.dll, d3d12core.dll) default ~/.cache/d4r-vkd3d-d4r
# D4R_ROCM_DIR ROCm with clang, for the kernels default /opt/rocm
# D4R_ROCM_RUNTIME ROCm runtime bundled as d4r/rocm (scripts/fetch_rocm_runtime.sh)
# default ~/.cache/d4r-rocm-runtime
# D4R_MAX_GLIBC highest GLIBC ABI the Linux libraries may require default 2.41
# D4R_GPU_ARCHS GPU targets to build kernels for default gfx1100 gfx1101 gfx1102 gfx1103 gfx1200 gfx1201
# (RDNA4 targets also get a <target>-fp8 folder: the kernels for d4r.ini NativeFp8 = on)
# D4R_OPTISCALER_LICENSE OptiScaler's LICENSE (GPL-3.0) text; default: the system's SPDX copy
# D4R_VKD3D_SRC vkd3d-proton source checkout, for its license files default ~/.cache/d4r-vkd3d-proton
# D4R_ZLUDA_SRC ZLUDA source checkout, for its license files default: D4R_ZLUDA_DIR's ../d4r-zluda-upstream
# SOURCE_DATE_EPOCH timestamp given to every packaged file default: the last commit's
# D4R_BUILD_INFO optional build-toolchain/provenance text to include in d4r/source/
# D4R_PACKAGE_KERNEL_JOBS independent target builds at once (default 1)
# The zip also contains NVIDIA's files and the texture kernels built from NVIDIA's PTX; redistributing
# those is up to whoever publishes it (they are not covered by d4r's license):
# D4R_BUNDLE_DLSS nvngx_dlss.dll to include D4R_BUNDLE_NGX _nvngx.dll to include
# D4R_BUNDLE_TEX directory with texture-kernel code objects (kernels/build.sh tex), one subdirectory
# per target folder (gfx1101, gfx1201, gfx1201-fp8, ...), or a flat gfx1101 directory for
# older builds
# Accuracy texture sets go in accuracy/<target>/, built with D4R_PREFER_ACCURACY=1.
# D4R_ZLUDA_EMIT d4r_emit from the patched ZLUDA build; required in full builds when an accuracy
# texture set or L's unfolded texture variants are not supplied in D4R_BUNDLE_TEX.
# D4R_BUNDLE_NVIDIA=0 leaves them out (d4r-VERSION-nonvidia.zip; users then add the two DLLs themselves).
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
OUT="$(realpath -m "${1:-$ROOT/dist}")"
VERSION="$(cat "$ROOT/packaging/VERSION")"
VARIANT=full
[[ "${D4R_BUNDLE_NVIDIA:-1}" == 0 ]] && VARIANT=clean
NAME="d4r-$VERSION"
[[ "$VARIANT" == clean ]] && NAME="$NAME-nonvidia"
STAGE="$OUT/$NAME"
ZLUDA="${D4R_ZLUDA_DIR:-$HOME/.cache/d4r-zluda-current}"
VKD3D="${D4R_VKD3D_DIR:-$HOME/.cache/d4r-vkd3d-d4r}"
ROCM="${D4R_ROCM_DIR:-/opt/rocm}"
ROCM_RUNTIME="${D4R_ROCM_RUNTIME:-$HOME/.cache/d4r-rocm-runtime}"
ARCHS="${D4R_GPU_ARCHS:-gfx1100 gfx1101 gfx1102 gfx1103 gfx1200 gfx1201}"
: "${D4R_OPTISCALER:?set D4R_OPTISCALER to the OptiScaler release archive or folder}"
: "${D4R_DLSS_DLLS:?set D4R_DLSS_DLLS to the nvngx_dlss.dll files the kernel manifest accepts}"
for f in "$ZLUDA/libnvcuda.so" "$VKD3D/d3d12.dll" "$VKD3D/d3d12core.dll" "$ROCM_RUNTIME/lib/libamdhip64.so.7"; do
[[ -f "$f" ]] || { echo "missing $f (the ROCm runtime comes from scripts/fetch_rocm_runtime.sh)" >&2; exit 2; }
done
# D4R_SKIP_BUILD=1 packages the shim and bridge already in build/ (e.g. the binaries that were tested)
if [[ "${D4R_SKIP_BUILD:-0}" != 1 ]]; then
"$ROOT/scripts/build_d4r_nvngx_shim.sh" >/dev/null
"$ROOT/scripts/build_wine_nvcuda_bridge.sh" >/dev/null
fi
rm -rf "$STAGE"
mkdir -p "$STAGE/d4r/zluda" "$STAGE/d4r/rocm" "$STAGE/d4r/ngx" "$STAGE/d4r/kernels" "$STAGE/d4r/licenses" "$STAGE/d4r/source"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
# OptiScaler, as dxgi.dll with its INI preconfigured for d4r
if [[ -d "$D4R_OPTISCALER" ]]; then
OPTI="$D4R_OPTISCALER"
else
OPTI="$TMP/optiscaler"
mkdir -p "$OPTI"
case "$D4R_OPTISCALER" in
*.7z) 7z x -y -o"$OPTI" "$D4R_OPTISCALER" >/dev/null ;;
*.zip) unzip -q -o "$D4R_OPTISCALER" -d "$OPTI" ;;
*) echo "D4R_OPTISCALER must be a .7z, a .zip or a folder" >&2; exit 2 ;;
esac
fi
cp "$OPTI/OptiScaler.dll" "$STAGE/dxgi.dll"
python3 - "$OPTI/OptiScaler.ini" "$ROOT/packaging/optiscaler.settings" "$STAGE/OptiScaler.ini" <<'PY'
import re, sys
lines = open(sys.argv[1], encoding="utf-8", newline="").read().split("\n") # keeps the file's line endings
for setting in open(sys.argv[2], encoding="utf-8"):
setting = setting.strip()
if not setting or setting.startswith("#"):
continue
path, value = setting.split("=", 1)
section, key = path.split(".", 1)
start = next((i for i, l in enumerate(lines) if l.strip() == f"[{section}]"), None)
if start is None:
sys.exit(f"OptiScaler.ini has no [{section}]")
end = next((i for i in range(start + 1, len(lines)) if lines[i].startswith("[")), len(lines))
for i in range(start + 1, end):
if re.match(rf"{re.escape(key)}\s*=", lines[i]):
lines[i] = f"{key}={value}" + ("\r" if lines[i].endswith("\r") else "")
break
else:
sys.exit(f"OptiScaler.ini has no {key} in [{section}]")
open(sys.argv[3], "w", encoding="utf-8", newline="").write("\n".join(lines))
PY
# d4r-patched vkd3d-proton: same-frame DLSS results
cp "$VKD3D/d3d12.dll" "$VKD3D/d3d12core.dll" "$STAGE/"
# d4r itself
cp "$ROOT/build/d4r_nvngx.dll" "$STAGE/d4r/nvngx.dll"
cp "$ROOT/build/wine-nvcuda/x86_64-unix/nvcuda.dll.so" "$STAGE/d4r/nvcuda.dll"
cp "$ZLUDA/libnvcuda.so" "$STAGE/d4r/zluda/libcuda.so"
cp -r "$ROCM_RUNTIME/lib" "$STAGE/d4r/rocm/lib"
"$ROOT/scripts/check_glibc_compat.sh" "${D4R_MAX_GLIBC:-2.41}" \
"$STAGE/d4r/nvcuda.dll" "$STAGE/d4r/zluda/libcuda.so" "$STAGE/d4r/rocm/lib/"*
cp "$ROOT/packaging/d4r.ini" "$STAGE/d4r/d4r.ini"
cp "$ROOT/packaging/d4r-check.sh" "$STAGE/d4r/d4r-check.sh"
if [[ "$VARIANT" == full ]]; then
: "${D4R_BUNDLE_DLSS:?set D4R_BUNDLE_DLSS}" "${D4R_BUNDLE_NGX:?set D4R_BUNDLE_NGX}" "${D4R_BUNDLE_TEX:?set D4R_BUNDLE_TEX}"
cp "$D4R_BUNDLE_DLSS" "$STAGE/d4r/nvngx_dlss.dll"
cp "$D4R_BUNDLE_NGX" "$STAGE/d4r/ngx/_nvngx.dll"
else
printf 'Put NVIDIA'"'"'s NGX runtime, _nvngx.dll, in this folder (see D4R_README.txt).\r\n' > "$STAGE/d4r/ngx/README.txt"
fi
IFS=: read -r -a DLLS <<< "$D4R_DLSS_DLLS"
# one folder per target; RDNA4 targets also get <target>-fp8 (native FP8 WMMA, d4r.ini NativeFp8), which the
# bridge serves instead when that setting is on
folders=()
for arch in $ARCHS; do
folders+=("$arch")
[[ "$arch" == gfx12* ]] && folders+=("$arch-fp8")
done
# Older texture bundles predate L. Complete them from the user's DLSS DLL rather
# than silently shipping only M's folded variants under the new L support claim.
ensure_l_textures() {
local dir="$1" accuracy="$2" missing=0 mv range v name
local names=(rrlite_dec0_4x4)
for mv in mvhi mvlo; do
for range in hdr ldr; do
names+=("rrlite_enc0_4x4_${mv}_${range}")
for v in 3_1 3_2; do names+=("rrlite_post_${v}_${mv}_${range}"); done
done
done
for name in "${names[@]}"; do [[ -f "$dir/$name.hsaco" ]] || missing=1; done
if [[ "$missing" == 1 ]]; then
: "${D4R_ZLUDA_EMIT:?set D4R_ZLUDA_EMIT or supply the unfolded L texture variants in D4R_BUNDLE_TEX}"
D4R_PREFER_ACCURACY="$accuracy" D4R_ROCM_DIR="$ROCM" D4R_GPU_ARCH="$arch" D4R_NATIVE_FP8="$fp8" \
D4R_DLSS_DLL="$D4R_BUNDLE_DLSS" "$ROOT/kernels/build.sh" l "$dir" >/dev/null
fi
}
build_target() {
local folder="$1" arch fp8 tex_dir accurate accurate_tex f
arch="${folder%-fp8}"
fp8=0
[[ "$folder" == *-fp8 ]] && fp8=1
D4R_PREFER_ACCURACY=0 D4R_ROCM_DIR="$ROCM" D4R_GPU_ARCH="$arch" D4R_NATIVE_FP8="$fp8" "$ROOT/kernels/build.sh" k "$STAGE/d4r/kernels/$folder" >/dev/null
D4R_PREFER_ACCURACY=0 D4R_ROCM_DIR="$ROCM" D4R_GPU_ARCH="$arch" D4R_NATIVE_FP8="$fp8" "$ROOT/kernels/build.sh" m "$STAGE/d4r/kernels/$folder" >/dev/null
rm -f "$STAGE/d4r/kernels/$folder"/*.resolution.txt # empty LTO notes from clang's -save-temps
if [[ "$VARIANT" == full ]]; then
tex_dir=""
if [[ -d "$D4R_BUNDLE_TEX/$folder" ]]; then
tex_dir="$D4R_BUNDLE_TEX/$folder"
elif [[ "$folder" == gfx1101 ]]; then
tex_dir="$D4R_BUNDLE_TEX" # older, flat gfx1101 texture-kernel builds
fi
if [[ -n "$tex_dir" ]]; then
for f in "$tex_dir"/*.hsaco; do # texture kernels only; the layers above are built from source
[[ -f "$f" ]] || continue
[[ -e "$STAGE/d4r/kernels/$folder/$(basename "$f")" ]] || cp "$f" "$STAGE/d4r/kernels/$folder/"
done
fi
fi
[[ "$VARIANT" != full ]] || ensure_l_textures "$STAGE/d4r/kernels/$folder" 0
python3 "$ROOT/kernels/tools/kernel_manifest.py" "$STAGE/d4r/kernels/$folder" "${DLLS[@]}"
# Every release target also gets conservative network and texture variants. Do not copy fast
# texture objects into this set: their compiler policy is fixed inside the binary.
accurate="$STAGE/d4r/kernels/accuracy/$folder"
D4R_PREFER_ACCURACY=1 D4R_ROCM_DIR="$ROCM" D4R_GPU_ARCH="$arch" D4R_NATIVE_FP8="$fp8" "$ROOT/kernels/build.sh" k "$accurate" >/dev/null
D4R_PREFER_ACCURACY=1 D4R_ROCM_DIR="$ROCM" D4R_GPU_ARCH="$arch" D4R_NATIVE_FP8="$fp8" "$ROOT/kernels/build.sh" m "$accurate" >/dev/null
if [[ "$VARIANT" == full ]]; then
accurate_tex="$D4R_BUNDLE_TEX/accuracy/$folder"
if [[ -f "$accurate_tex/d4r-accuracy.txt" && "$(cat "$accurate_tex/d4r-accuracy.txt")" == 1 ]]; then
for f in "$accurate_tex"/*.hsaco; do
[[ -f "$f" ]] || continue
[[ -e "$accurate/$(basename "$f")" ]] || cp "$f" "$accurate/"
done
else
: "${D4R_ZLUDA_EMIT:?set D4R_ZLUDA_EMIT or supply D4R_BUNDLE_TEX/accuracy/$folder}"
D4R_PREFER_ACCURACY=1 D4R_ROCM_DIR="$ROCM" D4R_GPU_ARCH="$arch" D4R_NATIVE_FP8="$fp8" \
D4R_DLSS_DLL="$D4R_BUNDLE_DLSS" "$ROOT/kernels/build.sh" tex "$accurate" >/dev/null
fi
fi
if [[ "$VARIANT" == full ]]; then
ensure_l_textures "$accurate" 1
for f in "$STAGE/d4r/kernels/$folder"/*.hsaco; do
[[ -f "$accurate/$(basename "$f")" ]] || {
echo "missing accuracy variant of $(basename "$f") for $folder" >&2; exit 2;
}
done
fi
rm -f "$accurate"/*.resolution.txt
python3 "$ROOT/kernels/tools/kernel_manifest.py" "$accurate" "${DLLS[@]}"
}
kernel_jobs="${D4R_PACKAGE_KERNEL_JOBS:-1}"
[[ "$kernel_jobs" =~ ^[1-9][0-9]*$ ]] || { echo "D4R_PACKAGE_KERNEL_JOBS must be positive" >&2; exit 2; }
pending=()
kernel_failed=0
for folder in "${folders[@]}"; do
build_target "$folder" &
pending+=("$!")
if (( ${#pending[@]} >= kernel_jobs )); then
wait "${pending[0]}" || kernel_failed=1
pending=("${pending[@]:1}")
fi
done
for pid in "${pending[@]}"; do wait "$pid" || kernel_failed=1; done
[[ "$kernel_failed" == 0 ]] || { echo "native target build failed; no release ZIP created" >&2; exit 1; }
# licenses and sources
ZLUDA_SRC="${D4R_ZLUDA_SRC:-$(dirname "$ZLUDA")/d4r-zluda-upstream}"
VKD3D_SRC="${D4R_VKD3D_SRC:-$HOME/.cache/d4r-vkd3d-proton}"
L="$STAGE/d4r/licenses"
cp "$ROOT/LICENSE" "$L/d4r-LICENSE.txt"
cp "$ROOT/NOTICE" "$L/d4r-NOTICE.txt"
cp "$ZLUDA_SRC/LICENSE-APACHE" "$L/ZLUDA-LICENSE-APACHE.txt"
cp "$ZLUDA_SRC/LICENSE-MIT" "$L/ZLUDA-LICENSE-MIT.txt"
cp "$ZLUDA_SRC/ext/llvm-project/llvm/LICENSE.TXT" "$L/LLVM-LICENSE.txt"
cp "$VKD3D_SRC/LICENSE" "$L/vkd3d-proton-LICENSE.txt"
cp "$VKD3D_SRC/COPYING" "$L/vkd3d-proton-COPYING.txt"
cp "${D4R_OPTISCALER_LICENSE:-/usr/share/licenses/spdx/GPL-3.0-only.txt}" "$L/OptiScaler-LICENSE-GPL-3.0.txt"
for f in "$ROCM_RUNTIME"/licenses/*; do cp "$f" "$L/ROCm-$(basename "$f")"; done
mkdir -p "$STAGE/d4r/source/patches"
cp -r "$ROOT/patches/zluda" "$ROOT/patches/vkd3d-proton" "$STAGE/d4r/source/patches/"
ZLUDA_COMMIT="$(git -C "$ZLUDA_SRC" rev-parse HEAD 2>/dev/null || echo unknown)"
VKD3D_COMMIT="$(git -C "$VKD3D_SRC" rev-parse HEAD 2>/dev/null || echo unknown)"
# "@clean " / "@full " lines belong to one variant only
variant() { sed -n -e "s/^@$VARIANT //" -e '/^@[a-z]* /d' -e p; }
file_version() { [[ -f "$1" ]] && strings -el "$1" | grep -A1 '^FileVersion$' | sed -n 2p | tr ',' '.' | tr -d ' '; }
sed -e "s/@VERSION@/$VERSION/g" -e "s/@ZLUDA_COMMIT@/$ZLUDA_COMMIT/g" -e "s/@VKD3D_COMMIT@/$VKD3D_COMMIT/g" \
-e "s/@DLSS_VERSION@/$(file_version "$STAGE/d4r/nvngx_dlss.dll")/g" -e "s/@NGX_VERSION@/$(file_version "$STAGE/d4r/ngx/_nvngx.dll")/g" \
"$ROOT/packaging/SOURCES.txt" | variant > "$STAGE/d4r/source/SOURCES.txt"
if [[ -n "${D4R_BUILD_INFO:-}" ]]; then
cp "$D4R_BUILD_INFO" "$STAGE/d4r/source/BUILD_INFO.txt"
fi
sed -e "s/@VERSION@/$VERSION/g" "$ROOT/packaging/D4R_README.txt" | variant | sed 's/$/\r/' > "$STAGE/D4R_README.txt"
# One timestamp for every file (SOURCE_DATE_EPOCH, default the last commit): ZLUDA's kernel cache is keyed on
# its library's size and mtime, so every extraction of the zip shares one cache.
EPOCH="${SOURCE_DATE_EPOCH:-$(git -C "$ROOT" log -1 --format=%ct)}"
find "$STAGE" -exec touch -h -d "@$EPOCH" {} +
# The zip holds the folder's contents, so it can be extracted straight into the game folder.
rm -f "$OUT/$NAME.zip"
(cd "$STAGE" && find . -type f | LC_ALL=C sort | sed 's|^\./||' | zip -q -X -9 "$OUT/$NAME.zip" -@)
(cd "$OUT" && sha256sum "$NAME.zip" > "$NAME.zip.sha256")
printf 'Built %s (%s)\n' "$OUT/$NAME.zip" "$(du -h "$OUT/$NAME.zip" | cut -f1)"
-20
View File
@@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# usage: run_bench_dlss_kernel.sh FATBIN REPLAY_DIR [ITERATIONS [OUTPUT_PREFIX]]
# Replays a launch captured with D4R_CUDA_REPLAY_DUMP_DIR (wine_nvcuda_bridge.c).
if [[ $# -lt 2 ]]; then
printf 'usage: %s FATBIN REPLAY_DIR [ITERATIONS [OUTPUT_PREFIX]]\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
if [[ -z "$ZLUDA_ROOT" || -z "$ROCM_ROOT" || ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the ZLUDA and HIP runtimes\n' >&2
exit 2
fi
[[ -x "$ROOT/build/bench_dlss_kernel" && "$ROOT/build/bench_dlss_kernel" -nt "$ROOT/tools/bench_dlss_kernel.cpp" ]] ||
"$ROOT/scripts/build_bench_dlss_kernel.sh" >/dev/null
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
"$ROOT/build/bench_dlss_kernel" "$@"
-48
View File
@@ -1,48 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Runs the D3D12 harness against d4r_nvngx.dll in an isolated Wine prefix.
# usage: run_d3d12_dlss_harness.sh PATH_TO_NGX_CORE_DLL PATH_TO_NVNGX_DLSS_DLL OUTPUT_RAW [FRAMES [IN_W IN_H OUT_W OUT_H]]
if [[ $# -lt 3 ]]; then
printf 'usage: %s PATH_TO_NGX_CORE_DLL PATH_TO_NVNGX_DLSS_DLL OUTPUT_RAW [FRAMES]\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CORE_PATH="$(realpath "$1")"
FEATURE_DLL_PATH="$(realpath "$2")"
OUTPUT_PATH="$(realpath -m "$3")"
FRAMES="${4:-6}"
SIZES=("${@:5}")
WINE_BIN="${WINE:-wine}"
WINEPREFIX="${D4R_WINEPREFIX:-${TMPDIR:-/tmp}/d4r-wineprefix}"
APP_DIR="${D4R_HARNESS_APPDIR:-${TMPDIR:-/tmp}/d4r-d3d12-harness-app}"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
if [[ ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the ZLUDA and HIP runtimes\n' >&2
exit 2
fi
mkdir -p "$APP_DIR" "$WINEPREFIX/drive_c/windows/system32"
"$ROOT/scripts/build_d3d12_dlss_harness.sh"
"$ROOT/scripts/build_wine_nvcuda_bridge.sh"
cp -f "$ROOT/build/wine-nvcuda/x86_64-windows/nvcuda.dll" "$WINEPREFIX/drive_c/windows/system32/nvcuda.dll"
cp -f "$ROOT/build/d3d12_dlss_harness.exe" "$ROOT/build/d4r_nvngx.dll" "$APP_DIR/"
cp -f "$FEATURE_DLL_PATH" "$APP_DIR/nvngx_dlss.dll"
winpath() { WINEPREFIX="$WINEPREFIX" winepath -w "$1"; }
WINE_OVERRIDES="${WINEDLLOVERRIDES:-}"
for override in 'dxgi=n,b' 'd3d12=n,b' 'd3d12core=n,b' 'nvcuda=b'; do
dll_name="${override%%=*}"
if [[ ";$WINE_OVERRIDES;" != *";$dll_name="* ]]; then
WINE_OVERRIDES="${WINE_OVERRIDES:+$WINE_OVERRIDES;}$override"
fi
done
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
WINEDLLPATH="$ROOT/build/wine-nvcuda/x86_64-windows:$ROOT/build/wine-nvcuda/x86_64-unix${WINEDLLPATH:+:$WINEDLLPATH}" \
WINEDLLOVERRIDES="$WINE_OVERRIDES" WINEPREFIX="$WINEPREFIX" WINEDEBUG="${D4R_WINEDEBUG:--all}" \
D4R_NGX_CORE="$(winpath "$CORE_PATH")" D4R_NGX_FEATURE_DIR="$(winpath "$APP_DIR")" \
D4R_SHIM_LOG="$(winpath "$APP_DIR/d4r_nvngx.log")" \
"$WINE_BIN" "$(winpath "$APP_DIR/d3d12_dlss_harness.exe")" "$(winpath "$APP_DIR/d4r_nvngx.dll")" \
"$(winpath "$OUTPUT_PATH")" "$FRAMES" "${SIZES[@]}"
printf '\nShim log (%s):\n' "$APP_DIR/d4r_nvngx.log"
cat "$APP_DIR/d4r_nvngx.log"
@@ -1,149 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
umask 077
# Runs the synthetic D3D12 harness through a locally supplied OptiScaler
# dxgi.dll and the d4r shim. All proxy files and the NVAPI identity bridge are
# staged in disposable /tmp paths; the Proton installation is not modified.
# usage: run_d3d12_dlss_harness_optiscaler_proton.sh PROTON_DIR OPTISCALER_DLL OUTPUT_RAW [FRAMES [IN_W IN_H OUT_W OUT_H]]
if [[ $# -lt 3 ]]; then
printf 'usage: %s PROTON_DIR OPTISCALER_DLL OUTPUT_RAW [FRAMES [IN_W IN_H OUT_W OUT_H]]\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROTON_DIR="$(realpath "$1")"
OPTISCALER_DLL="$(realpath "$2")"
OUTPUT_PATH="$(realpath -m "$3")"
shift 3
source "$ROOT/scripts/d4r_proton_env.sh"
for path in "$D4R_RUNTIME_DIR/bin/d4r_nvngx.dll" "$D4R_RUNTIME_DIR/bin/nvcuda.dll" \
"$D4R_RUNTIME_DIR/bin/nvngx_dlss.dll" "$D4R_RUNTIME_DIR/ngx/_nvngx.dll"; do
if [[ ! -f "$path" ]]; then
printf 'Missing staged d4r runtime file: %s\n' "$path" >&2
exit 2
fi
done
# DLSS Enabler has been found installed under the name OptiScaler.dll on this
# machine. Reject it here: its proxy rejects dxgi/NGX harness naming and can
# open a modal error dialog during LoadLibrary.
EXPORT_HEADER="$(x86_64-w64-mingw32-objdump -p "$OPTISCALER_DLL" | sed -n '/The Export Tables/,+6p')"
if [[ "$EXPORT_HEADER" != *OptiScaler.dll* ]]; then
printf 'Expected a real OptiScaler DLL (PE export name OptiScaler.dll): %s\n' "$OPTISCALER_DLL" >&2
exit 2
fi
"$ROOT/scripts/build_d4r_nvapi_identity.sh" >/dev/null
APP_DIR="${D4R_OPTISCALER_APP_DIR:-${TMPDIR:-/tmp}/d4r-optiscaler-harness-${UID}-$(date +%s%N)}"
mkdir -p "$APP_DIR"
LAUNCHER_DIR="$(mktemp -d "${TMPDIR:-/tmp}/d4r-optiscaler-proton.XXXXXXXX")"
COMPAT_DIR="${D4R_OPTISCALER_COMPAT_DIR:-${TMPDIR:-/tmp}/d4r-optiscaler-compat-$UID}"
mkdir -p "$COMPAT_DIR"
cp -f "$OPTISCALER_DLL" "$APP_DIR/dxgi.dll"
INPUT_HOOK="${D4R_OPTISCALER_ENABLE_DLSS_INPUTS:-false}"
ORIGINAL_HOOK="${D4R_OPTISCALER_HOOK_ORIGINAL_NVNGX_ONLY:-$INPUT_HOOK}"
if [[ "$INPUT_HOOK" != true && "$INPUT_HOOK" != false ]] ||
[[ "$ORIGINAL_HOOK" != true && "$ORIGINAL_HOOK" != false ]]; then
printf 'OptiScaler hook settings must be true or false\n' >&2
exit 2
fi
# D4R_OPTISCALER_STAGE_CORE=0 keeps the official core in the runtime directory,
# as in a game install; the shim then loads it below OptiScaler's hooks.
STAGE_CORE="${D4R_OPTISCALER_STAGE_CORE:-1}"
if [[ "$INPUT_HOOK" == true && "$STAGE_CORE" == 1 ]]; then
if [[ "$ORIGINAL_HOOK" != true || "$APP_DIR" != "${APP_DIR,,}" ]]; then
printf 'The DLSS input hook requires HookOriginalNvngxOnly=true and a lowercase app path\n' >&2
exit 2
fi
# OptiScaler hooks game-side nvngx loads. Keep the official core's required
# filename inside the harness EXE directory and pass a lowercase z: path;
# its hook then leaves this internal core load alone.
cp -f "$D4R_RUNTIME_DIR/ngx/_nvngx.dll" "$APP_DIR/_nvngx.dll"
cp -f "$D4R_RUNTIME_DIR/dlss/nvngx_dlss.dll" "$APP_DIR/nvngx_dlss.dll"
core_windows_path="$(d4r_winpath "$APP_DIR/_nvngx.dll")"
export D4R_NGX_CORE="z:${core_windows_path#Z:}"
fi
cat > "$APP_DIR/OptiScaler.ini" <<EOF
[Upscalers]
Dx12Upscaler=dlss
[FrameGen]
Enabled=false
FGInput=nofg
FGOutput=nofg
[DLSS]
Enabled=true
[Inputs]
EnableDlssInputs=$INPUT_HOOK
[Hooks]
HookOriginalNvngxOnly=$ORIGINAL_HOOK
[FSR]
FsrAgilitySDKUpgrade=false
[Libraries]
NvngxPath=$(d4r_winpath "$D4R_RUNTIME_DIR/bin/d4r_nvngx.dll")
NvngxDlssPath=$(d4r_winpath "$D4R_RUNTIME_DIR/bin")
[NvApi]
OverrideNvapiDll=false
[Spoofing]
Dxgi=false
[Plugins]
LoadAsiPlugins=false
[Log]
LogToFile=true
LogLevel=1
EOF
# Proton refreshes nvapi64.dll in the prefix on every run. Make a temporary
# launcher that copies our identity bridge instead. Its other files are links
# to the unmodified Proton installation.
cp -f "$PROTON_DIR/proton" "$PROTON_DIR/filelock.py" "$PROTON_DIR/version" "$LAUNCHER_DIR/"
ln -s "$PROTON_DIR/files" "$LAUNCHER_DIR/files"
ln -s "$PROTON_DIR/protonfixes" "$LAUNCHER_DIR/protonfixes"
LAUNCHER="$LAUNCHER_DIR/proton" python3 - <<'PY'
import os
from pathlib import Path
path = Path(os.environ["LAUNCHER"])
source = path.read_text()
old = 'try_copy(g_proton.arch_pe_dir("wine/nvapi", False) + "nvapi64.dll", "drive_c/windows/system32",'
new = 'try_copy(os.environ.get("D4R_NVAPI_IDENTITY_DLL", g_proton.arch_pe_dir("wine/nvapi", False) + "nvapi64.dll"), "drive_c/windows/system32",'
if source.count(old) != 1:
raise SystemExit("Proton NVAPI copy point changed; cannot stage identity bridge")
path.write_text(source.replace(old, new))
PY
chmod +x "$LAUNCHER_DIR/proton"
export STEAM_COMPAT_CLIENT_INSTALL_PATH="${STEAM_COMPAT_CLIENT_INSTALL_PATH:-$HOME/.local/share/Steam}"
export STEAM_COMPAT_DATA_PATH="$COMPAT_DIR"
PROTON_ENABLE_NVAPI=1 WINEDEBUG=-all "$PROTON_DIR/proton" run cmd /c exit 0 >/dev/null
NVAPI_REAL="$PROTON_DIR/files/lib/wine/nvapi/x86_64-windows/nvapi64.dll"
if [[ ! -f "$NVAPI_REAL" ]]; then
printf 'Cannot find Proton DXVK-NVAPI at %s\n' "$NVAPI_REAL" >&2
exit 2
fi
cp -f "$NVAPI_REAL" "$COMPAT_DIR/pfx/drive_c/windows/system32/d4r_nvapi64_real.dll"
export D4R_NVAPI_IDENTITY_DLL="$ROOT/build/nvapi64.dll"
export D4R_HARNESS_APP_DIR="$APP_DIR"
export D4R_HARNESS_NGX_DLL="$APP_DIR/dxgi.dll"
export D4R_HARNESS_LOAD_NGX_EARLY=1
export D4R_HARNESS_TRACE="$(d4r_winpath "$APP_DIR/harness.trace")"
export D4R_SHIM_LOG="$(d4r_winpath "$APP_DIR/d4r_nvngx.log")"
export D4R_PROTON_COMPAT_DATA="$COMPAT_DIR"
export DXVK_CONFIG="${DXVK_CONFIG:-dxgi.customVendorId = 10de}"
"$ROOT/scripts/run_d3d12_dlss_harness_proton.sh" "$LAUNCHER_DIR" "$OUTPUT_PATH" "$@"
if [[ ! -s "$OUTPUT_PATH" || ! -f "$APP_DIR/OptiScaler.log" || ! -f "$APP_DIR/d4r_nvngx.log" ]] ||
! rg -q 'DLSSFeatureDx12::Init _CreateFeature result: NVSDK_NGX_Result_Success' "$APP_DIR/OptiScaler.log" ||
! rg -q 'NVSDK_NGX_CUDA_CreateFeature -> 0x00000001' "$APP_DIR/d4r_nvngx.log" ||
! rg -q 'frame [0-9]+ done:' "$APP_DIR/d4r_nvngx.log"; then
printf 'OptiScaler did not complete the official DLSS path; inspect %s\n' "$APP_DIR" >&2
exit 1
fi
printf 'OptiScaler DLSS harness output: %s\n' "$OUTPUT_PATH"
printf 'OptiScaler, shim, and stage logs: %s\n' "$APP_DIR"
sha256sum "$OUTPUT_PATH"
-36
View File
@@ -1,36 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Runs the D3D12 harness through a Proton build's own launcher script, so the
# prefix, DXVK/vkd3d-proton/dxvk-nvapi and DLL overrides match a Steam game.
# usage: run_d3d12_dlss_harness_proton.sh PROTON_DIR OUTPUT_RAW [FRAMES [IN_W IN_H OUT_W OUT_H]]
if [[ $# -lt 2 ]]; then
printf 'usage: %s PROTON_DIR OUTPUT_RAW [FRAMES [IN_W IN_H OUT_W OUT_H]]\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROTON_DIR="$(realpath "$1")"
OUTPUT_PATH="$(realpath -m "$2")"
shift 2
source "$ROOT/scripts/d4r_proton_env.sh"
if [[ "${D4R_HARNESS_SKIP_BUILD:-0}" != 1 ]]; then
"$ROOT/scripts/build_d3d12_dlss_harness.sh" >/dev/null
fi
HARNESS_APP_DIR="${D4R_HARNESS_APP_DIR:-$ROOT/build}"
mkdir -p "$HARNESS_APP_DIR"
HARNESS_EXE="$HARNESS_APP_DIR/d3d12_dlss_harness.exe"
if [[ "$(realpath -m "$HARNESS_EXE")" != "$(realpath -m "$ROOT/build/d3d12_dlss_harness.exe")" ]]; then
cp -f "$ROOT/build/d3d12_dlss_harness.exe" "$HARNESS_EXE"
fi
export STEAM_COMPAT_CLIENT_INSTALL_PATH="${STEAM_COMPAT_CLIENT_INSTALL_PATH:-$HOME/.local/share/Steam}"
export STEAM_COMPAT_DATA_PATH="${D4R_PROTON_COMPAT_DATA:-${TMPDIR:-/tmp}/d4r-proton-harness-compat}"
mkdir -p "$STEAM_COMPAT_DATA_PATH"
# D4R_HARNESS_NGX_DLL selects the NGX DLL the harness drives (default: the
# shim; point it at OptiScaler installed as nvngx.dll to test OptiScaler).
NGX_DLL="${D4R_HARNESS_NGX_DLL:-$D4R_RUNTIME_DIR/bin/d4r_nvngx.dll}"
"$PROTON_DIR/proton" run "$HARNESS_EXE" "$(d4r_winpath "$NGX_DLL")" \
"$(d4r_winpath "$OUTPUT_PATH")" "$@"
printf '\nShim log:\n'
if [[ -f "$D4R_RUNTIME_DIR/d4r_nvngx.log" ]]; then
tail -n 20 "$D4R_RUNTIME_DIR/d4r_nvngx.log"
fi
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Zero-copy D3D12 <-> HIP sharing probe under Proton (see the .cpp).
# usage: run_d3d12_hip_interop_probe.sh PROTON_DIR REPORT_FILE [WIDTH HEIGHT]
if [[ $# -lt 2 ]]; then
printf 'usage: %s PROTON_DIR REPORT_FILE [WIDTH HEIGHT]\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROTON_DIR="$(realpath "$1")"
REPORT="$(realpath -m "$2")"
shift 2
source "$ROOT/scripts/d4r_proton_env.sh"
"$ROOT/scripts/build_d3d12_hip_interop_probe.sh" >/dev/null
export STEAM_COMPAT_CLIENT_INSTALL_PATH="${STEAM_COMPAT_CLIENT_INSTALL_PATH:-$HOME/.local/share/Steam}"
export STEAM_COMPAT_DATA_PATH="${D4R_PROTON_COMPAT_DATA:-${TMPDIR:-/tmp}/d4r-proton-harness-compat}"
mkdir -p "$STEAM_COMPAT_DATA_PATH"
"$PROTON_DIR/proton" run "$ROOT/build/d3d12_hip_interop_probe.exe" \
"$(d4r_winpath "$D4R_RUNTIME_DIR/bin/nvcuda.dll")" "$(d4r_winpath "$REPORT")" "$@" || status=$?
cat "$REPORT"
exit "${status:-0}"
-170
View File
@@ -1,170 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Launches a Windows game through a GE-Proton build's integrated OptiScaler
# (PROTON_USE_OPTISCALER) with OptiScaler's DLSS backend routed into the d4r
# shim, i.e. official NVIDIA DLSS executed through the Wine CUDA bridge and
# ZLUDA on the AMD GPU.
#
# usage: run_game_d4r_optiscaler_proton.sh PROTON_DIR COMPAT_DATA_DIR GAME_EXE [ARGS...]
#
# The Proton installation and game directory are not modified. The prefix's
# system32/umu/OptiScaler.ini (rewritten by GE-Proton from
# PROTON_OPTISCALER_CONFIG) is restored when the game exits, and the real
# DXVK-NVAPI is placed next to the identity bridge as d4r_nvapi64_real.dll.
# With D4R_VKD3D_DIR (a directory holding d3d12.dll and d3d12core.dll, e.g. the
# d4r-patched vkd3d-proton), those replace Proton's vkd3d-proton in the prefix
# for this launch; the prefix's previous copies are backed up to the log
# directory and restored when the game exits.
# With D4R_UE_ENGINE_INI (the game's Saved/Config/Windows/Engine.ini) and
# D4R_UE_CVARS ("r.A=0;r.B=1"), those console variables are added to its
# [SystemSettings] for this launch only: an existing file is backed up to the
# log directory and restored on exit, a new one is removed again. Unreal games
# apply tonemapper sharpening and chromatic fringe after the upscaler; e.g.
# Townfall's r.Tonemapper.Sharpen and r.SceneColorFringeQuality turn DLSS's
# clean thin lines into haloed, stippled and beaded ones.
# Logs go to D4R_GAME_LOG_DIR (default: a timestamped capture directory).
if [[ $# -lt 3 ]]; then
printf 'usage: %s PROTON_DIR COMPAT_DATA_DIR GAME_EXE [ARGS...]\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROTON_DIR="$(realpath "$1")"
COMPAT_DIR="$(realpath "$2")"
GAME_EXE="$(realpath "$3")"
shift 3
# User settings from d4r.ini (config/d4r.ini.default documents them); explicit environment wins.
# D4R_NO_CONFIG=1 ignores the file (automated tests); D4R_CONFIG picks another file.
if [[ "${D4R_NO_CONFIG:-0}" != 1 ]]; then
python3 "$ROOT/scripts/d4r_config.py" --print >&2 || true
D4R_CONFIG_EXPORTS="$(python3 "$ROOT/scripts/d4r_config.py")" || exit 2
eval "$D4R_CONFIG_EXPORTS"
fi
source "$ROOT/scripts/d4r_proton_env.sh"
PREFIX="$COMPAT_DIR/pfx"
UMU="$PREFIX/drive_c/windows/system32/umu"
LOG_DIR="${D4R_GAME_LOG_DIR:-$HOME/.cache/d4r-dlss-captures/game-$(basename "$GAME_EXE" .exe)-$(date +%Y%m%d-%H%M%S)}"
mkdir -p "$LOG_DIR"
[[ -d "$PREFIX" ]] || { printf 'No Proton prefix at %s\n' "$PREFIX" >&2; exit 2; }
# A second launch would join the running wineserver, and whichever run exits
# first would restore its OptiScaler.ini backup underneath the other.
SERVER_DIR="/tmp/.wine-$(id -u)/server-$(stat -c '%D' "$PREFIX" | sed 's/^0*//')-$(printf '%x' "$(stat -c '%i' "$PREFIX")")"
if [[ -S "$SERVER_DIR/socket" ]] && fuser "$SERVER_DIR/socket" >/dev/null 2>&1; then
printf 'A wineserver is already running for %s; close that game first\n' "$PREFIX" >&2
exit 2
fi
"$ROOT/scripts/build_d4r_nvapi_identity.sh" >/dev/null
NVAPI_REAL="$PROTON_DIR/files/lib/wine/nvapi/x86_64-windows/nvapi64.dll"
[[ -f "$NVAPI_REAL" ]] || { printf 'Cannot find DXVK-NVAPI at %s\n' "$NVAPI_REAL" >&2; exit 2; }
cp -f "$NVAPI_REAL" "$PREFIX/drive_c/windows/system32/d4r_nvapi64_real.dll"
# Temporary launcher: identical to the Proton build except that the NVAPI copy
# installs the identity bridge (so OptiScaler enables its DLSS backend).
LAUNCHER_DIR="$(mktemp -d "${TMPDIR:-/tmp}/d4r-game-proton.XXXXXXXX")"
for entry in "$PROTON_DIR"/*; do
[[ "$(basename "$entry")" == proton ]] || ln -s "$entry" "$LAUNCHER_DIR/$(basename "$entry")"
done
cp -f "$PROTON_DIR/proton" "$LAUNCHER_DIR/proton"
LAUNCHER="$LAUNCHER_DIR/proton" python3 - <<'PY'
import os
from pathlib import Path
path = Path(os.environ["LAUNCHER"])
source = path.read_text()
variants = [
'g_proton.arch_pe_dir("wine/nvapi", False) + "nvapi64.dll"',
'g_proton.arch_pe_dir("wine/" + nvapi_path, False) + "nvapi64.dll"',
]
for old in variants:
target = f'try_copy({old}, "drive_c/windows/system32",'
if source.count(target) == 1:
new = f'try_copy(os.environ.get("D4R_NVAPI_IDENTITY_DLL", {old}), "drive_c/windows/system32",'
path.write_text(source.replace(target, new))
break
else:
raise SystemExit("Proton NVAPI copy point not found; cannot stage identity bridge")
if os.environ.get("D4R_VKD3D_DIR"):
source = path.read_text()
old = 'try_copy(g_proton.arch_pe_dir("wine/vkd3d-proton", False) + f + ".dll", "drive_c/windows/system32",'
new = ('try_copy(os.path.join(os.environ["D4R_VKD3D_DIR"], f + ".dll"), "drive_c/windows/system32",')
if source.count(old) != 1:
raise SystemExit("Proton vkd3d-proton copy point not found; cannot stage D4R_VKD3D_DIR")
path.write_text(source.replace(old, new))
PY
# GE-Proton rewrites OptiScaler.ini from PROTON_OPTISCALER_CONFIG; keep the
# user's configuration and put it back afterwards.
INI="$UMU/OptiScaler.ini"
[[ -f "$INI" ]] && cp -f "$INI" "$LOG_DIR/OptiScaler.ini.before"
VKD3D_BACKUP="$LOG_DIR/vkd3d-prefix-backup"
if [[ -n "${D4R_VKD3D_DIR:-}" ]]; then
export D4R_VKD3D_DIR="$(realpath "$D4R_VKD3D_DIR")"
for dll in d3d12.dll d3d12core.dll; do
[[ -f "$D4R_VKD3D_DIR/$dll" ]] || { printf 'D4R_VKD3D_DIR lacks %s\n' "$dll" >&2; exit 2; }
done
mkdir -p "$VKD3D_BACKUP"
for dll in d3d12.dll d3d12core.dll; do
[[ -f "$PREFIX/drive_c/windows/system32/$dll" ]] && cp -f "$PREFIX/drive_c/windows/system32/$dll" "$VKD3D_BACKUP/$dll"
done
fi
ENGINE_INI="${D4R_UE_ENGINE_INI:-}"
ENGINE_INI_STATE=""
restore_prefix() {
[[ -f "$LOG_DIR/OptiScaler.ini.before" ]] && cp -f "$LOG_DIR/OptiScaler.ini.before" "$INI"
case "$ENGINE_INI_STATE" in
restore) cp -f "$LOG_DIR/Engine.ini.before" "$ENGINE_INI" ;;
remove) rm -f "$ENGINE_INI" ;;
esac
if [[ -n "${D4R_VKD3D_DIR:-}" ]]; then
for dll in d3d12.dll d3d12core.dll; do
[[ -f "$VKD3D_BACKUP/$dll" ]] && cp -f "$VKD3D_BACKUP/$dll" "$PREFIX/drive_c/windows/system32/$dll"
done
fi
rm -rf "$LAUNCHER_DIR"
}
trap restore_prefix EXIT
if [[ -n "$ENGINE_INI" && -n "${D4R_UE_CVARS:-}" ]]; then
if [[ -f "$ENGINE_INI" ]]; then
cp -f "$ENGINE_INI" "$LOG_DIR/Engine.ini.before"
ENGINE_INI_STATE=restore
else
mkdir -p "$(dirname "$ENGINE_INI")"
ENGINE_INI_STATE=remove
fi
{ printf '\n[SystemSettings]\n'; tr ';' '\n' <<<"$D4R_UE_CVARS"; printf '\n'; } >> "$ENGINE_INI"
fi
OPTI_CONFIG="Upscalers.Dx12Upscaler=dlss;DLSS.Enabled=true"
OPTI_CONFIG+=";Libraries.NvngxPath=$(d4r_winpath "$D4R_RUNTIME_DIR/bin/d4r_nvngx.dll")"
OPTI_CONFIG+=";Libraries.NvngxDlssPath=$(d4r_winpath "$D4R_RUNTIME_DIR/bin")"
# Game-side DLSS inputs stay hooked; only NGX loads outside the game directory
# are redirected, which lets the shim request the official core by an
# exe-relative path.
OPTI_CONFIG+=";Inputs.EnableDlssInputs=true;Hooks.HookOriginalNvngxOnly=true"
OPTI_CONFIG+=";NvApi.OverrideNvapiDll=false;FrameGen.Enabled=false;FrameGen.FGInput=nofg;FrameGen.FGOutput=nofg"
OPTI_CONFIG+=";Log.LogToFile=true;Log.LogLevel=${D4R_OPTISCALER_LOG_LEVEL:-2}"
# Detailed FPS overlay with frame-time graph (the user's own INI default too).
OPTI_CONFIG+=";Menu.ShowFps=${D4R_OPTISCALER_SHOW_FPS:-true};Menu.FpsOverlayType=${D4R_OPTISCALER_FPS_OVERLAY_TYPE:-3}"
OPTI_CONFIG+="${D4R_EXTRA_OPTISCALER_CONFIG:+;$D4R_EXTRA_OPTISCALER_CONFIG}"
export PROTON_USE_OPTISCALER=1
export PROTON_OPTISCALER_CONFIG="$OPTI_CONFIG"
export D4R_NVAPI_IDENTITY_DLL="$ROOT/build/nvapi64.dll"
export DXVK_CONFIG="${DXVK_CONFIG:-dxgi.customVendorId = 10de}"
export D4R_SHIM_LOG="$(d4r_winpath "$LOG_DIR/d4r_nvngx.log")"
export STEAM_COMPAT_CLIENT_INSTALL_PATH="${STEAM_COMPAT_CLIENT_INSTALL_PATH:-$HOME/.local/share/Steam}"
export STEAM_COMPAT_DATA_PATH="$COMPAT_DIR"
export PROTON_LOG=1 PROTON_LOG_DIR="$LOG_DIR"
export WINEDEBUG="${WINEDEBUG:--all}"
# Games load dozens of modules per launch; do not capture them unless asked.
export D4R_CUDA_CAPTURE="${D4R_CUDA_CAPTURE:-0}"
printf 'd4r game launch: %s\nlogs: %s\n' "$GAME_EXE" "$LOG_DIR"
status=0
(cd "$(dirname "$GAME_EXE")" && "$LAUNCHER_DIR/proton" waitforexitandrun "$GAME_EXE" "$@") \
>"$LOG_DIR/launcher.log" 2>&1 || status=$?
cp -f "$UMU/OptiScaler.log" "$LOG_DIR/OptiScaler.log" 2>/dev/null || true
printf 'game exited with status %s\n' "$status"
exit "$status"
-9
View File
@@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ROCM_ROOT="${ROCM_ROOT:-/opt/rocm}"
"$ROOT/scripts/build_hip_vk_interop_probe.sh"
LD_LIBRARY_PATH="$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
"$ROOT/build/hip_vk_interop_probe"
-71
View File
@@ -1,71 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 3 ]]; then
printf 'usage: %s PATH_TO_NGX_CORE_DLL PATH_TO_NVNGX_DLSS_DLL WRITABLE_APPDATA_DIRECTORY\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CORE_PATH="$(realpath "$1")"
FEATURE_DLL_PATH="$(realpath "$2")"
DATA_PATH="$(realpath -m "$3")"
WINE_BIN="${WINE:-wine}"
WINEPREFIX="${D4R_WINEPREFIX:-${TMPDIR:-/tmp}/d4r-wineprefix}"
APP_DIR="${D4R_NGX_CUDA_APPDIR:-${TMPDIR:-/tmp}/d4r-ngxcuda-app}"
CAPTURE_DIR="${D4R_CUDA_CAPTURE_DIR:-${TMPDIR:-/tmp}/d4r-dlss-cuda-modules}"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
TMP_ROOT="$(realpath -m "${TMPDIR:-/tmp}")"
WINEPREFIX="$(realpath -m "$WINEPREFIX")"
APP_DIR="$(realpath -m "$APP_DIR")"
DATA_PATH="$(realpath -m "$DATA_PATH")"
CAPTURE_DIR="$(realpath -m "$CAPTURE_DIR")"
case "$WINEPREFIX/" in
"$TMP_ROOT/"*) ;;
*)
printf 'D4R_WINEPREFIX must be an isolated prefix under %s; refusing to modify a non-temporary prefix\n' "$TMP_ROOT" >&2
exit 2
;;
esac
for isolated_path in "$APP_DIR" "$DATA_PATH" "$CAPTURE_DIR"; do
case "$isolated_path/" in
"$TMP_ROOT/"*) ;;
*)
printf 'App directory, appdata, and CUDA captures must stay under %s; refusing to write outside temporary storage\n' "$TMP_ROOT" >&2
exit 2
;;
esac
done
if [[ ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the temporary or installed ZLUDA/HIP runtimes\n' >&2
exit 2
fi
mkdir -p "$WINEPREFIX/drive_c/windows/system32" "$DATA_PATH" "$APP_DIR" "$CAPTURE_DIR"
"$ROOT/scripts/build_ngx_cuda_probe.sh"
"$ROOT/scripts/build_wine_nvcuda_bridge.sh"
cp -f "$ROOT/build/wine-nvcuda/x86_64-windows/nvcuda.dll" "$WINEPREFIX/drive_c/windows/system32/nvcuda.dll"
APP_EXE_PATH="$APP_DIR/ngx_cuda_probe.exe"
APP_FEATURE_DLL_PATH="$APP_DIR/nvngx_dlss.dll"
cp -f "$ROOT/build/ngx_cuda_probe.exe" "$APP_EXE_PATH"
cp -f "$FEATURE_DLL_PATH" "$APP_FEATURE_DLL_PATH"
CORE_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$CORE_PATH")"
FEATURE_DLL_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$APP_FEATURE_DLL_PATH")"
DATA_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$DATA_PATH")"
APP_EXE_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$APP_EXE_PATH")"
WINE_OVERRIDES="${WINEDLLOVERRIDES:-}"
for override in 'dxgi=n,b' 'd3d12=n,b' 'd3d12core=n,b' 'nvcuda=b'; do
dll_name="${override%%=*}"
if [[ ";$WINE_OVERRIDES;" != *";$dll_name="* ]]; then
WINE_OVERRIDES="${WINE_OVERRIDES:+$WINE_OVERRIDES;}$override"
fi
done
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
WINEDLLPATH="$ROOT/build/wine-nvcuda/x86_64-windows:$ROOT/build/wine-nvcuda/x86_64-unix${WINEDLLPATH:+:$WINEDLLPATH}" \
WINEDLLOVERRIDES="$WINE_OVERRIDES" WINEPREFIX="$WINEPREFIX" \
WINEDEBUG="${D4R_WINEDEBUG:--all}" \
D4R_CUDA_CAPTURE_DIR="$CAPTURE_DIR" \
"$WINE_BIN" "$APP_EXE_WIN_PATH" "$CORE_WIN_PATH" "$FEATURE_DLL_WIN_PATH" "$DATA_WIN_PATH"
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 3 ]]; then
printf 'usage: %s PATH_TO_NGX_CORE_DLL PATH_TO_NVNGX_DLSS_DLL WRITABLE_APPDATA_DIRECTORY\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CORE_PATH="$(realpath "$1")"
FEATURE_DLL_PATH="$(realpath "$2")"
DATA_PATH="$(realpath -m "$3")"
WINE_BIN="${WINE:-wine}"
WINEPREFIX="${D4R_WINEPREFIX:-${TMPDIR:-/tmp}/d4r-wineprefix}"
mkdir -p "$WINEPREFIX" "$DATA_PATH"
"$ROOT/scripts/build_ngx_d3d12_probe.sh"
CORE_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$CORE_PATH")"
FEATURE_DLL_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$FEATURE_DLL_PATH")"
DATA_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$DATA_PATH")"
WINEPREFIX="$WINEPREFIX" WINEDEBUG="${D4R_WINEDEBUG:--all}" \
"$WINE_BIN" "$ROOT/build/ngx_d3d12_probe.exe" "$CORE_WIN_PATH" "$FEATURE_DLL_WIN_PATH" "$DATA_WIN_PATH"
-18
View File
@@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 1 ]]; then
printf 'usage: %s PATH_TO_NVNGX_DLSS_DLL\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DLL_PATH="$(realpath "$1")"
WINE_BIN="${WINE:-wine}"
WINEPREFIX="${D4R_WINEPREFIX:-${TMPDIR:-/tmp}/d4r-wineprefix}"
"$ROOT/scripts/build_ngx_load_probe.sh"
mkdir -p "$WINEPREFIX"
DLL_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$DLL_PATH")"
WINEPREFIX="$WINEPREFIX" WINEDEBUG="${D4R_WINEDEBUG:--all}" \
"$WINE_BIN" "$ROOT/build/ngx_load_probe.exe" "$DLL_WIN_PATH"
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 3 ]]; then
printf 'usage: %s PATH_TO_NGX_CORE_DLL PATH_TO_NVNGX_DLSS_DLL WRITABLE_APPDATA_DIRECTORY\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CORE_PATH="$(realpath "$1")"
FEATURE_DLL_PATH="$(realpath "$2")"
DATA_PATH="$(realpath -m "$3")"
WINE_BIN="${WINE:-wine}"
WINEPREFIX="${D4R_WINEPREFIX:-${TMPDIR:-/tmp}/d4r-wineprefix}"
mkdir -p "$WINEPREFIX" "$DATA_PATH"
"$ROOT/scripts/build_ngx_vulkan_probe.sh"
CORE_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$CORE_PATH")"
FEATURE_DLL_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$FEATURE_DLL_PATH")"
DATA_WIN_PATH="$(WINEPREFIX="$WINEPREFIX" winepath -w "$DATA_PATH")"
WINEPREFIX="$WINEPREFIX" WINEDEBUG="${D4R_WINEDEBUG:--all}" \
"$WINE_BIN" "$ROOT/build/ngx_vulkan_probe.exe" "$CORE_WIN_PATH" "$FEATURE_DLL_WIN_PATH" "$DATA_WIN_PATH"
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
if [[ -z "$ZLUDA_ROOT" || -z "$ROCM_ROOT" || ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the ZLUDA and HIP runtimes\n' >&2
exit 2
fi
"$ROOT/scripts/build_replay_dlss_fp8_ops.sh"
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
"$ROOT/build/replay_dlss_fp8_ops"
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 1 ]]; then
printf 'usage: %s PATH_TO_LOCALLY_CAPTURED_DLSS_HISTOGRAM_FATBIN\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
if [[ -z "$ZLUDA_ROOT" || -z "$ROCM_ROOT" || ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the ZLUDA and HIP runtimes\n' >&2
exit 2
fi
"$ROOT/scripts/build_replay_dlss_histogram.sh"
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
"$ROOT/build/replay_dlss_histogram" "$1"
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -lt 1 || $# -gt 2 ]]; then
printf 'usage: %s PATH_TO_LOCALLY_CAPTURED_DLSS_FATBIN [KERNEL_NAME]\n' "$0" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
if [[ -z "$ZLUDA_ROOT" || -z "$ROCM_ROOT" || ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the ZLUDA and HIP runtimes\n' >&2
exit 2
fi
"$ROOT/scripts/build_replay_dlss_kernel.sh"
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
"$ROOT/build/replay_dlss_kernel" "$@"
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
if [[ -z "$ZLUDA_ROOT" || -z "$ROCM_ROOT" || ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the ZLUDA and HIP runtimes\n' >&2
exit 2
fi
"$ROOT/scripts/build_replay_dlss_surface_half_store.sh"
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
"$ROOT/build/replay_dlss_surface_half_store"
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
if [[ -z "$ZLUDA_ROOT" || -z "$ROCM_ROOT" || ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the ZLUDA and HIP runtimes\n' >&2
exit 2
fi
"$ROOT/scripts/build_replay_dlss_surface_store.sh"
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
"$ROOT/build/replay_dlss_surface_store"
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ZLUDA_ROOT="${ZLUDA_ROOT:-}"
ROCM_ROOT="${ROCM_ROOT:-}"
if [[ -z "$ZLUDA_ROOT" || -z "$ROCM_ROOT" || ! -f "$ZLUDA_ROOT/libcuda.so" || ! -f "$ROCM_ROOT/lib/libamdhip64.so" ]]; then
printf 'Set ZLUDA_ROOT and ROCM_ROOT to the ZLUDA and HIP runtimes\n' >&2
exit 2
fi
"$ROOT/scripts/build_replay_dlss_texture_sample.sh"
LD_LIBRARY_PATH="$ZLUDA_ROOT:$ROCM_ROOT/lib:$ROCM_ROOT/lib/llvm/lib:${LD_LIBRARY_PATH:-}" \
"$ROOT/build/replay_dlss_texture_sample"
@@ -1,17 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$Module,
[Parameter(Mandatory=$true)][string]$Candidate,
[Parameter(Mandatory=$true)][string]$FixtureDirectory,
[string]$HipRoot, [string]$Probe, [string]$OutputDirectory,
[ValidateRange(1,10000)][int]$Pairs=32,
[ValidateRange(1,256)][int[]]$Batches=@(1,64),
[ValidateSet('events','dispatch')][string[]]$Timings=@('events','dispatch'))
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$Probe) { $Probe=Join-Path $repo 'build/windows-rdna4-therock/d4r_native_replay_probe.exe' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/native-benchmark-'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
& python.exe (Join-Path $repo 'tools/windows/benchmark_native_replay.py') --probe $Probe --hip-root $HipRoot `
--module $Module --candidate $Candidate --fixture-dir $FixtureDirectory --output-dir $OutputDirectory `
--pairs $Pairs --batches @Batches --timings @Timings
if ($LASTEXITCODE) { throw "Native benchmark failed. Logs: $OutputDirectory" }
-28
View File
@@ -1,28 +0,0 @@
[CmdletBinding()]
param([string]$AdlxRoot, [string]$BuildDirectory, [string]$Compiler)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$commit='32b5a740d42295c5dfe9026b9f52683da0f3af91'
if (!$AdlxRoot) { $AdlxRoot=Join-Path $repo 'external/ADLX' }
if (!$BuildDirectory) { $BuildDirectory=Join-Path $repo 'build/gpu-telemetry' }
if (!$Compiler) { $Compiler=Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64/bin/x86_64-w64-mingw32-clang.exe' }
if (!(Test-Path -LiteralPath $AdlxRoot)) {
& git clone --no-checkout https://github.com/GPUOpen-LibrariesAndSDKs/ADLX.git $AdlxRoot
if ($LASTEXITCODE) { throw 'ADLX SDK download failed.' }
& git -C $AdlxRoot checkout --detach $commit
if ($LASTEXITCODE) { throw 'ADLX SDK checkout failed.' }
}
if ((& git -C $AdlxRoot rev-parse HEAD).Trim() -ne $commit -or (& git -C $AdlxRoot status --porcelain)) {
throw "Expected clean ADLX SDK $commit; use a separate AdlxRoot."
}
if (!(Test-Path -LiteralPath $Compiler)) { throw 'Set Compiler to an x64 LLVM-MinGW clang.exe.' }
New-Item -ItemType Directory -Force $BuildDirectory | Out-Null
$exe=Join-Path $BuildDirectory 'd4r_gpu_telemetry.exe'
& $Compiler -std=c11 -O2 -Wall -Wextra -Wno-unknown-pragmas -DWIN32_LEAN_AND_MEAN -D_M_AMD64 `
-isystem "$AdlxRoot/SDK/Include" (Join-Path $repo 'tools/windows/gpu_telemetry.c') -o $exe
if ($LASTEXITCODE) { throw "GPU telemetry compile failed: $LASTEXITCODE" }
@{sdkCommit=$commit; sdkLicense=(Join-Path $AdlxRoot 'ADLX SDK License Agreement.pdf');
executable=$exe; compiler=$Compiler; sha256=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash} |
ConvertTo-Json | Set-Content -LiteralPath (Join-Path $BuildDirectory 'build-info.json') -Encoding UTF8
Write-Host "Built local read-only telemetry: $exe"
# The SDK, driver DLL and SDK-dependent binary are not added to public packages.
@@ -1,68 +0,0 @@
[CmdletBinding()]
param([ValidateSet('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0')]
[string]$Layer='enc1', [ValidateSet('source','cu','wgp')][string]$Mode='source',
[ValidateSet('baseline','load','store','both')][string]$NonTemporal='baseline',
[ValidateSet(0,1,2,4)][int]$PosTiles=0, [switch]$ShareValues, [switch]$PrivateValues,
[switch]$PackedAccumulator,
[string]$HipRoot, [string]$OutputDirectory)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if ($ShareValues -and $PrivateValues) { throw 'Choose shared or private V storage.' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/native-k-experiment-$Layer-$Mode-$NonTemporal-pos$PosTiles-share$([int][bool]$ShareValues)-private$([int][bool]$PrivateValues)-packed$([int][bool]$PackedAccumulator)" }
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
foreach ($baseline in @('build/native-k-gfx1201','build/windows-rdna4-therock','dist/windows-rdna4-command-list')) {
if ($OutputDirectory.StartsWith([IO.Path]::GetFullPath((Join-Path $repo $baseline)), [StringComparison]::OrdinalIgnoreCase)) {
throw 'Keep experimental objects outside the validated baseline/package.'
}
}
$compiler=Join-Path $HipRoot 'lib/llvm/bin/clang++.exe'
if (!(Test-Path -LiteralPath $compiler)) { $compiler=Join-Path $HipRoot 'bin/clang++.exe' }
$name="dltss_pwin_${Layer}_layer"
$source=Join-Path $repo "kernels/k/$name.hip"
$flags=@()
if ((Get-Content -LiteralPath $source -Raw) -match '// d4r-build-flags: ([^\r\n]+)') { $flags=$Matches[1].Trim().Split(' ') }
if ($Mode -ne 'source') {
$flags=@($flags | Where-Object { $_ -ne '-mcumode' -and $_ -ne '-mno-cumode' })
$flags+=if ($Mode -eq 'cu') { '-mcumode' } else { '-mno-cumode' }
}
if ($NonTemporal -in @('load','both')) { $flags+='-DPWIN_NT_LOAD' }
if ($NonTemporal -in @('store','both')) { $flags+='-DPWIN_NT_STORE' }
if ($PosTiles) {
if ($Layer -notin @('enc0','enc1','dec0')) { throw 'Token tiling is audited for position-only layers only.' }
$flags+=if ($Layer -eq 'enc1') { "-DD4R_K_ENC1_POS_MT=$PosTiles" } else { "-DD4R_K_POS_MT=$PosTiles" }
}
if ($ShareValues) {
if ($Layer -notin @('enc0','dec0') -and !($Layer -eq 'enc1' -and $PosTiles)) {
throw 'ShareValues requires a position-only template.'
}
$flags+='-DPOS_VSHARE'
}
if ($PackedAccumulator) { $flags+='-DD4R_K_PACKED_ACC' }
if ($PrivateValues) { $flags+='-DD4R_K_PRIVATE_V' }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$object=Join-Path $OutputDirectory "$name.hsaco"
$arguments=@('-x','hip','-std=c++17','--offload-arch=gfx1201','--offload-device-only',
'--no-gpu-bundle-output','-mno-wavefrontsize64','-nogpuinc','-nogpulib','-O3',
'-DD4R_DEVICE_ONLY_MINIMAL','-DD4R_K_FP16_BASELINE')+$flags+@($source,'-o',$object)
$ErrorActionPreference='Continue'
& $compiler @arguments > (Join-Path $OutputDirectory "$name.build.stdout.log") 2> (Join-Path $OutputDirectory "$name.build.stderr.log")
$ErrorActionPreference='Stop'
if ($LASTEXITCODE) { throw "Experimental K compile failed: $Layer" }
& (Join-Path (Split-Path $compiler) 'llvm-objdump.exe') --disassemble --mcpu=gfx1201 $object `
> (Join-Path $OutputDirectory "$name.isa.txt")
if ($LASTEXITCODE) { throw 'Native object ISA extraction failed.' }
& (Join-Path (Split-Path $compiler) 'llvm-readobj.exe') --notes $object `
> (Join-Path $OutputDirectory "$name.metadata.txt")
if ($LASTEXITCODE) { throw 'Native object metadata extraction failed.' }
@{layer=$Layer; architecture='gfx1201'; experimental=$true; numericalValidation='pending';
mode=$Mode; nonTemporal=$NonTemporal; tokenTilesPerWave=$PosTiles; shareValues=[bool]$ShareValues;
privateValues=[bool]$PrivateValues;
packedAccumulator=[bool]$PackedAccumulator;
compiler=$compiler; arguments=$arguments;
sourceCommit=(git -C $repo rev-parse HEAD); workingTreeDirty=[bool](& git -C $repo status --porcelain);
compilerVersion=(& $compiler --version | Out-String).Trim();
sha256=(Get-FileHash -LiteralPath $object -Algorithm SHA256).Hash} |
ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $OutputDirectory "$name.build-info.json") -Encoding UTF8
Write-Host "Compiled gfx1201 K experiment: $Layer mode=$Mode nonTemporal=$NonTemporal posTiles=$PosTiles shareValues=$([bool]$ShareValues). Validate before installing."
# No override manifest or game installation is produced by this script.
@@ -1,40 +0,0 @@
[CmdletBinding()]
param([ValidateSet('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0')]
[string]$Layer='enc1', [string]$HipRoot, [string]$OutputDirectory)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo 'build/native-k-f16-wmma-experimental' }
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
if ($OutputDirectory -eq [IO.Path]::GetFullPath((Join-Path $repo 'build/native-k-gfx1201'))) {
throw 'Keep the validated baseline separate from this experimental build.'
}
$compiler=Join-Path $HipRoot 'lib/llvm/bin/clang++.exe'
if (!(Test-Path -LiteralPath $compiler)) { $compiler=Join-Path $HipRoot 'bin/clang++.exe' }
if (!(Test-Path -LiteralPath $compiler)) { throw "HIP compiler missing under $HipRoot" }
$name="dltss_pwin_${Layer}_layer"
$source=Join-Path $repo "kernels/k/$name.hip"
$flags=@()
if ((Get-Content -LiteralPath $source -Raw) -match '// d4r-build-flags: ([^\r\n]+)') { $flags=$Matches[1].Trim().Split(' ') }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$object=Join-Path $OutputDirectory "$name.hsaco"
$ErrorActionPreference='Continue'
& $compiler -x hip -std=c++17 --offload-arch=gfx1201 --offload-device-only --no-gpu-bundle-output `
-mno-wavefrontsize64 -nogpuinc -nogpulib -O3 -DD4R_DEVICE_ONLY_MINIMAL `
-DD4R_K_FP16_BASELINE -DD4R_K_F16_WMMA @flags $source -o $object `
> (Join-Path $OutputDirectory "$name.build.stdout.log") 2> (Join-Path $OutputDirectory "$name.build.stderr.log")
$ErrorActionPreference='Stop'
if ($LASTEXITCODE) { throw "Experimental K FP16 WMMA compile failed: $Layer" }
$isa=Join-Path $OutputDirectory "$name.isa.txt"
& (Join-Path (Split-Path $compiler) 'llvm-objdump.exe') --disassemble --mcpu=gfx1201 $object > $isa
if ($LASTEXITCODE -or !(Select-String -LiteralPath $isa -Pattern 'v_wmma_f16_16x16x16_f16')) {
throw 'Packed FP16 WMMA is absent from ISA; no alternative instruction is accepted.'
}
& (Join-Path (Split-Path $compiler) 'llvm-readobj.exe') --notes $object `
> (Join-Path $OutputDirectory "$name.metadata.txt")
if ($LASTEXITCODE) { throw 'Native object metadata extraction failed.' }
@{layer=$Layer; architecture='gfx1201'; experimental=$true; numericalValidation='pending';
compiler=$compiler; sha256=(Get-FileHash -LiteralPath $object -Algorithm SHA256).Hash} |
ConvertTo-Json | Set-Content -LiteralPath (Join-Path $OutputDirectory "$name.build-info.json") -Encoding UTF8
Write-Host "Compiled experimental gfx1201 packed FP16 WMMA: $Layer. Validate before selecting another layer."
# This script does not generate an override manifest or install into the game.
-59
View File
@@ -1,59 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$HipRoot, [string]$OutputDirectory, [switch]$HardwarePacking)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo $(if ($HardwarePacking) { 'build/native-m-fp8-hardware-pack' } else { 'build/native-m-fp8-experimental' }) }
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
if ($OutputDirectory -eq [IO.Path]::GetFullPath((Join-Path $repo 'build/native-m-gfx1201'))) {
throw 'Keep the validated FP16 baseline separate from the experimental FP8 build.'
}
$DlssDll=(Get-Item -LiteralPath $DlssDll -ErrorAction Stop).FullName
$compiler=Join-Path $HipRoot 'lib/llvm/bin/clang++.exe'
if (!(Test-Path -LiteralPath $compiler)) { $compiler=Join-Path $HipRoot 'bin/clang++.exe' }
if (!(Test-Path -LiteralPath $compiler)) { throw "HIP compiler missing under $HipRoot" }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$disassembler=Join-Path (Split-Path $compiler) 'llvm-objdump.exe'
if (!(Test-Path -LiteralPath $disassembler)) { throw 'HIP llvm-objdump is required to confirm native FP8 instructions.' }
foreach ($source in Get-ChildItem -LiteralPath (Join-Path $repo 'kernels/m') -Filter '*.hip' | Sort-Object Name) {
$flags=@()
if ((Get-Content -LiteralPath $source.FullName -Raw) -match '// d4r-build-flags: ([^\r\n]+)') { $flags=$Matches[1].Trim().Split(' ') }
if ($HardwarePacking) { $flags+='-DD4R_FP8_HW_PACK' }
$object=Join-Path $OutputDirectory ($source.BaseName+'.hsaco')
$ErrorActionPreference='Continue'
& $compiler -x hip -std=c++17 --offload-arch=gfx1201 --offload-device-only --no-gpu-bundle-output `
-mno-wavefrontsize64 -nogpuinc -nogpulib -O3 -DD4R_DEVICE_ONLY_MINIMAL `
-DSWIN_EXACT -DSWIN_EXACT_PV -DD4R_FP8_WMMA @flags $source.FullName `
-o $object > (Join-Path $OutputDirectory ($source.BaseName+'.build.stdout.log')) `
2> (Join-Path $OutputDirectory ($source.BaseName+'.build.stderr.log'))
$ErrorActionPreference='Stop'
if ($LASTEXITCODE) { throw "Experimental FP8 compile failed: $($source.Name)" }
$isa=Join-Path $OutputDirectory ($source.BaseName+'.isa.txt')
& $disassembler --disassemble --mcpu=gfx1201 $object > $isa
if ($LASTEXITCODE -or !(Select-String -LiteralPath $isa -Pattern 'v_wmma_f32_16x16x16_fp8_fp8')) {
throw "Native FP8 WMMA is absent from $($source.Name); no FP16 fallback is accepted."
}
if ($HardwarePacking -and !(Select-String -LiteralPath $isa -Pattern 'v_cvt_pk_fp8_f32')) { throw 'Native FP8 operand packing is absent from ISA.' }
Write-Host "Compiled gfx1201 FP8 WMMA: $($source.BaseName)"
}
if ($HardwarePacking) {
$probeDirectory=Join-Path $OutputDirectory 'packing-probe'
New-Item -ItemType Directory -Force $probeDirectory | Out-Null
& $compiler -x hip -std=c++17 --offload-arch=gfx1201 --offload-device-only --no-gpu-bundle-output `
-mno-wavefrontsize64 -nogpuinc -nogpulib -O3 -DD4R_DEVICE_ONLY_MINIMAL `
-DD4R_FP8_WMMA -DD4R_FP8_HW_PACK -DSWIN_EXACT -DSWIN_EXACT_PV `
(Join-Path $repo 'tools/windows/fp8_pack_probe.hip') -o (Join-Path $probeDirectory 'fp8_pack_probe.hsaco')
if ($LASTEXITCODE) { throw 'Native hardware packing diagnostic compile failed.' }
}
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $OutputDirectory $DlssDll
if ($LASTEXITCODE) { throw 'Experimental FP8 manifest generation failed.' }
@{architecture='gfx1201'; family='M'; experimental=$true; nativeFp8=$true; accuracy=$true;
numerics='SWIN_EXACT; SWIN_EXACT_PV; FP8 WMMA for e4m3 GEMMs; exact FP16 attention';
validation='not validated; do not install before layer/full-network checks';
compiler=$compiler; compilerVersion=(& $compiler --version | Select-Object -First 1);
sourceCommit=(& git -C $repo rev-parse HEAD).Trim(); nativeFp8IsaVerified=$true; hardwarePacking=[bool]$HardwarePacking;
sourceWorkingTreeDirty=[bool](& git -C $repo status --porcelain);
dlssSha256=(Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash;
modules=@(Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco' | Get-FileHash -Algorithm SHA256)} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'build-info.json') -Encoding UTF8
Write-Host "Experimental native FP8 M objects: $OutputDirectory (baseline unchanged)"
-19
View File
@@ -1,19 +0,0 @@
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$DlssDll,
[string]$Kernel = 'hiluma_engine_output_depthinv_mvlo_hdr_max_v2_rel',
[string]$HipRoot = 'C:\Program Files\AMD\ROCm\7.2',
[string]$ZludaRoot,
[ValidateSet('cu','wgp')][string]$ShaderMode='cu',
[string]$GpuArch='gfx1201',
[string]$OutputDirectory
)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
[void](Get-D4RGpuTargetInfo $GpuArch)
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/private-textures-$GpuArch" }
& python (Join-Path $repo 'tools/windows/build_native_texture.py') --dlss-dll $DlssDll --hip-root $HipRoot `
--zluda-root $ZludaRoot --kernel $Kernel --output-directory $OutputDirectory --shader-mode $ShaderMode --gpu-arch $GpuArch
if ($LASTEXITCODE) { throw "Native texture build failed ($LASTEXITCODE); inspect the output work directory." }
@@ -1,93 +0,0 @@
[CmdletBinding()]
param(
[string]$SourceRoot,
[string]$BuildToolsRoot,
[string]$InstallRoot,
[int]$Jobs = 6
)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/OptiScaler' }
if (!$InstallRoot) { $InstallRoot = Join-Path $repo 'dist/optiscaler-windows-d4r' }
$SourceRoot = [IO.Path]::GetFullPath($SourceRoot)
$InstallRoot = [IO.Path]::GetFullPath($InstallRoot)
$base = '45a2001303ddff632e279f77aef85ceede5832cb'
$patches = @(Get-ChildItem -LiteralPath (Join-Path $repo 'patches/optiscaler') -Filter '*.patch' | Sort-Object Name)
if (!$patches.Count) { throw 'OptiScaler source patches are missing.' }
$previousPath = $env:PATH
try {
# Git for Windows' submodule helper needs its POSIX utility directory.
$gitExe = (Get-Command git -ErrorAction Stop).Source
$gitInstall = [IO.Path]::GetFullPath((Join-Path (Split-Path $gitExe) '..'))
$gitUtilities = Join-Path $gitInstall 'usr/bin'
if (Test-Path -LiteralPath $gitUtilities) { $env:PATH = "$gitUtilities;$env:PATH" }
if (!(Test-Path -LiteralPath (Join-Path $SourceRoot '.git'))) {
& git clone --filter=blob:none --no-checkout https://github.com/optiscaler/OptiScaler.git $SourceRoot
if ($LASTEXITCODE) { throw 'OptiScaler clone failed.' }
& git -C $SourceRoot checkout --detach $base
if ($LASTEXITCODE) { throw 'Pinned OptiScaler checkout failed.' }
}
& git -C $SourceRoot merge-base --is-ancestor $base HEAD
if ($LASTEXITCODE) { throw "OptiScaler must be based on audited commit $base" }
foreach ($patch in $patches) {
$ErrorActionPreference = 'Continue'
& git -C $SourceRoot apply --reverse --check $patch.FullName 2>$null
$alreadyApplied = $LASTEXITCODE -eq 0
$ErrorActionPreference = 'Stop'
if (!$alreadyApplied) {
& git -C $SourceRoot apply --check $patch.FullName
if ($LASTEXITCODE) { throw "Source patch conflicts: $($patch.Name); existing changes retained." }
& git -C $SourceRoot apply $patch.FullName
if ($LASTEXITCODE) { throw "Source patch failed: $($patch.Name)" }
}
}
# Verify existing checkouts directly. A complete local checkout does not
# need Git's shell-based submodule helper (or a network connection).
$submodulePaths=@(& git -C $SourceRoot config --file .gitmodules --get-regexp '\.path$' | ForEach-Object { ($_ -split ' ',2)[1] })
$submodules=@()
foreach ($path in $submodulePaths) {
$tree=(& git -C $SourceRoot ls-tree HEAD -- $path) -split '\s+',4
if ($tree.Count -lt 4 -or $tree[0] -ne '160000') { throw "Missing pinned submodule: $path" }
$checkout=Join-Path $SourceRoot $path
$actual=if (Test-Path -LiteralPath (Join-Path $checkout '.git')) { (& git -C $checkout rev-parse HEAD).Trim() } else { '' }
if ($actual -ne $tree[2]) {
& git -C $SourceRoot submodule update --init --depth 1 -- $path
if ($LASTEXITCODE) { throw "Pinned OptiScaler submodule failed: $path" }
$actual=(& git -C $checkout rev-parse HEAD).Trim()
if ($actual -ne $tree[2]) { throw "Wrong submodule revision: $path" }
}
$submodules+=(' '+$actual+' '+$path)
}
if (!$BuildToolsRoot -and (Test-Path -LiteralPath (Join-Path $repo '.tools/vs2022/MSBuild/Current/Bin/MSBuild.exe'))) {
$BuildToolsRoot = Join-Path $repo '.tools/vs2022'
}
if (!$BuildToolsRoot) {
$vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio/Installer/vswhere.exe'
if (Test-Path -LiteralPath $vswhere) {
$BuildToolsRoot = & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
}
}
if (!$BuildToolsRoot) { throw 'MSVC v143 Build Tools and Windows SDK 10.0.26100 are required; see patches/optiscaler/README.md.' }
$msbuild = Join-Path $BuildToolsRoot 'MSBuild/Current/Bin/MSBuild.exe'
if (!(Test-Path -LiteralPath $msbuild)) { throw "MSBuild missing: $msbuild" }
New-Item -ItemType Directory -Force $InstallRoot | Out-Null
$log = Join-Path $InstallRoot 'build.log'
$ErrorActionPreference = 'Continue'
& $msbuild (Join-Path $SourceRoot 'OptiScaler.sln') "/m:$Jobs" /p:Configuration=Release /p:Platform=x64 `
/p:PostBuildEventUseInBuild=false /verbosity:quiet "/flp:logfile=$log;verbosity=normal"
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "OptiScaler build failed ($LASTEXITCODE); see $log" }
foreach ($file in @('OptiScaler.dll', 'OptiScaler.pdb')) {
Copy-Item -LiteralPath (Join-Path $SourceRoot "x64/Release/$file") -Destination $InstallRoot -Force
}
Copy-Item -LiteralPath (Join-Path $SourceRoot 'LICENSE') -Destination (Join-Path $InstallRoot 'GPL-3.0.txt') -Force
foreach ($patch in $patches) { Copy-Item -LiteralPath $patch.FullName -Destination $InstallRoot -Force }
$metadata = @{base=$base; sourceCommit=(& git -C $SourceRoot rev-parse HEAD).Trim();
sourceDirty=[bool](& git -C $SourceRoot status --porcelain); backendAbi=1;
buildTools=$BuildToolsRoot; msbuildVersion=(& $msbuild -version -nologo | Select-Object -Last 1);
patches=@($patches | ForEach-Object { @{name=$_.Name; sha256=(Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash} });
dllSha256=(Get-FileHash -LiteralPath (Join-Path $InstallRoot 'OptiScaler.dll') -Algorithm SHA256).Hash;
submodules=$submodules}
$metadata | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $InstallRoot 'build-info.json') -Encoding UTF8
Write-Host "Built OptiScaler with external Windows d4r backend: $InstallRoot"
} finally { $env:PATH = $previousPath }
@@ -1,44 +0,0 @@
[CmdletBinding()]
param(
[string[]]$GpuArchitectures,
[ValidateSet('stable','therock')][string]$RuntimeProfile='therock',
[string]$ZludaRoot, [string]$DlssDll,
[switch]$PackageGames,
[string]$BuildRoot, [string]$OutputRoot, [string]$ArchiveDirectory
)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$GpuArchitectures) { $GpuArchitectures=@(Get-D4RGpuTargets | ForEach-Object { $_.architecture }) }
foreach ($arch in $GpuArchitectures) { [void](Get-D4RGpuTargetInfo $arch) }
if (@($GpuArchitectures | Select-Object -Unique).Count -ne $GpuArchitectures.Count) { throw 'Duplicate GPU target.' }
if (!$BuildRoot) { $BuildRoot=Join-Path $repo 'build/windows-gpu-coverage' }
if (!$OutputRoot) { $OutputRoot=Join-Path $repo 'dist/windows-gpu-coverage' }
if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' }
if ($ArchiveDirectory -and !$PackageGames) { throw 'ArchiveDirectory requires PackageGames.' }
if ($PackageGames -and (!$DlssDll -or ![IO.Path]::IsPathRooted($DlssDll) -or !(Test-Path -LiteralPath $DlssDll))) {
throw 'PackageGames requires an absolute path to your local nvngx_dlss.dll; it will not be redistributed.'
}
New-Item -ItemType Directory -Force $BuildRoot | Out-Null
if ($ArchiveDirectory) { New-Item -ItemType Directory -Force $ArchiveDirectory | Out-Null }
$results=[Collections.Generic.List[object]]::new()
foreach ($arch in $GpuArchitectures) {
$build="$BuildRoot-$arch"; $diag="$OutputRoot-$arch"
$log=Join-Path $BuildRoot "$arch-build.log"
Write-Host "Building $arch (compile/package only; no GPU workloads). Log: $log"
& (Join-Path $PSScriptRoot 'build-windows-rdna4.ps1') -RuntimeProfile $RuntimeProfile -GpuArch $arch `
-ZludaRoot $ZludaRoot -BuildDirectory $build -InstallDirectory $diag *> $log
$row=[ordered]@{architecture=$arch; compiled=$true; hardwareTestExecuted=$false; buildDirectory=$build; diagnosticRoot=$diag; log=$log}
if ($PackageGames) {
$k="$BuildRoot-native-k-$arch"; $m="$BuildRoot-native-m-$arch"; $game="$OutputRoot-game-$arch"
& (Join-Path $PSScriptRoot 'stage-native-k.ps1') -DlssDll $DlssDll -PackageRoot $diag -GpuArch $arch -OutputDirectory $k
& (Join-Path $PSScriptRoot 'stage-native-m.ps1') -DlssDll $DlssDll -PackageRoot $diag -GpuArch $arch -OutputDirectory $m
$packageArgs=@{DiagnosticRoot=$diag; GpuArch=$arch; PackageRoot=$game; ZludaRoot=$ZludaRoot; KernelKRoot=$k; KernelMRoot=$m}
if ($ArchiveDirectory) { $packageArgs.ArchivePath=Join-Path $ArchiveDirectory "d4r-windows-$arch.zip" }
& (Join-Path $PSScriptRoot 'package-windows-game.ps1') @packageArgs
$row.gamePackage=$game
}
$results.Add($row)
$results | ConvertTo-Json -Depth 5 | Set-Content (Join-Path $BuildRoot 'matrix-build.json') -Encoding UTF8
Write-Host "Compiled $arch; hardware validation remains separate."
}
-79
View File
@@ -1,79 +0,0 @@
[CmdletBinding()]
param(
[string]$HipRoot = $env:HIP_PATH,
[ValidateSet('stable', 'therock')][string]$RuntimeProfile = 'stable',
[string]$GpuArch = 'gfx1201',
[string]$ZludaRoot,
[string]$ToolchainRoot,
[string]$BuildDirectory,
[string]$InstallDirectory
)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
[void](Get-D4RGpuTargetInfo $GpuArch)
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if ($RuntimeProfile -eq 'therock') {
if (!$PSBoundParameters.ContainsKey('HipRoot')) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$BuildDirectory) { $BuildDirectory = Join-Path $repo 'build/windows-rdna4-therock' }
if (!$InstallDirectory) { $InstallDirectory = Join-Path $repo 'dist/windows-rdna4-therock' }
}
if (!$HipRoot) { $HipRoot = 'C:\Program Files\AMD\ROCm\7.2' }
if (!$BuildDirectory) { $BuildDirectory = Join-Path $repo 'build/windows-rdna4' }
if (!$InstallDirectory) { $InstallDirectory = Join-Path $repo 'dist/windows-rdna4-diagnostics' }
if ($GpuArch -ne 'gfx1201') {
if (!$PSBoundParameters.ContainsKey('BuildDirectory')) { $BuildDirectory += "-$GpuArch" }
if (!$PSBoundParameters.ContainsKey('InstallDirectory')) { $InstallDirectory += "-$GpuArch" }
}
$HipRoot = [IO.Path]::GetFullPath($HipRoot).TrimEnd('\', '/')
$BuildDirectory = [IO.Path]::GetFullPath($BuildDirectory).TrimEnd('\', '/')
$InstallDirectory = [IO.Path]::GetFullPath($InstallDirectory).TrimEnd('\', '/')
if (!$ZludaRoot -and (Test-Path (Join-Path $repo '.tools/zluda/zluda/nvcuda.dll'))) {
$ZludaRoot = Join-Path $repo '.tools/zluda/zluda'
}
if (!$ToolchainRoot -and (Test-Path (Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64'))) {
$ToolchainRoot = Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64'
}
$cmakeCommand = Get-Command cmake -ErrorAction SilentlyContinue
$cmake = if ($cmakeCommand) { $cmakeCommand.Source } else { Join-Path $repo '.tools/python/cmake/data/bin/cmake.exe' }
$ninjaCommand = Get-Command ninja -ErrorAction SilentlyContinue
$ninja = if ($ninjaCommand) { $ninjaCommand.Source } else { Join-Path $repo '.tools/python/ninja/data/bin/ninja.exe' }
if (!(Test-Path $ninja)) { $ninja = Join-Path $repo '.tools/python/bin/ninja.exe' }
if (!(Test-Path $cmake) -or !(Test-Path $ninja)) {
throw 'CMake >=3.24 and Ninja required. See docs/windows-rdna4-port.md for local tool setup.'
}
New-Item -ItemType Directory -Force $BuildDirectory | Out-Null
$minhook = Join-Path $repo 'external/MinHook'
if (!(Test-Path (Join-Path $minhook 'include/MinHook.h'))) {
& git clone --depth 1 --branch v1.3.4 https://github.com/TsudaKageyu/minhook.git $minhook
if ($LASTEXITCODE) { throw 'MinHook 1.3.4 source download failed.' }
}
$minhookCommit = (& git -C $minhook rev-parse HEAD).Trim()
if ($minhookCommit -ne 'c3fcafdc10146beb5919319d0683e44e3c30d537') {
throw "Expected audited MinHook 1.3.4 source, found $minhookCommit"
}
$originalPath = $env:PATH
try {
$configure = @('--fresh', '-S', $repo, '-B', $BuildDirectory, '-G', 'Ninja', '-DCMAKE_BUILD_TYPE=RelWithDebInfo',
"-DCMAKE_MAKE_PROGRAM=$ninja", "-DD4R_HIP_ROOT=$HipRoot", "-DD4R_GPU_ARCH=$GpuArch", "-DCMAKE_INSTALL_PREFIX=$InstallDirectory")
if ($ToolchainRoot) {
$compiler = Join-Path $ToolchainRoot 'bin/x86_64-w64-mingw32-clang++.exe'
if (!(Test-Path $compiler)) { throw "Compiler missing: $compiler" }
$env:PATH = "$(Join-Path $ToolchainRoot 'bin');$originalPath"
$configure += "-DCMAKE_CXX_COMPILER=$compiler"
$configure += "-DCMAKE_C_COMPILER=$(Join-Path $ToolchainRoot 'bin/x86_64-w64-mingw32-clang.exe')"
}
if ($ZludaRoot) { $configure += "-DD4R_ZLUDA_ROOT=$ZludaRoot" }
$ErrorActionPreference = 'Continue'
& $cmake @configure 2>&1 | Tee-Object (Join-Path $BuildDirectory 'configure.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "CMake configure exit=$LASTEXITCODE" }
$ErrorActionPreference = 'Continue'
& $cmake --build $BuildDirectory --parallel 4 2>&1 | Tee-Object (Join-Path $BuildDirectory 'build.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "Build exit=$LASTEXITCODE" }
$ErrorActionPreference = 'Continue'
& $cmake --install $BuildDirectory 2>&1 | Tee-Object (Join-Path $BuildDirectory 'install.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "Install exit=$LASTEXITCODE" }
Write-Host "Built diagnostics: $InstallDirectory"
} finally { $env:PATH = $originalPath }
-70
View File
@@ -1,70 +0,0 @@
[CmdletBinding()]
param([string]$SourceRoot, [string]$HipRoot = 'C:\Program Files\AMD\ROCm\7.2', [string]$WorkRoot)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' }
if (!$WorkRoot) { $WorkRoot = Join-Path $repo 'build/zluda-helpers-windows' }
$toolchain = Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64'
$compiler = Join-Path $HipRoot 'bin/clang++.exe'
$dis = Join-Path $HipRoot 'bin/llvm-dis.exe'
$assembler = Join-Path $HipRoot 'bin/llvm-as.exe'
$ocml = Join-Path $HipRoot 'amdgcn/bitcode/ocml.bc'
foreach ($file in @($compiler,$dis,$assembler,$ocml)) {
if (!(Test-Path $file)) { throw "HIP helper dependency missing: $file" }
}
New-Item -ItemType Directory -Force $WorkRoot | Out-Null
$configInclude = Join-Path $WorkRoot 'libcxx-config'
New-Item -ItemType Directory -Force $configInclude | Out-Null
Copy-Item -LiteralPath (Join-Path $toolchain 'include/c++/v1/__config_site') -Destination $configInclude -Force
Copy-Item -LiteralPath (Join-Path $SourceRoot 'ext/llvm-project/libcxx/vendor/llvm/default_assertion_handler.in') `
-Destination (Join-Path $configInclude '__assertion_handler') -Force
# HIP 7.2's long shuffle overloads assume every non-MSVC compiler has LP64.
# Windows GNU also has 32-bit long. Correct that public header in a private
# mirror; the installed SDK remains untouched and the GPU target is unchanged.
$hipInclude = Join-Path $WorkRoot 'hip-include'
New-Item -ItemType Directory -Force $hipInclude | Out-Null
Copy-Item -LiteralPath (Join-Path $HipRoot 'include/hip') -Destination $hipInclude -Recurse -Force
$warpHeader = Join-Path $hipInclude 'hip/amd_detail/amd_warp_functions.h'
$warpSource = [IO.File]::ReadAllText($warpHeader)
$warpSource = $warpSource.Replace('#ifndef _MSC_VER', '#if __SIZEOF_LONG__ == 8')
[IO.File]::WriteAllText($warpHeader,$warpSource,[Text.UTF8Encoding]::new($false))
$variants = @(
@{Suffix=''; Flags=@()},
@{Suffix='_constrained'; Flags=@('-ffp-model=strict','-ffp-exception-behavior=ignore')},
@{Suffix='_w64'; Flags=@('-mwavefrontsize64','-DD4R_WAVE64')},
@{Suffix='_constrained_w64'; Flags=@('-ffp-model=strict','-ffp-exception-behavior=ignore','-mwavefrontsize64','-DD4R_WAVE64')}
)
foreach ($variant in $variants) {
$name = 'zluda_ptx_impl' + $variant.Suffix
$raw = Join-Path $WorkRoot "$name.raw.bc"
$ir = Join-Path $WorkRoot "$name.ll"
$output = Join-Path $SourceRoot "ptx/lib/$name.bc"
$arguments = @('-x','hip','-std=c++20','--target=x86_64-w64-windows-gnu','-stdlib=libc++',
'--offload-arch=gfx1030','--offload-device-only','-emit-llvm','-c','-nogpulib','-O3',
'-mno-wavefrontsize64','-DHIP_ENABLE_WARP_SYNC_BUILTINS',
'-Xclang','-fdenormal-fp-math=dynamic',
'-isystem',(Join-Path $SourceRoot 'ext/llvm-project/libcxx/include'),
'-isystem',$configInclude,
'-isystem',(Join-Path $toolchain 'include'),
'-I',$hipInclude,
'-Xclang','-mlink-bitcode-file','-Xclang',$ocml)
$arguments += $variant.Flags
$arguments += @('-o',$raw,(Join-Path $SourceRoot 'ptx/lib/zluda_ptx_impl.cpp'))
$ErrorActionPreference = 'Continue'
& $compiler @arguments 2>&1 | Tee-Object (Join-Path $WorkRoot "$name.compile.log")
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "PTX helper compile failed: $name ($LASTEXITCODE)" }
& $dis $raw -o $ir
if ($LASTEXITCODE) { throw "Disassemble failed: $raw" }
$clean = [Collections.Generic.List[string]]::new()
foreach ($line in [IO.File]::ReadLines($ir)) {
if ($line -match '@llvm.used|wchar_size|llvm.module.flags|__hip_cuid') { continue }
$line = $line -replace 'optnone','' -replace 'define hidden','define linkonce_odr'
$line = $line -replace '"target-cpu"="gfx1030"','' -replace '"target-features"="[^"]+"',''
$clean.Add($line)
}
[IO.File]::WriteAllLines($ir,$clean,[Text.UTF8Encoding]::new($false))
& $assembler $ir -o $output
if ($LASTEXITCODE) { throw "Assemble failed: $ir" }
Write-Host "Built $output ($((Get-Item $output).Length) bytes)"
}
-45
View File
@@ -1,45 +0,0 @@
[CmdletBinding()]
param([string]$SourceRoot, [string]$BuildRoot, [int]$Jobs = 4)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' }
if (!$BuildRoot) { $BuildRoot = Join-Path $repo 'build/zluda-llvm-windows-gnu' }
$toolchain = Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64'
$cmake = Join-Path $repo '.tools/python/cmake/data/bin/cmake.exe'
$ninja = Join-Path $repo '.tools/python/bin/ninja.exe'
if (!(Test-Path $ninja)) { $ninja = Join-Path $repo '.tools/python/ninja/data/bin/ninja.exe' }
if (!(Test-Path (Join-Path $SourceRoot 'ext/llvm-project/llvm/CMakeLists.txt'))) {
throw 'Run git submodule update --init --depth 1 ext/llvm-project in the ZLUDA checkout.'
}
New-Item -ItemType Directory -Force $BuildRoot | Out-Null
& (Join-Path $PSScriptRoot 'prepare-zluda-llvm-source.ps1') -LlvmSourceRoot (Join-Path $SourceRoot 'ext/llvm-project')
$oldPath = $env:PATH
try {
$env:PATH = "$(Join-Path $toolchain 'bin');$oldPath"
$arguments = @('-S', (Join-Path $SourceRoot 'ext/llvm-project/llvm'), '-B', $BuildRoot,
'-G', 'Ninja', "-DCMAKE_MAKE_PROGRAM=$ninja", '-DCMAKE_BUILD_TYPE=Release',
"-DCMAKE_C_COMPILER=$(Join-Path $toolchain 'bin/x86_64-w64-mingw32-clang.exe')",
"-DCMAKE_CXX_COMPILER=$(Join-Path $toolchain 'bin/x86_64-w64-mingw32-clang++.exe')",
'-DLLVM_TARGETS_TO_BUILD=AMDGPU', '-DLLVM_ENABLE_PROJECTS=llvm;lld',
'-DLLVM_ENABLE_WARNINGS=OFF', '-DLLVM_ENABLE_TERMINFO=OFF', '-DLLVM_ENABLE_LIBXML2=OFF',
'-DLLVM_ENABLE_LIBEDIT=OFF', '-DLLVM_ENABLE_LIBPFM=OFF', '-DLLVM_ENABLE_ZLIB=OFF',
'-DLLVM_ENABLE_ZSTD=OFF', '-DLLVM_INCLUDE_BENCHMARKS=OFF', '-DLLVM_INCLUDE_EXAMPLES=OFF',
'-DLLVM_INCLUDE_TESTS=OFF', '-DLLVM_BUILD_TESTS=OFF', '-DLLVM_BUILD_TOOLS=OFF',
'-DLLVM_OPTIMIZED_TABLEGEN=ON', '-DLLVM_PARALLEL_LINK_JOBS=1')
$ErrorActionPreference = 'Continue'
& $cmake @arguments 2>&1 | Tee-Object (Join-Path $BuildRoot 'configure.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "LLVM configure failed ($LASTEXITCODE)" }
$ErrorActionPreference = 'Continue'
& $cmake --build $BuildRoot --parallel $Jobs --target llvm-config llvm-libraries lldCommon lldELF `
2>&1 | Tee-Object (Join-Path $BuildRoot 'build.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "LLVM build failed ($LASTEXITCODE)" }
& (Join-Path $BuildRoot 'bin/llvm-config.exe') --version
if ($LASTEXITCODE) { throw 'llvm-config verification failed' }
@{sourceBase=(& git -C (Join-Path $SourceRoot 'ext/llvm-project') rev-parse HEAD).Trim(); fullSourceDeltaVerified=$true;
sourcePatches=@(Get-ChildItem (Join-Path $repo 'patches/zluda-llvm') -Filter *.patch | ForEach-Object {
@{name=$_.Name; sha256=(Get-FileHash -LiteralPath $_.FullName).Hash}})} |
ConvertTo-Json -Depth 5 | Set-Content (Join-Path $BuildRoot 'd4r-llvm-build-info.json') -Encoding UTF8
Write-Host "Native Windows LLVM: $BuildRoot"
} finally { $env:PATH = $oldPath }
-96
View File
@@ -1,96 +0,0 @@
[CmdletBinding()]
param([string]$SourceRoot, [string]$LlvmBuildRoot, [string]$InstallRoot, [switch]$FetchOnly, [switch]$CacheTestsOnly, [switch]$CompilerTestsOnly, [int]$Jobs = 4)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' }
if (!$LlvmBuildRoot) { $LlvmBuildRoot = Join-Path $repo 'build/zluda-llvm-windows-gnu' }
if (!$InstallRoot) { $InstallRoot = Join-Path $repo 'dist/zluda-windows-final' }
$rust = Join-Path $repo '.tools/rust-1.98.1-gnu'
$toolchain = Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64'
$target = Join-Path $repo 'build/zluda-rust-windows-gnu'
New-Item -ItemType Directory -Force $target,$InstallRoot | Out-Null
$settings = @{
PATH="$(Join-Path $rust 'bin');$(Join-Path $toolchain 'bin');$(Join-Path $repo '.tools/python/cmake/data/bin');$(Join-Path $repo '.tools/python/bin');C:\Program Files\Git\usr\bin;$env:PATH"
CARGO_HOME=(Join-Path $repo '.tools/cargo-home')
CARGO_TARGET_DIR=$target
CARGO_BUILD_JOBS="$Jobs"
RUSTC=(Join-Path $rust 'bin/rustc.exe')
CC=(Join-Path $toolchain 'bin/x86_64-w64-mingw32-clang.exe')
CXX=(Join-Path $toolchain 'bin/x86_64-w64-mingw32-clang++.exe')
AR=(Join-Path $toolchain 'bin/llvm-ar.exe')
CXXSTDLIB='c++'
LIBRARY_PATH=(Join-Path $rust 'lib/rustlib/x86_64-pc-windows-gnu/lib/self-contained')
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=(Join-Path $toolchain 'bin/x86_64-w64-mingw32-clang.exe')
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUSTFLAGS='-C link-arg=-static'
ZLUDA_LLVM_BUILD_DIR=$LlvmBuildRoot
}
$previous = @{}
foreach ($name in $settings.Keys) {
$previous[$name] = [Environment]::GetEnvironmentVariable($name,'Process')
[Environment]::SetEnvironmentVariable($name,$settings[$name],'Process')
}
Push-Location $SourceRoot
try {
$cargo = Join-Path $rust 'bin/cargo.exe'
if (!(Test-Path $cargo)) { throw 'Run setup-rust-toolchain.ps1 first.' }
if ($CompilerTestsOnly) {
$ErrorActionPreference = 'Continue'
& $cargo test --locked --release --target x86_64-pc-windows-gnu -p llvm_zluda shader_mode_tests `
2>&1 | Tee-Object (Join-Path $target 'compiler-tests.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "ZLUDA compiler regression tests failed ($LASTEXITCODE)" }
return
}
if ($CacheTestsOnly) {
$ErrorActionPreference = 'Continue'
& $cargo test --locked --release --target x86_64-pc-windows-gnu -p zluda_cache `
2>&1 | Tee-Object (Join-Path $target 'cache-tests.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "ZLUDA cache regression tests failed ($LASTEXITCODE)" }
return
}
if ($FetchOnly) {
$ErrorActionPreference = 'Continue'
& $cargo fetch --locked --target x86_64-pc-windows-gnu 2>&1 | Tee-Object (Join-Path $target 'fetch.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "Cargo fetch failed ($LASTEXITCODE)" }
return
}
if (!(Test-Path (Join-Path $LlvmBuildRoot 'bin/llvm-config.exe'))) { throw 'Run build-zluda-llvm.ps1 first.' }
foreach ($variant in @('','_constrained','_w64','_constrained_w64')) {
if (!(Test-Path "ptx/lib/zluda_ptx_impl$variant.bc")) { throw 'Run build-zluda-helpers.ps1 first.' }
}
$ErrorActionPreference = 'Continue'
& $cargo build --locked --release --target x86_64-pc-windows-gnu -p zluda -p nvapi -p zluda_trace `
2>&1 | Tee-Object (Join-Path $target 'build.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "ZLUDA build failed ($LASTEXITCODE)" }
$ErrorActionPreference = 'Continue'
& $cargo build --locked --release --target x86_64-pc-windows-gnu -p ptx --example d4r_emit `
2>&1 | Tee-Object (Join-Path $target 'emit-build.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "d4r_emit build failed ($LASTEXITCODE)" }
$release = Join-Path $target 'x86_64-pc-windows-gnu/release'
Copy-Item -LiteralPath (Join-Path $release 'nvcuda.dll') -Destination $InstallRoot -Force
Copy-Item -LiteralPath (Join-Path $release 'nvapi64.dll') -Destination $InstallRoot -Force
# The C++ dependencies select libc++ dynamically even when Rust requests
# static GNU support libraries. Keep these portable runtime DLLs local.
foreach ($runtime in @('libc++.dll', 'libunwind.dll')) {
Copy-Item -LiteralPath (Join-Path $toolchain "bin/$runtime") -Destination $InstallRoot -Force
}
New-Item -ItemType Directory -Force (Join-Path $InstallRoot 'trace') | Out-Null
Copy-Item -LiteralPath (Join-Path $release 'zluda_trace.dll') -Destination (Join-Path $InstallRoot 'trace/nvcuda.dll') -Force
Copy-Item -LiteralPath (Join-Path $release 'examples/d4r_emit.exe') -Destination $InstallRoot -Force
@{base='ee2f25a180099fa42f36b2346732e1f2470a03ad'; target='x86_64-pc-windows-gnu';
sourceCommit=(& git rev-parse HEAD); workingTreeDirty=[bool](& git status --porcelain);
rust='1.98.1'; llvm=(& (Join-Path $LlvmBuildRoot 'bin/llvm-config.exe') --version);
llvmSource=$(if (Test-Path (Join-Path $LlvmBuildRoot 'd4r-llvm-build-info.json')) {
Get-Content (Join-Path $LlvmBuildRoot 'd4r-llvm-build-info.json') -Raw | ConvertFrom-Json
} else { $null });
files=@(Get-ChildItem -LiteralPath $InstallRoot -Filter '*.dll' | Get-FileHash -Algorithm SHA256)} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $InstallRoot 'build-info.json') -Encoding UTF8
Write-Host "Native Windows d4r ZLUDA runtime: $InstallRoot"
} finally {
Pop-Location
foreach ($name in $previous.Keys) { [Environment]::SetEnvironmentVariable($name,$previous[$name],'Process') }
}
-58
View File
@@ -1,58 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][int]$GameProcessId, [Parameter(Mandatory=$true)][string]$OutputPath)
$ErrorActionPreference = 'Stop'
Add-Type -AssemblyName System.Drawing
if (!('D4RWindowCapture' -as [type])) {
Add-Type @'
using System;
using System.Runtime.InteropServices;
using System.Text;
public static class D4RWindowCapture {
public delegate bool Callback(IntPtr window, IntPtr data);
[StructLayout(LayoutKind.Sequential)] public struct Rect { public int Left, Top, Right, Bottom; }
[DllImport("user32.dll")] public static extern bool EnumWindows(Callback callback, IntPtr data);
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr window, out uint process);
[DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr window, out Rect rect);
[DllImport("user32.dll",CharSet=CharSet.Unicode)] public static extern int GetWindowText(IntPtr window, StringBuilder text, int count);
[DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr window);
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")] public static extern IntPtr SetThreadDpiAwarenessContext(IntPtr context);
}
'@
}
$windows = [Collections.Generic.List[object]]::new()
$previousDpi=[D4RWindowCapture]::SetThreadDpiAwarenessContext([IntPtr](-4))
try {
$callback = [D4RWindowCapture+Callback]{ param($window,$data)
[uint32]$owner = 0
[void][D4RWindowCapture]::GetWindowThreadProcessId($window,[ref]$owner)
if ($owner -eq $GameProcessId) {
$rect = [D4RWindowCapture+Rect]::new()
[void][D4RWindowCapture]::GetWindowRect($window,[ref]$rect)
$title = [Text.StringBuilder]::new(512)
[void][D4RWindowCapture]::GetWindowText($window,$title,512)
$windows.Add([pscustomobject]@{handle=$window; title=$title.ToString(); visible=[D4RWindowCapture]::IsWindowVisible($window); rect=$rect;
area=($rect.Right-$rect.Left)*($rect.Bottom-$rect.Top)})
}
return $true
}
[void][D4RWindowCapture]::EnumWindows($callback,[IntPtr]::Zero)
$windows | Select-Object handle,title,visible,area | Format-Table
$chosen = $windows | Where-Object { $_.visible -and $_.area -gt 4096 } | Sort-Object area -Descending | Select-Object -First 1
if (!$chosen) { throw "No visible game window for PID $GameProcessId" }
if ([D4RWindowCapture]::GetForegroundWindow() -ne $chosen.handle) {
throw 'Game window is not foreground; capture refused to avoid including unrelated overlapping windows.'
}
$rect = $chosen.rect
$bitmap = [Drawing.Bitmap]::new($rect.Right-$rect.Left,$rect.Bottom-$rect.Top)
$graphics = [Drawing.Graphics]::FromImage($bitmap)
try {
$graphics.CopyFromScreen($rect.Left,$rect.Top,0,0,$bitmap.Size)
$bitmap.Save([IO.Path]::GetFullPath($OutputPath),[Drawing.Imaging.ImageFormat]::Png)
} finally {
$graphics.Dispose(); $bitmap.Dispose()
}
Write-Host "Captured game window: $OutputPath"
} finally {
if ($previousDpi -ne [IntPtr]::Zero) { [void][D4RWindowCapture]::SetThreadDpiAwarenessContext($previousDpi) }
}
-101
View File
@@ -1,101 +0,0 @@
[CmdletBinding()]
param(
[int]$TargetProcessId,
[string]$ProcessName = 'SHProto-Win64-Shipping',
[ValidateRange(5,300)][int]$Seconds = 30,
[ValidateRange(0,300)][int]$DelaySeconds = 0,
[string]$PresentMonPath,
[switch]$GpuTelemetry,
[string]$TelemetryPath,
[string]$GpuName = 'RX 9070 XT',
[string]$OutputDirectory
)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$PresentMonPath) {
$PresentMonPath=Join-Path $repo '.tools/presentmon-2.6.0/PresentMon.exe'
if (!(Test-Path -LiteralPath $PresentMonPath)) {
New-Item -ItemType Directory -Force (Split-Path $PresentMonPath) | Out-Null
Invoke-WebRequest -UseBasicParsing -Uri 'https://github.com/GameTechDev/PresentMon/releases/download/v2.6.0/PresentMon-2.6.0-x64.exe' -OutFile $PresentMonPath
}
}
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/presentmon-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$PresentMonPath=(Get-Item -LiteralPath $PresentMonPath -ErrorAction Stop).FullName
if ((Get-FileHash -LiteralPath $PresentMonPath -Algorithm SHA256).Hash.ToLowerInvariant() -ne
'b2a706bc6ad475749e3b7e3409263aa1e6906d45bdcf993f6dbc0f660188f1af') {
throw 'Expected the official PresentMon 2.6.0 x64 CLI. See docs/windows-performance.md.'
}
if ($TargetProcessId) { $target=Get-Process -Id $TargetProcessId -ErrorAction Stop }
else {
$targets=@(Get-Process -Name $ProcessName -ErrorAction Stop)
if ($targets.Count -ne 1) { throw 'Select one running game process using -TargetProcessId.' }
$target=$targets[0]
}
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$csv=Join-Path $OutputDirectory 'presentmon.csv'
if (Test-Path -LiteralPath $csv) { throw 'Preserve the existing capture; choose another OutputDirectory.' }
if ($TelemetryPath) { $GpuTelemetry=$true }
if ($GpuTelemetry) {
if (!$TelemetryPath) { $TelemetryPath=Join-Path $repo 'build/gpu-telemetry/d4r_gpu_telemetry.exe' }
$TelemetryPath=(Get-Item -LiteralPath $TelemetryPath -ErrorAction Stop).FullName
if ($GpuName.Contains('"')) { throw 'GpuName cannot contain a double quote.' }
foreach ($file in @('gpu-telemetry.csv','gpu-telemetry.stderr.log','gpu-telemetry-environment.json')) {
if (Test-Path -LiteralPath (Join-Path $OutputDirectory $file)) { throw "Preserve existing $file; choose another OutputDirectory." }
}
}
@{version='2.6.0'; executable=$PresentMonPath; sha256=(Get-FileHash -LiteralPath $PresentMonPath -Algorithm SHA256).Hash;
targetProcessId=$target.Id; processName=$target.ProcessName; seconds=$Seconds; delaySeconds=$DelaySeconds;
gpuTelemetryRequested=[bool]$GpuTelemetry;
hwsRegistry=$(Get-ItemPropertyValue -LiteralPath 'HKLM:/SYSTEM/CurrentControlSet/Control/GraphicsDrivers' -Name HwSchMode -ErrorAction SilentlyContinue);
driver=@(Get-CimInstance Win32_VideoController | Select-Object Name,DriverVersion)} |
ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'presentmon-environment.json') -Encoding UTF8
# Unique ETW session: never stop or replace an existing user's trace. The CLI
# terminates itself at the bound/process exit, without a service installation.
$session='D4R_' + [Guid]::NewGuid().ToString('N')
$telemetry=$null; $telemetryStarted=$false; $outStream=$null; $errStream=$null; $outTask=$null; $errTask=$null
try {
if ($GpuTelemetry) {
$info=[Diagnostics.ProcessStartInfo]::new()
$info.FileName=$TelemetryPath; $info.UseShellExecute=$false; $info.CreateNoWindow=$true
$info.RedirectStandardOutput=$true; $info.RedirectStandardError=$true
$info.Arguments="--seconds $Seconds --delay-ms $($DelaySeconds*1000) --interval-ms 500 --target-pid $($target.Id) --gpu-name `"$GpuName`""
$outStream=[IO.File]::Open((Join-Path $OutputDirectory 'gpu-telemetry.csv'),[IO.FileMode]::CreateNew,[IO.FileAccess]::Write,[IO.FileShare]::Read)
$errStream=[IO.File]::Open((Join-Path $OutputDirectory 'gpu-telemetry.stderr.log'),[IO.FileMode]::CreateNew,[IO.FileAccess]::Write,[IO.FileShare]::Read)
$telemetry=[Diagnostics.Process]::new(); $telemetry.StartInfo=$info
if (!$telemetry.Start()) { throw 'GPU telemetry process failed to start.' }
$telemetryStarted=$true
$outTask=$telemetry.StandardOutput.BaseStream.CopyToAsync($outStream)
$errTask=$telemetry.StandardError.BaseStream.CopyToAsync($errStream)
}
& $PresentMonPath --process_id $target.Id --timed $Seconds --delay $DelaySeconds --terminate_after_timed --terminate_on_proc_exit --session_name $session --no_console_stats --no_track_input --qpc_time_ms --output_file $csv 2>&1 |
Tee-Object -FilePath (Join-Path $OutputDirectory 'presentmon-console.log')
if ($LASTEXITCODE) { throw "PresentMon failed with exit code $LASTEXITCODE; see presentmon-console.log." }
} finally {
try { if ($telemetryStarted) {
$timedOut=$false
if (!$telemetry.HasExited -and !$telemetry.WaitForExit(30000)) { $timedOut=$true; $telemetry.Kill(); $telemetry.WaitForExit() }
if ($outTask) { [void]$outTask.GetAwaiter().GetResult() }
if ($errTask) { [void]$errTask.GetAwaiter().GetResult() }
$driverDll=Join-Path $env:WINDIR 'System32/amdadlx64.dll'
$driverInfo=$null
if (Test-Path -LiteralPath $driverDll) {
$driverInfo=@{path=$driverDll; version=(Get-Item -LiteralPath $driverDll).VersionInfo.FileVersion;
sha256=(Get-FileHash -LiteralPath $driverDll -Algorithm SHA256).Hash}
}
@{executable=$TelemetryPath; sha256=(Get-FileHash -LiteralPath $TelemetryPath -Algorithm SHA256).Hash;
exitCode=$telemetry.ExitCode; timeout=$timedOut; targetProcessId=$target.Id; gpuName=$GpuName;
intervalMs=500; driverDll=$driverInfo; readOnly=$true;
buildInfo=$(if (Test-Path -LiteralPath (Join-Path (Split-Path $TelemetryPath) 'build-info.json')) {
Get-Content -LiteralPath (Join-Path (Split-Path $TelemetryPath) 'build-info.json') -Raw | ConvertFrom-Json
})} |
ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'gpu-telemetry-environment.json') -Encoding UTF8
if ($telemetry.ExitCode -ne 0) { Write-Warning 'GPU telemetry failed; retain PresentMon capture and see gpu-telemetry.stderr.log.' }
} } finally {
if ($telemetry) { $telemetry.Dispose() }
if ($outStream) { $outStream.Dispose() }
if ($errStream) { $errStream.Dispose() }
}
}
if (!(Test-Path -LiteralPath $csv) -or (Get-Item -LiteralPath $csv).Length -eq 0) { throw 'PresentMon captured no frames.' }
Write-Host "PresentMon capture: $csv"
-25
View File
@@ -1,25 +0,0 @@
[CmdletBinding()]
param([string]$SourceRoot)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' }
$base = 'ee2f25a180099fa42f36b2346732e1f2470a03ad'
$relative = 'build/zluda-patch-check-' + [Guid]::NewGuid().ToString('N')
$snapshot = Join-Path $repo $relative
New-Item -ItemType Directory -Force $snapshot | Out-Null
$archive = "$snapshot.tar"
& git -C $SourceRoot archive --format=tar "--output=$archive" $base
if ($LASTEXITCODE) { throw 'Could not archive the pinned ZLUDA base.' }
& tar.exe -xf $archive -C $snapshot
if ($LASTEXITCODE) { throw 'Could not extract the ZLUDA patch-check snapshot.' }
Push-Location $repo
try {
foreach ($patch in (Get-ChildItem -LiteralPath (Join-Path $repo 'patches/zluda') -Filter '*.patch' | Sort-Object Name)) {
& git apply "--directory=$relative" --check $patch.FullName
if ($LASTEXITCODE) { throw "Fresh-source patch check failed: $($patch.Name)" }
& git apply "--directory=$relative" --whitespace=nowarn $patch.FullName
if ($LASTEXITCODE) { throw "Fresh-source patch apply failed: $($patch.Name)" }
Write-Host "PASS patch $($patch.Name)"
}
Write-Host "Pinned-source patch snapshot: $snapshot"
} finally { Pop-Location }
-271
View File
@@ -1,271 +0,0 @@
# Checks a d4r install on Windows. It only reads files and prints what it finds.
# Run it from the game folder (the one holding the game's .exe and d4r\), or give that folder:
# powershell -ExecutionPolicy Bypass -File d4r\d4r-check.ps1 [GAME_FOLDER]
# Add -Report to also write one ZIP (logs, this output, GPU and driver) to send with a bug report.
[CmdletBinding()]
param(
[string]$GameFolder,
[switch]$Report,
[string]$InventoryFile, # tests: a gpu-inventory.json to use instead of running the GPU query
[string]$ReportDirectory # tests: where -Report writes its ZIP (default: your Desktop)
)
$ErrorActionPreference = 'Stop'
if (!$GameFolder) {
$GameFolder = if ((Split-Path $PSScriptRoot -Leaf) -eq 'd4r') { Split-Path $PSScriptRoot -Parent } else { (Get-Location).Path }
}
$game = [IO.Path]::GetFullPath($GameFolder).TrimEnd('\')
$d4r = Join-Path $game 'd4r'
$problems = 0
$lines = [Collections.Generic.List[string]]::new()
function Say([string]$text) { $lines.Add($text); Write-Host $text }
function Ok([string]$text) { Say (' ok ' + $text) }
function Bad([string]$text) { Say (' MISSING ' + $text); $script:problems++ }
function Note([string]$text) { Say (' note ' + $text) }
function Hash([string]$path) { (Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash }
function Version([string]$path) {
try { $v = (Get-Item -LiteralPath $path).VersionInfo; if ($v.FileVersion) { return ($v.FileVersion -replace ',\s*', '.') } } catch {}
return 'unknown'
}
function Read-TextFile([string]$path) { [IO.File]::ReadAllText($path) }
Say "d4r install in $game"
if (!(Test-Path -LiteralPath $d4r -PathType Container)) {
Say 'no d4r folder here; run this from the folder with the game .exe (extract the d4r ZIP there first)'
exit 1
}
if (@(Get-ChildItem -LiteralPath $game -Filter '*.exe' -File -ErrorAction SilentlyContinue).Count) { Ok 'game executable next to d4r\' }
else { Note 'no .exe next to d4r\ (the d4r files must sit in the folder of the game''s main .exe; for Unreal Engine games that is <game>\<Project>\Binaries\Win64)' }
# --- the install's own file list ---------------------------------------------------------------
$manifest = $null
$manifestPath = Join-Path $d4r 'package.json'
if (Test-Path -LiteralPath $manifestPath) {
try { $manifest = Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json } catch { $manifest = $null }
}
if (!$manifest) { Bad 'd4r\package.json is missing or damaged (extract the d4r ZIP again)' }
# --- files --------------------------------------------------------------------------------------
$required = @('dxgi.dll', 'OptiScaler.ini', 'd4r\_nvngx.dll', 'd4r\d4r.ini', 'd4r\dll-pins.txt',
'd4r\hip\bin\amdhip64_7.dll', 'd4r\zluda\nvcuda.dll', 'd4r\zluda\nvapi64.dll')
foreach ($file in $required) {
if (Test-Path -LiteralPath (Join-Path $game $file) -PathType Leaf) { Ok $file }
else { Bad "$file (extract the d4r ZIP again over the game folder)" }
}
if ($manifest) {
$edited = @('OptiScaler.ini', 'd4r/d4r.ini') # players are meant to edit these
$damaged = 0
foreach ($entry in $manifest.files) {
$path = Join-Path $game ($entry.path -replace '/', '\')
if (!(Test-Path -LiteralPath $path -PathType Leaf)) {
if ($required -notcontains ($entry.path -replace '/', '\')) { Bad "$($entry.path) (extract the d4r ZIP again)" }
continue
}
if ((Hash $path) -ne $entry.sha256) {
if ($entry.path -eq 'dxgi.dll') { Note 'dxgi.dll is not the one that came with d4r (another OptiScaler or ReShade?). Move it away and extract the d4r ZIP again' }
elseif ($edited -contains $entry.path) { Note "$($entry.path) has been edited (fine if you did it)" }
else { Bad "$($entry.path) differs from the release (damaged or replaced; extract the d4r ZIP again)"; $damaged++ }
}
}
if (!$damaged) { Ok 'every other d4r file matches the release' }
}
# --- OptiScaler.ini ---------------------------------------------------------------------------
$optiIni = Join-Path $game 'OptiScaler.ini'
if (Test-Path -LiteralPath $optiIni) {
$text = Read-TextFile $optiIni
if ($text -notmatch '(?im)^\s*AllowExternalBackend\s*=\s*true') { Bad 'OptiScaler.ini: [DLSS] AllowExternalBackend must be true (this is not the d4r OptiScaler.ini)' }
if ($text -notmatch '(?im)^\s*Dx12Upscaler\s*=\s*dlss') { Note 'OptiScaler.ini: [Upscalers] Dx12Upscaler is not dlss; the game will not use d4r' }
$m = [regex]::Match($text, '(?im)^\s*NvngxPath\s*=\s*(\S+)')
if (!$m.Success) { Bad 'OptiScaler.ini: [Libraries] NvngxPath is missing (it must name the d4r folder)' }
else {
$folder = $m.Groups[1].Value
$resolved = if ([IO.Path]::IsPathRooted($folder)) { $folder } else { Join-Path $game $folder }
if (Test-Path -LiteralPath (Join-Path $resolved '_nvngx.dll')) { Ok "OptiScaler.ini NvngxPath = $folder" }
else { Bad "OptiScaler.ini NvngxPath = $folder does not hold _nvngx.dll (use NvngxPath=d4r, or the full path of the d4r folder)" }
}
}
# --- NVIDIA DLLs (never shipped; the exact versions come from dll-pins.txt) -----------------------
$pins = @()
$pinsPath = Join-Path $d4r 'dll-pins.txt'
if (Test-Path -LiteralPath $pinsPath) {
foreach ($line in Get-Content -LiteralPath $pinsPath) {
$line = $line.Trim()
if (!$line -or $line.StartsWith('#')) { continue }
$f = $line -split '\s+'
if ($f.Count -ge 4 -and $f[1].Length -eq 64) { $pins += [pscustomobject]@{ kind = $f[0]; sha = $f[1].ToUpperInvariant(); version = $f[2]; status = $f[3] } }
}
}
function Check-Nvidia([string]$kind, [string]$relative, [string]$label, [string]$source) {
$path = Join-Path $game $relative
$wanted = @($pins | Where-Object { $_.kind -eq $kind } | ForEach-Object { $_.version }) -join ' or '
if (!$wanted) { Note "$label cannot be checked (d4r\dll-pins.txt is missing or damaged)"; return }
if (!(Test-Path -LiteralPath $path -PathType Leaf)) { Bad "${relative}: copy NVIDIA's $label here (version $wanted; $source)"; return }
$hash = Hash $path
$pin = @($pins | Where-Object { $_.kind -eq $kind -and $_.sha -eq $hash }) | Select-Object -First 1
if (!$pin) { Bad "$relative is version $(Version $path), which d4r does not accept. d4r on Windows needs exactly $wanted ($source)"; return }
if ($pin.status -eq 'validated') { Ok "$relative ($label $($pin.version), tested on Windows)" }
else { Ok "$relative ($label $($pin.version))"; Note "$label $($pin.version) is accepted but has had less Windows testing" }
}
Check-Nvidia 'dlss' 'd4r\nvngx_dlss.dll' 'nvngx_dlss.dll' 'many games ship one in their folder; see WINDOWS_README.txt'
Check-Nvidia 'ngx' 'd4r\ngx\_nvngx.dll' '_nvngx.dll' 'it is part of NVIDIA''s display driver package; see WINDOWS_README.txt'
# --- GPU and the build for it --------------------------------------------------------------------
$registryPath = Join-Path $d4r 'gpu-targets.json'
$registry = @()
if (Test-Path -LiteralPath $registryPath) { $registry = @((Get-Content -LiteralPath $registryPath -Raw | ConvertFrom-Json).targets) }
$inventory = $null
if ($InventoryFile) { $inventory = Get-Content -LiteralPath $InventoryFile -Raw | ConvertFrom-Json }
elseif (Test-Path -LiteralPath (Join-Path $d4r 'd4r_gpu_inventory.exe')) {
$work = Join-Path ([IO.Path]::GetTempPath()) ('d4r-check-' + [Guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $work | Out-Null
try {
$info = New-Object Diagnostics.ProcessStartInfo
$info.FileName = Join-Path $d4r 'd4r_gpu_inventory.exe'
$info.Arguments = '--hip-root "' + (Join-Path $d4r 'hip') + '" --output-dir "' + $work + '"'
$info.UseShellExecute = $false; $info.CreateNoWindow = $true
$info.RedirectStandardOutput = $true; $info.RedirectStandardError = $true
$info.EnvironmentVariables['D4R_DIAG_DIR'] = $work
$process = New-Object Diagnostics.Process; $process.StartInfo = $info
[void]$process.Start()
$null = $process.StandardOutput.ReadToEndAsync(); $null = $process.StandardError.ReadToEndAsync()
if (!$process.WaitForExit(30000)) { $process.Kill(); $process.WaitForExit() }
if (Test-Path -LiteralPath (Join-Path $work 'gpu-inventory.json')) { $inventory = Get-Content -LiteralPath (Join-Path $work 'gpu-inventory.json') -Raw | ConvertFrom-Json }
} catch {} finally {
$process.Dispose()
Get-ChildItem -LiteralPath $work -File -ErrorAction SilentlyContinue | ForEach-Object { Remove-Item -LiteralPath $_.FullName }
Remove-Item -LiteralPath $work -ErrorAction SilentlyContinue
}
}
$arch = $null
if (!$inventory) { Note 'could not ask the AMD runtime about your GPU (d4r_gpu_inventory.exe is missing, or the AMD graphics driver is not installed or is too old)' }
else {
$supported = @($registry | ForEach-Object { $_.architecture })
$devices = @($inventory.devices | Where-Object { $_.wavefrontSize -eq 32 -and ($supported -contains $_.architecture -or !$supported.Count) })
if (!$devices.Count) {
$seen = @($inventory.devices | ForEach-Object { "$($_.name) ($($_.architecture))" }) -join ', '
Bad ("no supported RDNA3/RDNA4 GPU found by the AMD runtime. It sees: " + $(if ($seen) { $seen } else { 'nothing' }) + '. Update the AMD Adrenalin driver; RDNA2 and older are not supported')
} else {
foreach ($device in $devices) {
$a = $device.architecture
$missing = @()
foreach ($rel in @("d4r\_nvngx_$a.dll", "d4r\pixel_convert_$a.hsaco", "d4r\nvapi\$a\nvapi64.dll", "d4r\native\$a\d4r-kernels.txt")) {
if (!(Test-Path -LiteralPath (Join-Path $game $rel))) { $missing += $rel }
}
$native = @(Get-ChildItem -LiteralPath (Join-Path $d4r "native\$a") -Filter '*.hsaco' -ErrorAction SilentlyContinue).Count
if ($missing.Count) { Bad "GPU $($device.name) ($a): this release has no complete build for it (missing: $($missing -join ', '))" }
else {
Ok "GPU $($device.name) ($a): build present, $native native kernels"
if (!$arch) { $arch = $a }
}
if ($a -ne 'gfx1201') { Note "only the RX 9070 XT (gfx1201) has been tested on real hardware; $a is compile-tested" }
}
}
if (@($inventory.devices | Where-Object { $_.wavefrontSize -eq 32 }).Count -gt 1) { Note 'several GPUs found; d4r uses the one the game renders on' }
}
if ($arch -and $registry.Count) {
$info = @($registry | Where-Object { $_.architecture -eq $arch }) | Select-Object -First 1
$bad = 0
$objects = @(Get-Item -LiteralPath (Join-Path $d4r "pixel_convert_$arch.hsaco") -ErrorAction SilentlyContinue) +
@(Get-ChildItem -LiteralPath (Join-Path $d4r "native\$arch") -Filter '*.hsaco' -ErrorAction SilentlyContinue)
foreach ($object in $objects) {
$stream = [IO.File]::OpenRead($object.FullName)
try { $header = New-Object byte[] 64; [void]$stream.Read($header, 0, 64) } finally { $stream.Dispose() }
if ($header[0] -ne 127 -or $header[1] -ne 69 -or $header[2] -ne 76 -or $header[3] -ne 70 -or $header[48] -ne $info.elfMachine) {
Bad "$($object.Name) is not built for $arch (do not rename or mix files from other GPUs; extract the d4r ZIP again)"; $bad++
}
}
if ($objects.Count -and !$bad) { Ok "all $($objects.Count) GPU code objects are built for $arch" }
}
# --- Linux / Wine leftovers ------------------------------------------------------------------------
$proxyFound = $false
foreach ($name in @('d3d12.dll', 'd3d12core.dll')) {
$proxy = Join-Path $game $name
if (Test-Path -LiteralPath $proxy -PathType Leaf) {
$item = Get-Item -LiteralPath $proxy
if ($item.Length -le 64MB -and [Text.Encoding]::ASCII.GetString([IO.File]::ReadAllBytes($proxy)) -match '(?i)vkd3d|wined3d') {
Bad "$name in the game folder is vkd3d-proton/Wine (left over from a Linux install?). Move it out; d4r on Windows uses native D3D12"
$proxyFound = $true
}
}
}
if (!$proxyFound) { Ok 'no vkd3d/Wine d3d12.dll in the game folder' }
# --- d4r.ini ---------------------------------------------------------------------------------------
$iniPath = Join-Path $d4r 'd4r.ini'
$model = 'K'
if (Test-Path -LiteralPath $iniPath) {
$section = ''; $iniProblems = 0
$known = @{ 'dlss.model' = 1; 'dlss.showwatermark' = 1; 'interop.asyncinterop' = 1; 'debug.validateoutput' = 1; 'debug.log' = 1; 'paths.cachedir' = 1 }
$boolean = @('dlss.showwatermark', 'interop.asyncinterop', 'debug.validateoutput')
foreach ($raw in (Read-TextFile $iniPath).TrimStart([char]0xFEFF) -split "`n") {
$line = $raw.Trim()
if (!$line -or $line.StartsWith(';') -or $line.StartsWith('#')) { continue }
if ($line.StartsWith('[')) { $section = $line.Trim('[', ']').Trim(); continue }
$eq = $line.IndexOf('='); if ($eq -lt 0) { continue }
$key = $line.Substring(0, $eq).Trim()
$value = ($line.Substring($eq + 1) -replace '\s[;#].*$', '').Trim()
$name = ("$section.$key").ToLowerInvariant()
$v = $value.ToLowerInvariant()
if (!$known.ContainsKey($name)) { Note "d4r.ini: [$section] $key is not a Windows setting; ignored"; $iniProblems++ }
elseif ($name -eq 'dlss.model') {
if (@('', 'auto', 'k', 'dlss4', '11') -contains $v) { $model = 'K' }
elseif (@('m', 'dlss4.5', '13') -contains $v) { $model = 'M' }
else { Note "d4r.ini: [DLSS] Model '$value' is not available on Windows (use K or M); K will be used"; $iniProblems++ }
}
elseif ($boolean -contains $name) {
if (@('', 'auto', '1', 'true', 'yes', 'on', '0', 'false', 'no', 'off') -notcontains $v) { Note "d4r.ini: [$section] $key must be true or false, not '$value'; the default will be used"; $iniProblems++ }
}
elseif ($name -eq 'debug.log' -and @('', 'auto', 'normal', 'verbose') -notcontains $v) { Note "d4r.ini: [Debug] Log must be normal or verbose, not '$value'; normal will be used"; $iniProblems++ }
}
if (!$iniProblems) { Ok "d4r.ini is valid (model $model)" }
}
# --- what the last game start said -----------------------------------------------------------------
$log = Join-Path $d4r 'd4r_nvngx.log'
if (Test-Path -LiteralPath $log) {
$messages = @(Get-Content -LiteralPath $log | Where-Object { $_ -match '^d4r: ' })
$failed = @($messages | Where-Object { $_ -match 'DLSS disabled' })
if ($failed.Count) { foreach ($m in $failed | Select-Object -First 3) { Bad ('last game start: ' + $m.Substring(5)) } }
elseif ($messages.Count) { Ok ('last game start: ' + $messages[0].Substring(5)) }
else { Note 'd4r\d4r_nvngx.log has no d4r summary line yet (the game may not have chosen DLSS)' }
foreach ($m in $messages | Where-Object { $_ -notmatch 'DLSS disabled|player mode' } | Select-Object -First 5) { Note ('last game start: ' + $m.Substring(5)) }
} else { Note 'no d4r\d4r_nvngx.log yet: start the game once and choose DLSS (or FSR/XeSS) in its graphics settings' }
if (Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path -and $_.Path.StartsWith($game + '\', [StringComparison]::OrdinalIgnoreCase) -and $_.ProcessName -notmatch '^(powershell|pwsh)$' }) {
Note 'the game is running; its log is rewritten at every start'
}
Say ''
if ($problems -eq 0) { Say 'Everything d4r needs is in place.' } else { Say "$problems thing(s) to fix above." }
# --- bug-report ZIP ------------------------------------------------------------------------------
if ($Report) {
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$destination = if ($ReportDirectory) { $ReportDirectory } else { [Environment]::GetFolderPath('Desktop') }
$staging = Join-Path ([IO.Path]::GetTempPath()) ("d4r-report-$stamp")
New-Item -ItemType Directory -Force -Path $staging | Out-Null
try {
$lines | Set-Content -LiteralPath (Join-Path $staging 'check.txt') -Encoding UTF8
foreach ($file in @('d4r\d4r_nvngx.log', 'd4r\d4r.ini', 'OptiScaler.ini', 'OptiScaler.log')) {
$source = Join-Path $game $file
if (Test-Path -LiteralPath $source) { Copy-Item -LiteralPath $source -Destination (Join-Path $staging (Split-Path $file -Leaf)) }
}
Get-ChildItem -LiteralPath $game -Filter 'OptiScaler*.log' -File | ForEach-Object { Copy-Item -LiteralPath $_.FullName -Destination $staging -Force }
try { Get-CimInstance Win32_VideoController | Select-Object Name, DriverVersion, DriverDate | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $staging 'driver.json') -Encoding UTF8 } catch {}
if ($inventory) { $inventory | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $staging 'gpu-inventory.json') -Encoding UTF8 }
Get-ChildItem -LiteralPath $game -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.FullName.StartsWith($d4r + '\') -or $_.Name -in @('dxgi.dll', 'OptiScaler.ini') } |
ForEach-Object { '{0} {1,12} {2}' -f (Hash $_.FullName), $_.Length, $_.FullName.Substring($game.Length + 1) } |
Set-Content -LiteralPath (Join-Path $staging 'files.sha256.txt') -Encoding UTF8
$zip = Join-Path $destination "d4r-report-$stamp.zip"
Compress-Archive -Path (Join-Path $staging '*') -DestinationPath $zip -Force
Write-Host ''
Write-Host "Bug report written: $zip" -ForegroundColor Cyan
Write-Host 'Also tell us: GPU, game, K or M, and what the image looked like. The logs can contain local folder names; look before posting publicly.'
} finally {
Get-ChildItem -LiteralPath $staging -File -ErrorAction SilentlyContinue | ForEach-Object { Remove-Item -LiteralPath $_.FullName }
Remove-Item -LiteralPath $staging -ErrorAction SilentlyContinue
}
}
if ($problems) { exit 1 }
-32
View File
@@ -1,32 +0,0 @@
# Parse completed diagnostic records. Empty streams are valid, including games
# that refuse a debugger before initializing the upscaler.
function Get-D4RGameSummary {
param([AllowEmptyString()][string]$Stdout='', [AllowEmptyString()][string]$Stderr='',
[AllowEmptyString()][string]$Debugger='', [int]$Preset=11, [double]$RunSeconds=0,
[bool]$ValidateOutput=$false, $GameCrash=$null)
$gameExit=[regex]::Match($Debugger, 'EXIT code=0x([0-9a-f]+)')
$exitCode=if ($gameExit.Success) { '0x'+$gameExit.Groups[1].Value } else { 'diagnostic_timeout' }
$frames=[regex]::Matches($Stdout, '(?m)^D4R_FRAME cpu_frame_copies=([0-9]+) frame_age=([0-9]+) interop_ngx_ms=([0-9.]+)\r?$')
$checks=[regex]::Matches($Stdout, '(?m)^D4R_OUTPUT_VALIDATION elements=([0-9]+) nan=([0-9]+) inf=([0-9]+) diagnostics_cpu_bytes=8\r?$')
$launches=[regex]::Matches($Stderr, '\[d4r-launch\] kernel="([^"]+)" backend=(native|translated)')
$kernels=@($launches | ForEach-Object { $_.Groups[1].Value+' '+$_.Groups[2].Value } | Group-Object | ForEach-Object {
$parts=$_.Name.Split(' '); @{kernel=$parts[0]; backend=$parts[1]; launches=$_.Count}
})
$capabilities=@([regex]::Matches($Stdout, '(?m)^D4R_CAPABILITIES available=(-?[0-9]+) feature_init=(0x[0-9a-f]+) needs_driver=(-?[0-9]+)\r?$') |
ForEach-Object { $_.Groups[2].Value } | Select-Object -Unique)
$session=if ($frames.Count) { 'completed-dlss-frames' }
elseif ($capabilities -contains '0xbad00004') { 'ngx-feature-not-found' }
elseif ($capabilities.Count -and $capabilities -ne '0x00000001') { 'ngx-capability-failure' }
elseif ($exitCode -eq '0x0') { 'process-exited-without-dlss-frames' }
elseif ($exitCode -eq 'diagnostic_timeout') { 'diagnostic-timeout-without-dlss-frames' }
else { 'process-failed-before-dlss-frames' }
return [ordered]@{exitCode=$exitCode; session=$session; featureInitResults=$capabilities;
runSeconds=$RunSeconds; preset=$Preset; gameCrash=$GameCrash;
nativeLaunches=([regex]::Matches($Stderr, '\[d4r-launch\].*backend=native')).Count;
completedFrames=$frames.Count; outputValidationRequested=$ValidateOutput;
outputGpuChecks=$checks.Count; kernels=$kernels;
nonfiniteOutputs=@($checks | Where-Object { $_.Groups[2].Value -ne '0' -or $_.Groups[3].Value -ne '0' }).Count;
previousFrameOutputs=@($frames | Where-Object { $_.Groups[2].Value -ne '0' }).Count;
cpuImageCopyFrames=@($frames | Where-Object { $_.Groups[1].Value -ne '0' }).Count;
failures=([regex]::Matches($Stderr, 'D4R_[A-Z0-9_]*FAILURE\b')).Count}
}
-58
View File
@@ -1,58 +0,0 @@
# Read-only inventory before touching game files. It allocates no GPU memory
# and executes no kernels; successful discovery is not hardware validation.
function Invoke-D4RGpuPreflight([string]$PackageRoot, [string]$GameDirectory, [string]$Target, [string]$OutputDirectory) {
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$result=[ordered]@{passed=$false; target=$Target; gpuWorkExecuted=$false; failure=$null}
try {
$proxy=Join-Path $GameDirectory 'd3d12.dll'
if (Test-Path -LiteralPath $proxy) {
$item=Get-Item -LiteralPath $proxy
$result.localD3D12=@{path=$proxy; sha256=(Get-FileHash -LiteralPath $proxy).Hash; product=$item.VersionInfo.ProductName}
# Identify known Vulkan/Wine proxies by their own strings. Do not
# load, remove or replace a third-party game DLL.
if ($item.Length -le 64MB -and [Text.Encoding]::ASCII.GetString([IO.File]::ReadAllBytes($proxy)) -match '(?i)vkd3d|wined3d') {
throw 'Local d3d12.dll identifies as vkd3d/Wine. Restore the game native D3D12 installation before using this Windows backend.'
}
}
$info=[Diagnostics.ProcessStartInfo]::new()
$info.FileName=Join-Path $PackageRoot 'd4r/d4r_gpu_inventory.exe'
$hip=Join-Path $PackageRoot 'd4r/hip'
foreach ($value in @($hip,$OutputDirectory)) { if ($value.Contains('"')) { throw 'Unsupported quote in inventory path.' } }
$info.Arguments='--hip-root "' + $hip + '" --output-dir "' + $OutputDirectory + '"'
$info.UseShellExecute=$false; $info.CreateNoWindow=$true
$info.EnvironmentVariables['D4R_DIAG_DIR']=$OutputDirectory
$info.RedirectStandardOutput=$true; $info.RedirectStandardError=$true
$process=[Diagnostics.Process]::new(); $process.StartInfo=$info
try {
if (!$process.Start()) { throw 'Cannot start GPU inventory.' }
$stdout=$process.StandardOutput.ReadToEndAsync(); $stderr=$process.StandardError.ReadToEndAsync()
$timedOut=!$process.WaitForExit(30000)
if ($timedOut) { $process.Kill(); $process.WaitForExit() }
$stdout.GetAwaiter().GetResult() | Set-Content (Join-Path $OutputDirectory 'gpu-inventory.stdout.log') -Encoding UTF8
$stderr.GetAwaiter().GetResult() | Set-Content (Join-Path $OutputDirectory 'gpu-inventory.stderr.log') -Encoding UTF8
$result.exitCode=$process.ExitCode
$result.exceptionOrExitHex='0x{0:X8}' -f [BitConverter]::ToUInt32([BitConverter]::GetBytes([int]$process.ExitCode),0)
if ($timedOut) { $result.timedOut=$true; throw 'HIP inventory timed out after 30 seconds.' }
if ($process.ExitCode) { throw "HIP inventory failed (exit $($process.ExitCode))." }
} finally { $process.Dispose() }
$inventory=Get-Content (Join-Path $OutputDirectory 'gpu-inventory.json') -Raw | ConvertFrom-Json
$result.inventory=$inventory
if ($inventory.compiledTarget -ne $Target) { throw "Inventory executable targets $($inventory.compiledTarget); package requires $Target." }
$matching=@($inventory.devices | Where-Object { $_.architecture -eq $Target -and $_.wavefrontSize -eq 32 })
if (!$matching.Count) {
$actual=@($inventory.devices | ForEach-Object { "$($_.architecture) ($($_.name))" }) -join ', '
throw "GPU target mismatch: detected $actual; package requires $Target. Use the package for the actual HIP architecture; do not rename code objects."
}
$result.passed=$true
Write-Host "D4R_PREFLIGHT target=$Target devices=$($matching.Count) gpu_work_executed=0"
} catch {
$result.failure=$_.Exception.Message
$result | ConvertTo-Json -Depth 8 | Set-Content (Join-Path $OutputDirectory 'preflight.json') -Encoding UTF8
try { Get-CimInstance Win32_VideoController | Select-Object Name,DriverVersion,DriverDate | ConvertTo-Json |
Set-Content (Join-Path $OutputDirectory 'driver.json') -Encoding UTF8 } catch {}
$bundle=$OutputDirectory+'.zip'
Compress-Archive -Path (Join-Path $OutputDirectory '*') -DestinationPath $bundle -Force
throw "$($result.failure) Diagnostic bundle: $bundle"
}
$result | ConvertTo-Json -Depth 8 | Set-Content (Join-Path $OutputDirectory 'preflight.json') -Encoding UTF8
}
-38
View File
@@ -1,38 +0,0 @@
# Shared by the build, diagnostics, staging and game package scripts.
function Get-D4RGpuTargets {
$registry=Join-Path $PSScriptRoot 'gpu-targets.json'
if (!(Test-Path -LiteralPath $registry)) { $registry=Join-Path $PSScriptRoot '../../tools/windows/gpu-targets.json' }
$data=Get-Content -LiteralPath $registry -Raw | ConvertFrom-Json
if ($data.schema -ne 1) { throw 'Unsupported GPU target registry schema.' }
return $data.targets
}
function Get-D4RGpuTargetInfo([string]$Target) {
$info=@(Get-D4RGpuTargets | Where-Object { $_.architecture -eq $Target })
if ($info.Count -ne 1) { throw "Unsupported GPU target: $Target" }
return $info[0]
}
function Get-D4RGpuTarget([string]$Root, [string]$Requested) {
$configured=$null
$targetFile=Join-Path $Root 'gpu-target.json'
if (Test-Path -LiteralPath $targetFile) {
$configured=(Get-Content -LiteralPath $targetFile -Raw | ConvertFrom-Json).architecture
[void](Get-D4RGpuTargetInfo $configured)
}
$target=if ($Requested) { $Requested } elseif ($configured) { $configured } else { 'gfx1201' }
[void](Get-D4RGpuTargetInfo $target)
if (!$configured -and $target -ne 'gfx1201') { throw "A $target build requires gpu-target.json; rebuild with -GpuArch $target." }
if ($configured -and $target -ne $configured) { throw "Requested $target differs from package target $configured" }
return $target
}
function Assert-D4RCodeObjectTarget([string]$Path, [string]$Target) {
$info=Get-D4RGpuTargetInfo $Target
$reader=[IO.BinaryReader]::new([IO.File]::OpenRead($Path))
try { $header=$reader.ReadBytes(64) } finally { $reader.Dispose() }
if ($header.Length -ne 64 -or $header[0] -ne 127 -or $header[1] -ne 69 -or $header[2] -ne 76 -or $header[3] -ne 70 -or
$header[4] -ne 2 -or $header[5] -ne 1 -or $header[18] -ne 224 -or $header[19] -ne 0) {
throw "Invalid AMDGPU ELF64 code object: $Path"
}
# LLVM AMDGPU e_flags machine IDs; inspect, never patch or spoof them.
$expected=$info.elfMachine
if ($header[48] -ne $expected) { throw "Code object does not target ${Target}: $Path (ELF machine=$($header[48]))" }
}
-137
View File
@@ -1,137 +0,0 @@
[CmdletBinding()]
param(
[string]$PackageRoot, [string]$DiagnosticRoot, [string]$OptiScalerRoot,
[string]$ZludaRoot, [string]$HipRoot, [string]$KernelKRoot, [string]$KernelMRoot,
[string]$GpuArch,
[string]$ArchivePath
)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$defaults = @{PackageRoot='dist/windows-rdna4-game'; DiagnosticRoot='dist/windows-rdna4-command-list';
OptiScalerRoot='dist/optiscaler-windows-d4r'; ZludaRoot='dist/zluda-windows-final';
HipRoot='.tools/therock-10.2.0a20260929/_rocm_sdk_core'}
foreach ($name in $defaults.Keys) {
if (!(Get-Variable -Name $name -ValueOnly)) { Set-Variable -Name $name -Value (Join-Path $repo $defaults[$name]) }
}
$GpuArch=Get-D4RGpuTarget $DiagnosticRoot $GpuArch
if ($GpuArch -ne 'gfx1201' -and !$PSBoundParameters.ContainsKey('PackageRoot')) { $PackageRoot += "-$GpuArch" }
if (!$KernelKRoot) { $KernelKRoot=Join-Path $repo "build/native-k-$GpuArch" }
if (!$KernelMRoot) { $KernelMRoot=Join-Path $repo "build/native-m-$GpuArch" }
foreach ($directory in @($KernelKRoot,$KernelMRoot)) {
$info=Join-Path $directory 'build-info.json'
if ((Test-Path -LiteralPath $info) -and (Get-Content -LiteralPath $info -Raw | ConvertFrom-Json).architecture -ne $GpuArch) {
throw "Native kernel directory does not target ${GpuArch}: $directory"
}
}
$PackageRoot = [IO.Path]::GetFullPath($PackageRoot)
if (Test-Path -LiteralPath (Join-Path $PackageRoot 'gpu-target.json')) {
[void](Get-D4RGpuTarget $PackageRoot $GpuArch)
}
$sourceCommit=(& git -C $repo rev-parse HEAD).Trim()
$sourceDirty=[bool](& git -C $repo status --porcelain)
if ($ArchivePath -and $sourceDirty) { throw 'Commit source changes before creating the distributable archive.' }
New-Item -ItemType Directory -Force $PackageRoot | Out-Null
$stagedFiles = [Collections.Generic.List[string]]::new()
function Stage([string]$source, [string]$relative) {
if (!(Test-Path -LiteralPath $source -PathType Leaf)) { throw "Required file missing: $source" }
if ($source.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget $source $GpuArch }
$destination = Join-Path $PackageRoot $relative
New-Item -ItemType Directory -Force (Split-Path $destination) | Out-Null
Copy-Item -LiteralPath $source -Destination $destination -Force
$stagedFiles.Add($relative)
}
Stage (Join-Path $OptiScalerRoot 'OptiScaler.dll') 'OptiScaler.dll'
Stage (Join-Path $DiagnosticRoot 'bin/d4r_nvngx.dll') 'd4r/_nvngx.dll'
Stage (Join-Path $DiagnosticRoot "bin/pixel_convert_${GpuArch}.hsaco") "d4r/pixel_convert_${GpuArch}.hsaco"
Stage (Join-Path $DiagnosticRoot 'nvapi-compat/nvapi64.dll') 'd4r/nvapi/nvapi64.dll'
Stage (Join-Path $DiagnosticRoot 'bin/d4r_debug_launcher.exe') 'd4r/d4r_debug_launcher.exe'
Stage (Join-Path $DiagnosticRoot 'bin/d4r_gpu_inventory.exe') 'd4r/d4r_gpu_inventory.exe'
foreach ($file in @('nvcuda.dll','nvapi64.dll','libc++.dll','libunwind.dll')) { Stage (Join-Path $ZludaRoot $file) "d4r/zluda/$file" }
foreach ($file in @('amdhip64_7.dll','amd_comgr.dll','hiprtc0717.dll','hiprtc-builtins0717.dll','rocm_kpack.dll','AMD.ROCM.Comgr.MANIFEST','.hipVersion')) {
Stage (Join-Path $HipRoot "bin/$file") "d4r/hip/bin/$file"
}
$entries = @{}
foreach ($directory in @($KernelKRoot, $KernelMRoot)) {
foreach ($line in Get-Content -LiteralPath (Join-Path $directory 'd4r-kernels.txt')) {
if (!$line.Trim() -or $line.StartsWith('#')) { continue }
if ($line -notmatch '^([A-Za-z0-9_]+) ([0-9a-f]{16})$') { throw "Invalid native manifest entry: $line" }
if ($entries.ContainsKey($Matches[1])) { throw "Duplicate native kernel: $($Matches[1])" }
$entries[$Matches[1]] = $line
Stage (Join-Path $directory ($Matches[1] + '.hsaco')) ('d4r/native/' + $Matches[1] + '.hsaco')
}
}
if ($entries.Count -ne 16) { throw "Expected 11 K and 5 M native objects; found $($entries.Count)" }
@("# Audited DLSS 310.9.1: K + M $GpuArch native kernels", '# Generated by package-windows-game.ps1') + @($entries.Values | Sort-Object) |
Set-Content -LiteralPath (Join-Path $PackageRoot 'd4r/native/d4r-kernels.txt') -Encoding ASCII
$stagedFiles.Add('d4r/native/d4r-kernels.txt')
Stage (Join-Path $repo 'scripts/windows/windows-game.ps1') 'windows-game.ps1'
Stage (Join-Path $repo 'scripts/windows/game-summary.ps1') 'game-summary.ps1'
Stage (Join-Path $repo 'scripts/windows/gpu-target.ps1') 'gpu-target.ps1'
Stage (Join-Path $repo 'scripts/windows/gpu-preflight.ps1') 'gpu-preflight.ps1'
Stage (Join-Path $repo 'tools/windows/gpu-targets.json') 'gpu-targets.json'
if (Test-Path -LiteralPath (Join-Path $DiagnosticRoot 'gpu-target.json')) {
Stage (Join-Path $DiagnosticRoot 'gpu-target.json') 'gpu-target.json'
} else {
# Builds predating target metadata were gfx1201 only. The resolver rejects
# any attempt to label such a build gfx1200.
@{schema=1; architecture=$GpuArch; wavefrontSize=32; validation='Legacy gfx1201 build; run the GPU diagnostics.'} |
ConvertTo-Json | Set-Content -LiteralPath (Join-Path $PackageRoot 'gpu-target.json') -Encoding UTF8
$stagedFiles.Add('gpu-target.json')
}
Stage (Join-Path $repo 'scripts/windows/capture-game-window.ps1') 'capture-game-window.ps1'
Stage (Join-Path $repo 'scripts/windows/send-game-key.ps1') 'send-game-key.ps1'
Stage (Join-Path $repo 'docs/windows-game.md') 'README.md'
Stage (Join-Path $repo 'docs/windows-performance.md') 'windows-performance.md'
Stage (Join-Path $repo 'docs/windows-gpu-support.md') 'windows-gpu-support.md'
Stage (Join-Path $repo 'docs/windows-rdna4-port.md') 'windows-rdna4-port.md'
Stage (Join-Path $repo 'LICENSE') 'licenses/d4r.txt'
Stage (Join-Path $OptiScalerRoot 'GPL-3.0.txt') 'licenses/OptiScaler.txt'
Stage (Join-Path $repo 'external/ZLUDA/LICENSE-MIT') 'licenses/ZLUDA-MIT.txt'
Stage (Join-Path $repo 'external/ZLUDA/LICENSE-APACHE') 'licenses/ZLUDA-APACHE.txt'
Stage (Join-Path $repo 'external/ZLUDA/ext/llvm-project/LICENSE.TXT') 'licenses/LLVM.txt'
Stage (Join-Path $repo 'external/MinHook/LICENSE.txt') 'licenses/MinHook.txt'
Stage (Join-Path $HipRoot 'share/doc/amd_comgr/LICENSE.txt') 'licenses/amd_comgr.txt'
Stage (Join-Path $repo 'external/clr/LICENSE.md') 'licenses/HIP-CLR.txt'
foreach ($patch in Get-ChildItem -LiteralPath (Join-Path $repo 'patches/optiscaler') -Filter '*.patch') { Stage $patch.FullName ('source-patches/optiscaler/' + $patch.Name) }
foreach ($patch in Get-ChildItem -LiteralPath (Join-Path $repo 'patches/zluda') -Filter '*.patch') { Stage $patch.FullName ('source-patches/zluda/' + $patch.Name) }
foreach ($patch in Get-ChildItem -LiteralPath (Join-Path $repo 'patches/zluda-llvm') -Filter '*.patch') { Stage $patch.FullName ('source-patches/zluda-llvm/' + $patch.Name) }
$sourceArchive=Join-Path $repo 'build/d4r-windows-rdna4-source.zip'
New-Item -ItemType Directory -Force (Split-Path $sourceArchive) | Out-Null
& git -C $repo archive --format=zip --output $sourceArchive $sourceCommit
if ($LASTEXITCODE) { throw 'Cannot archive the committed d4r source.' }
Stage $sourceArchive 'source/d4r-windows-rdna4-source.zip'
$metadata = [ordered]@{
architecture=$GpuArch; hardwareValidation=$(if ($GpuArch -eq 'gfx1201') { 'RX9070XT tested; other SKUs unverified' } else { 'compile-only; hardware unverified' }); nativeKernels=16; dlssSha256='3975567b8943c53acce397f2b72380092f84f162d00b0d2c7d08a1025c563983';
d4rCommit=$sourceCommit;
d4rWorkingTreeDirty=$sourceDirty;
optiScaler=(Get-Content -LiteralPath (Join-Path $OptiScalerRoot 'build-info.json') -Raw | ConvertFrom-Json);
zludaBuild=(Get-Content -LiteralPath (Join-Path $ZludaRoot 'build-info.json') -Raw | ConvertFrom-Json);
hipRuntime='TheRock 10.2.0a20260929 / HIP 7.17.26386';
files=@($stagedFiles | ForEach-Object { Get-Item -LiteralPath (Join-Path $PackageRoot $_) } | ForEach-Object {
@{path=$_.FullName.Substring($PackageRoot.Length+1); sha256=(Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash; version=$_.VersionInfo.FileVersion}
})
}
$metadata | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath (Join-Path $PackageRoot 'package.json') -Encoding UTF8
if (Get-ChildItem -LiteralPath $PackageRoot -Recurse -File | Where-Object { $_.Name -eq 'nvngx_dlss.dll' -or ($_.Name -eq '_nvngx.dll' -and $_.DirectoryName -ne (Join-Path $PackageRoot 'd4r')) }) {
throw 'Proprietary NVIDIA binaries must not be in the package.'
}
Write-Host "Windows game development package: $PackageRoot (NVIDIA DLLs excluded)"
if ($ArchivePath) {
$ArchivePath=[IO.Path]::GetFullPath($ArchivePath)
if ($ArchivePath.StartsWith($PackageRoot+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Place the ZIP outside the package directory.' }
Add-Type -AssemblyName System.IO.Compression,System.IO.Compression.FileSystem
New-Item -ItemType Directory -Force (Split-Path $ArchivePath) | Out-Null
$stream=[IO.File]::Open($ArchivePath,[IO.FileMode]::Create,[IO.FileAccess]::ReadWrite,[IO.FileShare]::None)
$archive=$null
try {
$archive=[IO.Compression.ZipArchive]::new($stream,[IO.Compression.ZipArchiveMode]::Create)
# Never archive caches, results, private texture outputs or a local DLL
# merely because it happens to be somewhere under PackageRoot.
foreach ($relative in @($stagedFiles)+@('package.json')) {
[void][IO.Compression.ZipFileExtensions]::CreateEntryFromFile($archive,
(Join-Path $PackageRoot $relative),$relative.Replace('\','/'),[IO.Compression.CompressionLevel]::Optimal)
}
} finally { if ($archive) { $archive.Dispose() }; $stream.Dispose() }
Write-Host "Public package archive: $ArchivePath"
}
@@ -1,109 +0,0 @@
[CmdletBinding()]
param(
[string]$GamePackagePrefix, [Parameter(Mandatory=$true)][string]$PackageRoot,
[string]$ArchivePath,
[string]$NvidiaDirectory, [string]$NvidiaLicensePath
)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$GamePackagePrefix) { $GamePackagePrefix=Join-Path $repo 'dist/windows-gpu-coverage-game' }
$PackageRoot=[IO.Path]::GetFullPath($PackageRoot)
if (Test-Path -LiteralPath $PackageRoot) { throw 'Use a new output directory to avoid mixing releases.' }
$commit=(& git -C $repo rev-parse HEAD).Trim()
if ($ArchivePath -and [bool](& git -C $repo status --porcelain)) { throw 'Commit source changes before creating a public ZIP.' }
New-Item -ItemType Directory -Force $PackageRoot | Out-Null
$files=[Collections.Generic.List[object]]::new()
function Stage([string]$Source,[string]$Relative) {
$destination=Join-Path $PackageRoot $Relative
New-Item -ItemType Directory -Force (Split-Path $destination) | Out-Null
Copy-Item -LiteralPath $Source -Destination $destination
$item=Get-Item -LiteralPath $destination
$entry=@{path=$Relative.Replace('\','/'); sha256=(Get-FileHash -LiteralPath $destination -Algorithm SHA256).Hash; version=$item.VersionInfo.FileVersion}
$files.Add($entry)
return $entry
}
$targets=[ordered]@{}; $common=@(); $baseline=$null
foreach ($gpu in Get-D4RGpuTargets) {
$arch=$gpu.architecture; $source="$GamePackagePrefix-$arch"
$metadata=Get-Content -LiteralPath (Join-Path $source 'package.json') -Raw | ConvertFrom-Json
if ($metadata.architecture -ne $arch -or $metadata.d4rWorkingTreeDirty) { throw "Uncommitted or wrong-target input: $source" }
$targetFiles=@()
foreach ($file in $metadata.files) {
$relative=$file.path.Replace('\','/')
if ((Get-FileHash -LiteralPath (Join-Path $source $file.path) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Input file changed: $source/$relative" }
if ($relative.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget (Join-Path $source $file.path) $arch }
if ($relative -eq 'gpu-target.json' -or $relative -eq 'd4r/_nvngx.dll' -or $relative -eq 'd4r/d4r_gpu_inventory.exe' -or $relative -eq 'd4r/d4r_debug_launcher.exe' -or $relative -eq 'd4r/nvapi/nvapi64.dll' -or
$relative.StartsWith('d4r/native/') -or $relative -like 'd4r/pixel_convert_*.hsaco') {
$entry=Stage (Join-Path $source $file.path) "files/targets/$arch/$relative"
$targetFiles+=@{path=$relative; sha256=$entry.sha256; version=$entry.version}
} elseif ($relative -eq 'OptiScaler.dll' -or $relative.StartsWith('d4r/') -or $relative.StartsWith('licenses/')) {
$publicPath=if ($relative.StartsWith('licenses/')) { $relative } else { "files/common/$relative" }
if (!$baseline) {
$entry=Stage (Join-Path $source $file.path) $publicPath
if (!$relative.StartsWith('licenses/')) { $common+=@{path=$relative; sha256=$entry.sha256; version=$entry.version} }
} elseif ((Get-FileHash -LiteralPath (Join-Path $PackageRoot $publicPath) -Algorithm SHA256).Hash -ne $file.sha256) {
throw "Shared runtime differs in $arch : $relative"
}
}
}
if (@($targetFiles | Where-Object { $_.path.EndsWith('.hsaco') }).Count -ne 17) { throw "Expected 17 code objects for $arch" }
$targets[$arch]=@{binarySourceCommit=$metadata.d4rCommit; hardwareValidation=$metadata.hardwareValidation; dlssSha256=$metadata.dlssSha256; files=$targetFiles}
if (!$baseline) { $baseline=$metadata }
if ($metadata.dlssSha256 -ne $baseline.dlssSha256 -or $metadata.zludaBuild.sourceCommit -ne $baseline.zludaBuild.sourceCommit) { throw 'Input packages do not use the same validated dependencies.' }
}
foreach ($name in @('windows-game.ps1','game-summary.ps1','gpu-target.ps1','gpu-preflight.ps1')) {
$entry=Stage (Join-Path $PSScriptRoot $name) "files/common/$name"
$common+=@{path=$name; sha256=$entry.sha256; version=$entry.version}
}
$entry=Stage (Join-Path $repo 'tools/windows/gpu-targets.json') 'files/common/gpu-targets.json'
$common+=@{path='gpu-targets.json'; sha256=$entry.sha256; version=$entry.version}
[void](Stage (Join-Path $PSScriptRoot 'quick-test.ps1') 'files/quick-test.ps1')
[void](Stage (Join-Path $repo 'docs/windows-quick-test.txt') 'READ-ME-FIRST.txt')
foreach ($launch in @(@{name='START-K.cmd'; arguments='-Preset 11'},@{name='START-M.cmd'; arguments='-Preset 13'},@{name='RESTORE-GAME.cmd'; arguments='-Action restore'})) {
$path=Join-Path $PackageRoot $launch.name
@('@echo off','cd /d "%~dp0"',('"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -STA -ExecutionPolicy Bypass -File "%~dp0files\quick-test.ps1" '+$launch.arguments),'pause') |
Set-Content -LiteralPath $path -Encoding ASCII
$files.Add(@{path=$launch.name; sha256=(Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash; version=$null})
}
$ngxCoreSha256='66767018C36B3BAB46398DADE3ADF173DAA3730FDA75965689EA848C9BC4E79B'
$bundledNvidia=$null
if ($NvidiaDirectory) {
# Opt-in for local testing or a distributor with appropriate permission.
# A matching hash establishes binary identity, not redistribution rights.
if (!$NvidiaLicensePath -or !(Test-Path -LiteralPath $NvidiaLicensePath -PathType Leaf)) {
throw 'Bundled NVIDIA files require -NvidiaLicensePath with their applicable license. This option does not establish redistribution permission.'
}
$core=Join-Path $NvidiaDirectory '_nvngx.dll'
$dlss=Join-Path $NvidiaDirectory 'nvngx_dlss.dll'
if ((Get-FileHash -LiteralPath $core -Algorithm SHA256).Hash -ne $ngxCoreSha256 -or
(Get-FileHash -LiteralPath $dlss -Algorithm SHA256).Hash -ne $baseline.dlssSha256) {
throw 'Bundled NVIDIA files must match the validated original NGX and DLSS hashes.'
}
[void](Stage $core 'files/nvidia/_nvngx.dll')
[void](Stage $dlss 'files/nvidia/nvngx_dlss.dll')
[void](Stage $NvidiaLicensePath 'licenses/NVIDIA-RTX.txt')
$bundledNvidia=@{ngxCore='nvidia/_nvngx.dll'; dlssDll='nvidia/nvngx_dlss.dll'; license='licenses/NVIDIA-RTX.txt'}
} elseif ($NvidiaLicensePath) { throw '-NvidiaLicensePath requires -NvidiaDirectory.' }
$metadata=[ordered]@{schema=1; packageCommit=$commit; binarySourceCommit=$baseline.d4rCommit;
ngxCoreSha256=$ngxCoreSha256; bundledNvidia=$bundledNvidia;
dependencies=@{optiScalerSourceCommit=$baseline.optiScaler.sourceCommit; zludaSourceCommit=$baseline.zludaBuild.sourceCommit;
llvmSource=$baseline.zludaBuild.llvmSource; hipRuntime=$baseline.hipRuntime};
commonFiles=$common; targets=$targets; files=$files}
$metadata | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath (Join-Path $PackageRoot 'files/package.json') -Encoding UTF8
if ($ArchivePath) {
$ArchivePath=[IO.Path]::GetFullPath($ArchivePath)
if ($ArchivePath.StartsWith($PackageRoot+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Place the ZIP outside the output directory.' }
New-Item -ItemType Directory -Force (Split-Path $ArchivePath) | Out-Null
Add-Type -AssemblyName System.IO.Compression,System.IO.Compression.FileSystem
$stream=[IO.File]::Open($ArchivePath,[IO.FileMode]::Create,[IO.FileAccess]::ReadWrite,[IO.FileShare]::None)
$archive=$null
try {
$archive=[IO.Compression.ZipArchive]::new($stream,[IO.Compression.ZipArchiveMode]::Create)
foreach ($relative in @($files.path)+@('files/package.json')) {
[void][IO.Compression.ZipFileExtensions]::CreateEntryFromFile($archive,(Join-Path $PackageRoot $relative),$relative,[IO.Compression.CompressionLevel]::Optimal)
}
} finally { if ($archive) { $archive.Dispose() }; $stream.Dispose() }
}
$nvidiaMode=if ($bundledNvidia) { 'bundled NVIDIA files; distributor must have appropriate permission' } else { 'user-supplied NVIDIA files' }
Write-Host "Quick-test package: $PackageRoot (11 targets, automatic GPU selection, $nvidiaMode)"
-105
View File
@@ -1,105 +0,0 @@
# Builds the Windows drag-in release: extract it into the game folder, copy
# the two NVIDIA DLLs, edit d4r\d4r.ini. Like the Linux release, no installer
# or launcher is involved. Inputs are the per-target game packages that
# package-windows-game.ps1 produces (the same inputs as the quick test).
[CmdletBinding()]
param(
[string]$GamePackagePrefix,
[Parameter(Mandatory=$true)][string]$LoaderDll,
[Parameter(Mandatory=$true)][string]$PackageRoot,
[string[]]$Architectures, # default: every target in gpu-targets.json; a subset makes a smaller release
[string]$ArchivePath
)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$GamePackagePrefix) { $GamePackagePrefix=Join-Path $repo 'dist/windows-gpu-coverage-game' }
$PackageRoot=[IO.Path]::GetFullPath($PackageRoot)
if (Test-Path -LiteralPath $PackageRoot) { throw 'Use a new output directory to avoid mixing releases.' }
$git=Get-Command git -ErrorAction SilentlyContinue
$commit=if ($git) { (& git -C $repo rev-parse HEAD).Trim() } else { $null }
if ($ArchivePath -and (!$git -or [bool](& git -C $repo status --porcelain))) { throw 'A public ZIP needs git and committed sources.' }
New-Item -ItemType Directory -Force $PackageRoot | Out-Null
$files=[Collections.Generic.List[object]]::new()
function Stage([string]$Source,[string]$Relative) {
$destination=Join-Path $PackageRoot $Relative
if (Test-Path -LiteralPath $destination) { throw "Duplicate release path: $Relative" }
New-Item -ItemType Directory -Force (Split-Path $destination) | Out-Null
Copy-Item -LiteralPath $Source -Destination $destination
$item=Get-Item -LiteralPath $destination
$files.Add(@{path=$Relative.Replace('\','/'); sha256=(Get-FileHash -LiteralPath $destination -Algorithm SHA256).Hash; version=$item.VersionInfo.FileVersion})
}
$targets=[ordered]@{}; $baseline=$null; $commonStaged=$false; $inventoryStaged=$false
$selected=@(Get-D4RGpuTargets | Where-Object { !$Architectures -or $Architectures -contains $_.architecture })
if (!$selected.Count -or ($Architectures -and $selected.Count -ne @($Architectures | Select-Object -Unique).Count)) { throw "Unknown GPU target in -Architectures: $($Architectures -join ', ')" }
foreach ($gpu in $selected) {
$arch=$gpu.architecture; $source="$GamePackagePrefix-$arch"
$metadata=Get-Content -LiteralPath (Join-Path $source 'package.json') -Raw | ConvertFrom-Json
if ($metadata.architecture -ne $arch -or $metadata.d4rWorkingTreeDirty) { throw "Uncommitted or wrong-target input: $source" }
if (!$baseline) { $baseline=$metadata }
if ($metadata.dlssSha256 -ne $baseline.dlssSha256 -or $metadata.zludaBuild.sourceCommit -ne $baseline.zludaBuild.sourceCommit) { throw 'Input packages do not use the same validated dependencies.' }
$objects=0
foreach ($file in $metadata.files) {
$relative=$file.path.Replace('\','/'); $path=Join-Path $source $file.path
if ((Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash -ne $file.sha256) { throw "Input file changed: $source/$relative" }
if ($relative.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget $path $arch; $objects++ }
# Per-target files get target-specific names so one folder serves every GPU.
# One GPU-query tool serves every target: it reports each device's real architecture.
if ($relative -eq 'd4r/d4r_gpu_inventory.exe') { if (!$inventoryStaged) { Stage $path 'd4r/d4r_gpu_inventory.exe'; $inventoryStaged=$true } }
elseif ($relative -eq 'd4r/_nvngx.dll') { Stage $path "d4r/_nvngx_$arch.dll" }
elseif ($relative -eq 'd4r/nvapi/nvapi64.dll') { Stage $path "d4r/nvapi/$arch/nvapi64.dll" }
elseif ($relative -like 'd4r/pixel_convert_*.hsaco') { Stage $path $relative }
elseif ($relative.StartsWith('d4r/native/')) { Stage $path ("d4r/native/$arch/" + $relative.Substring('d4r/native/'.Length)) }
elseif ($relative -eq 'OptiScaler.dll' -or $relative.StartsWith('licenses/') -or
($relative.StartsWith('d4r/hip/') -or $relative.StartsWith('d4r/zluda/'))) {
$public=if ($relative -eq 'OptiScaler.dll') { 'dxgi.dll' } elseif ($relative.StartsWith('licenses/')) { "d4r/$relative" } else { $relative }
if (!$commonStaged) { Stage $path $public }
elseif ((Get-FileHash -LiteralPath (Join-Path $PackageRoot $public) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Shared runtime differs in $arch : $relative" }
}
# Installer-only files (launcher, PowerShell installer, docs) are not part of a drag-in install.
}
if ($objects -ne 17) { throw "Expected 17 code objects for $arch" }
$commonStaged=$true
$targets[$arch]=@{binarySourceCommit=$metadata.d4rCommit; hardwareValidation=$metadata.hardwareValidation}
}
$loader=(Get-Item -LiteralPath $LoaderDll).FullName
if ([IO.Path]::GetFileName($loader) -ne 'd4r_nvngx_loader.dll') { throw 'Pass the d4r_nvngx_loader.dll built by CMake.' }
Stage $loader 'd4r/_nvngx.dll'
Stage (Join-Path $repo 'packaging/windows/OptiScaler.ini') 'OptiScaler.ini'
Stage (Join-Path $repo 'packaging/windows/d4r.ini') 'd4r/d4r.ini'
Stage (Join-Path $repo 'tools/windows/dll-pins.txt') 'd4r/dll-pins.txt'
Stage (Join-Path $repo 'tools/windows/gpu-targets.json') 'd4r/gpu-targets.json'
if (!$inventoryStaged) { throw 'No d4r/d4r_gpu_inventory.exe in the inputs; d4r-check.ps1 needs it to query the GPU.' }
foreach ($optional in @(@{source='packaging/windows/WINDOWS_README.txt'; path='WINDOWS_README.txt'},
@{source='scripts/windows/d4r-check.ps1'; path='d4r/d4r-check.ps1'})) {
$path=Join-Path $repo $optional.source
if (Test-Path -LiteralPath $path) { Stage $path $optional.path }
}
# Shows players where the NGX core goes; a ZIP cannot carry an empty folder.
$placeholder=Join-Path $PackageRoot 'd4r/ngx/PUT _nvngx.dll HERE.txt'
New-Item -ItemType Directory -Force (Split-Path $placeholder) | Out-Null
"Copy NVIDIA's _nvngx.dll into this folder. See WINDOWS_README.txt." | Set-Content -LiteralPath $placeholder -Encoding ASCII
$files.Add(@{path='d4r/ngx/PUT _nvngx.dll HERE.txt'; sha256=(Get-FileHash -LiteralPath $placeholder -Algorithm SHA256).Hash; version=$null})
if (Get-ChildItem -LiteralPath $PackageRoot -Recurse -File | Where-Object { $_.Name -eq 'nvngx_dlss.dll' -or ($_.Name -eq '_nvngx.dll' -and $_.DirectoryName -ne (Join-Path $PackageRoot 'd4r')) }) {
throw 'Proprietary NVIDIA binaries must not be in the release.'
}
# Read by d4r-check.ps1: every shipped file's hash, so a damaged or mixed install is reported.
$manifest=[ordered]@{schema=1; kind='windows-drag-in'; packageCommit=$commit; binarySourceCommit=$baseline.d4rCommit;
dependencies=@{optiScalerSourceCommit=$baseline.optiScaler.sourceCommit; zludaSourceCommit=$baseline.zludaBuild.sourceCommit; hipRuntime=$baseline.hipRuntime};
targets=$targets; files=$files}
$manifest | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $PackageRoot 'd4r/package.json') -Encoding UTF8
if ($ArchivePath) {
$ArchivePath=[IO.Path]::GetFullPath($ArchivePath)
if ($ArchivePath.StartsWith($PackageRoot+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Place the ZIP outside the output directory.' }
New-Item -ItemType Directory -Force (Split-Path $ArchivePath) | Out-Null
Add-Type -AssemblyName System.IO.Compression,System.IO.Compression.FileSystem
$stream=[IO.File]::Open($ArchivePath,[IO.FileMode]::Create,[IO.FileAccess]::ReadWrite,[IO.FileShare]::None)
$archive=$null
try {
$archive=[IO.Compression.ZipArchive]::new($stream,[IO.Compression.ZipArchiveMode]::Create)
foreach ($relative in @($files.path)+@('d4r/package.json')) {
[void][IO.Compression.ZipFileExtensions]::CreateEntryFromFile($archive,(Join-Path $PackageRoot $relative),$relative,[IO.Compression.CompressionLevel]::Optimal)
}
} finally { if ($archive) { $archive.Dispose() }; $stream.Dispose() }
}
Write-Host "Windows drag-in release: $PackageRoot ($($targets.Count) GPU target(s): $($targets.Keys -join ', '); no NVIDIA DLLs)"
@@ -1,34 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$LlvmSourceRoot)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$expected='ff4dc1f7c9e1c64d4d69e40f4ed30c2280a96dfd'
$actual=(& git -C $LlvmSourceRoot rev-parse HEAD).Trim()
if ($LASTEXITCODE -or $actual -ne $expected) { throw "Expected audited ZLUDA LLVM source $expected, found $actual; review the patch against this revision." }
$patches=@(Get-ChildItem (Join-Path $repo 'patches/zluda-llvm') -Filter *.patch | Sort-Object Name)
foreach ($patch in $patches) {
$oldPreference=$ErrorActionPreference
try {
$ErrorActionPreference='Continue'
& git -C $LlvmSourceRoot apply --reverse --check $patch.FullName 2>$null
$applied=($LASTEXITCODE -eq 0)
} finally { $ErrorActionPreference=$oldPreference }
if (!$applied) {
& git -C $LlvmSourceRoot apply --check $patch.FullName
if ($LASTEXITCODE) { throw "LLVM source patch conflicts: $($patch.Name)" }
& git -C $LlvmSourceRoot apply $patch.FullName
if ($LASTEXITCODE) { throw "LLVM source patch failed: $($patch.Name)" }
}
Write-Host "LLVM source patch present: $($patch.Name)"
}
# The pinned backport is the entire intended LLVM delta.
if ($patches.Count -ne 1) { throw 'Review combined LLVM source provenance before adding more patches.' }
$audit=Join-Path $repo ('build/llvm-source-audit-'+[Guid]::NewGuid().ToString('N')+'.patch')
New-Item -ItemType Directory -Force (Split-Path $audit) | Out-Null
try {
& git -C $LlvmSourceRoot diff --binary --output=$audit
if ($LASTEXITCODE) { throw 'Cannot audit LLVM source diff.' }
$actualDiff=[IO.File]::ReadAllText($audit).Replace("`r`n","`n").TrimEnd()
$expectedDiff=[IO.File]::ReadAllText($patches[0].FullName).Replace("`r`n","`n").TrimEnd()
if ($actualDiff -cne $expectedDiff) { throw 'LLVM source contains changes outside the exported audited patch.' }
} finally { if (Test-Path -LiteralPath $audit) { Remove-Item -LiteralPath $audit } }
-25
View File
@@ -1,25 +0,0 @@
[CmdletBinding()]
param([string]$SourceRoot)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' }
$SourceRoot = [IO.Path]::GetFullPath($SourceRoot)
$base = 'ee2f25a180099fa42f36b2346732e1f2470a03ad'
if (!(Test-Path (Join-Path $SourceRoot 'Cargo.toml'))) { throw 'Clone upstream ZLUDA into external/ZLUDA first.' }
Push-Location $SourceRoot
try {
$revision = (& git rev-parse HEAD).Trim()
if ($revision -ne $base) { throw "Expected ZLUDA $base, found $revision; review patches against the new revision." }
$dirty = @(& git status --porcelain --untracked-files=no --ignore-submodules=all)
if ($dirty.Count) { throw 'ZLUDA source has tracked modifications. Keep this prepared checkout; do not reapply patches.' }
& git switch -c windows-rdna4
if ($LASTEXITCODE) { throw 'Could not create the local ZLUDA branch.' }
foreach ($patch in (Get-ChildItem -LiteralPath (Join-Path $repo 'patches/zluda') -Filter '*.patch' | Sort-Object Name)) {
& git apply --check $patch.FullName
if ($LASTEXITCODE) { throw "Patch check failed: $($patch.Name)" }
& git apply --whitespace=nowarn $patch.FullName
if ($LASTEXITCODE) { throw "Patch failed: $($patch.Name)" }
Write-Host "Applied $($patch.Name)"
}
Write-Host "Prepared Windows ZLUDA source at $SourceRoot (base $base)"
} finally { Pop-Location }
-33
View File
@@ -1,33 +0,0 @@
[CmdletBinding()]
param(
[ValidateSet(11,13)][int]$Preset = 11,
[string]$ZludaRoot, [string]$PackageRoot, [string]$OutputDirectory,
[int]$Iterations = 4,
[switch]$Translated
)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' }
if (!$PackageRoot) { $PackageRoot=Join-Path $repo 'dist/windows-rdna4-command-list' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/profile-' + $Preset + '-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$settings=@{D4R_ZLUDA_PROFILE='1'; D4R_PROFILE_STAGES='1'; D4R_VALIDATE_OUTPUT='1';
D4R_ZLUDA_PROFILE_DEFERRED=$null; D4R_ZLUDA_PROFILE_ALLOW_LEGACY=$null; D4R_ZLUDA_PROFILE_EVERY=$null;
D4R_ZLUDA_NATIVE_DIR=$(if ($Translated) { $null } elseif ($Preset -eq 11) { Join-Path $repo "build/native-k-$GpuArch" } else { Join-Path $repo "build/native-m-$GpuArch" })}
$old=@{}
try {
foreach ($key in $settings.Keys) { $old[$key]=[Environment]::GetEnvironmentVariable($key,'Process'); [Environment]::SetEnvironmentVariable($key,$settings[$key],'Process') }
$arguments=@{RuntimeProfile='therock'; ZludaRoot=$ZludaRoot; PackageRoot=$PackageRoot; OutputDirectory=$OutputDirectory;
NgxCore=(Join-Path $repo '_nvngx.dll'); DlssDll=(Join-Path $repo 'nvngx_dlss.dll'); NgxMode='d3d12';
NgxAbi='project-legacy'; Preset=$Preset; NgxOnly=$true; RequireNativeNetwork=(!$Translated); CommandListBackend=$true;
CaptureExceptions=$true; EarlyIndirectProbe=$true; PixelProfile='depth-stencil'; BarrierMode='inherited-legacy';
Iterations=$Iterations; TimeoutSeconds=300; OptiScalerDll=(Join-Path $repo 'dist/optiscaler-windows-d4r/OptiScaler.dll')}
& (Join-Path $PSScriptRoot 'test-windows-rdna4.ps1') @arguments
if ($LASTEXITCODE) { throw 'Profiling workload failed; see diagnostic bundle.' }
$python=(Get-Command python.exe -ErrorAction Stop).Source
& $python (Join-Path $repo 'tools/windows/profile_report.py') $OutputDirectory --output (Join-Path $OutputDirectory 'profile.json')
if ($LASTEXITCODE) { throw 'No usable profile records.' }
} finally {
foreach ($key in $old.Keys) { [Environment]::SetEnvironmentVariable($key,$old[$key],'Process') }
}
-188
View File
@@ -1,188 +0,0 @@
[CmdletBinding()]
param(
[ValidateSet('run','install','restore')][string]$Action='run',
[ValidateSet(11,13)][int]$Preset=11,
[string]$GameExe, [string]$NgxCore, [string]$DlssDll,
[switch]$CaptureExceptions
)
$ErrorActionPreference='Stop'
$root=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
$work=Join-Path $root 'work'
$settingsPath=Join-Path $work 'settings.json'
New-Item -ItemType Directory -Force $work | Out-Null
$saved=$null
if (Test-Path -LiteralPath $settingsPath) {
try { $saved=Get-Content -LiteralPath $settingsPath -Raw | ConvertFrom-Json }
catch { Write-Host 'Saved choices could not be read. Select the files again.' }
}
function Select-LocalFile([string]$Title, [string]$FileName, [string]$Previous) {
if ($Previous -and (Test-Path -LiteralPath $Previous -PathType Leaf)) { return (Get-Item -LiteralPath $Previous).FullName }
Add-Type -AssemblyName System.Windows.Forms
$dialog=New-Object Windows.Forms.OpenFileDialog
try {
$dialog.Title=$Title; $dialog.FileName=$FileName
$dialog.Filter=if ($FileName -eq '*.exe') { 'Game executable (*.exe)|*.exe' } else { "$FileName|$FileName" }
if ($dialog.ShowDialog() -ne [Windows.Forms.DialogResult]::OK) { throw 'File selection cancelled. No test was launched.' }
return $dialog.FileName
} finally { $dialog.Dispose() }
}
function Copy-Payload([string]$Source, [string]$Destination, [string]$Relative) {
$path=[IO.Path]::GetFullPath((Join-Path $Destination $Relative))
if (!$path.StartsWith($Destination+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Invalid package path.' }
New-Item -ItemType Directory -Force (Split-Path $path) | Out-Null
Copy-Item -LiteralPath (Join-Path $Source $Relative) -Destination $path -Force
}
function Get-BundledNvidiaFile([string]$Relative) {
$directory=Join-Path $PSScriptRoot 'nvidia'
$path=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot $Relative))
if (!$path.StartsWith($directory+'\',[StringComparison]::OrdinalIgnoreCase) -or
!(Test-Path -LiteralPath $path -PathType Leaf)) { throw 'Invalid bundled NVIDIA file. Extract the complete package again.' }
return $path
}
if ($Action -eq 'restore') {
$GameExe=Select-LocalFile 'Select the SAME game executable used for the test' '*.exe' $(if ($GameExe) { $GameExe } elseif ($saved) { $saved.game })
& (Join-Path $PSScriptRoot 'common/windows-game.ps1') -Action restore -GameExe $GameExe
Write-Host 'RESTORED. Launch the game normally again.' -ForegroundColor Green
return
}
$output=Join-Path $root ('results/test-'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff'))
New-Item -ItemType Directory -Force $output | Out-Null
$status=[ordered]@{action=$Action; preset=$Preset; status='starting'; hardwareValidationCompleted=$false}
$selectedPackage=$null
try {
Write-Host 'd4r Windows quick test - keep this window open until you EXIT the game.'
Write-Host 'Checking package and detecting the GPU...'
$manifest=Get-Content -LiteralPath (Join-Path $PSScriptRoot 'package.json') -Raw | ConvertFrom-Json
foreach ($file in $manifest.files) {
$path=[IO.Path]::GetFullPath((Join-Path $root $file.path))
if (!$path.StartsWith($root+'\',[StringComparison]::OrdinalIgnoreCase) -or
(Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash -ne $file.sha256) { throw "Package is incomplete or changed. Extract the ZIP again. File: $($file.path)" }
}
$status.packageCommit=$manifest.packageCommit
$inventoryDir=Join-Path $output 'gpu'
New-Item -ItemType Directory -Force $inventoryDir | Out-Null
$info=New-Object Diagnostics.ProcessStartInfo
$info.FileName=Join-Path $PSScriptRoot 'targets/gfx1201/d4r/d4r_gpu_inventory.exe'
$info.Arguments='--hip-root "'+(Join-Path $PSScriptRoot 'common/d4r/hip')+'" --output-dir "'+$inventoryDir+'"'
$info.UseShellExecute=$false; $info.CreateNoWindow=$true
$info.EnvironmentVariables['D4R_DIAG_DIR']=$inventoryDir
$info.RedirectStandardOutput=$true; $info.RedirectStandardError=$true
$process=New-Object Diagnostics.Process; $process.StartInfo=$info
try {
if (!$process.Start()) { throw 'GPU detection could not start.' }
$stdout=$process.StandardOutput.ReadToEndAsync(); $stderr=$process.StandardError.ReadToEndAsync()
$timedOut=!$process.WaitForExit(30000)
if ($timedOut) { $process.Kill(); $process.WaitForExit() }
$stdout.GetAwaiter().GetResult() | Set-Content (Join-Path $inventoryDir 'stdout.log') -Encoding UTF8
$stderr.GetAwaiter().GetResult() | Set-Content (Join-Path $inventoryDir 'stderr.log') -Encoding UTF8
$status.inventoryExit='0x{0:X8}' -f [BitConverter]::ToUInt32([BitConverter]::GetBytes([int]$process.ExitCode),0)
if ($timedOut -or $process.ExitCode) { throw 'HIP could not detect your GPU. The diagnostic ZIP contains the details.' }
} finally { $process.Dispose() }
$inventory=Get-Content -LiteralPath (Join-Path $inventoryDir 'gpu-inventory.json') -Raw | ConvertFrom-Json
$devices=@($inventory.devices | Where-Object { $_.buildEligible -and $_.wavefrontSize -eq 32 -and $manifest.targets.PSObject.Properties.Name -contains $_.architecture } | Sort-Object vramBytes -Descending)
if (!$devices.Count) { throw 'No supported RDNA3/RDNA4 HIP device was detected. See the GPU inventory in the diagnostic ZIP.' }
$device=$devices[0]
if (@($devices.architecture | Select-Object -Unique).Count -gt 1) {
for ($i=0; $i -lt $devices.Count; $i++) { Write-Host "$($i+1): $($devices[$i].name) ($($devices[$i].architecture))" }
$choice=Read-Host 'Select the GPU used by your game (press Enter for 1)'
if ($choice) {
$index=0
if (![int]::TryParse($choice,[ref]$index) -or $index -lt 1 -or $index -gt $devices.Count) { throw 'Invalid GPU selection.' }
$device=$devices[$index-1]
}
}
$arch=$device.architecture; $target=$manifest.targets.$arch
$status.gpu=$device; $status.binarySourceCommit=$target.binarySourceCommit
Write-Host "Detected: $($device.name) / $arch" -ForegroundColor Cyan
Write-Host 'Experimental build. This run is a correctness test, not an FPS benchmark.'
$previousGame=if ($saved) { $saved.game } else { $null }
if (!$GameExe -and $previousGame -and (Test-Path -LiteralPath $previousGame)) {
Write-Host "Remembered game: $previousGame"
$reuse=Read-Host 'Press Enter to use this game, or type C to choose another (restore the old game first)'
if ($reuse -match '^(?i)c$') { $previousGame=$null }
elseif ($reuse) { throw 'Invalid choice. Press Enter or type C on the next run.' }
}
$GameExe=Select-LocalFile 'Select the actual D3D12 game .exe (not Steam or a launcher)' '*.exe' $(if ($GameExe) { $GameExe } else { $previousGame })
$bundledCore=$null; $bundledDlss=$null
if ($manifest.bundledNvidia) {
$bundledCore=Get-BundledNvidiaFile $manifest.bundledNvidia.ngxCore
$bundledDlss=Get-BundledNvidiaFile $manifest.bundledNvidia.dlssDll
}
$status.nvidiaDllSource=@{core=$(if ($NgxCore) { 'explicit' } elseif ($bundledCore) { 'bundled' } else { 'user-supplied' });
dlss=$(if ($DlssDll) { 'explicit' } elseif ($bundledDlss) { 'bundled' } else { 'user-supplied' })}
if ($bundledCore -and !$NgxCore -and !$DlssDll) { Write-Host 'Using the validated NVIDIA DLL pair included by this package distributor.' }
$NgxCore=Select-LocalFile 'Select your ORIGINAL NVIDIA _nvngx.dll (32.0.16.1714)' '_nvngx.dll' $(if ($NgxCore) { $NgxCore } elseif ($bundledCore) { $bundledCore } elseif ($saved) { $saved.ngxCore })
$DlssDll=Select-LocalFile 'Select your NVIDIA nvngx_dlss.dll (310.9.1)' 'nvngx_dlss.dll' $(if ($DlssDll) { $DlssDll } elseif ($bundledDlss) { $bundledDlss } elseif ($saved) { $saved.dlssDll })
$status.game=$GameExe
$status.localDlls=@($NgxCore,$DlssDll | ForEach-Object { $item=Get-Item -LiteralPath $_; @{path=$item.FullName; version=$item.VersionInfo.FileVersion; sha256=(Get-FileHash -LiteralPath $_ -Algorithm SHA256).Hash} })
if ((Get-FileHash -LiteralPath $NgxCore -Algorithm SHA256).Hash -ne $manifest.ngxCoreSha256) {
throw 'Wrong _nvngx.dll. This test needs the original NVIDIA 32.0.16.1714 DLL, not the d4r shim. Select the correct file on the next run.'
}
if ((Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash -ne $target.dlssSha256) {
throw 'Wrong nvngx_dlss.dll. This test needs exactly NVIDIA DLSS 310.9.1. Select the correct file on the next run.'
}
if ($GameExe.StartsWith($root+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Select the installed GAME executable, outside this extracted package.' }
# Save only validated choices. Wrong DLLs are never remembered.
@{game=$GameExe; ngxCore=$NgxCore; dlssDll=$DlssDll; architecture=$arch} | ConvertTo-Json | Set-Content -LiteralPath $settingsPath -Encoding UTF8
$selectedPackage=Join-Path $work "package-$arch"
New-Item -ItemType Directory -Force $selectedPackage | Out-Null
$selectedFiles=@()
foreach ($file in $manifest.commonFiles) {
Copy-Payload (Join-Path $PSScriptRoot 'common') $selectedPackage $file.path
$selectedFiles+=$file
}
foreach ($file in $target.files) {
Copy-Payload (Join-Path $PSScriptRoot "targets/$arch") $selectedPackage $file.path
$selectedFiles+=$file
}
@{architecture=$arch; d4rCommit=$target.binarySourceCommit; packageCommit=$manifest.packageCommit;
dlssSha256=$target.dlssSha256; hardwareValidation=$target.hardwareValidation; files=$selectedFiles} |
ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $selectedPackage 'package.json') -Encoding UTF8
Write-Host 'Original game files will be backed up. RESTORE-GAME.cmd reverses the installation.'
Write-Host 'In the game: select DLSS if available; otherwise select FSR/XeSS to let OptiScaler intercept it.'
Write-Host 'The first launch compiles shaders and can take several minutes. Then play for 30 seconds and EXIT the game normally.'
& (Join-Path $selectedPackage 'windows-game.ps1') -Action $Action -GameExe $GameExe -NgxCore $NgxCore -DlssDll $DlssDll `
-Preset $Preset -ValidateOutput -CaptureExceptions:$CaptureExceptions -OutputDirectory $output
if ($Action -eq 'install') { $status.status='installed-only' }
else {
$summary=Get-Content -LiteralPath (Join-Path $output 'summary.json') -Raw | ConvertFrom-Json
$status.gameSummary=$summary
$required=Get-Content -LiteralPath (Join-Path $selectedPackage 'd4r/native/d4r-kernels.txt') | Where-Object {
if ($Preset -eq 11) { $_ -match '^dltss_pwin_' } else { $_ -match '^rrlite_' }
} | ForEach-Object { $_.Split(' ')[0] }
$hits=@($summary.kernels | Where-Object { $_.backend -eq 'native' -and $_.launches -gt 0 } | ForEach-Object { $_.kernel })
$status.missingNativeKernels=@($required | Where-Object { $hits -notcontains $_ })
$status.translatedNativeKernels=@($summary.kernels | Where-Object { $_.backend -eq 'translated' -and $required -contains $_.kernel } | ForEach-Object { $_.kernel })
$passed=$summary.exitCode -eq '0x0' -and $summary.completedFrames -gt 0 -and $summary.nativeLaunches -gt 0 -and
$summary.outputGpuChecks -gt 0 -and $summary.failures -eq 0 -and $summary.nonfiniteOutputs -eq 0 -and
$summary.previousFrameOutputs -eq 0 -and $summary.cpuImageCopyFrames -eq 0 -and
@($required).Count -eq $(if ($Preset -eq 11) { 11 } else { 5 }) -and
$status.missingNativeKernels.Count -eq 0 -and $status.translatedNativeKernels.Count -eq 0
$status.hardwareValidationCompleted=[bool]$passed
$status.status=if ($passed) { 'backend-checks-passed-image-still-needs-user-review' }
elseif ($summary.completedFrames -eq 0 -and $summary.exitCode -eq '0x0' -and $summary.failures -eq 0) { 'inconclusive-process-exited-without-dlss-frames' }
else { 'backend-checks-failed-or-no-dlss-frames' }
$status.session=$summary.session
if ($status.status -eq 'inconclusive-process-exited-without-dlss-frames') {
Write-Host 'The launched process exited without a DLSS frame. A Steam/launcher restart is not tracked by this test. Keep Steam open and select the actual game executable. Send the ZIP if it restarts again.' -ForegroundColor Yellow
}
Write-Host $(if ($passed) { 'Backend checks PASSED. Please also report whether the image looked correct.' } else { 'Test did not pass. Send the diagnostic ZIP; do not guess from the FPS.' }) -ForegroundColor $(if ($passed) { 'Green' } else { 'Yellow' })
}
} catch {
$status.status='failed'; $status.error=$_.Exception.Message
$_ | Out-String | Set-Content -LiteralPath (Join-Path $output 'error.txt') -Encoding UTF8
Write-Host "TEST STOPPED: $($status.error)" -ForegroundColor Red
} finally {
if ($selectedPackage) {
$preflights=Join-Path $selectedPackage 'results'
$latest=Get-ChildItem -LiteralPath $preflights -Directory -ErrorAction SilentlyContinue | Sort-Object Name -Descending | Select-Object -First 1
if ($latest) { Copy-Item -LiteralPath $latest.FullName -Destination (Join-Path $output 'preflight') -Recurse -Force }
}
try { Get-CimInstance Win32_VideoController | Select-Object Name,DriverVersion,DriverDate | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $output 'driver.json') -Encoding UTF8 } catch {}
$status | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath (Join-Path $output 'quick-test.json') -Encoding UTF8
Compress-Archive -LiteralPath $output -DestinationPath ($output+'.zip') -Force
Write-Host "SEND THIS ONE FILE: $output.zip" -ForegroundColor Cyan
Write-Host 'Also tell us: GPU model, game name, K or M, and whether the image was correct.'
Write-Host 'Close the game before running RESTORE-GAME.cmd.'
}
if ($status.status -eq 'failed' -or $status.status -eq 'backend-checks-failed-or-no-dlss-frames' -or $status.status.StartsWith('inconclusive-')) { exit 1 }
-25
View File
@@ -1,25 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][int]$GameProcessId,
[ValidateSet('Enter','Escape','Up','Down','Tab')][string]$Key='Enter')
$ErrorActionPreference='Stop'
$process=Get-Process -Id $GameProcessId -ErrorAction Stop
if ($process.ProcessName -ne 'SHProto-Win64-Shipping') { throw 'This helper is scoped to the authorized Silent Hill 2 diagnostic.' }
if (!('D4RGameKeys' -as [type])) {
Add-Type @'
using System;
using System.Runtime.InteropServices;
public static class D4RGameKeys {
[DllImport("user32.dll")] public static extern bool PostMessage(IntPtr window, uint message, IntPtr key, IntPtr flags);
[DllImport("user32.dll")] public static extern uint MapVirtualKey(uint code, uint kind);
}
'@
}
$window=$process.MainWindowHandle
if ($window -eq [IntPtr]::Zero) { throw 'Game window missing on this desktop.' }
$codes=@{Enter=13; Escape=27; Up=38; Down=40; Tab=9}
$code=$codes[$Key]; $scan=[D4RGameKeys]::MapVirtualKey($code,0)
$flags=[long](1 -bor ($scan -shl 16))
if ($Key -in @('Up','Down')) { $flags=$flags -bor 0x01000000 }
if (![D4RGameKeys]::PostMessage($window,0x100,[IntPtr]$code,[IntPtr]$flags)) { throw 'Game key-down post failed.' }
if (![D4RGameKeys]::PostMessage($window,0x101,[IntPtr]$code,[IntPtr]($flags -bor 0xc0000000L))) { throw 'Game key-up post failed.' }
Write-Host "Sent $Key only to diagnostic game PID $GameProcessId."
-48
View File
@@ -1,48 +0,0 @@
[CmdletBinding()]
param([string]$ToolRoot, [string]$DownloadRoot)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$ToolRoot) { $ToolRoot = Join-Path $repo '.tools/rust-1.98.1-gnu' }
if (!$DownloadRoot) { $DownloadRoot = Join-Path $repo '.tools/downloads' }
$ToolRoot = [IO.Path]::GetFullPath($ToolRoot)
$DownloadRoot = [IO.Path]::GetFullPath($DownloadRoot)
New-Item -ItemType Directory -Force $ToolRoot,$DownloadRoot | Out-Null
# Pinned official Rust 2026-09-03 manifest. The toolchain is local to this
# workspace; rustup, PATH changes and machine-wide installation are unnecessary.
$components = @(
@{Name='rustc'; Hash='f0e8e33973771acc4d2f87891b19d4f3f2d3827e2e7848c091d7c070bd63479c'},
@{Name='cargo'; Hash='4bd77f16bd2a26db6eacf9320414d3a792d9998cb5e9ac122280ba56126f2a44'},
@{Name='rust-std'; Hash='5bb599a541fcb9c0edc00e512570f60d2262623f1e2a19a44cce3a7a97208788'},
@{Name='rust-mingw'; Hash='75d898804789c12ca969365f0a86d85c3bca1fdb070f0be615ca513a986b2674'}
)
foreach ($component in $components) {
$package = "$($component.Name)-1.98.1-x86_64-pc-windows-gnu"
$archive = Join-Path $DownloadRoot "$package.tar.xz"
if (!(Test-Path $archive) -or (Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash -ne $component.Hash) {
Write-Host "Downloading official Rust component $($component.Name)"
& curl.exe --fail --location --silent --show-error --connect-timeout 15 --max-time 300 --retry 2 `
"https://static.rust-lang.org/dist/2026-09-03/$package.tar.xz" --output $archive
if ($LASTEXITCODE) { throw "Download failed for $package (exit=$LASTEXITCODE)" }
}
if ((Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash -ne $component.Hash) {
throw "Rust component SHA256 mismatch: $archive"
}
$extract = Join-Path $DownloadRoot $package
if (!(Test-Path (Join-Path $extract 'components'))) {
& tar.exe -xf $archive -C $DownloadRoot
if ($LASTEXITCODE) { throw "Extract failed: $archive" }
}
foreach ($entry in (Get-Content -LiteralPath (Join-Path $extract 'components'))) {
$payload = Join-Path $extract $entry
foreach ($directory in @('bin','lib','share','etc')) {
$source = Join-Path $payload $directory
if (Test-Path $source) { Copy-Item -LiteralPath $source -Destination $ToolRoot -Recurse -Force }
}
}
Write-Host "Verified and installed $package"
}
& (Join-Path $ToolRoot 'bin/rustc.exe') --version
if ($LASTEXITCODE) { throw 'Rust compiler failed to start' }
& (Join-Path $ToolRoot 'bin/cargo.exe') --version
if ($LASTEXITCODE) { throw 'Cargo failed to start' }
Write-Host "Local Rust toolchain: $ToolRoot"
-46
View File
@@ -1,46 +0,0 @@
[CmdletBinding()]
param([ValidateSet('stable', 'therock')][string]$RuntimeProfile = 'stable')
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$localTools = Join-Path $repo '.tools'
$downloadDirectory = Join-Path $localTools 'downloads'
New-Item -ItemType Directory -Force $downloadDirectory | Out-Null
function Get-VerifiedArchive([string]$Url, [string]$Name, [string]$Hash, [string]$Destination, [string]$Marker) {
if (Test-Path -LiteralPath $Marker) { Write-Host "Already present: $Marker"; return }
$archive = Join-Path $downloadDirectory $Name
if (!(Test-Path -LiteralPath $archive)) {
Invoke-WebRequest -UseBasicParsing -Uri $Url -OutFile $archive
}
if ((Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash -ne $Hash) {
throw "SHA256 mismatch: $archive (remove this download and retry)"
}
if ([IO.Path]::GetExtension($archive) -eq '.whl') {
python -c 'import sys,zipfile; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])' $archive $Destination
if ($LASTEXITCODE) { throw "Wheel extraction exit=$LASTEXITCODE" }
} else { Expand-Archive -LiteralPath $archive -DestinationPath $Destination -Force }
if (!(Test-Path -LiteralPath $Marker)) { throw "Archive layout changed: $Marker" }
}
Get-VerifiedArchive 'https://github.com/mstorsjo/llvm-mingw/releases/download/20260922/llvm-mingw-20260922-ucrt-x86_64.zip' `
'llvm-mingw.zip' 'e3ad77d117a4bea19a7a3b333341824d79a5a371004a10e25b8504e7b3047666' $localTools `
(Join-Path $localTools 'llvm-mingw-20260922-ucrt-x86_64/bin/x86_64-w64-mingw32-clang++.exe')
Get-VerifiedArchive 'https://github.com/vosen/ZLUDA/releases/download/v7-preview.11/zluda-windows-ee2f25a.zip' `
'zluda.zip' '7788c1ed43385e62f0cc5f4d1aead24c92b671c02f1d685f63182540dea16d74' (Join-Path $localTools 'zluda') `
(Join-Path $localTools 'zluda/zluda/nvcuda.dll')
if ($RuntimeProfile -eq 'therock') {
Get-VerifiedArchive 'https://nightly.repo.amd.com/rocm/core/whl-next/rocm-sdk-core/rocm_sdk_core-10.2.0a20260929-py3-none-win_amd64.whl' `
'rocm_sdk_core-10.2.0a20260929-py3-none-win_amd64.whl' `
'9623b97ca511eaa176905075a504393eca6fde594222af10b55e4fb1edfe5a25' `
(Join-Path $localTools 'therock-10.2.0a20260929') `
(Join-Path $localTools 'therock-10.2.0a20260929/_rocm_sdk_core/bin/amdhip64_7.dll')
}
if (!(Test-Path (Join-Path $localTools 'python/cmake/data/bin/cmake.exe')) -or
!(Test-Path (Join-Path $localTools 'python/bin/ninja.exe'))) {
python -m pip install --target (Join-Path $localTools 'python') cmake==3.31.6 ninja==1.11.1.4
if ($LASTEXITCODE) { throw "pip install exit=$LASTEXITCODE" }
}
if (!(Test-Path (Join-Path $localTools 'python/vendor/numpy/__init__.py'))) {
python -m pip install --disable-pip-version-check --only-binary=:all: `
--target (Join-Path $localTools 'python/vendor') numpy==2.4.6
if ($LASTEXITCODE) { throw "NumPy reference install exit=$LASTEXITCODE" }
}
Write-Host 'Tools ready. Run scripts/windows/build-windows-rdna4.ps1.'
-30
View File
@@ -1,30 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory, [string]$GpuArch)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $GpuArch
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo "build/native-k-$GpuArch" }
if (![IO.Path]::IsPathRooted($DlssDll) -or !(Test-Path -LiteralPath $DlssDll)) {
throw 'Supply the absolute path to your local nvngx_dlss.dll.'
}
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
foreach ($object in Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco') {
Assert-D4RCodeObjectTarget $object.FullName $GpuArch
}
$layers = @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0')
foreach ($layer in $layers) {
$name = "dltss_pwin_${layer}_layer"
$source = Join-Path $PackageRoot "experimental/k/${name}_${GpuArch}.hsaco"
if (!(Test-Path -LiteralPath $source)) { throw "Native K module missing: $source" }
Assert-D4RCodeObjectTarget $source $GpuArch
Copy-Item -LiteralPath $source -Destination (Join-Path $OutputDirectory "$name.hsaco") -Force
}
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $OutputDirectory $DlssDll
if ($LASTEXITCODE) { throw "Native manifest generation failed ($LASTEXITCODE)" }
@{architecture=$GpuArch; family='K'; dlssSha256=(Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash;
validation='staged only; GPU execution and DLSS capture/reference validation required';
modules=@(Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco' | Get-FileHash -Algorithm SHA256)} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'build-info.json') -Encoding UTF8
Write-Host "Experimental native K directory: $OutputDirectory"
-30
View File
@@ -1,30 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory, [string]$GpuArch)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $GpuArch
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo "build/native-m-$GpuArch" }
if (![IO.Path]::IsPathRooted($DlssDll) -or !(Test-Path -LiteralPath $DlssDll)) {
throw 'Supply the absolute path to your local nvngx_dlss.dll.'
}
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
foreach ($object in Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco') {
Assert-D4RCodeObjectTarget $object.FullName $GpuArch
}
foreach ($layer in @('enc1','enc2','enc3_tube','dec2','dec1')) {
$name = "rrlite_${layer}_4x4"
$source = Join-Path $PackageRoot "experimental/m/${name}_${GpuArch}.hsaco"
if (!(Test-Path -LiteralPath $source)) { throw "Native M module missing: $source" }
Assert-D4RCodeObjectTarget $source $GpuArch
Copy-Item -LiteralPath $source -Destination (Join-Path $OutputDirectory "$name.hsaco") -Force
}
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $OutputDirectory $DlssDll
if ($LASTEXITCODE) { throw "Native manifest generation failed ($LASTEXITCODE)" }
@{architecture=$GpuArch; family='M'; numerics='SWIN_EXACT; SWIN_EXACT_PV; FP16 widening; native FP8 disabled';
dlssSha256=(Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash;
validation='staged only; GPU execution and DLSS capture/reference validation required';
modules=@(Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco' | Get-FileHash -Algorithm SHA256)} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'build-info.json') -Encoding UTF8
Write-Host "Experimental native M directory: $OutputDirectory"
-84
View File
@@ -1,84 +0,0 @@
[CmdletBinding()]
param(
[string]$NgxCore, [string]$DlssDll, [string]$NativeRoot,
[string]$ZludaRoot, [string]$PackageRoot,
[string]$Resolution = '3840x2160',
[string]$InputResolution,
[switch]$ProfileGpuBoundary,
[switch]$ProfileKernelsDeferred,
[switch]$BatchInputCopies,
[ValidateSet('baseline','packed','unorm','depth-stencil')][string]$PixelProfile = 'depth-stencil',
[string]$OutputDirectory
)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$NgxCore) { $NgxCore = Join-Path $repo '_nvngx.dll' }
if (!$DlssDll) { $DlssDll = Join-Path $repo 'nvngx_dlss.dll' }
if (!$ZludaRoot) { $ZludaRoot = Join-Path $repo 'dist/zluda-windows-api-profile' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-command-list' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$NativeRoot) { $NativeRoot = Join-Path $repo "build/native-k-$GpuArch" }
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/async-k-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
if ($Resolution -notmatch '^([0-9]+)x([0-9]+)$') { throw 'Resolution must be WIDTHxHEIGHT' }
$width=$Matches[1]; $height=$Matches[2]
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$settings = @{D4R_DIAG_BURST='1'; D4R_DIAG_RECREATE=$null; D4R_ASYNC_INTEROP=$null;
D4R_BATCH_INPUT_COPIES=$null;
D4R_ZLUDA_NATIVE_DIR=$NativeRoot; D4R_QUIET_API='1'; D4R_VALIDATE_OUTPUT='1';
D4R_PROFILE_STAGES='1'; D4R_ZLUDA_PROFILE=$null; D4R_ZLUDA_PROFILE_API=$null;
D4R_ZLUDA_PROFILE_DEFERRED=$(if ($ProfileKernelsDeferred) { '1' } else { $null });
D4R_ZLUDA_PROFILE_ALLOW_LEGACY=$(if ($ProfileKernelsDeferred) { '1' } else { $null });
D4R_ZLUDA_PROFILE_EVERY=$(if ($ProfileKernelsDeferred) { '1' } else { $null });
D4R_PROFILE_GPU_BOUNDARY=$(if ($ProfileGpuBoundary) { '1' } else { $null });
ZLUDA_CACHE_DIR=(Join-Path $repo 'build/zluda-cache-windows');
PYTHONPATH=(Join-Path $repo '.tools/python/vendor')}
$old=@{}
try {
foreach ($key in $settings.Keys) {
$old[$key]=[Environment]::GetEnvironmentVariable($key,'Process')
[Environment]::SetEnvironmentVariable($key,$settings[$key],'Process')
}
foreach ($mode in @('burst','recreate')) {
[Environment]::SetEnvironmentVariable('D4R_DIAG_RECREATE', $(if ($mode -eq 'recreate') { '1' } else { $null }), 'Process')
foreach ($variant in @('sync','async')) {
[Environment]::SetEnvironmentVariable('D4R_ASYNC_INTEROP', $(if ($variant -eq 'async') { '1' } else { $null }), 'Process')
[Environment]::SetEnvironmentVariable('D4R_BATCH_INPUT_COPIES', $(if ($BatchInputCopies -and $variant -eq 'async') { '1' } else { $null }), 'Process')
$output=Join-Path $OutputDirectory "$variant-$mode"
$arguments=@{RuntimeProfile='therock'; ZludaRoot=$ZludaRoot; PackageRoot=$PackageRoot;
NgxCore=$NgxCore; DlssDll=$DlssDll; NgxOnly=$true; NgxMode='d3d12'; NgxAbi='project-legacy';
Preset=11; NgxCreateFlags=11; NgxOutputResolution=$Resolution; RequireNativeNetwork=$true;
NgxInputResolution=$InputResolution;
CommandListBackend=$true; EarlyIndirectProbe=$true; PixelProfile=$PixelProfile;
BarrierMode='inherited-legacy'; Iterations=3; CaptureExceptions=$true; TimeoutSeconds=600;
OptiScalerDll=(Join-Path $repo 'dist/optiscaler-windows-d4r/OptiScaler.dll'); OutputDirectory=$output}
& (Join-Path $PSScriptRoot 'test-windows-rdna4.ps1') @arguments
if ($LASTEXITCODE) { throw "Failed $variant-$mode; logs: $output" }
if ($ProfileKernelsDeferred) {
$stderr=Get-Content -LiteralPath (Join-Path $output 'd3d12-evaluate-preset-11.stderr.log') -Raw
if ($stderr -match '(?m)^D4R_KERNEL_PROFILE .*serializing=1') { throw 'Unexpected serializing kernel profiler.' }
foreach ($layer in @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0')) {
$pattern='(?m)^D4R_KERNEL_PROFILE(?:_INVALID)? kernel="dltss_pwin_' + $layer + '_layer" backend=native phase=main '
$events=[regex]::Matches($stderr,$pattern)
if ($events.Count -ne 3) { throw "Expected three collected $layer events for $variant-$mode, found $($events.Count)." }
}
}
if ($ProfileGpuBoundary -and $variant -eq 'async') {
$stdout=Get-Content -LiteralPath (Join-Path $output 'd3d12-evaluate-preset-11.stdout.log') -Raw
$timings=[regex]::Matches($stdout, '(?m)^D4R_GPU_BOUNDARY [^\r\n]*diagnostics_cpu_bytes=32 serializing=0\r?$')
if ($timings.Count -ne 3) { throw "Expected three completed GPU timing records for $variant-$mode, found $($timings.Count)." }
}
}
& python.exe (Join-Path $repo 'tools/windows/frame_compare.py') --reference (Join-Path $OutputDirectory "sync-$mode") --actual (Join-Path $OutputDirectory "async-$mode") --width $width --height $height --exact |
Tee-Object -FilePath (Join-Path $OutputDirectory "$mode-comparison.log")
if ($LASTEXITCODE) { throw "Async $mode output mismatch" }
}
@{passed=$true; architecture=$GpuArch; preset=11; resolution=$Resolution;
inputResolution=$InputResolution;
modes=@('burst','recreate'); framesPerMode=3; exactRgb=$true; gpuBoundaryTiming=[bool]$ProfileGpuBoundary;
deferredKernelTiming=[bool]$ProfileKernelsDeferred; batchInputs=[bool]$BatchInputCopies; pixelProfile=$PixelProfile} |
ConvertTo-Json | Set-Content -LiteralPath (Join-Path $OutputDirectory 'validation.json') -Encoding UTF8
Write-Host "PASS asynchronous K burst/recreate: $OutputDirectory"
} finally {
foreach ($key in $old.Keys) { [Environment]::SetEnvironmentVariable($key,$old[$key],'Process') }
}
-52
View File
@@ -1,52 +0,0 @@
param(
[int]$Iterations = 32,
[switch]$NoHooks,
[switch]$SmallSeed,
[switch]$DebugLayer,
[switch]$Warp,
[switch]$NoHip,
[ValidateSet('basic','indirect','indirect-root-reset','initial-pso')][string]$Mode = 'indirect',
[string]$OutputDirectory = 'test-results/d3d12-command-development'
)
$ErrorActionPreference = 'Stop'
$repo = (Resolve-Path "$PSScriptRoot/../..").Path
Push-Location $repo
$names = @('D4R_COMMAND_PROBE_NO_HOOKS','D4R_COMMAND_PROBE_SMALL_SEED','D4R_COMMAND_DEBUG_SDK','D4R_DIAG_DIR','D4R_COMMAND_PROBE_WARP','D4R_COMMAND_PROBE_NO_HIP')
$saved = @{}
foreach ($name in $names) { $saved[$name] = [Environment]::GetEnvironmentVariable($name,'Process') }
try {
if ($Iterations -lt 1 -or $Iterations -gt 1024) { throw 'Iterations must be 1..1024' }
$cmake = "$repo/.tools/python/cmake/data/bin/cmake.exe"
$build = "$repo/build/windows-rdna4-therock"
$hip = "$repo/.tools/therock-10.2.0a20260929/_rocm_sdk_core"
$output = [IO.Path]::GetFullPath((Join-Path $repo $OutputDirectory))
New-Item -ItemType Directory -Force -Path $output | Out-Null
$target = 'd4r_d3d12_command_probe'
if ($DebugLayer) {
$sdk = "$repo/.tools/agility-1.619.5"
if (!(Test-Path "$sdk/build/native/bin/x64/d3d12SDKLayers.dll")) { throw 'Unpack Microsoft.Direct3D.D3D12 1.619.5 into .tools/agility-1.619.5 for this optional debug probe' }
& $cmake -S . -B $build "-DD4R_AGILITY_ROOT=$sdk" > "$output/configure.log"
if ($LASTEXITCODE) { throw 'Debug probe configuration failed' }
$target = 'd4r_d3d12_command_debug_probe'
}
& $cmake --build $build --target d4r_nvngx_windows $target > "$output/build.log"
if ($LASTEXITCODE) { throw "Build failed: $output/build.log" }
[Environment]::SetEnvironmentVariable($names[0], $(if ($NoHooks) { '1' } else { $null }), 'Process')
[Environment]::SetEnvironmentVariable($names[1], $(if ($SmallSeed) { '1' } else { $null }), 'Process')
[Environment]::SetEnvironmentVariable($names[2], $(if ($DebugLayer) { '1' } else { $null }), 'Process')
[Environment]::SetEnvironmentVariable($names[3], $output, 'Process')
[Environment]::SetEnvironmentVariable($names[4], $(if ($Warp) { '1' } else { $null }), 'Process')
[Environment]::SetEnvironmentVariable($names[5], $(if ($NoHip -or $Warp) { '1' } else { $null }), 'Process')
# PowerShell 5 treats native stderr as ErrorRecord: retain it without
# converting it into a terminating exception, then check the process code.
$ErrorActionPreference = 'Continue'
& "$build/$target.exe" --hip-root $hip --module "$build/d4r_nvngx.dll" --interop-mode $Mode --iterations $Iterations > "$output/stdout.log" 2> "$output/stderr.log"
$code = $LASTEXITCODE
$ErrorActionPreference = 'Stop'
Get-Content "$output/stdout.log", "$output/stderr.log" | Select-String 'D3D12_VALIDATION|DRED|DEVICE_REMOVED|PROBE_GPU|DIFFERENT|FAIL|PASS|installed'
Write-Host "D3D12 command diagnostic logs: $output"
if ($code) { throw "D3D12 probe exit=$code" }
} finally {
foreach ($name in $names) { [Environment]::SetEnvironmentVariable($name,$saved[$name],'Process') }
Pop-Location
}
-122
View File
@@ -1,122 +0,0 @@
# d4r-check.ps1 against fixture installs. No GPU, no NVIDIA binaries: the packaging test's
# synthetic release is the install, a fake inventory file stands in for the GPU query, and
# fixture text files stand in for the NVIDIA DLLs (pinned in a fixture dll-pins.txt).
[CmdletBinding()]
param([string]$OutputDirectory)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/d4r-check/'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
& (Join-Path $PSScriptRoot 'test-windows-release-package.ps1') -OutputDirectory (Join-Path $OutputDirectory 'package') | Out-Null
$release=Join-Path $OutputDirectory 'package/release'
$check=Join-Path $repo 'scripts/windows/d4r-check.ps1'
$powershell="$env:SystemRoot/System32/WindowsPowerShell/v1.0/powershell.exe"
$results=@()
function Sha([string]$path) { (Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash }
function Set-ManifestHash([string]$game,[string]$relative) {
$path=Join-Path $game 'd4r/package.json'
$manifest=Get-Content -LiteralPath $path -Raw | ConvertFrom-Json
foreach ($entry in $manifest.files) { if ($entry.path -eq $relative) { $entry.sha256=Sha (Join-Path $game ($relative -replace '/','\')) } }
$manifest | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $path -Encoding UTF8
}
function New-Install([string]$name) {
$game=Join-Path $OutputDirectory "cases/$name"
New-Item -ItemType Directory -Force (Split-Path $game) | Out-Null
Copy-Item -LiteralPath $release -Destination $game -Recurse
Set-Content -LiteralPath (Join-Path $game 'Game.exe') 'fixture' -Encoding ASCII
Set-Content -LiteralPath (Join-Path $game 'd4r/nvngx_dlss.dll') 'fixture dlss' -Encoding ASCII
Set-Content -LiteralPath (Join-Path $game 'd4r/ngx/_nvngx.dll') 'fixture core' -Encoding ASCII
$unrelated=('B'*64)
@('# fixture pins',
"dlss $(Sha (Join-Path $game 'd4r/nvngx_dlss.dll')) 310.9.1 validated",
"dlss $unrelated 310.7.0 unvalidated",
"ngx $(Sha (Join-Path $game 'd4r/ngx/_nvngx.dll')) 32.0.16.1714 validated") |
Set-Content -LiteralPath (Join-Path $game 'd4r/dll-pins.txt') -Encoding ASCII
Set-ManifestHash $game 'd4r/dll-pins.txt'
return $game
}
function Write-Inventory([string]$name,[string]$arch,[string]$gpu='AMD Radeon RX 7700 XT') {
$path=Join-Path $OutputDirectory "inventory-$name.json"
@{devices=@(@{name=$gpu; architecture=$arch; wavefrontSize=32})} | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath $path -Encoding UTF8
return $path
}
function Run-Check([string]$game,[string]$inventory,[string[]]$More=@()) {
$ErrorActionPreference='Continue' # native stderr must not become a terminating error
$text=& $powershell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $game 'd4r/d4r-check.ps1') -GameFolder $game -InventoryFile $inventory @More 2>&1 | Out-String
return @{exit=$LASTEXITCODE; text=$text}
}
function Expect([string]$case,$run,[int]$exit,[string[]]$patterns) {
if ($run.exit -ne $exit) { throw "$case : exit $($run.exit), expected $exit`n$($run.text)" }
foreach ($pattern in $patterns) { if ($run.text -notmatch $pattern) { throw "$case : output lacks /$pattern/`n$($run.text)" } }
$script:results+=@{case=$case; passed=$true; gpuKernelsExecuted=$false}
}
# 1. Healthy install.
$game=New-Install 'healthy'; $inv=Write-Inventory 'a' 'gfx1101'
Expect 'healthy-install' (Run-Check $game $inv) 0 @('ok\s+d4r\\nvngx_dlss\.dll \(nvngx_dlss\.dll 310\.9\.1, tested on Windows\)','ok\s+d4r\\ngx\\_nvngx\.dll',
'ok\s+GPU AMD Radeon RX 7700 XT \(gfx1101\): build present, 16 native kernels','ok\s+all 17 GPU code objects are built for gfx1101',
'ok\s+no vkd3d/Wine d3d12\.dll','ok\s+d4r\.ini is valid \(model K\)','compile-tested','Everything d4r needs is in place')
# 2. NVIDIA DLL problems, each with the fix.
$game=New-Install 'dll-missing'; Remove-Item -LiteralPath (Join-Path $game 'd4r/nvngx_dlss.dll')
Expect 'dll-missing' (Run-Check $game $inv) 1 @("MISSING\s+d4r\\nvngx_dlss\.dll: copy NVIDIA's nvngx_dlss\.dll here \(version 310\.9\.1 or 310\.7\.0","1 thing\(s\) to fix")
$game=New-Install 'dll-wrong'; Set-Content -LiteralPath (Join-Path $game 'd4r/nvngx_dlss.dll') 'some other version' -Encoding ASCII
Expect 'dll-wrong-version' (Run-Check $game $inv) 1 @('MISSING\s+d4r\\nvngx_dlss\.dll is version \S+, which d4r does not accept\. d4r on Windows needs exactly 310\.9\.1 or 310\.7\.0')
$game=New-Install 'dll-less-tested'; Set-Content -LiteralPath (Join-Path $game 'd4r/nvngx_dlss.dll') 'fixture dlss 310.7' -Encoding ASCII
@('dlss '+(Sha (Join-Path $game 'd4r/nvngx_dlss.dll'))+' 310.7.0 unvalidated','ngx '+(Sha (Join-Path $game 'd4r/ngx/_nvngx.dll'))+' 32.0.16.1714 validated') | Set-Content -LiteralPath (Join-Path $game 'd4r/dll-pins.txt') -Encoding ASCII
Set-ManifestHash $game 'd4r/dll-pins.txt'
Expect 'dll-less-tested-accepted' (Run-Check $game $inv) 0 @('ok\s+d4r\\nvngx_dlss\.dll \(nvngx_dlss\.dll 310\.7\.0\)','note\s+nvngx_dlss\.dll 310\.7\.0 is accepted but has had less Windows testing')
# 3. Leftovers, edited files, a replaced dxgi.dll, and a broken OptiScaler.ini.
$game=New-Install 'vkd3d'; Set-Content -LiteralPath (Join-Path $game 'd3d12.dll') 'vkd3d-proton fixture' -Encoding ASCII
Expect 'vkd3d-proxy' (Run-Check $game $inv) 1 @('MISSING\s+d3d12\.dll in the game folder is vkd3d-proton/Wine')
$game=New-Install 'dxgi-replaced'; Set-Content -LiteralPath (Join-Path $game 'dxgi.dll') 'another dxgi' -Encoding ASCII
Expect 'foreign-dxgi' (Run-Check $game $inv) 0 @('note\s+dxgi\.dll is not the one that came with d4r')
$game=New-Install 'opti-path'; (Get-Content -LiteralPath (Join-Path $game 'OptiScaler.ini')) -replace '^NvngxPath=.*$','NvngxPath=nowhere' | Set-Content -LiteralPath (Join-Path $game 'OptiScaler.ini') -Encoding ASCII
Expect 'optiscaler-ini-path' (Run-Check $game $inv) 1 @('MISSING\s+OptiScaler\.ini NvngxPath = nowhere does not hold _nvngx\.dll')
# 4. d4r.ini mistakes are notes with what will happen instead.
$game=New-Install 'ini'; Set-Content -LiteralPath (Join-Path $game 'd4r/d4r.ini') "[DLSS]`nModel = E`nShowWatermark = sometimes`n[Latency]`nFrameAge = 1`n[Debug]`nLog = loud`n" -Encoding ASCII
Expect 'ini-mistakes' (Run-Check $game $inv) 0 @("note\s+d4r\.ini: \[DLSS\] Model 'E' is not available on Windows",'must be true or false, not ''sometimes''','\[Latency\] FrameAge is not a Windows setting','Log must be normal or verbose')
# 5. GPU cases.
$game=New-Install 'gpu-no-build'; Remove-Item -LiteralPath (Join-Path $game 'd4r/_nvngx_gfx1103.dll')
Expect 'gpu-without-build' (Run-Check $game (Write-Inventory 'b' 'gfx1103' 'AMD Radeon 780M')) 1 @('MISSING\s+GPU AMD Radeon 780M \(gfx1103\): this release has no complete build for it \(missing: d4r\\_nvngx_gfx1103\.dll\)')
$game=New-Install 'gpu-rdna2'
Expect 'gpu-unsupported' (Run-Check $game (Write-Inventory 'c' 'gfx1030' 'AMD Radeon RX 6800')) 1 @('MISSING\s+no supported RDNA3/RDNA4 GPU found by the AMD runtime\. It sees: AMD Radeon RX 6800 \(gfx1030\)')
$game=New-Install 'gpu-wrong-object'
$other=@(Get-ChildItem -LiteralPath (Join-Path $game 'd4r/native/gfx1100') -Filter '*.hsaco')[0].FullName
Copy-Item -LiteralPath $other -Destination (Join-Path $game 'd4r/native/gfx1101/kernel3.hsaco') -Force
Expect 'code-object-for-another-gpu' (Run-Check $game $inv) 1 @('MISSING\s+kernel3\.hsaco is not built for gfx1101','differs from the release')
# 6. What the last game start said, and the bug-report ZIP.
$game=New-Install 'log-failure'
Set-Content -LiteralPath (Join-Path $game 'd4r/d4r_nvngx.log') "d4r: DLSS disabled: Wrong nvngx_dlss.dll: you have version 1.2.3.4" -Encoding ASCII
Expect 'log-reports-failure' (Run-Check $game $inv) 1 @('MISSING\s+last game start: DLSS disabled: Wrong nvngx_dlss\.dll')
$game=New-Install 'log-ok'
Set-Content -LiteralPath (Join-Path $game 'd4r/d4r_nvngx.log') "d4r: player mode, model=K validate=0 async=0 log=normal, architecture=gfx1101" -Encoding ASCII
Expect 'log-reports-ok' (Run-Check $game $inv) 0 @('ok\s+last game start: player mode, model=K')
$game=New-Install 'report'; $reportDir=Join-Path $OutputDirectory 'reports'; New-Item -ItemType Directory -Force $reportDir | Out-Null
Set-Content -LiteralPath (Join-Path $game 'd4r/d4r_nvngx.log') "d4r: DLSS disabled: test failure" -Encoding ASCII
$run=Run-Check $game $inv @('-Report','-ReportDirectory',$reportDir)
$zip=@(Get-ChildItem -LiteralPath $reportDir -Filter 'd4r-report-*.zip')
if ($zip.Count -ne 1) { throw "Expected one report ZIP.`n$($run.text)" }
Add-Type -AssemblyName System.IO.Compression.FileSystem
$archive=[IO.Compression.ZipFile]::OpenRead($zip[0].FullName)
try { $names=@($archive.Entries | ForEach-Object { $_.Name }) } finally { $archive.Dispose() }
foreach ($required in @('check.txt','d4r_nvngx.log','d4r.ini','OptiScaler.ini','files.sha256.txt','gpu-inventory.json')) { if ($names -notcontains $required) { throw "Report lacks $required (has: $($names -join ', '))" } }
if ($names -contains 'nvngx_dlss.dll' -or $names -contains '_nvngx.dll') { throw 'The report must never contain NVIDIA DLLs.' }
if ($run.text -notmatch 'Bug report written') { throw 'Report location was not printed.' }
$results+=@{case='bug-report-zip'; passed=$true; entries=$names}
# 7. No d4r folder at all.
$empty=Join-Path $OutputDirectory 'cases/empty'; New-Item -ItemType Directory -Force $empty | Out-Null
$ErrorActionPreference='Continue'
$text=& $powershell -NoProfile -ExecutionPolicy Bypass -File $check -GameFolder $empty 2>&1 | Out-String
$exitEmpty=$LASTEXITCODE; $ErrorActionPreference='Stop'
if ($exitEmpty -ne 1 -or $text -notmatch 'no d4r folder here') { throw "A folder without d4r must be reported.`n$text" }
$results+=@{case='no-d4r-folder'; passed=$true}
$results | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Write-Host "PASS D4R_CHECK cases=$($results.Count) Report: $OutputDirectory"
@@ -1,103 +0,0 @@
[CmdletBinding()]
param([string]$ZludaRoot, [string]$PackageRoot, [string]$HipRoot, [string]$OutputDirectory)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$ZludaRoot) { $ZludaRoot = Join-Path $repo 'dist/zluda-windows-deferred-profile' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-command-list' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/deferred-profile-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$settings = @{
D4R_ZLUDA_PROFILE=$null; D4R_ZLUDA_PROFILE_DEFERRED='1'; D4R_ZLUDA_PROFILE_EVERY='1';
D4R_ZLUDA_PROFILE_ALLOW_LEGACY=$null;
D4R_DIAG_NONBLOCKING_STREAM='1'; D4R_DIAG_QUEUE_PTX=$null;
D4R_DIAG_DIR=$OutputDirectory;
ZLUDA_CACHE_DIR=(Join-Path $repo 'build/zluda-cache-windows');
PATH=((Join-Path $HipRoot 'bin') + ';' + $ZludaRoot + ';' + $env:PATH)
}
$old=@{}; $cases=@()
function RunProbe([string[]]$Arguments, [string]$Stdout, [string]$Stderr) {
$info=[Diagnostics.ProcessStartInfo]::new()
$info.FileName=Join-Path $PackageRoot 'bin/d4r_cuda_driver_probe.exe'
$info.Arguments=$Arguments -join ' '
$info.UseShellExecute=$false; $info.CreateNoWindow=$true
$info.RedirectStandardOutput=$true; $info.RedirectStandardError=$true
$p=[Diagnostics.Process]::new(); $p.StartInfo=$info
$outFile=$null; $errFile=$null; $outTask=$null; $errTask=$null
try {
if (!$p.Start()) { throw 'Could not launch the CUDA diagnostic.' }
$outFile=[IO.File]::Open($Stdout,[IO.FileMode]::Create,[IO.FileAccess]::Write,[IO.FileShare]::Read)
$errFile=[IO.File]::Open($Stderr,[IO.FileMode]::Create,[IO.FileAccess]::Write,[IO.FileShare]::Read)
$outTask=$p.StandardOutput.BaseStream.CopyToAsync($outFile)
$errTask=$p.StandardError.BaseStream.CopyToAsync($errFile)
$timer=[Diagnostics.Stopwatch]::StartNew()
while (!$p.WaitForExit(1000)) {
if ($timer.Elapsed.TotalSeconds -ge 120) { throw "CUDA diagnostic timed out; logs: $OutputDirectory" }
}
$p.WaitForExit()
[void]$outTask.GetAwaiter().GetResult(); [void]$errTask.GetAwaiter().GetResult()
return $p.ExitCode
} finally {
if (!$p.HasExited) { $p.Kill(); $p.WaitForExit() }
if ($outTask) { try { [void]$outTask.GetAwaiter().GetResult() } catch {} }
if ($errTask) { try { [void]$errTask.GetAwaiter().GetResult() } catch {} }
if ($outFile) { $outFile.Dispose() }; if ($errFile) { $errFile.Dispose() }
$p.Dispose()
}
}
try {
foreach ($key in $settings.Keys) {
$old[$key]=[Environment]::GetEnvironmentVariable($key,'Process')
[Environment]::SetEnvironmentVariable($key,$settings[$key],'Process')
}
foreach ($context in @('primary','created')) {
foreach ($queued in @($false,$true)) {
$name="$context-$(if ($queued) { 'queued' } else { 'single' })"
[Environment]::SetEnvironmentVariable('D4R_DIAG_QUEUE_PTX', $(if ($queued) { '1' } else { $null }), 'Process')
$iterations=129
$stdout=Join-Path $OutputDirectory "$name.stdout.log"
$stderr=Join-Path $OutputDirectory "$name.stderr.log"
# Native Windows argument parsing: quote absolute paths explicitly.
$arguments=@('--hip-root', ('"' + $HipRoot + '"'), '--cuda-dll', ('"' + (Join-Path $ZludaRoot 'nvcuda.dll') + '"'),
'--context', $context, '--iterations', "$iterations")
$exitCode=RunProbe $arguments $stdout $stderr
if ($exitCode) { throw "$name failed ($exitCode); logs: $OutputDirectory" }
$out=Get-Content -LiteralPath $stdout -Raw
$err=Get-Content -LiteralPath $stderr -Raw
if ($out -notmatch "PASS CUDA architecture=$GpuArch" -or $out -notmatch 'guard_verified=1') { throw "$name did not verify PTX output" }
$records=[regex]::Matches($err, '(?m)^D4R_KERNEL_PROFILE kernel="d4r_ptx_pattern" [^\r\n]*serializing=0 deferred=1 [^\r\n]+')
$invalid=[regex]::Matches($err, '(?m)^D4R_KERNEL_PROFILE_INVALID kernel="d4r_ptx_pattern" [^\r\n]*reason=invalid_elapsed_time serializing=0 deferred=1 [^\r\n]+')
if ($records.Count + $invalid.Count -ne $iterations -or $err -match 'serializing=1|D4R_KERNEL_PROFILE_SKIPPED') {
throw "$name expected $iterations collected deferred records, found $($records.Count) valid / $($invalid.Count) invalid"
}
foreach ($record in $records) {
if ($record.Value -notmatch 'gpu_ms=([0-9.]+)') {
throw "$name contains an invalid GPU time"
}
$gpuMs=[double]::Parse($Matches[1], [Globalization.CultureInfo]::InvariantCulture)
if ([double]::IsNaN($gpuMs) -or [double]::IsInfinity($gpuMs)) { throw "$name contains an invalid GPU time" }
}
$cases += @{context=$context; queued=$queued; launches=$iterations; collected=($records.Count+$invalid.Count);
validTimings=$records.Count; invalidTimings=$invalid.Count; exitCode=$exitCode}
Write-Host "PASS ${name}: $($records.Count) valid / $($invalid.Count) invalid deferred timings; exact PTX output and guards"
}
}
# Legacy default-stream timing markers would add stream dependencies.
[Environment]::SetEnvironmentVariable('D4R_DIAG_NONBLOCKING_STREAM',$null,'Process')
[Environment]::SetEnvironmentVariable('D4R_DIAG_QUEUE_PTX',$null,'Process')
$stdout=Join-Path $OutputDirectory 'default-stream.stdout.log'; $stderr=Join-Path $OutputDirectory 'default-stream.stderr.log'
$arguments=@('--hip-root', ('"' + $HipRoot + '"'), '--cuda-dll', ('"' + (Join-Path $ZludaRoot 'nvcuda.dll') + '"'), '--iterations', '3')
$exitCode=RunProbe $arguments $stdout $stderr
$out=Get-Content -LiteralPath $stdout -Raw; $err=Get-Content -LiteralPath $stderr -Raw
if ($exitCode -or $out -notmatch "PASS CUDA architecture=$GpuArch" -or
$err -notmatch 'reason=legacy_default_stream' -or $err -match '(?m)^D4R_KERNEL_PROFILE ') {
throw 'Default-stream diagnostics did not safely skip timing events.'
}
@{passed=$true; architecture=$GpuArch; cases=$cases; defaultStreamSkipped=$true; addedCompletionWaits=0} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'validation.json') -Encoding UTF8
Write-Host "PASS deferred kernel profiling: $OutputDirectory"
} finally {
foreach ($key in $old.Keys) { [Environment]::SetEnvironmentVariable($key,$old[$key],'Process') }
}
-38
View File
@@ -1,38 +0,0 @@
[CmdletBinding()]
param([string]$LogRoot, [string]$OutputDirectory)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'game-summary.ps1')
$cases=@(
@{name='empty-streams-debugger-refused'; stdout=''; stderr=''; debugger='EXIT code=0xdeadc0de'; session='process-failed-before-dlss-frames'},
@{name='launcher-exit'; stdout=''; stderr=''; debugger='EXIT code=0x0'; session='process-exited-without-dlss-frames'},
@{name='feature-not-found'; stdout='D4R_CAPABILITIES available=0 feature_init=0xbad00004 needs_driver=0'; stderr='D4R_WINDOWS_FAILURE unavailable'; debugger='EXIT code=0xc0000409'; session='ngx-feature-not-found'},
@{name='complete-frame'; stdout="D4R_FRAME cpu_frame_copies=0 frame_age=0 interop_ngx_ms=12.4`nD4R_OUTPUT_VALIDATION elements=3 nan=0 inf=0 diagnostics_cpu_bytes=8";
stderr='[d4r-launch] kernel="dltss_pwin_enc0_layer" backend=native'; debugger='EXIT code=0x0'; session='completed-dlss-frames'},
@{name='truncated-frame'; stdout='D4R_FRAME cpu_frame_copies=0 frame_age=0 interop_ngx_ms='; stderr=''; debugger=''; session='diagnostic-timeout-without-dlss-frames'}
)
$results=@()
foreach ($case in $cases) {
$summary=Get-D4RGameSummary -Stdout $case.stdout -Stderr $case.stderr -Debugger $case.debugger
if ($summary.session -ne $case.session) { throw "Wrong session classification: $($case.name)" }
if ($case.name -eq 'complete-frame') {
if ($summary.completedFrames -ne 1 -or $summary.outputGpuChecks -ne 1 -or $summary.nativeLaunches -ne 1 -or
$summary.nonfiniteOutputs -or $summary.previousFrameOutputs -or $summary.cpuImageCopyFrames) { throw 'Complete frame counters are wrong.' }
} elseif ($summary.completedFrames -ne 0) { throw 'A failed or incomplete run was counted as a frame.' }
$results+=@{case=$case.name; passed=$true; summary=$summary}
}
if ($LogRoot) {
foreach ($entry in @{ 'acbf-k'='process-failed-before-dlss-frames'; 'cyberpunk-k'='ngx-feature-not-found';
'cyberpunk-m'='ngx-feature-not-found'; 'sm2-k'='process-exited-without-dlss-frames' }.GetEnumerator()) {
$dir=Get-ChildItem -LiteralPath (Join-Path $LogRoot $entry.Key) -Directory | Select-Object -First 1
$summary=Get-D4RGameSummary -Stdout ([IO.File]::ReadAllText((Join-Path $dir.FullName 'd4r.stdout.log'))) `
-Stderr ([IO.File]::ReadAllText((Join-Path $dir.FullName 'd4r.stderr.log'))) `
-Debugger ([IO.File]::ReadAllText((Join-Path $dir.FullName 'debugger.log')))
if ($summary.session -ne $entry.Value -or $summary.completedFrames -ne 0 -or $summary.nativeLaunches -ne 0) { throw "Unexpected classification for actual report $($entry.Key)" }
$results+=@{case='issue-10-'+$entry.Key; passed=$true; summary=$summary}
}
}
if ($OutputDirectory) {
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$results | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary-parser.json') -Encoding UTF8
}
Write-Host "PASS GAME_SUMMARY cases=$($results.Count)"
@@ -1,23 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$PackageRoot, [Parameter(Mandatory=$true)][string]$CodeObject)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$target=Get-D4RGpuTarget $PackageRoot $null
$other=if ($target -eq 'gfx1201') { 'gfx1200' } else { 'gfx1201' }
function Expect-Rejection([scriptblock]$Action) {
$rejected=$false
try { & $Action | Out-Null } catch { $rejected=$true }
if (!$rejected) { throw 'GPU target contract accepted incompatible input.' }
}
if ((Get-D4RGpuTarget $PackageRoot $target) -ne $target) { throw 'Incorrect package target.' }
Assert-D4RCodeObjectTarget $CodeObject $target
Expect-Rejection { Get-D4RGpuTarget $PackageRoot $other }
Expect-Rejection { Get-D4RGpuTarget $PackageRoot 'gfx1250' }
Expect-Rejection { Assert-D4RCodeObjectTarget $CodeObject $other }
Expect-Rejection { Assert-D4RCodeObjectTarget (Join-Path $PackageRoot 'gpu-target.json') $target }
# Old packages had no target metadata and were gfx1201 only.
$legacy=Join-Path $PackageRoot '__no-target-metadata__'
if (Test-Path -LiteralPath (Join-Path $legacy 'gpu-target.json')) { throw 'Unexpected legacy test fixture.' }
if ((Get-D4RGpuTarget $legacy $null) -ne 'gfx1201') { throw 'Legacy target changed.' }
Expect-Rejection { Get-D4RGpuTarget $legacy 'gfx1200' }
Write-Host "PASS GPU_TARGET_SCRIPT target=$target rejected=5 hardware_executed=0"
-54
View File
@@ -1,54 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$CaptureDirectory, [string]$HipRoot,
[string]$PackageRoot, [string]$OutputDirectory, [int]$Windows = 12,
[Parameter(Mandatory=$true)][string]$DlssDll, [int]$PtxWindows = 2)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/k-real-reference-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previousPython = $env:PYTHONPATH
$previousDiag = $env:D4R_DIAG_DIR
$env:PYTHONPATH = "$(Join-Path $repo '.tools/python/vendor');$previousPython"
$summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); captureDirectory=$CaptureDirectory; layers=@(); passed=$false}
try {
foreach ($layer in @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0')) {
$name = "dltss_pwin_${layer}_layer"
$captures = @(Get-ChildItem -LiteralPath $CaptureDirectory -Directory | Where-Object Name -Match ("^replay-[0-9]+-" + $name + '$'))
if (!$captures.Count) { throw "Missing actual K capture: $name" }
$capture = $captures | Sort-Object Name | Select-Object -First 1
$folder = Join-Path $OutputDirectory $layer
$output = Join-Path $folder 'output'
New-Item -ItemType Directory -Force $folder | Out-Null
$env:D4R_DIAG_DIR = $folder
& (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot `
--module (Join-Path $PackageRoot "experimental/k/${name}_${GpuArch}.hsaco") `
--fixture-dir $capture.FullName --output-dir $output --iterations 1 `
> (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log')
if ($LASTEXITCODE) { throw "K $layer actual GPU replay failed: $folder" }
& python (Join-Path $PackageRoot 'k_replay_validate.py') validate --layer $layer `
--fixture-dir $capture.FullName --output-dir $output --windows $Windows --real-capture `
> (Join-Path $folder 'reference.stdout.log') 2> (Join-Path $folder 'reference.stderr.log')
if ($LASTEXITCODE) { throw "K $layer mismatch; stopping before the next layer: $folder" }
Get-Content -LiteralPath (Join-Path $folder 'reference.stdout.log') | Write-Host
$ptxValidator = Join-Path $PackageRoot 'k_ptx_validate.py'
if (!(Test-Path -LiteralPath $ptxValidator)) { $ptxValidator = Join-Path $repo 'tools/windows/k_ptx_validate.py' }
& python -u $ptxValidator --layer $layer `
--capture-dir $capture.FullName --native-dir $output --dlss-dll $DlssDll `
--output-dir (Join-Path $folder 'private-ptx') --windows $PtxWindows `
> (Join-Path $folder 'ptx-reference.stdout.log') 2> (Join-Path $folder 'ptx-reference.stderr.log')
if ($LASTEXITCODE) { throw "K $layer independent PTX mismatch; stopping: $folder" }
Get-Content -LiteralPath (Join-Path $folder 'ptx-reference.stdout.log') | Write-Host
$summary.layers += @{layer=$layer; passed=$true}
}
$summary.passed = $true
} catch { $summary.error=$_.Exception.Message; Write-Warning $summary.error }
finally {
$env:PYTHONPATH = $previousPython; $env:D4R_DIAG_DIR = $previousDiag
$summary | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Write-Host "Private real-weight replay results: $OutputDirectory (do not redistribute captures/allocations)"
}
if (!$summary.passed) { exit 1 }
-55
View File
@@ -1,55 +0,0 @@
[CmdletBinding()]
param(
[string]$HipRoot,
[string]$PackageRoot,
[string]$OutputDirectory,
[string[]]$Layers = @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0'),
[int]$Iterations = 32
)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/k-replay-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previousPython = $env:PYTHONPATH
$previousDiag = $env:D4R_DIAG_DIR
$env:PYTHONPATH = "$(Join-Path $repo '.tools/python/vendor');$previousPython"
$summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); hipRoot=$HipRoot; architecture=$GpuArch; layers=@(); passed=$false}
try {
if ($Iterations -lt 1 -or $Iterations -gt 10000) { throw 'Iterations must be 1..10000' }
foreach ($layer in $Layers) {
if ($layer -notmatch '^(enc[0-4]|dec[0-5])$') { throw "Invalid K layer $layer" }
$folder = Join-Path $OutputDirectory $layer
$fixture = Join-Path $folder 'fixture'
$output = Join-Path $folder 'output'
New-Item -ItemType Directory -Force $folder | Out-Null
$env:D4R_DIAG_DIR = $folder
& python (Join-Path $PackageRoot 'k_replay_validate.py') generate --layer $layer --fixture-dir $fixture `
> (Join-Path $folder 'fixture.stdout.log') 2> (Join-Path $folder 'fixture.stderr.log')
if ($LASTEXITCODE) { throw "K $layer fixture generation failed; see $folder" }
& (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot `
--module (Join-Path $PackageRoot "experimental/k/dltss_pwin_${layer}_layer_${GpuArch}.hsaco") `
--fixture-dir $fixture --output-dir $output --iterations $Iterations `
> (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log')
if ($LASTEXITCODE) { throw "K $layer GPU replay failed; see $folder" }
& python (Join-Path $PackageRoot 'k_replay_validate.py') validate --layer $layer --fixture-dir $fixture --output-dir $output `
> (Join-Path $folder 'reference.stdout.log') 2> (Join-Path $folder 'reference.stderr.log')
if ($LASTEXITCODE) { throw "K $layer reference mismatch; stopping before the next layer. See $folder" }
Get-Content -LiteralPath (Join-Path $folder 'reference.stdout.log') | Write-Host
$summary.layers += @{layer=$layer; passed=$true; iterations=$Iterations}
}
$summary.passed = $true
} catch {
$summary.error = $_.Exception.Message
Write-Warning $summary.error
} finally {
$env:PYTHONPATH = $previousPython
$env:D4R_DIAG_DIR = $previousDiag
$summary | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Compress-Archive -LiteralPath $OutputDirectory -DestinationPath "$OutputDirectory.zip" -Force
Write-Host "K replay bundle: $OutputDirectory.zip"
}
if (!$summary.passed) { exit 1 }
-51
View File
@@ -1,51 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$CaptureDirectory, [string]$HipRoot,
[string]$PackageRoot, [string]$OutputDirectory, [int]$Blocks = 12,
[Parameter(Mandatory=$true)][string]$DlssDll, [int]$PtxBlocks = 2)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/m-real-reference-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previousPython=$env:PYTHONPATH; $previousDiag=$env:D4R_DIAG_DIR
$env:PYTHONPATH = "$(Join-Path $repo '.tools/python/vendor');$previousPython"
$summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); captureDirectory=$CaptureDirectory; layers=@(); passed=$false}
try {
foreach ($layer in @('enc1','enc2','enc3_tube','dec2','dec1')) {
$name = "rrlite_${layer}_4x4"
$captures = @(Get-ChildItem -LiteralPath $CaptureDirectory -Directory | Where-Object Name -Match ("^replay-[0-9]+-" + $name + '$'))
if (!$captures.Count) { throw "Missing actual M capture: $name" }
$capture = $captures | Sort-Object Name | Select-Object -First 1
$folder = Join-Path $OutputDirectory $layer
$output = Join-Path $folder 'output'
New-Item -ItemType Directory -Force $folder | Out-Null
$env:D4R_DIAG_DIR = $folder
& (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot `
--module (Join-Path $PackageRoot "experimental/m/${name}_${GpuArch}.hsaco") `
--fixture-dir $capture.FullName --output-dir $output --iterations 1 `
> (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log')
if ($LASTEXITCODE) { throw "M $layer actual GPU replay failed: $folder" }
& python (Join-Path $PackageRoot 'm_replay_validate.py') validate --layer $layer `
--fixture-dir $capture.FullName --output-dir $output --blocks $Blocks --real-capture `
> (Join-Path $folder 'reference.stdout.log') 2> (Join-Path $folder 'reference.stderr.log')
if ($LASTEXITCODE) { throw "M $layer mismatch; stopping before the next layer: $folder" }
Get-Content -LiteralPath (Join-Path $folder 'reference.stdout.log') | Write-Host
& python -u (Join-Path $PackageRoot 'm_ptx_validate.py') --layer $layer `
--capture-dir $capture.FullName --native-dir $output --dlss-dll $DlssDll `
--output-dir (Join-Path $folder 'private-ptx') --blocks $PtxBlocks `
> (Join-Path $folder 'ptx-reference.stdout.log') 2> (Join-Path $folder 'ptx-reference.stderr.log')
if ($LASTEXITCODE) { throw "M $layer independent PTX mismatch; stopping: $folder" }
Get-Content -LiteralPath (Join-Path $folder 'ptx-reference.stdout.log') | Write-Host
$summary.layers += @{layer=$layer; passed=$true}
}
$summary.passed=$true
} catch { $summary.error=$_.Exception.Message; Write-Warning $summary.error }
finally {
$env:PYTHONPATH=$previousPython; $env:D4R_DIAG_DIR=$previousDiag
$summary | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Write-Host "Private real-weight replay results: $OutputDirectory (do not redistribute captures/allocations)"
}
if (!$summary.passed) { exit 1 }
-47
View File
@@ -1,47 +0,0 @@
[CmdletBinding()]
param([string]$HipRoot, [string]$PackageRoot, [string]$OutputDirectory,
[string[]]$Layers = @('enc1','enc2','enc3_tube','dec2','dec1'),
[ValidateRange(1,10000)][int]$Iterations = 32)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/m-replay-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previousPython = $env:PYTHONPATH
$previousDiag = $env:D4R_DIAG_DIR
$env:PYTHONPATH = "$(Join-Path $repo '.tools/python/vendor');$previousPython"
$summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); hipRoot=$HipRoot; architecture=$GpuArch; layers=@(); passed=$false}
try {
foreach ($layer in $Layers) {
if ($layer -notmatch '^(enc[12]|enc3_tube|dec[12])$') { throw "Invalid M layer $layer" }
$folder = Join-Path $OutputDirectory $layer
$fixture = Join-Path $folder 'fixture'
$output = Join-Path $folder 'output'
New-Item -ItemType Directory -Force $folder | Out-Null
$env:D4R_DIAG_DIR = $folder
& python (Join-Path $PackageRoot 'm_replay_validate.py') generate --layer $layer --fixture-dir $fixture `
> (Join-Path $folder 'fixture.stdout.log') 2> (Join-Path $folder 'fixture.stderr.log')
if ($LASTEXITCODE) { throw "M $layer fixture generation failed: $folder" }
& (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot `
--module (Join-Path $PackageRoot "experimental/m/rrlite_${layer}_4x4_${GpuArch}.hsaco") `
--fixture-dir $fixture --output-dir $output --iterations $Iterations `
> (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log')
if ($LASTEXITCODE) { throw "M $layer GPU replay failed: $folder" }
& python (Join-Path $PackageRoot 'm_replay_validate.py') validate --layer $layer --fixture-dir $fixture --output-dir $output `
> (Join-Path $folder 'reference.stdout.log') 2> (Join-Path $folder 'reference.stderr.log')
if ($LASTEXITCODE) { throw "M $layer reference mismatch; stopping before the next layer: $folder" }
Get-Content -LiteralPath (Join-Path $folder 'reference.stdout.log') | Write-Host
$summary.layers += @{layer=$layer; passed=$true; iterations=$Iterations}
}
$summary.passed = $true
} catch { $summary.error=$_.Exception.Message; Write-Warning $summary.error }
finally {
$env:PYTHONPATH=$previousPython; $env:D4R_DIAG_DIR=$previousDiag
$summary | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Compress-Archive -LiteralPath $OutputDirectory -DestinationPath "$OutputDirectory.zip" -Force
Write-Host "M replay bundle: $OutputDirectory.zip"
}
if (!$summary.passed) { exit 1 }
-28
View File
@@ -1,28 +0,0 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$CaptureDirectory,
[Parameter(Mandatory=$true)][string]$BaselineValidation,
[string]$ModuleDirectory, [string]$HipRoot, [string]$OutputDirectory, [switch]$Benchmark)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$ModuleDirectory) { $ModuleDirectory=Join-Path $repo 'build/native-m-fp8-experimental' }
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo 'test-results/m-native-fp8-replay' }
$previousPython=$env:PYTHONPATH
try {
$env:PYTHONPATH="$(Join-Path $repo '.tools/python/vendor');$previousPython"
$metadata=Get-Content -LiteralPath (Join-Path $ModuleDirectory 'build-info.json') -Raw | ConvertFrom-Json
if ($metadata.hardwarePacking) {
& python -u (Join-Path $repo 'tools/windows/fp8_pack_validate.py') `
--probe (Join-Path $repo 'dist/windows-rdna4-command-list/bin/d4r_native_replay_probe.exe') `
--module (Join-Path $ModuleDirectory 'packing-probe/fp8_pack_probe.hsaco') `
--hip-root $HipRoot --output-dir (Join-Path $OutputDirectory 'packing-check')
if ($LASTEXITCODE) { throw 'Hardware packing does not preserve every finite FP8 encoding; stopping before network replay.' }
}
$benchmarkArguments=@()
if ($Benchmark) { $benchmarkArguments=@('--benchmark-control-dir',(Join-Path $repo 'build/native-m-gfx1201')) }
& python -u (Join-Path $repo 'tools/windows/m_native_replay_compare.py') `
--capture-dir $CaptureDirectory --module-dir $ModuleDirectory --hip-root $HipRoot `
--probe (Join-Path $repo 'dist/windows-rdna4-command-list/bin/d4r_native_replay_probe.exe') `
--baseline-validation $BaselineValidation --output-dir $OutputDirectory @benchmarkArguments
if ($LASTEXITCODE) { throw "Experimental FP8 validation failed; baseline unchanged. Logs: $OutputDirectory" }
} finally { $env:PYTHONPATH=$previousPython }
-52
View File
@@ -1,52 +0,0 @@
[CmdletBinding()]
param([string]$HipRoot, [string]$PackageRoot, [string]$ZludaRoot, [string]$OutputDirectory)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$ZludaRoot) { $ZludaRoot = Join-Path $repo 'dist/zluda-windows-final' }
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/native-identity-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previous = @{D4R_ZLUDA_NATIVE_DIR=$env:D4R_ZLUDA_NATIVE_DIR; D4R_ZLUDA_VERBOSE=$env:D4R_ZLUDA_VERBOSE; D4R_DIAG_DIR=$env:D4R_DIAG_DIR}
function Invoke-NativeProbe([string]$Name) {
$info = New-Object Diagnostics.ProcessStartInfo
$info.FileName = Join-Path $PackageRoot 'bin/d4r_cuda_driver_probe.exe'
$info.Arguments = '--hip-root "' + $HipRoot + '" --cuda-dll "' + (Join-Path $ZludaRoot 'nvcuda.dll') + '" --iterations 32'
$info.UseShellExecute=$false; $info.CreateNoWindow=$true; $info.RedirectStandardOutput=$true; $info.RedirectStandardError=$true
$process = New-Object Diagnostics.Process
$process.StartInfo=$info
if (!$process.Start()) { throw 'Cannot start native override probe' }
$stdout=$process.StandardOutput.ReadToEndAsync(); $stderr=$process.StandardError.ReadToEndAsync()
if (!$process.WaitForExit(120000)) { $process.Kill(); $process.WaitForExit(); throw 'Native override test timed out' }
[IO.File]::WriteAllText((Join-Path $OutputDirectory "$Name.stdout.log"),$stdout.GetAwaiter().GetResult())
[IO.File]::WriteAllText((Join-Path $OutputDirectory "$Name.stderr.log"),$stderr.GetAwaiter().GetResult())
$code=$process.ExitCode; $process.Dispose()
return $code
}
try {
$env:D4R_ZLUDA_VERBOSE = '1'; $env:D4R_DIAG_DIR = $OutputDirectory
$bad = Join-Path $OutputDirectory 'wrong-identity'
$good = Join-Path $OutputDirectory 'matching-identity'
New-Item -ItemType Directory -Force $bad,$good | Out-Null
foreach ($directory in @($bad,$good)) {
Copy-Item -LiteralPath (Join-Path $PackageRoot "bin/probe_${GpuArch}.hsaco") -Destination (Join-Path $directory 'd4r_ptx_pattern.hsaco') -Force
}
'd4r_ptx_pattern 0000000000000000' | Set-Content -LiteralPath (Join-Path $bad 'd4r-kernels.txt') -Encoding ASCII
$env:D4R_ZLUDA_NATIVE_DIR = $bad
if (Invoke-NativeProbe 'wrong') { throw 'Wrong identity must use the correct translated fallback' }
if (!(Select-String -LiteralPath (Join-Path $OutputDirectory 'wrong.stderr.log') -Pattern 'reason=ptx_identity.*fallback=translated' -Quiet)) {
throw 'Wrong identity was not explicitly rejected'
}
$identity = Select-String -LiteralPath (Join-Path $OutputDirectory 'wrong.stdout.log') -Pattern 'fnv1a64=([0-9a-f]{16})'
if (!$identity) { throw 'PTX probe did not report its identity' }
"d4r_ptx_pattern $($identity.Matches[0].Groups[1].Value)" | Set-Content -LiteralPath (Join-Path $good 'd4r-kernels.txt') -Encoding ASCII
$env:D4R_ZLUDA_NATIVE_DIR = $good
if (Invoke-NativeProbe 'matching') { throw 'Matching native override produced incorrect output' }
$hits = @(Select-String -LiteralPath (Join-Path $OutputDirectory 'matching.stderr.log') -Pattern '\[d4r-launch\].*backend=native')
if ($hits.Count -ne 32) { throw "Expected 32 native launches, got $($hits.Count)" }
Write-Host 'PASS NATIVE_IDENTITY wrong_hash=fallback matching_hash=native launches=32'
} finally {
foreach ($name in $previous.Keys) { [Environment]::SetEnvironmentVariable($name,$previous[$name],'Process') }
}
-94
View File
@@ -1,94 +0,0 @@
[CmdletBinding()]
param([string]$TextureRoot, [string]$ControlTextureRoot, [string]$CommonTextureRoot, [string]$ZludaRoot, [string]$PackageRoot,
[string]$OutputDirectory, [int]$Iterations=8, [string]$OutputResolution='512x288', [string]$InputResolution,
[switch]$CandidateFirst,
[ValidateSet('output','input')][string]$KernelStage='output')
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$PackageRoot) { $PackageRoot=Join-Path $repo 'dist/windows-rdna4-command-list' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$TextureRoot) { $TextureRoot=Join-Path $repo "build/private-textures-$GpuArch" }
if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo 'test-results/k-native-texture-reference' }
if ($OutputResolution -notmatch '^([0-9]+)x([0-9]+)$') { throw 'OutputResolution must be WIDTHxHEIGHT.' }
$outputWidth=[int]$Matches[1]; $outputHeight=[int]$Matches[2]
$combined=Join-Path $OutputDirectory 'private-native'
New-Item -ItemType Directory -Force $combined | Out-Null
foreach ($directory in @((Join-Path $repo "build/native-k-$GpuArch"),$CommonTextureRoot,$TextureRoot) | Where-Object { $_ }) {
Get-ChildItem -LiteralPath $directory -Filter '*.hsaco' | Copy-Item -Destination $combined -Force
}
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $combined (Join-Path $repo 'nvngx_dlss.dll')
if ($LASTEXITCODE) { throw 'Combined private manifest failed.' }
$controlNative=Join-Path $repo "build/native-k-$GpuArch"
if ($ControlTextureRoot -or $CommonTextureRoot) {
$controlNative=Join-Path $OutputDirectory 'control-private-native'
New-Item -ItemType Directory -Force $controlNative | Out-Null
foreach ($directory in @((Join-Path $repo "build/native-k-$GpuArch"),$CommonTextureRoot,$ControlTextureRoot) | Where-Object { $_ }) {
Get-ChildItem -LiteralPath $directory -Filter '*.hsaco' | Copy-Item -Destination $controlNative -Force
}
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $controlNative (Join-Path $repo 'nvngx_dlss.dll')
if ($LASTEXITCODE) { throw 'Control private manifest failed.' }
}
$settings=@{D4R_VALIDATE_OUTPUT='1'; D4R_PROFILE_STAGES='1'; D4R_ZLUDA_PROFILE='1'; D4R_QUIET_API='1';
D4R_ZLUDA_WMMA='1'; D4R_ZLUDA_WMMA_FP8='1'; D4R_ZLUDA_WMMA_FP8_NATIVE='0';
D4R_ZLUDA_WMMA_F16_REFERENCE='1'; D4R_ZLUDA_PROFILE_DEFERRED=$null;
ZLUDA_CACHE_DIR=(Join-Path $repo 'build/zluda-cache-windows'); PYTHONPATH=(Join-Path $repo '.tools/python/vendor');
D4R_ZLUDA_NATIVE_DIR=$null}
$old=@{}
$stagedObjects=@{}
foreach ($stage in @(@{name='control'; root=$controlNative},@{name='candidate'; root=$combined})) {
$stagedObjects[$stage.name]=@{}
foreach ($object in Get-ChildItem -LiteralPath $stage.root -Filter '*.hsaco') {
Assert-D4RCodeObjectTarget $object.FullName $GpuArch
$stagedObjects[$stage.name][$object.Name]=(Get-FileHash -LiteralPath $object.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
}
}
try {
foreach ($key in $settings.Keys) { $old[$key]=[Environment]::GetEnvironmentVariable($key,'Process'); [Environment]::SetEnvironmentVariable($key,$settings[$key],'Process') }
foreach ($flags in @(0,11)) {
$variant=if ($flags -eq 11) { 'depthinv_mvlo_hdr' } else { 'depthreg_mvhi_ldr' }
$suffix=if ($KernelStage -eq 'output') { '_max_v2_rel' } else { '_v2_rel' }
$kernel="hiluma_engine_${KernelStage}_${variant}${suffix}"
$order=if ($CandidateFirst) { @('candidate','control') } else { @('control','candidate') }
foreach ($mode in $order) {
$env:D4R_ZLUDA_NATIVE_DIR=if ($mode -eq 'control') { $controlNative } else { $combined }
$expectedBackend=if (Test-Path -LiteralPath (Join-Path $env:D4R_ZLUDA_NATIVE_DIR ($kernel + '.hsaco'))) { 'native' } else { 'translated' }
if ($mode -eq 'candidate' -and $expectedBackend -ne 'native') { throw "Missing candidate object: $kernel" }
$arguments=@{RuntimeProfile='therock'; ZludaRoot=$ZludaRoot;
PackageRoot=$PackageRoot; NgxCore=(Join-Path $repo '_nvngx.dll');
DlssDll=(Join-Path $repo 'nvngx_dlss.dll'); NgxMode='d3d12'; NgxAbi='project-legacy'; Preset=11;
NgxCreateFlags=$flags; NgxOutputResolution=$OutputResolution; NgxOnly=$true; RequireNativeNetwork=$true; CommandListBackend=$true;
NgxInputResolution=$InputResolution;
PixelProfile='depth-stencil'; BarrierMode='inherited-legacy'; CaptureExceptions=$true; EarlyIndirectProbe=$true;
Iterations=$Iterations; TimeoutSeconds=300; OptiScalerDll=(Join-Path $repo 'dist/optiscaler-windows-d4r/OptiScaler.dll');
OutputDirectory=(Join-Path $OutputDirectory "$mode-$flags")}
& (Join-Path $PSScriptRoot 'test-windows-rdna4.ps1') @arguments
if ($LASTEXITCODE) { throw "Texture $mode flags=$flags workload failed." }
& python (Join-Path $repo 'tools/windows/profile_report.py') $arguments.OutputDirectory --output (Join-Path $arguments.OutputDirectory 'profile.json')
if ($LASTEXITCODE) { throw 'Texture profile report failed.' }
$profile=Get-Content -LiteralPath (Join-Path $arguments.OutputDirectory 'profile.json') -Raw | ConvertFrom-Json
$samples=@($profile.kernels | Where-Object { $_.kernel -eq $kernel -and $_.backend -eq $expectedBackend -and $_.phase -eq 'main' -and $_.serializing })
if ($samples.Count -ne 1 -or $samples[0].gpuMs.samples -ne $Iterations) {
throw "Missing valid serializing $KernelStage-kernel timings ($expectedBackend) for $mode flags=$flags; retain this run as correctness evidence only."
}
}
$control=Join-Path $OutputDirectory "control-$flags"; $candidate=Join-Path $OutputDirectory "candidate-$flags"
$stderr=Get-Content -LiteralPath (Join-Path $candidate 'd3d12-evaluate-preset-11.stderr.log') -Raw
$hits=[regex]::Matches($stderr, ('\[d4r-launch\] kernel="' + $kernel + '" backend=native')).Count
if ($hits -ne $Iterations) { throw "Texture override was not executed on every frame: $kernel hits=$hits" }
& python (Join-Path $repo 'tools/windows/frame_compare.py') --reference $control --actual $candidate --width $outputWidth --height $outputHeight --exact
if ($LASTEXITCODE) { throw "Texture flags=$flags full-frame RGB mismatch; preserve baseline." }
}
@{passed=$true; architecture=$GpuArch; framesPerVariant=$Iterations; outputResolution=$OutputResolution; createFlags=@(0,11); strictRgb=$true;
inputResolution=$InputResolution;
serializingProfile=$true; candidateFirst=[bool]$CandidateFirst; kernelStage=$KernelStage;
controlTextureRoot=$ControlTextureRoot; commonTextureRoot=$CommonTextureRoot;
stagedObjects=$stagedObjects;
manifestSha256=(Get-FileHash -LiteralPath (Join-Path $TextureRoot 'd4r-kernels.txt') -Algorithm SHA256).Hash.ToLowerInvariant();
privateNvidiaDerivedCode=$true; source=(Get-Content -LiteralPath (Join-Path $TextureRoot 'build-info.json') -Raw | ConvertFrom-Json)} |
ConvertTo-Json -Depth 12 | Set-Content -LiteralPath (Join-Path $TextureRoot 'validation.json') -Encoding UTF8
Write-Host "PASS: both private K $KernelStage variants executed and matched every RGB component. $OutputDirectory"
} finally {
foreach ($key in $old.Keys) { [Environment]::SetEnvironmentVariable($key,$old[$key],'Process') }
}
-160
View File
@@ -1,160 +0,0 @@
# Reproduce numeric NGX feature discovery without launching or modifying a game.
# The private NVIDIA DLL staging directory is deleted; reports contain logs only.
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$DiagnosticRoot,
[Parameter(Mandatory=$true)][string]$HipRoot,
[Parameter(Mandatory=$true)][string]$ZludaRoot,
[Parameter(Mandatory=$true)][string]$NativeRoot,
[Parameter(Mandatory=$true)][string]$OptiScalerDll,
[Parameter(Mandatory=$true)][string]$NgxCore,
[Parameter(Mandatory=$true)][string]$DlssDll,
[Parameter(Mandatory=$true)][string]$OutputDirectory,
[UInt64]$ApplicationId=100152211)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
foreach ($name in @('DiagnosticRoot','HipRoot','ZludaRoot','NativeRoot','OptiScalerDll','NgxCore','DlssDll')) {
Set-Variable -Name $name -Value ((Get-Item -LiteralPath (Get-Variable -Name $name -ValueOnly)).FullName)
}
$arch=Get-D4RGpuTarget $DiagnosticRoot
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$runtime=Join-Path ([IO.Path]::GetTempPath()) ('d4r-feature-layout-'+[Guid]::NewGuid().ToString('N'))
$settings=@{HIP_PATH=$HipRoot; PATH="$HipRoot\bin;$ZludaRoot;$env:PATH";
D4R_NVAPI_BACKEND=(Join-Path $ZludaRoot 'nvapi64.dll'); ZLUDA_CUDA_LIB=(Join-Path $ZludaRoot 'nvcuda.dll');
D4R_ZLUDA_NATIVE_DIR=$NativeRoot; D4R_ZLUDA_VERBOSE='1';
D4R_ZLUDA_WMMA='1'; D4R_ZLUDA_WMMA_F16_REFERENCE='1'; D4R_ZLUDA_WMMA_FP8='1'; D4R_ZLUDA_WMMA_FP8_NATIVE='0';
D4R_VALIDATE_OUTPUT='1'; D4R_DIAG_DIR=$null; ZLUDA_LOG_DIR=$null; D4R_FORMAT_MODULE=$null;
D4R_ASYNC_INTEROP=$null; D4R_BATCH_INPUT_COPIES=$null; D4R_D3D12_COMMAND_BACKEND=$null}
$old=@{}; $results=@()
try {
foreach ($key in $settings.Keys) { $old[$key]=[Environment]::GetEnvironmentVariable($key,'Process'); [Environment]::SetEnvironmentVariable($key,$settings[$key],'Process') }
foreach ($dir in @('app','d4r','d4r/vendor')) { New-Item -ItemType Directory -Force (Join-Path $runtime $dir) | Out-Null }
$exe=Join-Path $runtime 'app/d4r_d3d12_dlss_probe.exe'
$shim=Join-Path $runtime 'd4r/_nvngx.dll'
$core=Join-Path $runtime 'd4r/vendor/_nvngx.dll'
$feature=Join-Path $runtime 'd4r/vendor/nvngx_dlss.dll'
Copy-Item -LiteralPath (Join-Path $DiagnosticRoot 'bin/d4r_d3d12_dlss_probe.exe') -Destination $exe
Copy-Item -LiteralPath (Join-Path $DiagnosticRoot 'bin/d4r_nvngx.dll') -Destination $shim
Copy-Item -LiteralPath (Join-Path $DiagnosticRoot "bin/pixel_convert_${arch}.hsaco") -Destination (Split-Path $shim)
Copy-Item -LiteralPath $NgxCore -Destination $core
Copy-Item -LiteralPath $DlssDll -Destination $feature
$opti=Join-Path $runtime 'app/OptiScaler.dll'
Copy-Item -LiteralPath $OptiScalerDll -Destination $opti
$cases=@(@{name='vendor-only-negative'; preset=11; frontend='d4r'; expectedExit=4},
@{name='optiscaler-vendor-only-negative'; preset=11; frontend='optiscaler'; expectedExit=4},
@{name='caller-dll-k'; preset=11; frontend='d4r'; expectedExit=0},
@{name='optiscaler-caller-k'; preset=11; frontend='optiscaler'; expectedExit=0},
@{name='optiscaler-caller-m'; preset=13; frontend='optiscaler'; expectedExit=0})
foreach ($case in $cases) {
$out=Join-Path $OutputDirectory $case.name
New-Item -ItemType Directory -Force $out | Out-Null
if ($case.expectedExit -eq 0) {
$feature=Join-Path $runtime 'd4r/nvngx_dlss.dll'
if (!(Test-Path -LiteralPath $feature)) { Copy-Item -LiteralPath $DlssDll -Destination $feature }
}
$env:D4R_DIAG_DIR=$out; $env:ZLUDA_LOG_DIR=Join-Path $out 'zluda-trace'
$env:D4R_FORMAT_MODULE=Join-Path $runtime "d4r/pixel_convert_${arch}.hsaco"
$module=if ($case.frontend -eq 'optiscaler') { $opti } else { $shim }
if ($case.frontend -eq 'optiscaler') {
@"
[Upscalers]
Dx12Upscaler=dlss
[FrameGen]
Enabled=false
FGInput=nofg
FGOutput=nofg
[DLSS]
Enabled=true
AllowExternalBackend=true
RenderPresetOverride=true
RenderPresetForAll=$($case.preset)
UseGenericAppIdWithDlss=false
[Libraries]
NvngxPath=$(Split-Path $shim)
NvngxDlssPath=$(Split-Path $feature)
NvngxFeaturePath=$(Split-Path $feature)
[Hotfix]
RestoreComputeSignature=false
RestoreGraphicSignature=false
ExtendedStateRestore=false
[Log]
LogToFile=true
LogLevel=0
[Menu]
DisableSplash=true
"@ | Set-Content -LiteralPath (Join-Path $runtime 'app/OptiScaler.ini') -Encoding UTF8
}
$arguments=@('--hip-root',$HipRoot,'--cuda-dll',(Join-Path $ZludaRoot 'nvcuda.dll'),
'--module',$module,'--ngx-core',$core,'--dlss-dll',$feature,
'--nvapi-dll',(Join-Path $DiagnosticRoot 'nvapi-compat/nvapi64.dll'),
'--ngx-app-id',"$ApplicationId",'--ngx-abi','driver','--ngx-frontend',$case.frontend,
'--interop-mode','command-list','--iterations','3','--preset',"$($case.preset)")
$info=New-Object Diagnostics.ProcessStartInfo
# Capture harness faults outside OptiScaler's loader hooks. Games use
# the no-debug launcher by default; this developer reproducer is separate.
$arguments=@('--output-directory',$out,'--',$exe)+$arguments
$info.FileName=Join-Path $DiagnosticRoot 'bin/d4r_debug_launcher.exe'; $info.WorkingDirectory=Split-Path $exe
$info.Arguments=(@($arguments | ForEach-Object { if ($_.Contains('"')) { throw 'Unsupported quote in test path.' }; '"'+$_+'"' }) -join ' ')
$info.UseShellExecute=$false; $info.CreateNoWindow=$true; $info.RedirectStandardOutput=$true; $info.RedirectStandardError=$true
foreach ($key in $settings.Keys) { if (![Environment]::GetEnvironmentVariable($key,'Process')) { $info.EnvironmentVariables.Remove($key) } }
$process=New-Object Diagnostics.Process; $process.StartInfo=$info
try {
[void]$process.Start(); $stdout=$process.StandardOutput.ReadToEndAsync(); $stderr=$process.StandardError.ReadToEndAsync()
if (!$process.WaitForExit(240000)) { $process.Kill(); $process.WaitForExit(); throw "NGX layout test timed out: $($case.name)" }
$log=$stdout.GetAwaiter().GetResult(); $errorLog=$stderr.GetAwaiter().GetResult()
[IO.File]::WriteAllText((Join-Path $out 'stdout.log'),$log)
[IO.File]::WriteAllText((Join-Path $out 'stderr.log'),$errorLog)
if ($process.ExitCode -ne $case.expectedExit) { throw "Unexpected exit $($process.ExitCode): $($case.name), see $out" }
if ($case.expectedExit) {
if ($log -notmatch 'D4R_CAPABILITIES available=0 feature_init=0xbad00004' -or $log -match 'D4R_FRAME ') { throw 'Old vendor-only layout did not reproduce FeatureNotFound.' }
if ($case.frontend -eq 'optiscaler' -and $errorLog -notmatch 'FAIL D3D12_DLSS D3D12 Init NGX=') { throw 'OptiScaler swallowed the numeric backend initialization failure.' }
} else {
if ($log -notmatch 'D4R_CAPABILITIES available=1 feature_init=0x00000001 needs_driver=0' -or
([regex]::Matches($log,'D3D12_OUTPUT preset=\d+ frame=\d+ finite=1')).Count -ne 3 -or
([regex]::Matches($log,'D4R_OUTPUT_VALIDATION elements=\d+ nan=0 inf=0 diagnostics_cpu_bytes=8')).Count -ne 3 -or
$log -notmatch 'PASS D3D12_DLSS .*fast_path_cpu_copies=0 frame_age=0' -or $errorLog -match 'D4R_WINDOWS_FAILURE') { throw 'Corrected feature layout did not complete finite zero-copy frames.' }
$required=@(Get-Content -LiteralPath (Join-Path $NativeRoot 'd4r-kernels.txt') | Where-Object {
if ($case.preset -eq 11) { $_ -match '^dltss_pwin_' } else { $_ -match '^rrlite_' }
} | ForEach-Object { $_.Split(' ')[0] })
if ($required.Count -ne $(if ($case.preset -eq 11) { 11 } else { 5 })) { throw 'Incomplete native manifest.' }
foreach ($kernel in $required) {
if ($errorLog -notmatch ('\[d4r-launch\] kernel="'+[regex]::Escape($kernel)+'" backend=native') -or
$errorLog -match ('\[d4r-launch\] kernel="'+[regex]::Escape($kernel)+'" backend=translated')) { throw "Missing native network execution: $kernel" }
}
if ($case.frontend -eq 'd4r' -and $log -notmatch 'D3D12_REQUIREMENTS warp_supported=0 enumeration_success=1') { throw 'WARP adapter enumeration regression failed.' }
}
$results+=@{case=$case.name; passed=$true; expectedExit=$case.expectedExit; application=$ApplicationId; preset=$case.preset; architecture=$arch}
Write-Host "PASS NGX_FEATURE_LAYOUT $($case.name)"
} finally {
if ($case.frontend -eq 'optiscaler') {
Get-ChildItem -LiteralPath (Split-Path $exe) -Filter '*.log' -File | ForEach-Object {
Copy-Item -LiteralPath $_.FullName -Destination $out -Force
}
}
$process.Dispose()
}
}
for ($frame=0; $frame -lt 3; $frame++) {
$direct=[IO.File]::ReadAllBytes((Join-Path $OutputDirectory "caller-dll-k/output-$frame.rgba16f"))
$frontend=[IO.File]::ReadAllBytes((Join-Path $OutputDirectory "optiscaler-caller-k/output-$frame.rgba16f"))
if ($direct.Length -ne $frontend.Length -or $direct.Length -ne 512*288*8) { throw 'RGB comparison dimensions differ.' }
for ($pixel=0; $pixel -lt $direct.Length; $pixel+=8) {
if (([BitConverter]::ToUInt64($direct,$pixel) -band [UInt64]0xffffffffffff) -ne
([BitConverter]::ToUInt64($frontend,$pixel) -band [UInt64]0xffffffffffff)) { throw "K frontend RGB mismatch: frame=$frame offset=$pixel" }
}
}
$results+=@{case='k-direct-optiscaler-rgb'; passed=$true; frames=3; rgbByteExact=$true; maxAbsoluteError=0; maxRelativeError=0}
Write-Host 'PASS NGX_FEATURE_LAYOUT k_direct_optiscaler_rgb exact=1 max_abs=0 max_rel=0'
} finally {
foreach ($key in $old.Keys) { [Environment]::SetEnvironmentVariable($key,$old[$key],'Process') }
$results | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'feature-layout.json') -Encoding UTF8
$resolved=[IO.Path]::GetFullPath($runtime)
$temp=[IO.Path]::GetFullPath([IO.Path]::GetTempPath()).TrimEnd('\')+'\'
if (!$resolved.StartsWith($temp,[StringComparison]::OrdinalIgnoreCase) -or [IO.Path]::GetFileName($resolved) -notmatch '^d4r-feature-layout-[0-9a-f]{32}$') { throw 'Refusing cleanup outside private NGX staging.' }
if (Test-Path -LiteralPath $resolved) {
foreach ($attempt in 1..10) {
try { Remove-Item -LiteralPath $resolved -Recurse -Force; break }
catch { if ($attempt -eq 10) { throw }; Start-Sleep -Milliseconds 300 }
}
}
}
-92
View File
@@ -1,92 +0,0 @@
# Drag-in player mode checks. Builds with the vendored llvm-mingw; needs no
# NVIDIA DLLs and launches no GPU kernels. The loader case enumerates HIP
# devices and is skipped (reported, not passed) without a supported AMD GPU.
[CmdletBinding()]
param(
[string]$CompilerRoot, [string]$HipRoot, [string]$OutputDirectory
)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$CompilerRoot) { $CompilerRoot=Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64' }
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/player-config/'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$cxx=Join-Path $CompilerRoot 'bin/x86_64-w64-mingw32-clang++.exe'
if (!(Test-Path -LiteralPath $cxx)) { throw "llvm-mingw not found: $cxx" }
if (!(Test-Path -LiteralPath (Join-Path $HipRoot 'include/hip/hip_runtime_api.h'))) { throw "HIP headers not found under $HipRoot" }
# Same generated target table as CMakeLists.txt.
$targets=(Get-Content -LiteralPath (Join-Path $repo 'tools/windows/gpu-targets.json') -Raw | ConvertFrom-Json).targets
$generated=Join-Path $OutputDirectory 'generated'
New-Item -ItemType Directory -Force $generated | Out-Null
$entries=($targets | ForEach-Object { " GpuTarget{`"$($_.architecture)`", $($_.elfMachine), $($_.isaMajor), `"$($_.family)`"}," }) -join "`n"
@('#pragma once','#include <array>','namespace d4r::diag {',
'struct GpuTarget { const char* architecture; unsigned elf_machine; unsigned isa_major; const char* family; };',
"inline constexpr std::array<GpuTarget, $($targets.Count)> gpu_targets = {{",$entries,'}};','}') |
Set-Content -LiteralPath (Join-Path $generated 'gpu_targets.generated.h') -Encoding ASCII
$common=@('-std=c++17','-O1','-static','-DWIN32_LEAN_AND_MEAN','-DNOMINMAX','-D__HIP_PLATFORM_AMD__','-DD4R_TARGET_ARCH="gfx1201"',
'-I',$generated,'-I',(Join-Path $repo 'tools/windows'),'-I',(Join-Path $repo 'tools'),'-I',(Join-Path $HipRoot 'include'))
# Windows PowerShell turns native stderr into terminating errors under Stop;
# judge native tools by exit code and keep their output in the log.
function Invoke-Native([string]$Log,[string]$Exe,[string[]]$Arguments) {
$ErrorActionPreference='Continue'
& $Exe @Arguments *> $Log
return $LASTEXITCODE
}
function Build([string]$Name,[string[]]$Arguments) {
$log=Join-Path $OutputDirectory "build-$Name.log"
# PowerShell 5 / Legacy native passing strips embedded quotes. PowerShell
# 7's Standard/Windows passing preserves them and must not double-escape.
if ($PSVersionTable.PSVersion.Major -le 5 -or $PSNativeCommandArgumentPassing -eq 'Legacy') {
$Arguments=@($Arguments | ForEach-Object { $_.Replace('"','\"') })
}
if (Invoke-Native $log $cxx $Arguments) { throw "Build failed: $Name; see $log" }
}
$results=@()
# 1. d4r.ini validation and DLL pin decisions (the shim's own header).
$probe=Join-Path $OutputDirectory 'player_config_probe.exe'
Build 'player-config' ($common+@('-municode',(Join-Path $repo 'tools/windows/player_config_probe.cpp'),'-o',$probe,'-lversion','-ldbghelp','-lbcrypt'))
if (Invoke-Native (Join-Path $OutputDirectory 'player-config.log') $probe @((Join-Path $OutputDirectory 'pins-fixture'))) { throw "player_config_probe failed; see $(Join-Path $OutputDirectory 'player-config.log')" }
$results+=@{case='d4r-ini-and-dll-pins'; passed=$true}
# 2. Loader: GPU-free marker, LUID-based target selection, forwarding, and a
# clear failure when the folder has no build for the detected GPU.
$folder=Join-Path $OutputDirectory 'game/d4r'
New-Item -ItemType Directory -Force (Join-Path $folder 'hip/bin') | Out-Null
Build 'loader' ($common+@('-shared',(Join-Path $repo 'tools/windows/d4r_nvngx_loader.cpp'),'-o',(Join-Path $folder '_nvngx.dll'),'-lversion','-ldbghelp'))
$harness=Join-Path $OutputDirectory 'loader_selection_probe.exe'
Build 'harness' @('-municode','-static',(Join-Path $repo 'tools/windows/loader_selection_probe.cpp'),'-o',$harness,'-ldxgi','-ldxguid')
$stub=Join-Path $OutputDirectory 'stub.cpp'
@('#define API extern "C" __declspec(dllexport)',
'struct Req { unsigned FeatureSupported, MinHWArchitecture; char MinOSVersion[255]; };',
'API unsigned NVSDK_NGX_D3D12_GetFeatureRequirements(void*, const void*, Req* r) { r->FeatureSupported = 0; r->MinHWArchitecture = 0x5101; return 1; }') |
Set-Content -LiteralPath $stub -Encoding ASCII
$stubDll=Join-Path $OutputDirectory 'stub.dll'
Build 'stub' @('-shared','-static',$stub,'-o',$stubDll)
foreach ($name in @('amdhip64_7.dll','amd_comgr.dll','rocm_kpack.dll')) {
$source=Join-Path $HipRoot "bin/$name"
if (Test-Path -LiteralPath $source) { Copy-Item -LiteralPath $source -Destination (Join-Path $folder 'hip/bin') }
}
$log=Join-Path $OutputDirectory 'loader-without-builds.log'
[void](Invoke-Native $log $harness @((Join-Path $folder '_nvngx.dll')))
$text=Get-Content -LiteralPath $log -Raw
if ($text -notmatch 'MARKER version=1 hip_loaded=0') { throw "Discovery marker loaded HIP or failed; see $log" }
if ($text -match 'supported=0') { throw "An adapter was reported supported without any target build; see $log" }
$gpuLog=Join-Path $folder 'd4r_nvngx.log'
$detected=$null
if (Test-Path -LiteralPath $gpuLog) { $detected=[regex]::Match((Get-Content -LiteralPath $gpuLog -Raw),'no build for your GPU \((gfx[0-9a-f]+)\)').Groups[1].Value }
if (!$detected) {
$results+=@{case='loader-selection'; passed=$null; skipped='no supported AMD HIP device detected'}
Write-Host 'SKIP loader selection: no supported AMD HIP device detected on this machine.' -ForegroundColor Yellow
} else {
if ((Get-Content -LiteralPath $gpuLog -Raw) -notmatch 'It supports: none \(the d4r folder is incomplete') { throw "Unclear unsupported-GPU message; see $gpuLog" }
Copy-Item -LiteralPath $stubDll -Destination (Join-Path $folder "_nvngx_$detected.dll")
$log=Join-Path $OutputDirectory 'loader-with-build.log'
[void](Invoke-Native $log $harness @((Join-Path $folder '_nvngx.dll')))
if ((Get-Content -LiteralPath $log -Raw) -notmatch 'vendor=0x1002 status=0x1 supported=0 marker=0x5101') { throw "AMD adapter was not forwarded to _nvngx_$detected.dll; see $log" }
$results+=@{case='loader-selection'; passed=$true; architecture=$detected; gpuKernelsExecuted=$false}
}
$results | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Write-Host "PASS PLAYER_CONFIG cases=$(@($results | Where-Object { $_.passed }).Count) skipped=$(@($results | Where-Object { $_.skipped }).Count) Report: $OutputDirectory"
-133
View File
@@ -1,133 +0,0 @@
# Isolated installer checks; never starts a real game or launches GPU kernels.
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$PackageRoot,
[Parameter(Mandatory=$true)][string]$NgxCore,
[Parameter(Mandatory=$true)][string]$DlssDll,
[string]$OutputDirectory
)
$ErrorActionPreference='Stop'
if ($PSVersionTable.PSVersion.Major -ge 6) {
# The fixture uses the .NET Framework C# compiler; the shipped launcher
# also runs Windows PowerShell 5. PowerShell 7 cannot emit an EXE via Add-Type.
$arguments=@('-NoProfile','-STA','-ExecutionPolicy','Bypass','-File',$PSCommandPath,
'-PackageRoot',$PackageRoot,'-NgxCore',$NgxCore,'-DlssDll',$DlssDll)
if ($OutputDirectory) { $arguments+=@('-OutputDirectory',$OutputDirectory) }
& "$env:SystemRoot/System32/WindowsPowerShell/v1.0/powershell.exe" @arguments
exit $LASTEXITCODE
}
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$PackageRoot=(Get-Item -LiteralPath $PackageRoot).FullName
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/windows-quick-test/'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
function Invoke-Child([string]$Name,[string[]]$Arguments,[int]$ExpectedExit=0) {
$log=Join-Path $OutputDirectory "$Name.log"
& "$env:SystemRoot/System32/WindowsPowerShell/v1.0/powershell.exe" -NoProfile -STA -ExecutionPolicy Bypass `
-File (Join-Path $PackageRoot 'files/quick-test.ps1') @Arguments *> $log
if ($LASTEXITCODE -ne $ExpectedExit) { throw "Unexpected exit $LASTEXITCODE for $Name; see $log" }
}
function Fixture([string]$Name) {
$dir=Join-Path $OutputDirectory $Name
New-Item -ItemType Directory -Force $dir | Out-Null
$exe=Join-Path $dir 'Fixture.exe'
Set-Content -LiteralPath $exe 'installer fixture; do not execute' -Encoding ASCII
return $exe
}
$results=@()
$exe=Fixture ('space GPU '+[char]0x03a9+' test')
$game=Split-Path $exe
$before=@{}
foreach ($name in @('dxgi.dll','OptiScaler.ini','nvngx_dlss.dll')) {
Set-Content -LiteralPath (Join-Path $game $name) "original $name" -Encoding ASCII
$before[$name]=(Get-FileHash -LiteralPath (Join-Path $game $name)).Hash
}
Invoke-Child 'install' @('-Action','install','-GameExe',$exe,'-NgxCore',$NgxCore,'-DlssDll',$DlssDll)
if ((Get-FileHash -LiteralPath (Join-Path $game 'd4r/nvngx_dlss.dll')).Hash -ne (Get-FileHash -LiteralPath $DlssDll).Hash) {
throw 'Numeric NGX driver feature DLL was not staged beside the shim.'
}
if ((Get-FileHash -LiteralPath (Join-Path $game 'nvngx_dlss.dll')).Hash -ne $before['nvngx_dlss.dll']) { throw 'Original application DLSS DLL was changed.' }
$saved=Get-Content -LiteralPath (Join-Path $PackageRoot 'work/settings.json') -Raw | ConvertFrom-Json
if ($saved.game -ne $exe -or $saved.architecture -ne 'gfx1201') { throw 'GPU detection or remembered selection failed on this RX9070XT fixture.' }
# Restore uses remembered game selection and needs neither HIP nor NVIDIA DLLs.
Invoke-Child 'restore' @('-Action','restore')
foreach ($name in $before.Keys) { if ((Get-FileHash -LiteralPath (Join-Path $game $name)).Hash -ne $before[$name]) { throw 'Original game bytes not restored.' } }
if (Test-Path -LiteralPath (Join-Path $game 'd4r')) { throw 'Runtime directory remains after restore.' }
$results+=@{case='auto-gfx1201-install-remember-restore'; passed=$true; gpuKernelsExecuted=$false}
$manifest=Get-Content -LiteralPath (Join-Path $PackageRoot 'files/package.json') -Raw | ConvertFrom-Json
if ($manifest.bundledNvidia) {
# Bundled originals take precedence over stale remembered shim selections;
# explicit overrides still go through the existing strict negative gates.
$exe=Fixture 'bundled auto selection'
$saved.ngxCore=Join-Path $PackageRoot 'files/targets/gfx1201/d4r/_nvngx.dll'
$saved.dlssDll=$saved.ngxCore
$saved | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $PackageRoot 'work/settings.json') -Encoding UTF8
Invoke-Child 'bundled-install' @('-Action','install','-GameExe',$exe)
$game=Split-Path $exe
foreach ($pair in @(@{path='d4r/vendor/_nvngx.dll'; expected=$NgxCore},@{path='d4r/nvngx_dlss.dll'; expected=$DlssDll})) {
if ((Get-FileHash -LiteralPath (Join-Path $game $pair.path)).Hash -ne (Get-FileHash -LiteralPath $pair.expected).Hash) { throw 'Bundled original DLL selection failed.' }
}
$report=Get-ChildItem -LiteralPath (Join-Path $PackageRoot 'results') -Directory | Sort-Object Name -Descending | Select-Object -First 1
$status=Get-Content -LiteralPath (Join-Path $report.FullName 'quick-test.json') -Raw | ConvertFrom-Json
if ($status.nvidiaDllSource.core -ne 'bundled' -or $status.nvidiaDllSource.dlss -ne 'bundled') { throw 'Bundled DLL provenance is missing.' }
Invoke-Child 'bundled-restore' @('-Action','restore','-GameExe',$exe)
if (Test-Path -LiteralPath (Join-Path $game 'd4r')) { throw 'Bundled runtime directory remains after restore.' }
$results+=@{case='bundled-auto-selection-ignores-stale-choices'; passed=$true; gpuKernelsExecuted=$false}
$core=Join-Path (Join-Path $PackageRoot 'files') $manifest.bundledNvidia.ngxCore
$original=[IO.File]::ReadAllBytes($core)
try {
[IO.File]::AppendAllText($core,'tampered bundled fixture')
$exe=Fixture 'tampered bundled core'
Invoke-Child 'tampered-bundled-core' @('-Action','install','-GameExe',$exe) 1
$game=Split-Path $exe
if ((Test-Path -LiteralPath (Join-Path $game '.d4r-backup')) -or (Test-Path -LiteralPath (Join-Path $game 'dxgi.dll'))) { throw 'Tampered bundled DLL changed game files.' }
$results+=@{case='tampered-bundled-core'; passed=$true; rejectedBeforeGameChanges=$true; gpuKernelsExecuted=$false}
} finally { [IO.File]::WriteAllBytes($core,$original) }
}
# A harmless child refuses attached debuggers and produces an empty stderr.
# The default launcher must allow it to exit and must report no DLSS session.
$exe=Join-Path (Join-Path $OutputDirectory 'launcher-fixture') 'Fixture.exe'
New-Item -ItemType Directory -Force (Split-Path $exe) | Out-Null
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
public static class D4RLauncherFixture {
[DllImport("kernel32.dll")] private static extern bool IsDebuggerPresent();
public static int Main(string[] args) { return IsDebuggerPresent() ? 91 : 0; }
}
'@ -OutputAssembly $exe -OutputType ConsoleApplication
Invoke-Child 'run-no-debug' @('-Action','run','-GameExe',$exe,'-NgxCore',$NgxCore,'-DlssDll',$DlssDll) 1
$report=Get-ChildItem -LiteralPath (Join-Path $PackageRoot 'results') -Directory | Sort-Object Name -Descending | Select-Object -First 1
$status=Get-Content -LiteralPath (Join-Path $report.FullName 'quick-test.json') -Raw | ConvertFrom-Json
$environment=Get-Content -LiteralPath (Join-Path $report.FullName 'environment.json') -Raw | ConvertFrom-Json
if ($environment.attachedDebugger -or $status.hardwareValidationCompleted -or
$status.status -ne 'inconclusive-process-exited-without-dlss-frames' -or $status.gameSummary.exitCode -ne '0x0' -or
(Get-Item -LiteralPath (Join-Path $report.FullName 'd4r.stderr.log')).Length -ne 0) {
throw 'Default launch attaches a debugger, mishandles empty stderr or falsely validates a launcher exit.'
}
Invoke-Child 'restore-launcher-fixture' @('-Action','restore','-GameExe',$exe)
$results+=@{case='run-no-debug-empty-stderr-no-false-pass'; passed=$true; gpuKernelsExecuted=$false}
foreach ($case in @('wrong-core','wrong-dlss','vkd3d')) {
$exe=Fixture $case; $game=Split-Path $exe
$core=if ($case -eq 'wrong-core') { Join-Path $PackageRoot 'files/targets/gfx1201/d4r/_nvngx.dll' } else { $NgxCore }
$dlss=if ($case -eq 'wrong-dlss') { $NgxCore } else { $DlssDll }
if ($case -eq 'vkd3d') { Set-Content -LiteralPath (Join-Path $game 'd3d12.dll') 'vkd3d-proton fixture; do not load' -Encoding ASCII }
Invoke-Child $case @('-Action','install','-GameExe',$exe,'-NgxCore',$core,'-DlssDll',$dlss) 1
if ((Test-Path -LiteralPath (Join-Path $game '.d4r-backup')) -or (Test-Path -LiteralPath (Join-Path $game 'dxgi.dll'))) { throw "$case changed game files before rejection." }
$message=Get-Content -LiteralPath (Join-Path $OutputDirectory "$case.log") -Raw
$match=[regex]::Match($message,'SEND THIS ONE FILE: (.+\.zip)')
if (!$match.Success -or !(Test-Path -LiteralPath $match.Groups[1].Value.Trim())) { throw "$case did not produce its single report ZIP." }
$results+=@{case=$case; passed=$true; rejectedBeforeGameChanges=$true; gpuKernelsExecuted=$false}
}
$readme=Join-Path $PackageRoot 'READ-ME-FIRST.txt'
$original=[IO.File]::ReadAllBytes($readme)
try {
Add-Content -LiteralPath $readme 'tampered fixture'
$exe=Fixture 'tampered-package'
Invoke-Child 'tampered-package' @('-Action','install','-GameExe',$exe,'-NgxCore',$NgxCore,'-DlssDll',$DlssDll) 1
$game=Split-Path $exe
if ((Test-Path -LiteralPath (Join-Path $game '.d4r-backup')) -or (Test-Path -LiteralPath (Join-Path $game 'dxgi.dll'))) { throw 'Tampered package changed game files.' }
$results+=@{case='tampered-package'; passed=$true; rejectedBeforeGameChanges=$true; gpuKernelsExecuted=$false}
} finally { [IO.File]::WriteAllBytes($readme,$original) }
$results | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Write-Host "PASS QUICK_TEST_FIXTURES cases=$($results.Count) real_game_untouched=1 Report: $OutputDirectory"
-415
View File
@@ -1,415 +0,0 @@
[CmdletBinding()]
param(
[string]$HipRoot = $env:HIP_PATH,
[ValidateSet('stable', 'therock')][string]$RuntimeProfile = 'stable',
[string]$ZludaRoot,
[string]$PackageRoot,
[string]$GpuArch,
[string]$OutputDirectory,
[string]$NgxCore = $env:D4R_NGX_CORE,
[string]$DlssDll = $env:D4R_DLSS_DLL,
[ValidateSet('init', 'evaluate', 'd3d12')][string]$NgxMode = 'init',
[ValidateSet('driver','sdk','project','project-legacy')][string]$NgxAbi = 'driver',
[string]$OptiScalerDll,
[ValidateSet(5, 11, 13)][int]$Preset = 11,
[ValidateSet(0,11)][int]$NgxCreateFlags = 0,
[string]$NgxOutputResolution = '512x288',
[string]$NgxInputResolution,
[switch]$NgxOnly,
[switch]$Trace,
[switch]$RequireNativeNetwork,
[switch]$CommandListBackend,
[switch]$CaptureExceptions,
[switch]$EarlyIndirectProbe,
[ValidateSet('baseline','packed','unorm','depth-stencil')][string]$PixelProfile = 'baseline',
[ValidateSet('legacy','enhanced','inherited-legacy','inherited-enhanced')][string]$BarrierMode = 'legacy',
[int]$Iterations = 32,
[int]$TimeoutSeconds = 180
)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repoRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if ($RuntimeProfile -eq 'therock') {
# Works both from scripts/windows and the installed dist/<profile> directory.
if (!$PSBoundParameters.ContainsKey('HipRoot')) { $HipRoot = Join-Path $repoRoot '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) {
if (Test-Path (Join-Path $PSScriptRoot 'bin/d4r_hip_gfx1201_probe.exe')) { $PackageRoot = $PSScriptRoot }
else { $PackageRoot = Join-Path $repoRoot 'dist/windows-rdna4-therock' }
}
}
if (!$PackageRoot) {
if (Test-Path (Join-Path $PSScriptRoot 'bin/d4r_hip_gfx1201_probe.exe')) { $PackageRoot = $PSScriptRoot }
else { $PackageRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../../dist/windows-rdna4-diagnostics')) }
}
$PackageRoot = [IO.Path]::GetFullPath($PackageRoot)
$GpuArch=Get-D4RGpuTarget $PackageRoot $GpuArch
if (!$HipRoot) { $HipRoot = 'C:\Program Files\AMD\ROCm\7.2' }
$HipRoot = [IO.Path]::GetFullPath($HipRoot)
if (!$ZludaRoot) {
$builtZluda = Join-Path $repoRoot 'dist/zluda-windows-final'
$localZluda = [IO.Path]::GetFullPath((Join-Path $PackageRoot '../../.tools/zluda/zluda'))
if (Test-Path (Join-Path $builtZluda 'build-info.json')) { $ZludaRoot = $builtZluda }
elseif (Test-Path (Join-Path $localZluda 'nvcuda.dll')) { $ZludaRoot = $localZluda }
else { throw 'Pass -ZludaRoot with the directory containing the Windows ZLUDA nvcuda.dll.' }
}
$ZludaRoot = [IO.Path]::GetFullPath($ZludaRoot)
if (!$OutputDirectory) { $OutputDirectory = Join-Path $PackageRoot ('results/' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$OutputDirectory = [IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$originalPath = $env:PATH
$originalHip = $env:HIP_PATH
$originalDiag = $env:D4R_DIAG_DIR
$originalLog = $env:ZLUDA_LOG_DIR
$originalCuda = $env:ZLUDA_CUDA_LIB
$originalNvapi = $env:D4R_NVAPI_BACKEND
$originalPythonPath = $env:PYTHONPATH
$originalVerbose = $env:D4R_ZLUDA_VERBOSE
$originalCache = $env:ZLUDA_CACHE_DIR
$originalCodegen = @{}
foreach ($setting in @('D4R_ZLUDA_WMMA','D4R_ZLUDA_WMMA_FP8','D4R_ZLUDA_WMMA_FP8_NATIVE','D4R_ZLUDA_WMMA_F16_REFERENCE')) {
$originalCodegen[$setting] = [Environment]::GetEnvironmentVariable($setting,'Process')
}
$exitStatus = 1
$ngxRuntimeDirectory = $null
$summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); profile=$RuntimeProfile; architecture=$GpuArch; hipRoot=$HipRoot; zludaRoot=$ZludaRoot; tests=@()}
function Quote-Argument([string]$Value) {
# All generated paths are absolute file/directory paths, with no trailing backslash.
if ($Value.Contains('"')) { throw 'Double quotes are not allowed in arguments' }
return '"' + $Value.TrimEnd('\') + '"'
}
function Invoke-Probe([string]$Name, [string]$Exe, [string[]]$Arguments) {
if (!(Test-Path -LiteralPath $Exe)) { throw "Executable missing: $Exe" }
if ($CaptureExceptions) {
$Arguments = @('--output-directory', $OutputDirectory, '--', $Exe) + $Arguments
$Exe = Join-Path $PackageRoot 'bin/d4r_debug_launcher.exe'
if (!(Test-Path -LiteralPath $Exe)) { throw "Debugger launcher missing: $Exe" }
}
$stdout = Join-Path $OutputDirectory "$Name.stdout.log"
$stderr = Join-Path $OutputDirectory "$Name.stderr.log"
$argumentLine = ($Arguments | ForEach-Object { Quote-Argument $_ }) -join ' '
$info = New-Object System.Diagnostics.ProcessStartInfo
$info.FileName = $Exe
$info.Arguments = $argumentLine
$info.UseShellExecute = $false
$info.CreateNoWindow = $true
$info.RedirectStandardOutput = $true
$info.RedirectStandardError = $true
# Some PowerShell/.NET hosts restore a removed variable as an empty value.
# These task switches/paths use an empty value to mean unset, whereas Rust
# presence-based diagnostic flags would otherwise enable profiling.
foreach ($key in @($info.EnvironmentVariables.Keys)) {
if ($key.StartsWith('D4R_') -and [string]::IsNullOrWhiteSpace($info.EnvironmentVariables[$key])) {
$info.EnvironmentVariables.Remove($key)
}
}
# Disabled WGP has the ordinary CU semantics. Omit a disabled/empty switch
# from child environments so older ZLUDA builds keep their existing cache.
if ([Environment]::GetEnvironmentVariable('D4R_ZLUDA_WGP','Process') -ne '1') {
$info.EnvironmentVariables.Remove('D4R_ZLUDA_WGP')
}
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $info
if (!$process.Start()) { throw "Process start failed: $Exe" }
# Consume both streams concurrently; a verbose JIT trace must not block its child.
$outFile = [IO.File]::Open($stdout, [IO.FileMode]::Create, [IO.FileAccess]::Write, [IO.FileShare]::Read)
$errFile = [IO.File]::Open($stderr, [IO.FileMode]::Create, [IO.FileAccess]::Write, [IO.FileShare]::Read)
$outTask = $process.StandardOutput.BaseStream.CopyToAsync($outFile)
$errTask = $process.StandardError.BaseStream.CopyToAsync($errFile)
$finished = $process.WaitForExit($TimeoutSeconds * 1000)
if (!$finished) { $process.Kill(); $process.WaitForExit() }
$code = $process.ExitCode
try {
$null = $outTask.GetAwaiter().GetResult()
$null = $errTask.GetAwaiter().GetResult()
} finally { $outFile.Dispose(); $errFile.Dispose() }
$process.Dispose()
$codeHex = if ($null -eq $code) { 'unknown' } else {
'0x{0:x8}' -f [BitConverter]::ToUInt32([BitConverter]::GetBytes([int]$code), 0)
}
$pass = $finished -and $code -eq 0 -and (Select-String -LiteralPath $stdout -Pattern '^PASS ' -Quiet)
$summary.tests += [ordered]@{name=$Name; passed=$pass; timedOut=(!$finished); exitCode=$code; exceptionOrExitHex=$codeHex}
Write-Host "$Name passed=$pass exit=$codeHex timeout=$(!$finished)"
return $pass
}
try {
if (!$env:ZLUDA_CACHE_DIR) { $env:ZLUDA_CACHE_DIR = Join-Path $repoRoot 'build/zluda-cache-windows' }
$summary.zludaCacheDirectory = $env:ZLUDA_CACHE_DIR
foreach ($setting in @('D4R_ZLUDA_WMMA','D4R_ZLUDA_WMMA_FP8','D4R_ZLUDA_WMMA_FP8_NATIVE','D4R_ZLUDA_WMMA_F16_REFERENCE')) {
if ([string]::IsNullOrWhiteSpace($originalCodegen[$setting])) {
[Environment]::SetEnvironmentVariable($setting, $(if ($setting -eq 'D4R_ZLUDA_WMMA_FP8_NATIVE') { '0' } else { '1' }), 'Process')
}
}
$summary.codegen = @{}
foreach ($setting in $originalCodegen.Keys) { $summary.codegen[$setting] = [Environment]::GetEnvironmentVariable($setting,'Process') }
Write-Host "ZLUDA codegen: WMMA=$env:D4R_ZLUDA_WMMA FP8 widening=$env:D4R_ZLUDA_WMMA_FP8 native FP8=$env:D4R_ZLUDA_WMMA_FP8_NATIVE f16 reference=$env:D4R_ZLUDA_WMMA_F16_REFERENCE"
if ($NgxOnly -and (!$NgxCore -or !$DlssDll)) { throw '-NgxOnly requires both locally supplied NVIDIA DLL paths.' }
if ($RequireNativeNetwork) {
if ($NgxMode -notin @('evaluate','d3d12') -or $Preset -notin @(11,13) -or !$env:D4R_ZLUDA_NATIVE_DIR) {
throw '-RequireNativeNetwork requires K/M Evaluate and D4R_ZLUDA_NATIVE_DIR.'
}
$env:D4R_ZLUDA_VERBOSE = '1'
}
$summary.foundationDiagnosticsPerformed = !$NgxOnly
if ($Iterations -lt 1 -or $Iterations -gt 10000) { throw 'Iterations must be 1..10000' }
if ($TimeoutSeconds -lt 1) { throw 'TimeoutSeconds must be positive' }
$env:HIP_PATH = $HipRoot
$env:PATH = "$(Join-Path $HipRoot 'bin');$ZludaRoot;$originalPath"
$env:D4R_DIAG_DIR = $OutputDirectory
$env:ZLUDA_LOG_DIR = Join-Path $OutputDirectory 'zluda-trace'
$env:ZLUDA_CUDA_LIB = Join-Path $ZludaRoot 'nvcuda.dll'
$env:D4R_NVAPI_BACKEND = Join-Path $ZludaRoot 'nvapi64.dll'
$localPythonVendor = Join-Path $repoRoot '.tools/python/vendor'
if (Test-Path (Join-Path $localPythonVendor 'numpy/__init__.py')) {
$env:PYTHONPATH = "$localPythonVendor;$originalPythonPath"
}
$comgr = Join-Path $HipRoot 'bin/amd_comgr_3.dll'
if (!(Test-Path -LiteralPath $comgr)) { $comgr = Join-Path $HipRoot 'bin/amd_comgr.dll' }
$files = @((Join-Path $HipRoot 'bin/amdhip64_7.dll'), $comgr,
(Join-Path $ZludaRoot 'nvcuda.dll'), (Join-Path $PackageRoot "bin/probe_${GpuArch}.hsaco"),
(Join-Path $PackageRoot "bin/wmma_${GpuArch}.hsaco"),
(Join-Path $PackageRoot "experimental/k/dltss_pwin_enc1_layer_${GpuArch}.hsaco"),
(Join-Path $PackageRoot "experimental/k/dltss_pwin_enc2_layer_${GpuArch}.hsaco"))
if ($OptiScalerDll) {
if ($NgxMode -ne 'd3d12' -or !$CommandListBackend) { throw '-OptiScalerDll requires D3D12 and -CommandListBackend' }
if (![IO.Path]::IsPathRooted($OptiScalerDll)) { throw '-OptiScalerDll must be absolute' }
$files += $OptiScalerDll
}
if ($NgxCore -or $DlssDll) {
if (!$NgxCore -or !$DlssDll) { throw 'Supply both -NgxCore and -DlssDll absolute paths.' }
if (![IO.Path]::IsPathRooted($NgxCore) -or ![IO.Path]::IsPathRooted($DlssDll)) {
throw 'NVIDIA DLL paths must be absolute.'
}
$files += @($NgxCore, $DlssDll)
}
$summary.files = @($files | ForEach-Object {
if (!(Test-Path -LiteralPath $_)) { throw "Required file missing: $_" }
$file = Get-Item -LiteralPath $_
[ordered]@{path=$file.FullName; version=$file.VersionInfo.FileVersion;
sha256=(Get-FileHash -LiteralPath $_ -Algorithm SHA256).Hash}
})
try {
$summary.displayDrivers = @(Get-CimInstance Win32_VideoController |
Select-Object Name,DriverVersion,DriverDate,PNPDeviceID)
$summary.os = Get-CimInstance Win32_OperatingSystem | Select-Object Caption,Version,BuildNumber
} catch { $summary.inventoryError = $_.Exception.Message }
$bin = Join-Path $PackageRoot 'bin'
$hipOk = $true
if (!$NgxOnly) { $hipOk = Invoke-Probe 'hip' (Join-Path $bin 'd4r_hip_gfx1201_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin "probe_${GpuArch}.hsaco"), '--iterations', "$Iterations")
}
if ($hipOk) {
if (!$NgxOnly) {
$wmmaOk = Invoke-Probe 'gfx12-wmma' (Join-Path $bin 'd4r_gfx12_wmma_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin "wmma_${GpuArch}.hsaco"), '--iterations', "$Iterations")
if (!$wmmaOk) { throw 'gfx12 WMMA layout validation failed; refusing to mark K/M readiness.' }
$pythonCommand = Get-Command python -ErrorAction SilentlyContinue
if (!$pythonCommand) { throw 'Python 3.11+ with NumPy 2.4.6 is needed for K reference checks; run setup-windows-tools.ps1.' }
foreach ($layer in @('enc1', 'enc2')) {
$kFixture = Join-Path $OutputDirectory "k-$layer-fixture"
$kModuleOk = Invoke-Probe "k-$layer-gpu" (Join-Path $bin 'd4r_k_module_probe.exe') @(
'--hip-root', $HipRoot,
'--module', (Join-Path $PackageRoot "experimental/k/dltss_pwin_${layer}_layer_${GpuArch}.hsaco"),
'--kernel-name', $layer, '--fixture-dir', $kFixture, '--iterations', "$Iterations")
if (!$kModuleOk) { throw "K $layer GPU execution failed; see the k-$layer-gpu logs." }
$kReferenceOk = Invoke-Probe "k-$layer-reference" $pythonCommand.Source @(
(Join-Path $PackageRoot 'k_layer_validate.py'), '--kernel-name', $layer, '--fixture-dir', $kFixture)
if (!$kReferenceOk) { throw "K $layer output differs from pwin_model.py; see the k-$layer-reference logs." }
}
}
$cudaOk = $true
if (!$NgxOnly) {
foreach ($context in @('primary', 'created')) {
$ok = Invoke-Probe "cuda-$context" (Join-Path $bin 'd4r_cuda_driver_probe.exe') @(
'--hip-root', $HipRoot, '--cuda-dll', (Join-Path $ZludaRoot 'nvcuda.dll'),
'--context', $context, '--iterations', "$Iterations")
$cudaOk = $cudaOk -and $ok
# On failure collect the upstream trace automatically if available.
if (!$ok -and (Test-Path (Join-Path $ZludaRoot 'trace/nvcuda.dll'))) {
Invoke-Probe "cuda-$context-trace" (Join-Path $bin 'd4r_cuda_driver_probe.exe') @(
'--hip-root', $HipRoot, '--cuda-dll', (Join-Path $ZludaRoot 'trace/nvcuda.dll'),
'--context', $context, '--iterations', '1') | Out-Null
}
}
if ($cudaOk -and ($NgxMode -eq 'evaluate' -or (Test-Path (Join-Path $ZludaRoot 'build-info.json')))) {
$cudaOk = Invoke-Probe 'cuda-images' (Join-Path $bin 'd4r_cuda_image_probe.exe') @(
'--hip-root', $HipRoot, '--cuda-dll', (Join-Path $ZludaRoot 'nvcuda.dll'), '--iterations', "$Iterations")
if ($cudaOk) {
$previousF16 = $env:D4R_ZLUDA_WMMA_F16_REFERENCE
try {
$env:D4R_ZLUDA_WMMA_F16_REFERENCE = '1'
$cudaOk = Invoke-Probe 'cuda-f16-mma-reference' (Join-Path $bin 'd4r_cuda_mma_probe.exe') @(
'--hip-root', $HipRoot, '--cuda-dll', (Join-Path $ZludaRoot 'nvcuda.dll'))
} finally { $env:D4R_ZLUDA_WMMA_F16_REFERENCE = $previousF16 }
}
}
}
if ($cudaOk) {
$mapOk = $interopOk = $true
if (!$NgxOnly) {
$commandOk = Invoke-Probe 'd3d12-command-backend' (Join-Path $bin 'd4r_d3d12_command_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin 'd4r_nvngx.dll'), '--interop-mode', 'indirect', '--iterations', "$Iterations")
if (!$commandOk) { throw 'D3D12 command-list order/state/lifetime validation failed.' }
$pixelsOk = Invoke-Probe 'd3d12-gpu-pixel-formats' (Join-Path $bin 'd4r_d3d12_pixel_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin "pixel_convert_${GpuArch}.hsaco"), '--iterations', '2')
if (!$pixelsOk) { throw 'D3D12 typed SRV/UAV format conversion validation failed.' }
$mapOk = Invoke-Probe 'interop-map-lifetime' (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @(
'--hip-root', $HipRoot, '--interop-mode', 'map', '--iterations', '64')
$interopOk = Invoke-Probe 'interop-roundtrip' (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin "probe_${GpuArch}.hsaco"), '--iterations', "$Iterations")
if (!$mapOk -or !$interopOk) {
foreach ($mode in @('resource', 'import')) {
Invoke-Probe "interop-$mode-lifetime" (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @(
'--hip-root', $HipRoot, '--interop-mode', $mode, '--iterations', '32') | Out-Null
}
Invoke-Probe 'hip-stream-lifetime' (Join-Path $bin 'd4r_hip_stream_lifecycle_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin "probe_${GpuArch}.hsaco"), '--iterations', '32') | Out-Null
}
}
if ($mapOk -and $interopOk) { $exitStatus = 0 }
if ($exitStatus -eq 0 -and $NgxCore) {
# The driver Init ABI searches the executable directory. Keep the
# supplied binaries in a private temporary runtime, outside dist/ZIP.
$ngxRuntimeDirectory = Join-Path ([IO.Path]::GetTempPath()) ('d4r-ngx-' + [Guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $ngxRuntimeDirectory | Out-Null
$ngxExe = Join-Path $ngxRuntimeDirectory 'd4r_ngx_cuda_init_probe.exe'
$localCore = Join-Path $ngxRuntimeDirectory '_nvngx.dll'
$localDlss = Join-Path $ngxRuntimeDirectory 'nvngx_dlss.dll'
$probeName = if ($NgxMode -eq 'd3d12') { 'd4r_d3d12_dlss_probe.exe' } else { 'd4r_ngx_cuda_init_probe.exe' }
Copy-Item -LiteralPath (Join-Path $bin $probeName) -Destination $ngxExe
Copy-Item -LiteralPath $NgxCore -Destination $localCore
Copy-Item -LiteralPath $DlssDll -Destination $localDlss
$selectedCuda = if ($Trace) { Join-Path $ZludaRoot 'trace/nvcuda.dll' } else { Join-Path $ZludaRoot 'nvcuda.dll' }
if (!(Test-Path -LiteralPath $selectedCuda)) { throw "CUDA runtime missing: $selectedCuda" }
$summary.traceRequested = [bool]$Trace
$ngxArguments = @('--hip-root', $HipRoot, '--cuda-dll', $selectedCuda,
'--ngx-core', $localCore, '--dlss-dll', $localDlss,
'--nvapi-dll', (Join-Path $PackageRoot 'nvapi-compat/nvapi64.dll'),
'--ngx-mode', $NgxMode, '--ngx-abi', $NgxAbi, '--preset', "$Preset", '--iterations', "$Iterations")
if ($NgxMode -eq 'd3d12') {
# The driver NGX core resolves feature DLLs relative to its
# caller module as well as the executable. Keep the shim
# alongside the private user-supplied DLLs for this test.
$localShim = Join-Path $ngxRuntimeDirectory 'd4r_nvngx.dll'
Copy-Item -LiteralPath (Join-Path $bin 'd4r_nvngx.dll') -Destination $localShim
Copy-Item -LiteralPath (Join-Path $bin "pixel_convert_${GpuArch}.hsaco") -Destination $ngxRuntimeDirectory
if ($OptiScalerDll) {
$bridgeDirectory = Join-Path $ngxRuntimeDirectory 'd4r'
New-Item -ItemType Directory -Path $bridgeDirectory | Out-Null
Copy-Item -LiteralPath $localShim -Destination (Join-Path $bridgeDirectory '_nvngx.dll')
Copy-Item -LiteralPath (Join-Path $bin "pixel_convert_${GpuArch}.hsaco") -Destination $bridgeDirectory
$localShim = Join-Path $ngxRuntimeDirectory 'OptiScaler.dll'
Copy-Item -LiteralPath $OptiScalerDll -Destination $localShim
$ini = @"
[Upscalers]
Dx12Upscaler=dlss
[FrameGen]
Enabled=false
FGInput=nofg
FGOutput=nofg
[DLSS]
Enabled=true
AllowExternalBackend=true
RenderPresetOverride=true
RenderPresetForAll=$Preset
UseGenericAppIdWithDlss=false
[Libraries]
NvngxPath=$bridgeDirectory
NvngxDlssPath=$ngxRuntimeDirectory
NvngxFeaturePath=$ngxRuntimeDirectory
[Hotfix]
RestoreComputeSignature=false
RestoreGraphicSignature=false
ExtendedStateRestore=false
[Log]
LogToFile=true
LogLevel=0
[Menu]
DisableSplash=true
"@
$ini | Set-Content -LiteralPath (Join-Path $ngxRuntimeDirectory 'OptiScaler.ini') -Encoding UTF8
$summary.optiScaler = @{path=$OptiScalerDll; mode='standalone'; preset=$Preset}
$ngxArguments += @('--ngx-frontend', 'optiscaler')
}
$ngxArguments += @('--module', $localShim, '--pixel-profile', $PixelProfile, '--barrier-mode', $BarrierMode,
'--ngx-create-flags', "$NgxCreateFlags", '--ngx-output-resolution', $NgxOutputResolution)
if ($NgxInputResolution) { $ngxArguments += @('--ngx-input-resolution', $NgxInputResolution) }
if ($EarlyIndirectProbe) {
if (!$CommandListBackend) { throw '-EarlyIndirectProbe requires -CommandListBackend' }
$ngxArguments += @('--early-indirect', '1')
}
if ($CommandListBackend) { $ngxArguments += @('--interop-mode', 'command-list') }
}
$ngxName = if ($NgxMode -eq 'evaluate') { "ngx-evaluate-preset-$Preset" } elseif ($NgxMode -eq 'd3d12') { "d3d12-evaluate-preset-$Preset" } else { 'ngx-init' }
$ngxOk = Invoke-Probe $ngxName $ngxExe $ngxArguments
if ($OptiScalerDll) {
Get-ChildItem -LiteralPath $ngxRuntimeDirectory -Filter '*.log' -File |
ForEach-Object { Copy-Item -LiteralPath $_.FullName -Destination (Join-Path $OutputDirectory ('optiscaler-' + $_.Name)) }
Copy-Item -LiteralPath (Join-Path $ngxRuntimeDirectory 'OptiScaler.ini') -Destination (Join-Path $OutputDirectory 'OptiScaler.ini')
}
if ($ngxOk -and $RequireNativeNetwork) {
$hits = @()
$nativeLayers = if ($Preset -eq 11) { @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0') }
else { @('enc1','enc2','enc3_tube','dec2','dec1') }
foreach ($layer in $nativeLayers) {
$name = if ($Preset -eq 11) { "dltss_pwin_${layer}_layer" } else { "rrlite_${layer}_4x4" }
$pattern = '\[d4r-launch\] kernel="' + $name + '" backend=native'
$count = @(Select-String -LiteralPath (Join-Path $OutputDirectory "$ngxName.stderr.log") -Pattern $pattern).Count
$hits += @{layer=$layer; nativeLaunches=$count; expectedFrames=$Iterations}
if ($count -lt $Iterations) { $ngxOk=$false }
}
$summary.nativeTransformer = $hits
$summary.nativeTransformerPassed = $ngxOk
Write-Host "Native preset $Preset transformer launches validated=$ngxOk"
}
if (!$ngxOk) {
$exitStatus = 1
if (!$Trace -and (Test-Path (Join-Path $ZludaRoot 'trace/nvcuda.dll'))) {
$traceArguments = @(
'--hip-root', $HipRoot, '--cuda-dll', (Join-Path $ZludaRoot 'trace/nvcuda.dll'),
'--ngx-core', $localCore, '--dlss-dll', $localDlss,
'--nvapi-dll', (Join-Path $PackageRoot 'nvapi-compat/nvapi64.dll'),
'--ngx-mode', $NgxMode, '--preset', "$Preset", '--iterations', '1')
if ($NgxMode -eq 'd3d12') { $traceArguments += @('--module', $localShim) }
Invoke-Probe "$ngxName-trace" $ngxExe $traceArguments | Out-Null
}
}
}
}
}
} catch {
$summary.error = $_.Exception.Message
Write-Warning $summary.error
} finally {
if ($ngxRuntimeDirectory -and (Test-Path -LiteralPath $ngxRuntimeDirectory)) {
$resolvedRuntime = [IO.Path]::GetFullPath($ngxRuntimeDirectory)
$tempRoot = [IO.Path]::GetFullPath([IO.Path]::GetTempPath()).TrimEnd('\') + '\'
if (!$resolvedRuntime.StartsWith($tempRoot, [StringComparison]::OrdinalIgnoreCase) -or
[IO.Path]::GetFileName($resolvedRuntime) -notmatch '^d4r-ngx-[0-9a-f]{32}$') {
throw 'Refusing to remove a path outside the private NGX temporary runtime.'
}
# A scanner can briefly hold the just-unloaded DLL open. Cleanup must
# not skip environment restoration or discard the completed GPU logs.
$cleanupError=$null
foreach ($attempt in 1..10) {
try { Remove-Item -LiteralPath $resolvedRuntime -Recurse -Force -ErrorAction Stop; $cleanupError=$null; break }
catch { $cleanupError=$_.Exception.Message; if ($attempt -lt 10) { Start-Sleep -Milliseconds 300 } }
}
if ($cleanupError) { $summary.cleanupError=$cleanupError; $exitStatus=1; Write-Warning "Private runtime cleanup failed: $cleanupError" }
}
$summary.passed = $exitStatus -eq 0
$summary | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
$env:PATH = $originalPath
$env:HIP_PATH = $originalHip
$env:D4R_DIAG_DIR = $originalDiag
$env:ZLUDA_LOG_DIR = $originalLog
$env:ZLUDA_CUDA_LIB = $originalCuda
$env:D4R_NVAPI_BACKEND = $originalNvapi
$env:PYTHONPATH = $originalPythonPath
$env:D4R_ZLUDA_VERBOSE = $originalVerbose
$env:ZLUDA_CACHE_DIR = $originalCache
foreach ($setting in $originalCodegen.Keys) { [Environment]::SetEnvironmentVariable($setting, $originalCodegen[$setting], 'Process') }
$archive = "$OutputDirectory.zip"
Compress-Archive -LiteralPath $OutputDirectory -DestinationPath $archive -Force
Write-Host "Diagnostic bundle: $archive"
}
exit $exitStatus
@@ -1,109 +0,0 @@
# Drag-in release packaging with synthetic per-target inputs. No GPU, no
# NVIDIA DLLs, no game. Code objects carry real AMDGPU ELF target headers.
[CmdletBinding()]
param([string]$OutputDirectory)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/windows-release-package/'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$targets=@(Get-D4RGpuTargets)
function Write-CodeObject([string]$Path,[int]$Machine) {
$header=New-Object byte[] 64
$header[0]=127; $header[1]=69; $header[2]=76; $header[3]=70; $header[4]=2; $header[5]=1; $header[18]=224; $header[48]=$Machine
New-Item -ItemType Directory -Force (Split-Path $Path) | Out-Null
[IO.File]::WriteAllBytes($Path,$header)
}
function New-Inputs([string]$Prefix,[scriptblock]$Mutate) {
foreach ($target in $targets) {
$arch=$target.architecture; $root="$Prefix-$arch"
$text=@{'OptiScaler.dll'='optiscaler'; 'd4r/_nvngx.dll'="shim $arch"; 'd4r/nvapi/nvapi64.dll'="nvapi $arch";
'd4r/hip/bin/amdhip64_7.dll'='hip'; 'd4r/zluda/nvcuda.dll'='zluda'; 'd4r/zluda/nvapi64.dll'='zluda nvapi'; 'licenses/d4r.txt'='license';
'd4r/d4r_gpu_inventory.exe'='inventory'; 'd4r/d4r_debug_launcher.exe'='launcher'; 'windows-game.ps1'='installer';
'd4r/native/d4r-kernels.txt'='manifest'}
foreach ($entry in $text.GetEnumerator()) {
$path=Join-Path $root $entry.Key; New-Item -ItemType Directory -Force (Split-Path $path) | Out-Null
Set-Content -LiteralPath $path $entry.Value -Encoding ASCII
}
$objects=@("d4r/pixel_convert_$arch.hsaco")+@(1..16 | ForEach-Object { "d4r/native/kernel$_.hsaco" })
foreach ($object in $objects) { Write-CodeObject (Join-Path $root $object) $target.elfMachine }
if ($Mutate) { & $Mutate $root $arch }
$files=@(Get-ChildItem -LiteralPath $root -Recurse -File | Where-Object { $_.Name -ne 'package.json' } | ForEach-Object {
@{path=$_.FullName.Substring($root.Length+1).Replace('\','/'); sha256=(Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash}
})
@{architecture=$arch; d4rWorkingTreeDirty=$false; d4rCommit='fixture'; hardwareValidation='fixture';
dlssSha256='3975567b8943c53acce397f2b72380092f84f162d00b0d2c7d08a1025c563983';
zludaBuild=@{sourceCommit='fixture'}; optiScaler=@{sourceCommit='fixture'}; hipRuntime='fixture'; files=$files} |
ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $root 'package.json') -Encoding UTF8
}
}
function Invoke-Package([string]$Prefix,[string]$Root) {
& (Join-Path $PSScriptRoot 'package-windows-release.ps1') -GamePackagePrefix $Prefix -LoaderDll $loader -PackageRoot $Root | Out-Null
}
$loader=Join-Path $OutputDirectory 'build/d4r_nvngx_loader.dll'
New-Item -ItemType Directory -Force (Split-Path $loader) | Out-Null
Set-Content -LiteralPath $loader 'loader fixture' -Encoding ASCII
$results=@()
# 1. Layout of a good release.
$prefix=Join-Path $OutputDirectory 'inputs/good/game'
New-Inputs $prefix
$release=Join-Path $OutputDirectory 'release'
Invoke-Package $prefix $release
foreach ($path in @('dxgi.dll','OptiScaler.ini','d4r/_nvngx.dll','d4r/d4r.ini','d4r/dll-pins.txt','d4r/package.json',
'd4r/hip/bin/amdhip64_7.dll','d4r/zluda/nvcuda.dll','d4r/licenses/d4r.txt','d4r/ngx/PUT _nvngx.dll HERE.txt',
'd4r/gpu-targets.json','d4r/d4r_gpu_inventory.exe','d4r/d4r-check.ps1','WINDOWS_README.txt')) {
if (!(Test-Path -LiteralPath (Join-Path $release $path))) { throw "Release lacks $path" }
}
if ((Get-Content -LiteralPath (Join-Path $release 'd4r/_nvngx.dll') -Raw).Trim() -ne 'loader fixture') { throw 'd4r/_nvngx.dll is not the loader.' }
foreach ($target in $targets) {
$arch=$target.architecture
if ((Get-Content -LiteralPath (Join-Path $release "d4r/_nvngx_$arch.dll") -Raw).Trim() -ne "shim $arch") { throw "Wrong shim for $arch" }
if ((Get-Content -LiteralPath (Join-Path $release "d4r/nvapi/$arch/nvapi64.dll") -Raw).Trim() -ne "nvapi $arch") { throw "Wrong NVAPI for $arch" }
Assert-D4RCodeObjectTarget (Join-Path $release "d4r/pixel_convert_$arch.hsaco") $arch
$native=@(Get-ChildItem -LiteralPath (Join-Path $release "d4r/native/$arch") -Filter '*.hsaco')
if ($native.Count -ne 16 -or !(Test-Path -LiteralPath (Join-Path $release "d4r/native/$arch/d4r-kernels.txt"))) { throw "Native folder for $arch is incomplete" }
foreach ($object in $native) { Assert-D4RCodeObjectTarget $object.FullName $arch }
}
if (@(Get-ChildItem -LiteralPath $release -Recurse -Filter 'd4r_gpu_inventory.exe').Count -ne 1) { throw 'The GPU query tool must ship exactly once.' }
foreach ($excluded in @('d4r/d4r_debug_launcher.exe','windows-game.ps1','d4r/native/kernel1.hsaco','d4r/nvapi/nvapi64.dll')) {
if (Test-Path -LiteralPath (Join-Path $release $excluded)) { throw "Installer-only or untargeted file shipped: $excluded" }
}
$manifest=Get-Content -LiteralPath (Join-Path $release 'd4r/package.json') -Raw | ConvertFrom-Json
foreach ($file in $manifest.files) {
if ((Get-FileHash -LiteralPath (Join-Path $release $file.path) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Manifest hash wrong: $($file.path)" }
}
$shipped=@(Get-ChildItem -LiteralPath $release -Recurse -File | ForEach-Object { $_.FullName.Substring($release.Length+1).Replace('\','/') } | Where-Object { $_ -ne 'd4r/package.json' })
if (Compare-Object $shipped @($manifest.files.path)) { throw 'Manifest and shipped files differ.' }
$results+=@{case='drag-in-layout'; passed=$true; targets=$targets.Count; files=$shipped.Count}
# 1b. A subset release carries only the requested targets.
$subset=Join-Path $OutputDirectory 'release-subset'
& (Join-Path $PSScriptRoot 'package-windows-release.ps1') -GamePackagePrefix $prefix -LoaderDll $loader -PackageRoot $subset -Architectures gfx1101,gfx1201 | Out-Null
$kept=@(Get-ChildItem -LiteralPath (Join-Path $subset 'd4r') -Filter '_nvngx_gfx*.dll' | ForEach-Object { $_.Name })
if (($kept | Sort-Object) -join ',' -ne '_nvngx_gfx1101.dll,_nvngx_gfx1201.dll') { throw "Subset shipped the wrong shims: $($kept -join ',')" }
$rejected=$false
try { & (Join-Path $PSScriptRoot 'package-windows-release.ps1') -GamePackagePrefix $prefix -LoaderDll $loader -PackageRoot (Join-Path $OutputDirectory 'release-unknown') -Architectures gfx9999 | Out-Null } catch { $rejected=$_.Exception.Message -match 'Unknown GPU target' }
if (!$rejected) { throw 'An unknown architecture was not rejected.' }
$results+=@{case='architecture-subset'; passed=$true; shipped=$kept}
# 2. A code object for another GPU in a target's input is rejected.
$prefix=Join-Path $OutputDirectory 'inputs/mixed/game'
New-Inputs $prefix { param($root,$arch) if ($arch -eq 'gfx1101') { Write-CodeObject (Join-Path $root 'd4r/native/kernel3.hsaco') 65 } }
$rejected=$false
try { Invoke-Package $prefix (Join-Path $OutputDirectory 'release-mixed') } catch { $rejected=$_.Exception.Message -match 'does not target gfx1101' }
if (!$rejected) { throw 'A gfx1100 code object in the gfx1101 input was not rejected.' }
$results+=@{case='mixed-target-rejected'; passed=$true}
# 3. Shared runtime files must be identical across targets.
$prefix=Join-Path $OutputDirectory 'inputs/runtime/game'
New-Inputs $prefix { param($root,$arch) if ($arch -eq 'gfx1200') { Set-Content -LiteralPath (Join-Path $root 'd4r/zluda/nvcuda.dll') 'other zluda' -Encoding ASCII } }
$rejected=$false
try { Invoke-Package $prefix (Join-Path $OutputDirectory 'release-runtime') } catch { $rejected=$_.Exception.Message -match 'Shared runtime differs' }
if (!$rejected) { throw 'A differing shared runtime was not rejected.' }
$results+=@{case='shared-runtime-mismatch-rejected'; passed=$true}
$results | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Write-Host "PASS WINDOWS_RELEASE_PACKAGE cases=$($results.Count) Report: $OutputDirectory"
-24
View File
@@ -1,24 +0,0 @@
[CmdletBinding()]
param([string]$HipRoot, [string]$PackageRoot, [string]$OutputDirectory)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot=Join-Path $repo 'dist/windows-rdna4-command-list' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/wmma-f16-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$compiler=Join-Path $HipRoot 'lib/llvm/bin/clang++.exe'
if (!(Test-Path -LiteralPath $compiler)) { $compiler=Join-Path $HipRoot 'bin/clang++.exe' }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$module=Join-Path $OutputDirectory 'wmma_f16_compare.hsaco'
& $compiler -x hip -std=c++17 --offload-arch=gfx1201 --offload-device-only --no-gpu-bundle-output `
-mno-wavefrontsize64 -nogpuinc -nogpulib -O3 (Join-Path $repo 'tools/windows/wmma_f16_compare.hip') -o $module
if ($LASTEXITCODE) { throw 'WMMA arithmetic probe compilation failed.' }
$previousPython=$env:PYTHONPATH
try {
$env:PYTHONPATH="$(Join-Path $repo '.tools/python/vendor');$previousPython"
& python.exe (Join-Path $repo 'tools/windows/wmma_f16_compare.py') `
--probe (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --module $module `
--hip-root $HipRoot --output-dir $OutputDirectory
if ($LASTEXITCODE) { throw "WMMA arithmetic diagnostic failed; logs: $OutputDirectory" }
} finally { $env:PYTHONPATH=$previousPython }
# A successful diagnostic is not acceptance of native FP16 accumulators for K.
# Read baselineEquivalent/gameOptimizationAccepted in validation.json.
@@ -1,67 +0,0 @@
[CmdletBinding()]
param([string]$ZludaRoot, [string[]]$GpuArchitectures, [string]$OutputDirectory)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo 'test-results/zluda-target-compilation' }
if (!$GpuArchitectures) { $GpuArchitectures=@(Get-D4RGpuTargets | ForEach-Object { $_.architecture }) }
foreach ($arch in $GpuArchitectures) { [void](Get-D4RGpuTargetInfo $arch) }
$emitter=Join-Path $ZludaRoot 'd4r_emit.exe'
if (!(Test-Path -LiteralPath $emitter)) { throw "Rebuild ZLUDA and its offline emitter: $emitter" }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$settings=@{PATH="$ZludaRoot;$env:PATH"; D4R_ZLUDA_WMMA='1'; D4R_ZLUDA_WMMA_FP8='1';
D4R_ZLUDA_WMMA_F16_REFERENCE='1'; D4R_ZLUDA_WMMA_FP8_NATIVE='0'; D4R_ZLUDA_WMMA_LAYOUT=$null;
D4R_ZLUDA_WAVE64=$null; D4R_ZLUDA_FAST_MATH=$null; D4R_ZLUDA_IGNORE_DENORMAL=$null;
D4R_ZLUDA_WMMA_F32ACC=$null; D4R_ZLUDA_EXTRA_BC=$null; D4R_ZLUDA_WGP=$null}
$old=@{}; $rows=[Collections.Generic.List[object]]::new()
try {
foreach ($key in $settings.Keys) {
$old[$key]=[Environment]::GetEnvironmentVariable($key,'Process')
if ($null -eq $settings[$key]) { Remove-Item -LiteralPath "Env:$key" -ErrorAction SilentlyContinue }
else { [Environment]::SetEnvironmentVariable($key,$settings[$key],'Process') }
}
foreach ($fixture in @(@{name='pattern'; source='cuda_driver_probe.cpp'; reference='1'},
@{name='f16-mma-reference'; source='cuda_mma_probe.cpp'; reference='1'},
@{name='f16-mma-wmma'; source='cuda_mma_probe.cpp'; reference='0'})) {
$env:D4R_ZLUDA_WMMA_F16_REFERENCE=$fixture.reference
# Reuse the public synthetic PTX exercised by the hardware diagnostics.
# Reading source does not execute a probe or load HIP/NVIDIA libraries.
$match=[regex]::Match((Get-Content (Join-Path $repo ('tools/windows/'+$fixture.source)) -Raw),'(?s)R"PTX\((.*?)\)PTX"')
if (!$match.Success) { throw 'Public PTX fixture not found.' }
$ptx=Join-Path $OutputDirectory ($fixture.name+'.ptx')
$match.Groups[1].Value | Set-Content -LiteralPath $ptx -Encoding ASCII
foreach ($arch in $GpuArchitectures) {
$output=Join-Path $OutputDirectory ($arch+'/'+$fixture.name)
New-Item -ItemType Directory -Force $output | Out-Null
$log=Join-Path $output 'compile.log'
$oldPreference=$ErrorActionPreference
try { $ErrorActionPreference='Continue'; & $emitter $ptx $output $arch *> $log; $code=$LASTEXITCODE }
finally { $ErrorActionPreference=$oldPreference }
if ($code) { throw "Offline ZLUDA compilation failed: $arch $($fixture.name), exit=$code; see $log" }
Assert-D4RCodeObjectTarget (Join-Path $output 'module.hsaco') $arch
$text=Get-Content -LiteralPath $log -Raw
if ($text -match 'not a recognized processor|ignoring processor|unsupported processor') { throw "Target rejected by compiler: $log" }
$asm=Get-Content (Join-Path $output 'asm.s') -Raw
if ($asm -notmatch '\.amdhsa_wavefront_size32\s+1') { throw "Missing wave32 code generation: $output" }
$hasWmma=($asm -match 'v_wmma_')
if (($fixture.name -eq 'f16-mma-wmma' -or ($fixture.name -eq 'f16-mma-reference' -and $arch.StartsWith('gfx11'))) -and !$hasWmma) {
throw "WMMA lowering missing: $output"
}
# gfx12 strict F16 accumulation intentionally uses the existing
# double-precision reference helper. Do not label it native WMMA.
if ($fixture.name -eq 'f16-mma-reference' -and $arch.StartsWith('gfx12') -and
($hasWmma -or $asm -notmatch 'v_fma_f64')) { throw "Strict gfx12 reference lowering changed: $output" }
$rows.Add(@{architecture=$arch; fixture=$fixture.name; compiled=$true; elfTargetCorrect=$true;
nativeWmma=$hasWmma; hardwareExecuted=$false})
Write-Host "PASS ZLUDA_OFFLINE target=$arch fixture=$($fixture.name) wave=32 hardware_executed=0"
}
}
@{passed=$true; fixtures=@($rows); emitterSha256=(Get-FileHash -LiteralPath $emitter).Hash; gpuWorkExecuted=$false} |
ConvertTo-Json -Depth 6 | Set-Content (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
} finally {
foreach ($key in $old.Keys) {
if ($null -eq $old[$key]) { Remove-Item -LiteralPath "Env:$key" -ErrorAction SilentlyContinue }
else { [Environment]::SetEnvironmentVariable($key,$old[$key],'Process') }
}
}
-325
View File
@@ -1,325 +0,0 @@
[CmdletBinding()]
param(
[ValidateSet('install','restore','run')][string]$Action = 'run',
[Parameter(Mandatory=$true)][string]$GameExe,
[string]$NgxCore, [string]$DlssDll,
[ValidateSet(11,13)][int]$Preset = 11,
[int]$RunSeconds = 0,
[string]$DiagnosticResolution,
[string]$CacheDirectory = $env:ZLUDA_CACHE_DIR,
[string]$LocalTextureKernels,
[switch]$ValidateOutput,
[switch]$ProfileStages,
[switch]$ProfileKernels,
[switch]$ProfileKernelsDeferred,
[switch]$ProfileLegacyStream,
[ValidateRange(1,1000000)][int]$KernelProfileEvery = 17,
[switch]$ProfileCommandHooks,
[switch]$ProfileCudaApi,
[switch]$ProfileGpuBoundary,
[switch]$UncachedInteropLists,
[switch]$AsyncInterop,
[switch]$BatchInputCopies,
[switch]$VerboseRuntime,
[switch]$CaptureExceptions,
[string[]]$GameArguments = @('-dx12'),
[string]$OutputDirectory
)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
. (Join-Path $PSScriptRoot 'gpu-preflight.ps1')
. (Join-Path $PSScriptRoot 'game-summary.ps1')
if ($ProfileGpuBoundary -and !$AsyncInterop) { throw '-ProfileGpuBoundary requires -AsyncInterop.' }
if ($ProfileKernels -and $ProfileKernelsDeferred) { throw 'Choose either serializing or deferred kernel profiling.' }
if ($ProfileLegacyStream -and !$ProfileKernelsDeferred) { throw '-ProfileLegacyStream requires -ProfileKernelsDeferred.' }
$package = [IO.Path]::GetFullPath($PSScriptRoot)
$GameExe = (Get-Item -LiteralPath $GameExe -ErrorAction Stop).FullName
$game = Split-Path $GameExe
$backup = Join-Path $game '.d4r-backup'
$manifestPath = Join-Path $backup 'manifest.json'
function GamePath([string]$relative) {
$path = [IO.Path]::GetFullPath((Join-Path $game $relative))
if (!$path.StartsWith($game + '\', [StringComparison]::OrdinalIgnoreCase)) { throw "Path escapes game directory: $relative" }
return $path
}
if (Get-Process -Name ([IO.Path]::GetFileNameWithoutExtension($GameExe)) -ErrorAction SilentlyContinue) { throw 'Close the game before installing, restoring or running this diagnostic.' }
if ($Action -eq 'restore') {
if (!(Test-Path -LiteralPath $manifestPath)) { throw 'No d4r installation manifest exists.' }
$manifest = Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json
foreach ($entry in $manifest.files) {
$path = GamePath $entry.path
if ((Test-Path -LiteralPath $path) -and (Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash -ne $entry.installedHash) { throw "File changed since installation; preserved: $path" }
}
foreach ($entry in $manifest.files) {
$path = GamePath $entry.path
if ($entry.existed) { Copy-Item -LiteralPath (Join-Path $backup ('original/' + $entry.path)) -Destination $path -Force }
elseif (Test-Path -LiteralPath $path) { Remove-Item -LiteralPath $path -Force }
}
# Remove only empty directories; preserve user files and diagnostic logs.
if (Test-Path -LiteralPath (GamePath 'd4r')) {
Get-ChildItem -LiteralPath (GamePath 'd4r') -Directory -Recurse | Sort-Object { $_.FullName.Length } -Descending | ForEach-Object {
if (!(Get-ChildItem -LiteralPath $_.FullName -Force)) { Remove-Item -LiteralPath $_.FullName }
}
if (!(Get-ChildItem -LiteralPath (GamePath 'd4r') -Force)) { Remove-Item -LiteralPath (GamePath 'd4r') }
}
Move-Item -LiteralPath $manifestPath -Destination (Join-Path $backup ('restored-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff') + '.json'))
Write-Host "Original game files restored. Backups retained: $backup"
return
}
if (!$NgxCore -or !$DlssDll) { throw 'Pass both local NVIDIA DLL paths with -NgxCore and -DlssDll.' }
$NgxCore = (Get-Item -LiteralPath $NgxCore).FullName
$DlssDll = (Get-Item -LiteralPath $DlssDll).FullName
$metadata = Get-Content -LiteralPath (Join-Path $package 'package.json') -Raw | ConvertFrom-Json
$GpuArch=Get-D4RGpuTarget $package $metadata.architecture
foreach ($file in $metadata.files) {
if ($file.path.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget (Join-Path $package $file.path) $GpuArch }
if ((Get-FileHash -LiteralPath (Join-Path $package $file.path) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Package file changed; rebuild package: $($file.path)" }
}
if ((Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash -ne $metadata.dlssSha256) { throw 'DLSS DLL does not match the validated 310.9.1 native manifest. Rebuild and validate native manifests for this DLL first.' }
Invoke-D4RGpuPreflight $package $game $GpuArch (Join-Path $package ('results/preflight-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')))
$textureFiles=@(); $textureManifest=@()
if ($LocalTextureKernels) {
$LocalTextureKernels=(Get-Item -LiteralPath $LocalTextureKernels -ErrorAction Stop).FullName
$validation=Get-Content -LiteralPath (Join-Path $LocalTextureKernels 'validation.json') -Raw | ConvertFrom-Json
if (!$validation.passed -or !$validation.strictRgb -or $validation.architecture -ne $GpuArch -or
$validation.source.dlssSha256 -ne $metadata.dlssSha256 -or !$validation.source.accuracy) {
throw 'Local texture kernels must pass test-native-texture.ps1 with the exact packaged DLSS identity.'
}
foreach ($object in $validation.source.objects.PSObject.Properties) {
if ($object.Name -notin @('hiluma_engine_output_depthinv_mvlo_hdr_max_v2_rel.hsaco','hiluma_engine_output_depthreg_mvhi_ldr_max_v2_rel.hsaco')) {
throw "Unvalidated local texture variant: $($object.Name)"
}
$path=Join-Path $LocalTextureKernels $object.Name
if ((Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash.ToLowerInvariant() -ne $object.Value) { throw 'Local texture object changed after validation.' }
Assert-D4RCodeObjectTarget $path $GpuArch
$textureFiles+=Get-Item -LiteralPath $path
}
if ($textureFiles.Count -ne 2) { throw 'Expected both validated local K output variants.' }
# Use the manifest covered by validation, rather than a mutable extra file.
foreach ($line in Get-Content -LiteralPath (Join-Path $LocalTextureKernels 'd4r-kernels.txt')) {
if (!$line.Trim() -or $line.StartsWith('#')) { continue }
if ($line -notmatch '^([A-Za-z0-9_]+) ([0-9a-f]{16})$' -or ($Matches[1]+'.hsaco') -notin @($textureFiles.Name)) { throw 'Invalid local texture manifest.' }
$textureManifest+=$line
}
if ($textureManifest.Count -ne 2) { throw 'Expected two local texture manifest identities.' }
if ((Get-FileHash -LiteralPath (Join-Path $LocalTextureKernels 'd4r-kernels.txt') -Algorithm SHA256).Hash.ToLowerInvariant() -ne $validation.manifestSha256) { throw 'Local texture manifest changed after validation.' }
}
$manifest = if (Test-Path -LiteralPath $manifestPath) { Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json } else { [pscustomobject]@{game=$GameExe; files=@()} }
if ($manifest.game -ne $GameExe) { throw 'Backup manifest belongs to another executable.' }
if (!(Test-Path -LiteralPath $manifestPath) -and (Test-Path -LiteralPath (GamePath 'd4r'))) { throw 'An existing d4r directory has no installation manifest; preserved.' }
New-Item -ItemType Directory -Force $backup | Out-Null
function InstallFile([string]$source, [string]$relative) {
$relative=$relative.Replace('/','\')
$path = GamePath $relative
$entry = @($manifest.files | Where-Object { $_.path.Replace('/','\') -eq $relative }) | Select-Object -First 1
if ($entry) {
if ((Test-Path -LiteralPath $path) -and (Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash -ne $entry.installedHash) { throw "Installed file changed; preserved: $path" }
} else {
$existed = Test-Path -LiteralPath $path
if ($existed) {
$original = Join-Path $backup ('original/' + $relative)
New-Item -ItemType Directory -Force (Split-Path $original) | Out-Null
Copy-Item -LiteralPath $path -Destination $original
}
$entry = [pscustomobject]@{path=$relative; existed=[bool]$existed; installedHash=''}
$manifest.files = @($manifest.files) + @($entry)
}
New-Item -ItemType Directory -Force (Split-Path $path) | Out-Null
Copy-Item -LiteralPath $source -Destination $path -Force
$entry.installedHash = (Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash
$manifest | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $manifestPath -Encoding UTF8
}
InstallFile (Join-Path $package 'OptiScaler.dll') 'dxgi.dll'
foreach ($file in $metadata.files) {
$relative=$file.path.Replace('/','\')
if ($relative.StartsWith('d4r\',[StringComparison]::OrdinalIgnoreCase)) {
InstallFile (Join-Path $package $relative) $relative
}
}
if ($LocalTextureKernels) {
foreach ($file in $textureFiles) { InstallFile $file.FullName ('d4r/native/' + $file.Name) }
$combinedManifest=Join-Path $backup 'generated-native-manifest.txt'
@(Get-Content -LiteralPath (Join-Path $package 'd4r/native/d4r-kernels.txt')) + $textureManifest |
Set-Content -LiteralPath $combinedManifest -Encoding ASCII
InstallFile $combinedManifest 'd4r/native/d4r-kernels.txt'
}
# Private local test copies only; these are never added to the public package.
InstallFile $NgxCore 'd4r/vendor/_nvngx.dll'
# The numeric driver Init ABI searches the calling module's directory; it does
# not accept FeatureCommonInfo. Keep the exact local feature DLL alongside the
# d4r shim. Putting it only beside the core in vendor/ produces FeatureNotFound.
InstallFile $DlssDll 'd4r/nvngx_dlss.dll'
$bridge = GamePath 'd4r'
$vendor = GamePath 'd4r/vendor'
$ini = @"
[Upscalers]
Dx12Upscaler=dlss
[FrameGen]
Enabled=false
FGInput=nofg
FGOutput=nofg
[DLSS]
Enabled=true
AllowExternalBackend=true
RenderPresetOverride=true
RenderPresetForAll=$Preset
UseGenericAppIdWithDlss=false
[Libraries]
NvngxPath=$bridge
NvngxDlssPath=$bridge
NvngxFeaturePath=$bridge
[Hotfix]
RestoreComputeSignature=false
RestoreGraphicSignature=false
ExtendedStateRestore=false
[Log]
LogToFile=true
LogLevel=$(if ($VerboseRuntime) { 0 } else { 2 })
[Menu]
DisableSplash=true
"@
$tempIni = Join-Path $backup 'generated-OptiScaler.ini'
$ini | Set-Content -LiteralPath $tempIni -Encoding UTF8
InstallFile $tempIni 'OptiScaler.ini'
if ($Action -eq 'install') { Write-Host "Installed development backend for preset $Preset. Use -Action restore to revert."; return }
if (!$OutputDirectory) { $OutputDirectory = Join-Path $package ('results/game-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$OutputDirectory = [IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
if (!$CacheDirectory) { $CacheDirectory = Join-Path $package 'cache' }
$CacheDirectory = [IO.Path]::GetFullPath($CacheDirectory)
$settings = @{
D4R_HIP_ROOT=(GamePath 'd4r/hip'); HIP_PATH=(GamePath 'd4r/hip');
D4R_NVCUDA_DLL=(GamePath 'd4r/zluda/nvcuda.dll'); ZLUDA_CUDA_LIB=(GamePath 'd4r/zluda/nvcuda.dll');
D4R_NVAPI_DLL=(GamePath 'd4r/nvapi/nvapi64.dll'); D4R_NVAPI_BACKEND=(GamePath 'd4r/zluda/nvapi64.dll');
D4R_NGX_CORE=(GamePath 'd4r/vendor/_nvngx.dll'); D4R_DLSS_DLL=(GamePath 'd4r/nvngx_dlss.dll');
D4R_FORMAT_MODULE=(GamePath "d4r/pixel_convert_${GpuArch}.hsaco");
D4R_ZLUDA_NATIVE_DIR=(GamePath 'd4r/native'); D4R_D3D12_COMMAND_BACKEND='1'; D4R_ZLUDA_VERBOSE='1';
D4R_ZLUDA_WMMA='1'; D4R_ZLUDA_WMMA_FP8='1'; D4R_ZLUDA_WMMA_FP8_NATIVE='0'; D4R_ZLUDA_WMMA_F16_REFERENCE='1';
# Do not inherit relaxation flags from unrelated experiments. Unset and
# false have the same numerical effect; unset reuses the validated cache.
D4R_ZLUDA_IGNORE_DENORMAL=$null; D4R_ZLUDA_FAST_MATH=$null;
D4R_ZLUDA_WMMA_F32ACC=$null; D4R_ZLUDA_WAVE64=$null;
D4R_ZLUDA_WMMA_LAYOUT=$null;
D4R_QUIET_API=$(if ($VerboseRuntime) { $null } else { '1' });
D4R_VALIDATE_OUTPUT=$(if ($ValidateOutput) { '1' } else { $null });
D4R_PROFILE_STAGES=$(if ($ProfileStages) { '1' } else { $null });
D4R_ZLUDA_PROFILE=$(if ($ProfileKernels) { '1' } else { $null });
D4R_ZLUDA_PROFILE_DEFERRED=$(if ($ProfileKernelsDeferred) { '1' } else { $null });
D4R_ZLUDA_PROFILE_ALLOW_LEGACY=$(if ($ProfileLegacyStream) { '1' } else { $null });
D4R_ZLUDA_PROFILE_EVERY=$(if ($ProfileKernelsDeferred) { "$KernelProfileEvery" } else { $null });
D4R_PROFILE_COMMAND_HOOKS=$(if ($ProfileCommandHooks) { '1' } else { $null });
D4R_ZLUDA_PROFILE_API=$(if ($ProfileCudaApi) { '1' } else { $null });
D4R_PROFILE_GPU_BOUNDARY=$(if ($ProfileGpuBoundary) { '1' } else { $null });
D4R_DISABLE_INTEROP_LIST_CACHE=$(if ($UncachedInteropLists) { '1' } else { $null });
D4R_ASYNC_INTEROP=$(if ($AsyncInterop) { '1' } else { $null });
D4R_BATCH_INPUT_COPIES=$(if ($BatchInputCopies) { '1' } else { $null });
D4R_DIAG_DIR=$OutputDirectory; ZLUDA_LOG_DIR=(Join-Path $OutputDirectory 'zluda-trace');
ZLUDA_CACHE_DIR=$CacheDirectory; PATH=((GamePath 'd4r/hip/bin') + ';' + (GamePath 'd4r/zluda') + ';' + $env:PATH)
}
$old = @{}; $process = $null; $originalSettings = @()
$outFile = $null; $errFile = $null; $outTask = $null; $errTask = $null
try {
if ($DiagnosticResolution) {
if ([IO.Path]::GetFileName($GameExe) -ne 'SHProto-Win64-Shipping.exe' -or $DiagnosticResolution -notmatch '^([0-9]{3,4})x([0-9]{3,4})$') { throw 'DiagnosticResolution currently supports Silent Hill 2 only; use e.g. 1280x720.' }
$renderWidth=[int]$Matches[1]; $renderHeight=[int]$Matches[2]
if ($renderWidth -gt 4096 -or $renderHeight -gt 2160) { throw 'Diagnostic resolution is too large.' }
$userRoot=Join-Path $env:LOCALAPPDATA 'SilentHill2/Saved'
foreach ($relative in @('Config/Windows/GameUserSettings.ini','SaveGames/GFXSettings.SHProto-Win64-Shipping.xml')) {
$path=Join-Path $userRoot $relative
$saved=Join-Path $OutputDirectory ('original-settings/' + $relative)
New-Item -ItemType Directory -Force (Split-Path $saved) | Out-Null
Copy-Item -LiteralPath $path -Destination $saved
$originalSettings += @{path=$path; saved=$saved}
if ($relative.EndsWith('.ini')) {
$text=[IO.File]::ReadAllText($path)
$text=$text -replace 'Resolution=\(X=[0-9]+,Y=[0-9]+\)', "Resolution=(X=$renderWidth,Y=$renderHeight)"
$text=$text -replace 'ScreenMode=Borderless', 'ScreenMode=Windowed'
$text=$text -replace '(?m)^ResolutionSizeX=[0-9]+', "ResolutionSizeX=$renderWidth"
$text=$text -replace '(?m)^ResolutionSizeY=[0-9]+', "ResolutionSizeY=$renderHeight"
$text=$text -replace '(?m)^FullscreenMode=[0-9]+', 'FullscreenMode=2'
[IO.File]::WriteAllText($path,$text,[Text.UTF8Encoding]::new($false))
} else {
$xml=[xml](Get-Content -LiteralPath $path -Raw -Encoding Unicode)
$xml.GSA_SDK.GAMESETTINGS.RESOLUTION.Width="$renderWidth"
$xml.GSA_SDK.GAMESETTINGS.RESOLUTION.Height="$renderHeight"
$xml.Save($path)
}
}
Write-Host "Temporary diagnostic resolution: $DiagnosticResolution; original settings restore at exit."
}
foreach ($key in $settings.Keys) { $old[$key] = [Environment]::GetEnvironmentVariable($key,'Process'); [Environment]::SetEnvironmentVariable($key,$settings[$key],'Process') }
@{preset=$Preset; game=$GameExe; package=$metadata; attachedDebugger=[bool]$CaptureExceptions;
diagnostics=@{asyncInterop=[bool]$AsyncInterop; batchInputCopies=[bool]$BatchInputCopies; validateOutput=[bool]$ValidateOutput;
profileGpuBoundary=[bool]$ProfileGpuBoundary; profileStages=[bool]$ProfileStages; profileCudaApi=[bool]$ProfileCudaApi;
profileKernels=[bool]$ProfileKernels; profileKernelsDeferred=[bool]$ProfileKernelsDeferred;
profileLegacyStream=[bool]$ProfileLegacyStream; kernelProfileEvery=$KernelProfileEvery};
driver=@(Get-CimInstance Win32_VideoController | Select-Object Name,DriverVersion,DriverDate); arguments=$GameArguments} |
ConvertTo-Json -Depth 12 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'environment.json') -Encoding UTF8
function Quote([string]$value) { if ($value.Contains('"')) { throw 'A command argument contains an unsupported quote.' }; return '"' + $value + '"' }
$arguments = @('--output-directory', (Quote $OutputDirectory))
if (!$CaptureExceptions) { $arguments += '--no-debug' }
$arguments += @('--', (Quote $GameExe)) + @($GameArguments | ForEach-Object { Quote $_ })
# Drain raw bytes concurrently. PowerShell's line-oriented redirection can
# throttle a verbose game and distort the very timings we are collecting.
$info = [Diagnostics.ProcessStartInfo]::new()
$info.FileName = GamePath 'd4r/d4r_debug_launcher.exe'
$info.Arguments = $arguments -join ' '
$info.WorkingDirectory = $game
$info.UseShellExecute = $false; $info.CreateNoWindow = $true
$info.RedirectStandardOutput = $true; $info.RedirectStandardError = $true
# Empty task switches mean unset. Some PowerShell/.NET hosts preserve empty
# values, which would enable Rust's presence-based diagnostic flags.
foreach ($key in @($info.EnvironmentVariables.Keys)) {
if ($key.StartsWith('D4R_') -and [string]::IsNullOrWhiteSpace($info.EnvironmentVariables[$key])) {
$info.EnvironmentVariables.Remove($key)
}
}
if ([Environment]::GetEnvironmentVariable('D4R_ZLUDA_WGP','Process') -ne '1') {
$info.EnvironmentVariables.Remove('D4R_ZLUDA_WGP')
}
$process = [Diagnostics.Process]::new(); $process.StartInfo = $info
if (!$process.Start()) { throw 'Game diagnostic launch failed.' }
$outFile = [IO.File]::Open((Join-Path $OutputDirectory 'd4r.stdout.log'), [IO.FileMode]::Create, [IO.FileAccess]::Write, [IO.FileShare]::Read)
$errFile = [IO.File]::Open((Join-Path $OutputDirectory 'd4r.stderr.log'), [IO.FileMode]::Create, [IO.FileAccess]::Write, [IO.FileShare]::Read)
$outTask = $process.StandardOutput.BaseStream.CopyToAsync($outFile)
$errTask = $process.StandardError.BaseStream.CopyToAsync($errFile)
Write-Host "Game diagnostic started (preset $Preset). Logs: $OutputDirectory"
$timer = [Diagnostics.Stopwatch]::StartNew()
while (!$process.WaitForExit(1000)) {
if ($RunSeconds -gt 0 -and $timer.Elapsed.TotalSeconds -ge $RunSeconds) { $process.Kill(); $process.WaitForExit(); break }
}
$process.WaitForExit()
[void]$outTask.GetAwaiter().GetResult(); [void]$errTask.GetAwaiter().GetResult()
$outFile.Dispose(); $outFile = $null; $errFile.Dispose(); $errFile = $null
foreach ($file in Get-ChildItem -LiteralPath $game -Filter 'OptiScaler*.log' -File) { Copy-Item -LiteralPath $file.FullName -Destination $OutputDirectory -Force }
$stderr = [IO.File]::ReadAllText((Join-Path $OutputDirectory 'd4r.stderr.log'))
$stdout = [IO.File]::ReadAllText((Join-Path $OutputDirectory 'd4r.stdout.log'))
$debugger = [IO.File]::ReadAllText((Join-Path $OutputDirectory 'debugger.log'))
$gameExit = [regex]::Match($debugger, 'EXIT code=0x([0-9a-f]+)')
$gameCrash = $null
if ([IO.Path]::GetFileName($GameExe) -eq 'SHProto-Win64-Shipping.exe' -and $gameExit.Success -and $gameExit.Groups[1].Value -ne '0') {
$crashRoot = Join-Path $env:LOCALAPPDATA 'SilentHill2/Saved/Crashes'
$latest = Get-ChildItem -LiteralPath $crashRoot -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -ge (Get-Date).AddSeconds(-$timer.Elapsed.TotalSeconds-5) } |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if ($latest) {
Copy-Item -LiteralPath $latest.FullName -Destination (Join-Path $OutputDirectory 'ue-crash') -Recurse
[xml]$context = Get-Content -LiteralPath (Join-Path $latest.FullName 'CrashContext.runtime-xml') -Raw
$gameCrash = @{type=[string]$context.FGenericCrashContext.RuntimeProperties.CrashType;
reason=[string]$context.FGenericCrashContext.RuntimeProperties.ErrorMessage}
}
}
Get-D4RGameSummary -Stdout $stdout -Stderr $stderr -Debugger $debugger -Preset $Preset `
-RunSeconds $timer.Elapsed.TotalSeconds -ValidateOutput ([bool]$ValidateOutput) -GameCrash $gameCrash |
ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Compress-Archive -LiteralPath $OutputDirectory -DestinationPath ($OutputDirectory + '.zip') -Force
Write-Host "Game diagnostic bundle: $OutputDirectory.zip"
} finally {
if ($process -and !$process.HasExited) { $process.Kill(); $process.WaitForExit() }
if ($outTask) { try { [void]$outTask.GetAwaiter().GetResult() } catch {} }
if ($errTask) { try { [void]$errTask.GetAwaiter().GetResult() } catch {} }
if ($outFile) { $outFile.Dispose() }; if ($errFile) { $errFile.Dispose() }
if ($process) { $process.Dispose() }
foreach ($key in $old.Keys) { [Environment]::SetEnvironmentVariable($key,$old[$key],'Process') }
foreach ($entry in $originalSettings) { Copy-Item -LiteralPath $entry.saved -Destination $entry.path -Force }
}