Queue native Windows DLSS asynchronously and drain feature consumers

This commit is contained in:
Codex committed 2026-10-02 10:00:26 +03:00
1 parent df44d8aeae
commit 0b471be024
13 files changed
+771 -59

No files matched your search

+12
View File
@@ -61,11 +61,23 @@ The recording interval measures NGX calls on the recording thread, not Present.
frame scheduling; use it separately from a production FPS measurement.
`-ProfileCommandHooks` samples one in 64 D3D12 interceptions to distinguish
tracking/lock waits from driver calls. It is disabled in ordinary runs.
`-ProfileCudaApi` aggregates existing CUDA API host durations without adding
HIP events or synchronization. `-UncachedInteropLists` restores per-frame
copy-list allocation for comparison with the normal safely reused lists.
The runner drains stdout/stderr concurrently as raw bytes; the earlier
line-oriented PowerShell collector imposed large per-frame delays. The optional
ZLUDA kernel profiler is for diagnostics only. Measurements and reproduction
commands are in [windows-performance.md](windows-performance.md).
`-AsyncInterop` enables the experimental K scheduling path. Submission queues
the current frame's input/output dependencies and returns while a CUDA worker
executes DLSS. Owned command memory is retained until GPU completion; feature
release and resource reconfiguration wait for pending consumers. It passes
the standalone queued-frame and Release/CreateFeature exact-output regression,
but remains opt-in while game stability and performance are checked. It
currently requires one D3D12 command queue. This switch is independent of
profiling and output scans; omit those diagnostics for a production FPS run.
Ordinary runs use OptiScaler info logging and suppress successful HIP/CUDA API
messages. Errors, GPU identity, imports, frame records and native/translated
kernel launches remain logged. `-VerboseRuntime` enables all API and frontend
+58
View File
@@ -72,6 +72,64 @@ and compiler spill counts. Reports and proprietary workload inputs remain local.
Native FP8 remains a separate optional experiment; the package uses the
validated FP16-equivalent baseline. Its later checks and timings are below.
## K host synchronization and asynchronous submission
Current priority is K performance. The user's synchronous 4K reading is
49–51 FPS / 53% GPU utilization, versus approximately 80+ FPS / 100% with
FSR4. These readings do not identify a CPU hardware limit or provide a
controlled same-scene comparison. M/FP8 optimization is deferred.
ZLUDA candidate `a1c506f` adds `D4R_ZLUDA_PROFILE_API`, enabled by the game
runner's `-ProfileCudaApi`. It measures existing API host durations, aggregates
per thread and logs every two seconds without HIP events or additional waits.
The synchronous control shows five `cuCtxSynchronize` calls per frame with
about 3.9 ms aggregate host time. CUDA launch host overhead is approximately
0.46 ms per frame. Cached copy-list setup is only 0.011 ms median. These host
measurements include GPU waits and must not be added to GPU kernel times.
| K/4K command submission, CPU median | Synchronous | First async | Async without CUDA mutex |
| --- | ---: | ---: | ---: |
| Entire submission, ms | 10.512 | 2.676 | 0.181 |
| DLSS boundary, ms | 10.083 | 2.604 | 0.124 |
| Consumer suffix completion, ms | 0.350 | 0.005 | 0.004 |
The first async game run completes 9481 finite frames; the user reports
60 FPS / 63% GPU. The mutex-free run crashes during feature recreation after
366 finite frames, so its submission timing is not a successful gameplay
benchmark. The standalone burst/recreate reproducer subsequently identifies
caller-owned GPU backing freed after ReleaseFeature returns. Waiting for
pending D3D12 consumers in ReleaseFeature fixes the reproducer: all twelve
sync/async test frames pass, and corresponding RGB outputs are exact. Game
stability and FPS must be checked separately on the fixed build.
The fixed game retest on 2026-10-02 completes 16941 K/4K frames, all finite,
including feature recreation and color-format reimports, with zero backend
failures. The user reports 62 FPS / 63% GPU. Median CPU submission is
0.197 ms, NGX host completion on the worker is 4.400 ms and output validation
is 0.380 ms. The 10.162 ms median worker input wait includes queued game
rendering. These results establish a stable five-minute test of this fix,
not a conclusion about the remaining GPU idle time or FSR4 performance.
`-AsyncInterop` is opt-in. It queues input/output fences on the submission
thread, executes CUDA on a worker and retires owned command memory by GPU
completion. Three copy slots bound outstanding ownership. The queue consumes
the output of the same frame, with no CPU image copy. The worker's input wait
includes its lead behind submitted rendering and is not a CPU submission
stall. Neither that duration nor the NGX recording interval measures Present
latency. Reconfiguration waits for all consumers; ordinary submission does not
hold the CUDA mutex. The experimental runtime currently supports one queue.
```powershell
.\scripts\windows\test-async-k.ps1
```
The test generates fresh synchronous controls, submits three frames without
intermediate CPU completion, and repeats while releasing/recreating the DLSS
feature with work pending. Results include exact RGB comparisons, finite GPU
scans, stdout/stderr, exceptions and runtime provenance. To include the local
validated output-store optimization, pass its combined native directory with
`-NativeRoot`; proprietary objects remain local.
Further game coverage (HIP kernel profiling disabled, GPU output checks enabled):
M at 1920x1080 completes 4833 frames, all finite. K at 3840x2160 completes
4685 frames, all finite. Neither has a backend failure, CPU image copy or an
+81
View File
@@ -10,6 +10,87 @@ explicit limits; the validated package keeps conservative arithmetic.
## Milestone and gates
**Current milestone: K performance remains open.** The user reports 49–51 FPS
and about 53% GPU utilization in 4K Silent Hill 2, compared with roughly 80+
FPS / 100% GPU utilization with FSR4 on this system. Functional K/M and the
reproducible archive do not close this gate. Prioritize K queue scheduling and
host synchronization; postpone further M/FP8 optimization. These user readings
are not a controlled same-scene benchmark. Do not infer a hardware CPU limit
from utilization alone.
The next diagnostics add `-ProfileCudaApi` (ZLUDA patch 0015): aggregate host
CUDA API durations without HIP-event waits. Boundary stages now separate
prepare, copy-list setup, input/output submission and output-copy drain.
Feature-owned input/output command lists and allocators are reused only after
the existing completion fence; `-UncachedInteropLists` restores per-frame
allocation for an A/B control. Submission drain fences/events are queue-owned
and reused. No completion dependency or current-frame output is removed.
The opt-in `-AsyncInterop` experiment reserves D3D12 input/output dependencies
at submission, runs CUDA on a feature worker, and retires owned suffix command
memory on a separate fence-completion service. Worker order is shared across
features using the context; this experimental runtime requires one D3D12 queue.
Three reusable copy contexts bound outstanding ownership. Every consumer waits
for **its own** output; no previous-image selection or CPU image staging occurs.
Steady-state submission uses immutable allocation metadata and per-frame
resource/parameter snapshots, avoiding the CUDA mutex. Resize/reimport and
feature creation/release drain D3D12 outside that mutex, keeping workers able to signal
already-published waits. Worker failures poison the context and are logged.
First async game run: 9481 K/4K frames and finite GPU scans, zero backend failures;
the user reports **60 FPS / 63% GPU**. Median command submission drops from
10.512 ms (synchronous control) to 2.676 ms. The next mutex-free candidate
submits in median 0.181 ms, but its initial game test exits with UE
`DXGI_ERROR_DEVICE_HUNG` during resource/feature recreation after 366 finite
frames. Its crash context and dump are in
`test-results/silent-hill2-k-async-nolock-4k/ue-crash`. Do not classify this as
success or enable the experiment by default until the game reconfiguration gate
passes. The new standalone burst + Release/CreateFeature mode reproduces the
GPU hang without the game. Retaining the d4r Feature through completion does
not retain OptiScaler's caller-owned root-CBV buffers: OptiScaler frees its
shader backing immediately after NGX ReleaseFeature returns. ReleaseFeature
now waits for pending workers, copy contexts and all submitted D3D12 consumers
before returning, outside the CUDA mutex. The fixed four-way regression
(sync/async x burst/recreate) completes twelve K/4K frames; all six async RGB
outputs exactly match their corresponding fresh synchronous controls, with
no NaN/Inf or GPU hang. Results:
`test-results/k-async-release-drain-4k/validation.json`. The fixed game retest
on 2026-10-02 completes **16941 K/4K frames**, 16941 finite GPU scans and
203292 native launches, with zero backend failures/CPU image copies/previous
frame outputs. It includes two feature creations and color-format reimports;
the previous recreation crash does not recur in this five-minute run. The
user reports **62 FPS / 63% GPU** in the comparison scene. Median command
submission is 0.197 ms; DLSS worker NGX completion is 4.400 ms and output
scan is 0.380 ms. Logs:
`test-results/silent-hill2-k-async-release-fix-4k`. The runner deliberately
stops at its bound (`diagnostic_timeout`); there is no recorded game crash.
The K performance gate remains open.
Three ordinary K/4K async frames and three queued together without intermediate
CPU completion all match their corresponding prior synchronous RGB exactly;
the temporal controls differ between frames. One burst attempt times out during
NGX creation before submitting a frame after the game GPU crash; HIP/D3D12
sanity probes pass and the 600-second retry completes and matches all frames.
`test-async-k.ps1` generates fresh synchronous controls and checks burst and
Release/CreateFeature with pending work, rather than depending on saved fixtures:
```powershell
.\scripts\windows\test-async-k.ps1
```
New game crashes are automatically copied from the current Silent Hill 2 UE
crash directory into the diagnostic bundle, including its error reason and
minidump; proprietary/private artifacts remain excluded from public packaging.
The profiling candidate is ZLUDA
`a1c506fc956cfc347c56c44311669700c0d500ac` in
`dist/zluda-windows-api-profile`. Patch 0015 adds optional per-thread host API
aggregates without extra synchronization; ordinary runs leave it disabled.
All fourteen patches (0002 through 0015) apply to pinned base `ee2f25a`.
All sixteen CTest gates also pass with `D4R_ASYNC_INTEROP=1` after the release
fix. The previously archived synchronous package described below remains a
separate artifact; it does not contain this async scheduling change.
Upstream refreshed and merged on 2026-10-01 through
[`f0d1a65`](https://github.com/countervolts/d4r/commit/f0d1a65e27aff6cbe7eeaa13227c80facb9056ab)
and artifact fix `65dfc9f`. Windows retains strict f16 rounding and the exact