release: engine models skip L/M on RDNA2 and render in parallel
RDNA2 has native kernels for K's layers only; L's and M's test frames still compiled their transformer layers with emulated matrix products for most of an hour. The builder now builds e, f, k, k-ldr on gfx103x (detected like the native kernels: D4R_GPU_ARCH, else the KFD node with the most SIMDs); D4R_ENGINE_ALL_MODELS=1 builds L and M anyway. install.sh takes the model list from build-engine-models.sh --list-sr-models and keys the shared cache on it. Models build in alphabetical order (E, F, K, L, M). The first frame renders alone to create the Proton prefix; the rest render at the same time, each model built as soon as its frame is done (ZLUDA compiles in one thread per process). Cold install.sh --yes on a Steam Deck: 185 s.
This commit is contained in:
1 parent
4064117244
commit
916b0d1467
2 files changed
+67
-28
No files matched your search
+5
-3
@@ -167,10 +167,12 @@ if [[ ! -f "$BUILDER" ]]; then
|
|||||||
[[ "$DO_ENGINE" != 1 ]] || fail "missing $BUILDER (this release has no engine-model builder)"
|
[[ "$DO_ENGINE" != 1 ]] || fail "missing $BUILDER (this release has no engine-model builder)"
|
||||||
done_msg; exit 0
|
done_msg; exit 0
|
||||||
fi
|
fi
|
||||||
models=(rr-d rr-e rr-f k k-ldr m m-ldr l l-ldr e f)
|
# the Super Resolution models depend on the GPU (RDNA2 builds no L and M), so the builder lists them
|
||||||
# One build serves every game with the same DLLs and builder: the key covers both and the accuracy choice.
|
models=(rr-d rr-e rr-f $(bash "$BUILDER" --list-sr-models))
|
||||||
|
# One build serves every game with the same DLLs, builder and model set: the key covers them and the accuracy choice.
|
||||||
key() { # key EXACT(0|1)
|
key() { # key EXACT(0|1)
|
||||||
{ echo "exact=$1"
|
{ echo "exact=$1"
|
||||||
|
echo "models=${models[*]}"
|
||||||
sha256sum -- "$RUNTIME/nvngx_dlss.dll" "$RUNTIME/nvngx_dlssd.dll" 2>/dev/null | cut -d' ' -f1
|
sha256sum -- "$RUNTIME/nvngx_dlss.dll" "$RUNTIME/nvngx_dlssd.dll" 2>/dev/null | cut -d' ' -f1
|
||||||
(cd "$RUNTIME/tools" && find . -type f ! -name '*.pyc' -print0 | LC_ALL=C sort -z | xargs -0 sha256sum); } | sha256sum | cut -c1-16
|
(cd "$RUNTIME/tools" && find . -type f ! -name '*.pyc' -print0 | LC_ALL=C sort -z | xargs -0 sha256sum); } | sha256sum | cut -c1-16
|
||||||
}
|
}
|
||||||
@@ -193,7 +195,7 @@ if [[ "$DO_ENGINE" == ask ]]; then
|
|||||||
echo ' + On RDNA2 (Steam Deck) it is the route for DLSS 3'"'"'s CNN presets E and F: those models run without cooperative matrices.'
|
echo ' + On RDNA2 (Steam Deck) it is the route for DLSS 3'"'"'s CNN presets E and F: those models run without cooperative matrices.'
|
||||||
echo ' + Lower latency: the game shows the upscaled result of the frame it just rendered, not an older one.'
|
echo ' + Lower latency: the game shows the upscaled result of the frame it just rendered, not an older one.'
|
||||||
echo ' + No minute-long freeze while DLSS'"'"'s CUDA kernels compile the first time a model is used.'
|
echo ' + No minute-long freeze while DLSS'"'"'s CUDA kernels compile the first time a model is used.'
|
||||||
echo ' - Longer setup, once: building its models takes a minute or two (it renders a test frame per model'
|
echo ' - Longer setup, once: building its models takes a few minutes (it renders a test frame per model'
|
||||||
echo ' through GE-Proton) and needs ~300 MB of temporary space. Later installs reuse the models.'
|
echo ' through GE-Proton) and needs ~300 MB of temporary space. Later installs reuse the models.'
|
||||||
echo ' - Slower for K and M on RDNA3; there d4r keeps those two models on its normal path.'
|
echo ' - Slower for K and M on RDNA3; there d4r keeps those two models on its normal path.'
|
||||||
echo ' Without it, d4r uses its normal path; anything the engine does not cover uses that path anyway.'
|
echo ' Without it, d4r uses its normal path; anything the engine does not cover uses that path anyway.'
|
||||||
|
|||||||
@@ -4,12 +4,14 @@
|
|||||||
#
|
#
|
||||||
# usage: bash d4r/tools/build-engine-models.sh [--rr-only | --sr-only] [--exact] [D4R_FOLDER]
|
# usage: bash d4r/tools/build-engine-models.sh [--rr-only | --sr-only] [--exact] [D4R_FOLDER]
|
||||||
# bash d4r/tools/build-engine-models.sh --find-proton prints the GE-Proton it would use (or nothing)
|
# bash d4r/tools/build-engine-models.sh --find-proton prints the GE-Proton it would use (or nothing)
|
||||||
|
# bash d4r/tools/build-engine-models.sh --list-sr-models prints the Super Resolution models it builds here
|
||||||
# Ray Reconstruction engine/rr-d, rr-e, rr-f from d4r/nvngx_dlssd.dll 310.9.1 alone (about half a minute)
|
# Ray Reconstruction engine/rr-d, rr-e, rr-f from d4r/nvngx_dlssd.dll 310.9.1 alone (about half a minute)
|
||||||
# Super Resolution engine/k, k-ldr, m, m-ldr, l, l-ldr, e, f
|
# Super Resolution engine/e, f, k, k-ldr, l, l-ldr, m, m-ldr (on RDNA2 only e, f, k, k-ldr; D4R_ENGINE_ALL_MODELS=1
|
||||||
|
# builds L and M there too, which takes most of an hour)
|
||||||
# NVIDIA's DLSS keeps these weights packed in nvngx_dlss.dll; they are read where NGX unpacks
|
# NVIDIA's DLSS keeps these weights packed in nvngx_dlss.dll; they are read where NGX unpacks
|
||||||
# them: the bundled D3D12 test app renders one frame per model through this d4r folder under
|
# them: the bundled D3D12 test app renders one frame per model through this d4r folder under
|
||||||
# GE-Proton, and the uploads are saved (a minute or two each; the first run also compiles
|
# GE-Proton, and the uploads are saved (the frames after the first render at the same time;
|
||||||
# DLSS's kernels and creates a temporary Proton prefix)
|
# the first run also compiles DLSS's kernels and creates a temporary Proton prefix)
|
||||||
# Needs python3 with numpy, and for Super Resolution a GE-Proton (D4R_PROTON=/path/to/GE-Proton11-3 to choose one).
|
# Needs python3 with numpy, and for Super Resolution a GE-Proton (D4R_PROTON=/path/to/GE-Proton11-3 to choose one).
|
||||||
# The models are the fastest builds (this GPU's own arithmetic; engine/README.md). --exact builds NVIDIA's roundings
|
# The models are the fastest builds (this GPU's own arithmetic; engine/README.md). --exact builds NVIDIA's roundings
|
||||||
# instead: bit-identical to the CUDA path, about 20% slower (K is the same either way).
|
# instead: bit-identical to the CUDA path, about 20% slower (K is the same either way).
|
||||||
@@ -17,14 +19,15 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
fail() { printf 'build-engine-models: %s\n' "$*" >&2; exit 1; }
|
fail() { printf 'build-engine-models: %s\n' "$*" >&2; exit 1; }
|
||||||
DO_RR=1 DO_SR=1 FIND_PROTON=0
|
DO_RR=1 DO_SR=1 FIND_PROTON=0 LIST_SR=0
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--rr-only) DO_SR=0; shift ;;
|
--rr-only) DO_SR=0; shift ;;
|
||||||
--sr-only) DO_RR=0; shift ;;
|
--sr-only) DO_RR=0; shift ;;
|
||||||
--exact) export D4R_RR_RELAXED=0 M_EXACT=1; shift ;;
|
--exact) export D4R_RR_RELAXED=0 M_EXACT=1; shift ;;
|
||||||
--find-proton) FIND_PROTON=1; shift ;;
|
--find-proton) FIND_PROTON=1; shift ;;
|
||||||
-h|--help) sed -n '2,19p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
--list-sr-models) LIST_SR=1; shift ;;
|
||||||
|
-h|--help) sed -n '2,22p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||||
*) break ;;
|
*) break ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@@ -45,6 +48,27 @@ find_proton() {
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
gpu_arch() { # the GPU the native kernels are chosen for: D4R_GPU_ARCH, else the KFD node with the most SIMDs
|
||||||
|
if [[ -n "${D4R_GPU_ARCH:-}" ]]; then printf '%s\n' "$D4R_GPU_ARCH"; return; fi
|
||||||
|
local f simds version best=0 found=''
|
||||||
|
for f in /sys/class/kfd/kfd/topology/nodes/*/properties; do
|
||||||
|
[[ -r "$f" ]] || continue
|
||||||
|
simds=$(awk '$1 == "simd_count" { print $2 }' "$f")
|
||||||
|
version=$(awk '$1 == "gfx_target_version" { print $2 }' "$f") # gfx1033 = 100303
|
||||||
|
if (( ${simds:-0} > best )); then best=$simds; found=$version; fi
|
||||||
|
done
|
||||||
|
[[ -z "$found" ]] || printf 'gfx%d%d%x\n' $((found / 10000)) $((found / 100 % 100)) $((found % 100))
|
||||||
|
}
|
||||||
|
sr_models() {
|
||||||
|
# RDNA2 has native kernels for K's layers only: L's and M's test frames would compile their transformer layers
|
||||||
|
# with emulated matrix products for most of an hour, so d4r's normal path keeps those two models there
|
||||||
|
if [[ "${D4R_ENGINE_ALL_MODELS:-0}" != 1 && "$(gpu_arch)" == gfx103* ]]; then
|
||||||
|
echo e f k k-ldr
|
||||||
|
else
|
||||||
|
echo e f k k-ldr l l-ldr m m-ldr
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
if (( LIST_SR )); then sr_models; exit 0; fi
|
||||||
if (( FIND_PROTON )); then find_proton; [[ -z "$PROTON" ]] || printf '%s\n' "$PROTON"; exit 0; fi
|
if (( FIND_PROTON )); then find_proton; [[ -z "$PROTON" ]] || printf '%s\n' "$PROTON"; exit 0; fi
|
||||||
TOOLS="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
TOOLS="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
KIT="$TOOLS/models"
|
KIT="$TOOLS/models"
|
||||||
@@ -61,7 +85,7 @@ glslangValidator --version > /dev/null 2>&1 || fail "glslangValidator ($KIT/bin)
|
|||||||
sha() { sha256sum -- "$1" | cut -d' ' -f1; }
|
sha() { sha256sum -- "$1" | cut -d' ' -f1; }
|
||||||
|
|
||||||
WORK="$(mktemp -d "${TMPDIR:-/tmp}/d4r-models.XXXXXX")"
|
WORK="$(mktemp -d "${TMPDIR:-/tmp}/d4r-models.XXXXXX")"
|
||||||
trap 'rm -rf -- "$WORK"' EXIT
|
trap 'kill $(jobs -p) 2> /dev/null || true; rm -rf -- "$WORK"' EXIT
|
||||||
trap 'exit 130' INT
|
trap 'exit 130' INT
|
||||||
trap 'exit 143' TERM
|
trap 'exit 143' TERM
|
||||||
|
|
||||||
@@ -119,6 +143,7 @@ if (( DO_SR )); then
|
|||||||
else
|
else
|
||||||
fail "d4r's d3d12.dll / d3d12core.dll not found next to $RUNTIME"
|
fail "d4r's d3d12.dll / d3d12core.dll not found next to $RUNTIME"
|
||||||
fi
|
fi
|
||||||
|
PTX="$WORK/ptx"
|
||||||
winpath() { printf 'Z:%s' "$(printf '%s' "$1" | tr '/' '\\')"; }
|
winpath() { printf 'Z:%s' "$(printf '%s' "$1" | tr '/' '\\')"; }
|
||||||
dump() { # dump NAME PRESET PATTERN [FLAGS]: the uploads of one frame of preset PRESET in WORK/NAME/replay
|
dump() { # dump NAME PRESET PATTERN [FLAGS]: the uploads of one frame of preset PRESET in WORK/NAME/replay
|
||||||
local w="$WORK/$1"
|
local w="$WORK/$1"
|
||||||
@@ -136,9 +161,32 @@ if (( DO_SR )); then
|
|||||||
fail "model $1: the test frame did not run through DLSS (logs above)"
|
fail "model $1: the test frame did not run through DLSS (logs above)"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
echo 'Building the Super Resolution models (K, M and L) from what NGX uploads...'
|
|
||||||
mkdir -p "$WORK/prefix"
|
mkdir -p "$WORK/prefix"
|
||||||
dump k 11 dltss_pwin_dec0_layer
|
models=" $(sr_models) "
|
||||||
|
echo "Building the Super Resolution models ($(sr_models)) from what NGX uploads..."
|
||||||
|
[[ "$models" == *" m "* ]] || echo " (L and M are left to d4r's normal path on this GPU ($(gpu_arch)); D4R_ENGINE_ALL_MODELS=1 builds them)"
|
||||||
|
run ptx.log python3 "$KIT/kernels/tools/extract_dlss_ptx.py" "$DLL" "$PTX"
|
||||||
|
# Each test frame compiles its DLSS kernels in one thread, so the frames render at the same time; the first
|
||||||
|
# renders alone because it creates the Proton prefix. A model is built as soon as its frame is done.
|
||||||
|
declare -A JOBS
|
||||||
|
start() { dump "$@" & JOBS[$1]=$!; }
|
||||||
|
finish() { wait "${JOBS[$1]}" || exit 1; } # dump has said why
|
||||||
|
# presets E and F (DLSS 3's CNN): LDR with render-size motion (the model serves every flag set)
|
||||||
|
dump e 5 cuda_engine_input_kernel_rel 0xa
|
||||||
|
start f 6 cuda_engine_input_kernel_rel 0xa
|
||||||
|
start k 11 dltss_pwin_dec0_layer
|
||||||
|
if [[ "$models" == *" m "* ]]; then
|
||||||
|
start l 12 'rrlite_enc0_4x4_mvlo_hdr$'
|
||||||
|
start m 13 rrlite_enc0_4x4_mvlo_hdr_folded
|
||||||
|
fi
|
||||||
|
for c in "e E" "f F"; do
|
||||||
|
set -- $c
|
||||||
|
[[ $1 == e ]] || finish "$1"
|
||||||
|
run "$1.log" python3 "$KIT/engine/compile_sr_e.py" "$WORK/$1/replay" "$DLL" "$WORK/$1-out" --preset "$2" --ptx-dir "$PTX"
|
||||||
|
place "$1" "$WORK/$1-out" $(ls "$WORK/$1-out")
|
||||||
|
rm -rf -- "${WORK:?}/$1"
|
||||||
|
done
|
||||||
|
finish k
|
||||||
run k-extract.log python3 "$KIT/engine/extract_k.py" "$WORK/k/replay" "$WORK/k/model"
|
run k-extract.log python3 "$KIT/engine/extract_k.py" "$WORK/k/replay" "$WORK/k/model"
|
||||||
run k-lut.log python3 "$KIT/engine/prepare_k.py" "$WORK/k" "$WORK/k/case" --lut-only
|
run k-lut.log python3 "$KIT/engine/prepare_k.py" "$WORK/k" "$WORK/k/case" --lut-only
|
||||||
for v in k k-ldr; do
|
for v in k k-ldr; do
|
||||||
@@ -147,25 +195,14 @@ if (( DO_SR )); then
|
|||||||
place "$v" "$WORK/$v-out" $(ls "$WORK/$v-out")
|
place "$v" "$WORK/$v-out" $(ls "$WORK/$v-out")
|
||||||
done
|
done
|
||||||
rm -rf -- "$WORK/k"
|
rm -rf -- "$WORK/k"
|
||||||
for c in "m 13 rrlite_enc0_4x4_mvlo_hdr_folded" "l 12 rrlite_enc0_4x4_mvlo_hdr$"; do
|
for m in l m; do
|
||||||
set -- $c
|
[[ "$models" == *" $m "* ]] || continue
|
||||||
dump "$1" "$2" "$3"
|
finish "$m"
|
||||||
for v in "$1" "$1-ldr"; do
|
for v in "$m" "$m-ldr"; do
|
||||||
run "$v.log" python3 "$KIT/engine/compile_m.py" "$WORK/$1" "$WORK/$v-out" $([[ $v == *-ldr ]] && echo --ldr)
|
run "$v.log" python3 "$KIT/engine/compile_m.py" "$WORK/$m" "$WORK/$v-out" $([[ $v == *-ldr ]] && echo --ldr)
|
||||||
place "$v" "$WORK/$v-out" $(ls "$WORK/$v-out")
|
place "$v" "$WORK/$v-out" $(ls "$WORK/$v-out")
|
||||||
done
|
done
|
||||||
rm -rf -- "${WORK:?}/$1"
|
rm -rf -- "${WORK:?}/$m"
|
||||||
done
|
|
||||||
# presets E and F (DLSS 3's CNN): one frame each, LDR with render-size motion (the model serves every flag set)
|
|
||||||
echo 'Building the Super Resolution CNN models (E and F)...'
|
|
||||||
PTX="$WORK/ptx"
|
|
||||||
run ptx.log python3 "$KIT/kernels/tools/extract_dlss_ptx.py" "$DLL" "$PTX"
|
|
||||||
for c in "e 5 E" "f 6 F"; do
|
|
||||||
set -- $c
|
|
||||||
dump "$1" "$2" cuda_engine_input_kernel_rel 0xa
|
|
||||||
run "$1.log" python3 "$KIT/engine/compile_sr_e.py" "$WORK/$1/replay" "$DLL" "$WORK/$1-out" --preset "$3" --ptx-dir "$PTX"
|
|
||||||
place "$1" "$WORK/$1-out" $(ls "$WORK/$1-out")
|
|
||||||
rm -rf -- "${WORK:?}/$1"
|
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
printf 'Engine models are in %s/engine.\n' "$RUNTIME"
|
printf 'Engine models are in %s/engine.\n' "$RUNTIME"
|
||||||
Reference in new issue
Block a user