rr: add FSR Ray Regeneration, exact RDNA3 inference and motion experiments
Add an experimental FSR Ray Regeneration backend for D3D12 RR requests: - Convert depth, motion, normals and albedos into AMD denoiser inputs. - Split and recompose diffuse/specular signals, then run Super Sampling. - Add stability/detail controls, demodulation guards and halo limiting. - Handle AMD provider discovery under NVIDIA GPU spoofing. - Add runtime probes, synthetic reference scenes and per-dispatch profiling. Add exact gfx11 DLSS-RR inference using f16 cooperative matrices: - Reproduce FP8 conversions, accumulation and camera reprojection arithmetic. - Widen model weights and avoid requiring VK_EXT_shader_float8. - Extend model building, replay tools and descriptor metadata. Expand motion preprocessing and experimental AW2 native-motion support: - Add tiled LDS dilation, padded allocation handling and thin-only sky fill. - Order dilation with input waits and NGX on the selected stream. - Add jitter-aligned native composition, hybrid routing and wire history repair. - Add prepared masks, sparse repair and independent motion/repair controls. Add optional fused R11G11B10 input/output conversion, sampled stage timings and profile summarization. Extend configuration, packaging, documentation, FidelityFX headers and CPU/GPU regression coverage.
This commit is contained in:
1 parent
17c1828f97
commit
34e6b0fe71
83 files changed
+11300
-195
No files matched your search
@@ -25,7 +25,7 @@ PARAM_OBJECT="$ROOT/build/d4r_ngx_param_msvc.obj"
|
||||
"$MINGW_CXX" -std=c++20 -O2 -Wall -Wextra -Wno-missing-field-initializers -DD4R_ENGINE_VK_TABLE -I"$ROOT/build/vulkan-include" -I"$ROOT/build/vulkan-staging" -shared -static -static-libgcc -static-libstdc++ \
|
||||
"$ROOT/tools/d4r_nvngx_shim.cpp" "$ROOT/tools/d4r_ngx_param_host.cpp" "$PARAM_OBJECT" \
|
||||
"$ROOT/engine/runtime.cpp" "$ROOT/engine/game.cpp" "$ROOT/engine/game_m.cpp" "$ROOT/engine/game_rr.cpp" "$ROOT/engine/vk_dispatch.cpp" \
|
||||
-Wl,--entry,d4r_dll_entry -o "$ROOT/build/d4r_nvngx.dll"
|
||||
-ldxgi -lbcrypt -Wl,--entry,d4r_dll_entry -o "$ROOT/build/d4r_nvngx.dll"
|
||||
printf 'Built %s\n' "$ROOT/build/d4r_nvngx.dll"
|
||||
cp "$ROOT/build/d4r_nvngx.dll" "$ROOT/build/d4r.asi"
|
||||
printf 'Built %s\n' "$ROOT/build/d4r.asi"
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Builds build/fsr_rr_probe.exe, the standalone AMD FSR Ray Regeneration provider/execution check
|
||||
# (tools/fsr_rr_probe.cpp). It needs no NVIDIA or d4r runtime files.
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
|
||||
|
||||
VULKAN_INCLUDE="${VULKAN_INCLUDE:-/usr/include}"
|
||||
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" -std=c++20 -O2 -Wall -Wextra -Wno-missing-field-initializers -municode -static -static-libgcc \
|
||||
-static-libstdc++ -I"$ROOT/build/vulkan-include" "$ROOT/tools/fsr_rr_probe.cpp" -ld3d12 -ldxgi -o "$ROOT/build/fsr_rr_probe.exe"
|
||||
printf 'Built %s\n' "$ROOT/build/fsr_rr_probe.exe"
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Builds build/rr_backend_check.exe (tools/rr_backend_check.cpp): a DLSS Ray Reconstruction request
|
||||
# through d4r_nvngx.dll, measured against the synthetic scene's ground truth. Builds the shim first,
|
||||
# for the NGX parameter object it links against.
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
MINGW_CXX="${MINGW_CXX:-x86_64-w64-mingw32-g++}"
|
||||
|
||||
"$ROOT/scripts/build_d4r_nvngx_shim.sh" >/dev/null
|
||||
"$MINGW_CXX" -std=c++20 -O2 -Wall -Wextra -Wno-missing-field-initializers -static -static-libgcc -static-libstdc++ \
|
||||
"$ROOT/tools/rr_backend_check.cpp" "$ROOT/tools/d4r_ngx_param_host.cpp" "$ROOT/build/d4r_ngx_param_msvc.obj" \
|
||||
-ld3d12 -ldxgi -o "$ROOT/build/rr_backend_check.exe"
|
||||
printf 'Built %s\n' "$ROOT/build/rr_backend_check.exe"
|
||||
@@ -6,7 +6,11 @@ set -euo pipefail
|
||||
# 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).
|
||||
# VKD3D_PROTON_COMMIT (default 3dfc6f07, the base GE-Proton11-3 ships),
|
||||
# D4R_VKD3D_FSR_RR=1: also what AMD's FSR Ray Regeneration needs on RDNA 3
|
||||
# ([RayReconstruction] Backend = fsr): dxil-spirv's accepted scalar FP8 fallback (upstream PR 307,
|
||||
# merge f9f6294f, cherry-picked onto the linked translator) and -Denable_extended_emulation=true,
|
||||
# in a build directory of its own. Run games with DXIL_SPIRV_CONFIG=wmma_rdna3_workaround.
|
||||
if [[ $# -ne 1 ]]; then
|
||||
printf 'usage: %s OUT_DIR\n' "$0" >&2
|
||||
exit 2
|
||||
@@ -22,7 +26,18 @@ BUILD="$SRC-build"
|
||||
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"
|
||||
EXTRA=()
|
||||
if [[ "${D4R_VKD3D_FSR_RR:-0}" == 1 ]]; then
|
||||
DXIL="$SRC/subprojects/dxil-spirv"
|
||||
git -C "$DXIL" fetch -q origin f9f6294f3a6795e071bef3a64d2bee99e7c1b7bc
|
||||
if ! git -C "$DXIL" merge-base --is-ancestor f9f6294f3a6795e071bef3a64d2bee99e7c1b7bc^2 HEAD; then
|
||||
git -C "$DXIL" -c user.name=d4r -c user.email=d4r@localhost cherry-pick -x \
|
||||
$(git -C "$DXIL" rev-list --reverse f9f6294f3a6795e071bef3a64d2bee99e7c1b7bc^1..f9f6294f3a6795e071bef3a64d2bee99e7c1b7bc^2)
|
||||
fi
|
||||
BUILD="$SRC-build-fsrrr"
|
||||
EXTRA=(-Denable_extended_emulation=true)
|
||||
fi
|
||||
[[ -d "$BUILD" ]] || meson setup --cross-file "$SRC/build-win64.txt" --buildtype release -Denable_tests=false "${EXTRA[@]}" "$BUILD" "$SRC"
|
||||
ninja -C "$BUILD"
|
||||
mkdir -p "$OUT"
|
||||
x86_64-w64-mingw32-strip -o "$OUT/d3d12.dll" "$BUILD/libs/d3d12/d3d12.dll"
|
||||
|
||||
@@ -5,6 +5,9 @@ OUT="${1:-$ROOT/build/vulkan-staging}"
|
||||
mkdir -p "$OUT"
|
||||
glslangValidator -V --target-env vulkan1.0 -o "$OUT/read.spv" "$ROOT/kernels/support/vulkan_read.comp" >/dev/null
|
||||
glslangValidator -V --target-env vulkan1.0 -o "$OUT/wait.spv" "$ROOT/kernels/support/vulkan_wait.comp" >/dev/null
|
||||
# FSR Ray Regeneration backend (tools/d4r_fsr_rr_passes.h)
|
||||
glslangValidator -V --target-env vulkan1.0 -o "$OUT/fsr_rr_prepare.spv" "$ROOT/kernels/support/fsr_rr_prepare.comp" >/dev/null
|
||||
glslangValidator -V --target-env vulkan1.0 -o "$OUT/fsr_rr_compose.spv" "$ROOT/kernels/support/fsr_rr_compose.comp" >/dev/null
|
||||
for format in rgba16f rgba32f r11f_g11f_b10f rgb10_a2 rgba8; do
|
||||
glslangValidator -V --target-env vulkan1.0 -DOUTPUT_FORMAT="$format" \
|
||||
-o "$OUT/write_$format.spv" "$ROOT/kernels/support/vulkan_write.comp" >/dev/null
|
||||
|
||||
@@ -100,6 +100,34 @@ def main(argv):
|
||||
env["D4R_RR_PRESET"] = rr_model
|
||||
else:
|
||||
fail(f"[RayReconstruction] Model {rr_model!r}: use auto, default, D, E or F")
|
||||
# Backend: which denoiser serves a game's Ray Reconstruction request. dlss (the default) is
|
||||
# NVIDIA's model (Model above); fsr is AMD's FSR Ray Regeneration, followed by Super Sampling.
|
||||
rr_backend = get("RayReconstruction", "Backend")
|
||||
if rr_backend is not None:
|
||||
if rr_backend.lower() not in ("dlss", "fsr"):
|
||||
fail(f"[RayReconstruction] Backend {rr_backend!r}: use dlss or fsr")
|
||||
env["D4R_RR_BACKEND"] = rr_backend.lower()
|
||||
# FSR denoiser tuning: FsrStabilityBias (auto = AMD's default, or a number >= 0) and FsrDetail (the share,
|
||||
# 0-1, of the colour that goes around the denoiser; 0 = off).
|
||||
fsr_stability = get("RayReconstruction", "FsrStabilityBias")
|
||||
if fsr_stability is not None and fsr_stability.lower() != "auto":
|
||||
try:
|
||||
if float(fsr_stability) < 0:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
fail(f"[RayReconstruction] FsrStabilityBias {fsr_stability!r}: use auto or a number >= 0")
|
||||
env["D4R_FSR_RR_STABILITY_BIAS"] = fsr_stability
|
||||
fsr_detail = get("RayReconstruction", "FsrDetail")
|
||||
if fsr_detail is not None:
|
||||
try:
|
||||
if not 0 <= float(fsr_detail) <= 1:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
fail(f"[RayReconstruction] FsrDetail {fsr_detail!r}: use a number from 0 to 1")
|
||||
env["D4R_FSR_RR_DETAIL"] = fsr_detail
|
||||
fsr_denoiser = path_value("RayReconstruction", "FsrDenoiser")
|
||||
if fsr_denoiser:
|
||||
env["D4R_FSR_RR_DLL"] = fsr_denoiser
|
||||
|
||||
age = get("Latency", "FrameAge")
|
||||
if age is not None:
|
||||
@@ -162,6 +190,7 @@ def main(argv):
|
||||
if value is not None:
|
||||
env[var] = "1" if value else "0"
|
||||
value = get("Interop", "MarkerPollUs")
|
||||
env["D4R_MOTION_THIN_SKY"] = "1" if flag("Interop", "MotionDilationThinSky") else "0"
|
||||
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")
|
||||
@@ -213,6 +242,11 @@ def main(argv):
|
||||
|
||||
if flag("Debug", "Profile"):
|
||||
env["D4R_PROFILE"] = "1"
|
||||
every = get("Debug", "ProfileLogEvery")
|
||||
if every is not None:
|
||||
if not every.isascii() or not every.isdecimal() or not 1 <= int(every) <= 4294967295:
|
||||
fail(f"[Debug] ProfileLogEvery must be 1-4294967295, not {every!r}")
|
||||
env["D4R_PROFILE_LOG_EVERY"] = str(int(every))
|
||||
if path_value("Debug", "LogDir"):
|
||||
env["D4R_GAME_LOG_DIR"] = path_value("Debug", "LogDir")
|
||||
|
||||
|
||||
@@ -128,6 +128,11 @@ cp -r "$ROCM_RUNTIME/lib" "$STAGE/d4r/rocm/lib"
|
||||
"$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"
|
||||
# AMD FSR Ray Regeneration 1.2 for [RayReconstruction] Backend = fsr: AMD's unmodified denoiser DLL (MIT)
|
||||
if [[ -n "${D4R_BUNDLE_FSR_RR_DLL:-}" ]]; then
|
||||
cp "$D4R_BUNDLE_FSR_RR_DLL" "$STAGE/d4r/amd_fidelityfx_denoiser_dx12.dll"
|
||||
cp "$ROOT/third_party/fidelityfx/LICENSE.txt" "$STAGE/d4r/licenses/FidelityFX-LICENSE.txt"
|
||||
fi
|
||||
if [[ "$VARIANT" != clean ]]; then
|
||||
: "${D4R_BUNDLE_DLSS:?set D4R_BUNDLE_DLSS}" "${D4R_BUNDLE_TEX:?set D4R_BUNDLE_TEX}"
|
||||
if [[ "$VARIANT" == full ]]; then
|
||||
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Runs build/fsr_rr_probe.exe through a Proton build in its own prefix, with a given vkd3d-proton
|
||||
# (d3d12.dll + d3d12core.dll) and AMD denoiser DLL copied next to the exe, as a game install would
|
||||
# have them. Nothing outside APP_DIR and the prefix is touched.
|
||||
# usage: run_fsr_rr_probe_proton.sh PROTON_DIR VKD3D_DIR DENOISER_DLL OUT_DIR [probe args...]
|
||||
# Env: D4R_FSR_PROBE_COMPAT prefix (default ${TMPDIR:-/tmp}/d4r-fsr-rr-probe-compat)
|
||||
# D4R_FSR_PROBE_APP app directory (default OUT_DIR/app)
|
||||
# DXIL_SPIRV_CONFIG passed through; defaults to wmma_rdna3_workaround (gfx11 WMMA path)
|
||||
# D4R_FSR_PROBE_SPOOF=1 report an NVIDIA GPU the way d4r's DLSS games run
|
||||
# (PROTON_FORCE_NVAPI=1 DXVK_NVAPI_GPU_ARCH=AD100)
|
||||
if [[ $# -lt 4 ]]; then
|
||||
printf 'usage: %s PROTON_DIR VKD3D_DIR DENOISER_DLL OUT_DIR [probe args...]\n' "$0" >&2
|
||||
exit 2
|
||||
fi
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
PROTON_DIR="$(realpath "$1")"
|
||||
VKD3D_DIR="$(realpath "$2")"
|
||||
DENOISER="$(realpath "$3")"
|
||||
OUT="$(realpath -m "$4")"
|
||||
shift 4
|
||||
winpath() { printf 'Z:%s' "$(printf '%s' "$1" | tr '/' '\\')"; }
|
||||
|
||||
[[ -f "$ROOT/build/fsr_rr_probe.exe" ]] || "$ROOT/scripts/build_fsr_rr_probe.sh" >/dev/null
|
||||
APP="${D4R_FSR_PROBE_APP:-$OUT/app}"
|
||||
mkdir -p "$APP" "$OUT"
|
||||
cp -f "$ROOT/build/fsr_rr_probe.exe" "$APP/"
|
||||
cp -f "$VKD3D_DIR/d3d12.dll" "$VKD3D_DIR/d3d12core.dll" "$APP/"
|
||||
cp -f "$DENOISER" "$APP/amd_fidelityfx_denoiser_dx12.dll"
|
||||
{
|
||||
printf 'proton=%s\n' "$PROTON_DIR"
|
||||
sha256sum "$APP/d3d12.dll" "$APP/d3d12core.dll" "$APP/amd_fidelityfx_denoiser_dx12.dll" "$APP/fsr_rr_probe.exe"
|
||||
} > "$OUT/run-manifest.txt"
|
||||
|
||||
export STEAM_COMPAT_CLIENT_INSTALL_PATH="${STEAM_COMPAT_CLIENT_INSTALL_PATH:-$HOME/.local/share/Steam}"
|
||||
export STEAM_COMPAT_DATA_PATH="$(realpath -m "${D4R_FSR_PROBE_COMPAT:-${TMPDIR:-/tmp}/d4r-fsr-rr-probe-compat}")"
|
||||
mkdir -p "$STEAM_COMPAT_DATA_PATH"
|
||||
export WINEDLLOVERRIDES="d3d12,d3d12core=n,b${WINEDLLOVERRIDES:+;$WINEDLLOVERRIDES}"
|
||||
export DXIL_SPIRV_CONFIG="${DXIL_SPIRV_CONFIG-wmma_rdna3_workaround}"
|
||||
export VKD3D_SHADER_CACHE_PATH="${VKD3D_SHADER_CACHE_PATH:-$(winpath "$OUT")}"
|
||||
export VKD3D_DEBUG="${VKD3D_DEBUG:-warn}"
|
||||
if [[ "${D4R_FSR_PROBE_SPOOF:-0}" == 1 ]]; then
|
||||
export PROTON_FORCE_NVAPI=1 DXVK_NVAPI_GPU_ARCH=AD100
|
||||
fi
|
||||
printf 'DXIL_SPIRV_CONFIG=%s spoof=%s\n' "$DXIL_SPIRV_CONFIG" "${D4R_FSR_PROBE_SPOOF:-0}" >> "$OUT/run-manifest.txt"
|
||||
set +e
|
||||
"$PROTON_DIR/proton" run "$APP/fsr_rr_probe.exe" "$(winpath "$APP/amd_fidelityfx_denoiser_dx12.dll")" \
|
||||
"$(winpath "$OUT")" "$@" 2> "$OUT/stderr.log" | tee "$OUT/stdout.log"
|
||||
status=${PIPESTATUS[0]}
|
||||
set -e
|
||||
printf 'exit=%s\n' "$status" >> "$OUT/run-manifest.txt"
|
||||
exit "$status"
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Runs build/rr_backend_check.exe through a Proton build in its own prefix, against a portable d4r
|
||||
# folder (d4r.ini, d4r_nvngx.dll, nvcuda.dll, ngx/, zluda/, and amd_fidelityfx_denoiser_dx12.dll or
|
||||
# nvngx_dlssd.dll for the backend under test), with the d4r vkd3d-proton next to the exe.
|
||||
# The GPU is reported as NVIDIA (PROTON_FORCE_NVAPI=1 DXVK_NVAPI_GPU_ARCH=AD100), as d4r's games run.
|
||||
# usage: run_rr_backend_check_proton.sh PROTON_DIR VKD3D_DIR D4R_DIR OUT_DIR [check args...]
|
||||
# Env: D4R_RR_BACKEND (dlss|fsr) and any other shim variable are passed through.
|
||||
# D4R_RR_CHECK_COMPAT prefix (default ${TMPDIR:-/tmp}/d4r-rr-check-compat)
|
||||
if [[ $# -lt 4 ]]; then
|
||||
printf 'usage: %s PROTON_DIR VKD3D_DIR D4R_DIR OUT_DIR [check args...]\n' "$0" >&2
|
||||
exit 2
|
||||
fi
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
PROTON_DIR="$(realpath "$1")"
|
||||
VKD3D_DIR="$(realpath "$2")"
|
||||
D4R_DIR="$(realpath "$3")"
|
||||
OUT="$(realpath -m "$4")"
|
||||
shift 4
|
||||
winpath() { printf 'Z:%s' "$(printf '%s' "$1" | tr '/' '\\')"; }
|
||||
|
||||
[[ -f "$ROOT/build/rr_backend_check.exe" ]] || "$ROOT/scripts/build_rr_backend_check.sh" >/dev/null
|
||||
APP="$OUT/app"
|
||||
mkdir -p "$APP"
|
||||
cp -f "$ROOT/build/rr_backend_check.exe" "$APP/"
|
||||
cp -f "$VKD3D_DIR/d3d12.dll" "$VKD3D_DIR/d3d12core.dll" "$APP/"
|
||||
{
|
||||
printf 'proton=%s\nd4r=%s\nbackend=%s\n' "$PROTON_DIR" "$D4R_DIR" "${D4R_RR_BACKEND:-ini}"
|
||||
sha256sum "$APP/d3d12.dll" "$APP/d3d12core.dll" "$D4R_DIR"/*.dll
|
||||
} > "$OUT/run-manifest.txt"
|
||||
export STEAM_COMPAT_CLIENT_INSTALL_PATH="${STEAM_COMPAT_CLIENT_INSTALL_PATH:-$HOME/.local/share/Steam}"
|
||||
export STEAM_COMPAT_DATA_PATH="$(realpath -m "${D4R_RR_CHECK_COMPAT:-${TMPDIR:-/tmp}/d4r-rr-check-compat}")"
|
||||
mkdir -p "$STEAM_COMPAT_DATA_PATH"
|
||||
export WINEDLLOVERRIDES="d3d12,d3d12core=n,b${WINEDLLOVERRIDES:+;$WINEDLLOVERRIDES}"
|
||||
export DXIL_SPIRV_CONFIG="${DXIL_SPIRV_CONFIG-wmma_rdna3_workaround}"
|
||||
export VKD3D_SHADER_CACHE_PATH="${VKD3D_SHADER_CACHE_PATH:-$(winpath "$OUT")}"
|
||||
export PROTON_FORCE_NVAPI=1 DXVK_NVAPI_GPU_ARCH=AD100
|
||||
export D4R_SHIM_LOG="$(winpath "$OUT/d4r_nvngx.log")"
|
||||
set +e
|
||||
"$PROTON_DIR/proton" run "$APP/rr_backend_check.exe" "$(winpath "$D4R_DIR/d4r_nvngx.dll")" "$(winpath "$OUT")" "$@" \
|
||||
> "$OUT/stdout.log" 2> "$OUT/stderr.log"
|
||||
status=$?
|
||||
set -e
|
||||
printf 'exit=%s\n' "$status" >> "$OUT/run-manifest.txt"
|
||||
grep -E '^(check=|overall=|tonemapped)' "$OUT/stdout.log" || true
|
||||
exit "$status"
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Summarize warm D4R_PROFILE samples without merging feature instances or sizes.
|
||||
|
||||
GPU pass fields and delayed vk_* fields are summarized independently. Their
|
||||
per-line difference is deliberately not calculated; they describe different frames.
|
||||
"""
|
||||
import argparse
|
||||
from collections import defaultdict
|
||||
import json
|
||||
import math
|
||||
from pathlib import Path
|
||||
import re
|
||||
import statistics
|
||||
|
||||
GROUP_FIELDS = ('render', 'output', 'preset', 'quality', 'flags', 'input_wait',
|
||||
'feature', 'native_field', 'native_substitute', 'wire_requested', 'gpu_completion', 'vk_output_mode', 'vk_input_mode')
|
||||
|
||||
FIELDS = ('vk_total', 'dlss_gpu', 'vk_input', 'vk_dlss_wait', 'vk_output',
|
||||
'native_motion_gpu', 'wire_repair_gpu', 'marker_wait', 'pipeline',
|
||||
'throughput_interval')
|
||||
|
||||
|
||||
def summarize(text, min_frame=300, since_clock=None, until_clock=None):
|
||||
groups = defaultdict(list)
|
||||
instance = 0
|
||||
for line in text.splitlines():
|
||||
if 'NVSDK_NGX_D3D12_CreateFeature(feature=' in line:
|
||||
instance += 1
|
||||
if 'D4R_PROFILE frame=' not in line:
|
||||
continue
|
||||
if since_clock is not None or until_clock is not None:
|
||||
clock = re.search(r'^\[\s*([0-9.]+)\]', line)
|
||||
if clock is None:
|
||||
continue
|
||||
seconds = float(clock[1])
|
||||
if since_clock is not None and seconds < since_clock:
|
||||
continue
|
||||
if until_clock is not None and seconds > until_clock:
|
||||
continue
|
||||
values = dict(re.findall(r'(\w+)=([^\s]+)', line))
|
||||
if int(values['frame']) < min_frame or values.get('reset') != '0':
|
||||
continue
|
||||
key = (instance, *(values.get(k, 'unknown') for k in
|
||||
GROUP_FIELDS))
|
||||
groups[key].append(values)
|
||||
result = []
|
||||
for key, samples in groups.items():
|
||||
row = dict(zip(('feature_instance', *GROUP_FIELDS), key))
|
||||
row.update(samples=len(samples), first_frame=int(samples[0]['frame']), last_frame=int(samples[-1]['frame']))
|
||||
row['timings_ms'] = {}
|
||||
for field in FIELDS:
|
||||
values = [float(s.get(field, '-1')) for s in samples]
|
||||
valid = [v for v in values if math.isfinite(v) and v >= 0]
|
||||
row['timings_ms'][field] = (dict(n=len(valid), median=statistics.median(valid),
|
||||
min=min(valid), max=max(valid)) if valid else None)
|
||||
result.append(row)
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('log', type=Path)
|
||||
parser.add_argument('--min-frame', type=int, default=300)
|
||||
parser.add_argument('--since-clock', type=float, help='minimum bracketed log-clock seconds')
|
||||
parser.add_argument('--until-clock', type=float, help='maximum bracketed log-clock seconds')
|
||||
args = parser.parse_args()
|
||||
print(json.dumps(summarize(args.log.read_text(errors='replace'), args.min_frame,
|
||||
args.since_clock, args.until_clock), indent=2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in new issue
Block a user