Add native K/M/RR inference engines, HIP kernels, replay and validation harnesses, and Windows DLSS setup and runtime support. Include GPU profiling tools, build and packaging scripts, platform integration patches, and implementation documentation.
150 lines
6.1 KiB
Bash
150 lines
6.1 KiB
Bash
#!/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"
|