Repository navigation
Improved CPU timing with async thread - #6
breno-assis wants to merge 4 commits into
Conversation
- Introduced multi-threading support in draw_ids.h for non-blocking GPU timestamp spans, including new methods PrepareBegin and PrepareEnd to manage preparation of draw IDs. - Updated the Forget method to include a preparation wait to ensure thread safety. - Enhanced performance tracking by adding new tick counters for various preparation stages in draw_ids.h. - Modified the DidPrepare method in motion_vectors.cpp to utilize the new PrepareBegin and PrepareEnd methods, improving clarity and separation of concerns. - Updated the DidStatsTag function in inject.cpp to report detailed CPU timing metrics for preparation stages. - Adjusted motion_vectors.h to include flags for tracking preparation state, ensuring proper synchronization between preparation and execution phases.
…ved rendering accuracy
- Introduced `xr_hook.h` to manage OpenXR swapchain image releases and provide a callback mechanism for D3D11 textures. - Implemented functions for tracking view poses and overlay parameters, enabling VR tuning panel and FPS box as OpenXR quad layers. - Enhanced diagnostics for swapchain releases and view corrections. - Updated `drawid_harness.cpp` to include new VR model shadow tests with union clipping for both eyes. - Added support for new configuration options related to consensus failure tolerance and VR model shadow initialization.
|
Hi @breno-assis, thank you for this PR!!!! You are credited as co-author on the commit (e5db8ff) and in the README’s thanks line. The test build with it is here, if you want to try it: PR did not merge as it stands. What I found when reviewing and running it:
The version in the mod adds owned references, hooks on ClearState / ExecuteCommandList / SwapDeviceContextState, a check that the hooked entries still point at our detours, a drop on another thread’s Set, and a verify mode (did_shadow_verify) that compares every Nth record with the getters: 6490 compares, 0 mismatches in a VR drive. The harness passes 136,840 / 136,840 with it on. Check the latest version.... If you spot something I got wrong in the rewrite, please let me know. Many thanks for spending your time helping here :) |
…cheaper draw-id record, GPU-per-pass timing
All tested in ETS2 VR on 2026-10-11 (RTX 5090, 9950X3D, Virtual Desktop). New features are OFF by default;
the mod behaves as v0.10.3 unless dlaa.ini or the tuning menu switches them on.
- phase 30 + 33: Turbo mode (xr_hook.cpp "TURBO MODE", ini xr_turbo = 0, menu row "Turbo mode (VR)"). Async xrWaitFrame
ported from OpenXR Toolkit (MIT, THIRD_PARTY.md). 33 rewrote it for ETS2's split threads (wait/begin on the main
thread, end on the render thread): no 1-s freeze at switch-on, clean switch-off. Tested: 0 failures, no fps gain when
GPU-limited (100 % scaling + DLAA). Also OpenXR session / event logging ("started by the GAME / RUNTIME").
- phase 31: CPU profiler cpu_prof.h ("CPU prof" line per thread every 10 s, ini cpu_prof = -1 follows debug); log.h
writes on a writer thread; OFXR rescan off-thread; PollKeys reads each key once. Mod CPU on the render thread measured
~2-2.5 ms/frame (not the ~3.5 ms estimated before).
- phase 32: cpu_pin.h, ini cpu_cache_pin: keeps the game on the V-Cache CCD of mixed-L3 X3D CPUs. Default 0 (OFF, opt-in):
no fps gain was measured in an A/B, so a mod must not change process affinity on its own.
- phase 34 + 34b: VRS fixed foveated rendering (vrs.cpp, NVAPI via external/nvapi, MIT; ini vrs = 0, vrs_inner / vrs_outer /
vrs_quality / vrs_debug; menu rows "Foveated (VRS)" + "Foveated size"; CMake WITH_VRS auto when external/nvapi exists).
Coarse 2x2 only inside the game's world G-buffer + forward binds; cut-outs, SV_Depth writers and the mod's own passes
stay full rate. 34b: the eye of a bind is learned from the blit-RT cycle (the eye order flips every 3rd frame), full
rate when unsure. Tested: 0 eye misses, sharp centre OK, gain only ~0.5 ms GPU per frame.
- phase 35: did_shadow (draw_ids.h DidShadow, ini did_shadow = 1, did_shadow_verify = -1): the draw-id record copies
IA / VS / RS state from hooked Set calls instead of ~10 getters per draw; dropped on ClearState / ExecuteCommandList /
SwapDeviceContextState, another thread's Set, or a vtable entry that no longer points at the detour; verify mode compares
every 64th record with debug = 1. Tested: 6490 verifies, 0 mismatches, did-rec ~130 -> ~105 ns/draw. Idea from
pull request JRDevo#6 by Breno Assis, rewritten with owned references and the re-verification above. Harness S19.
- phase 36: gpu_pass.h "GPU per pass" line (shadow / gbuffer / lighting / forward / post / mirror / other ms per frame,
measurement only, with debug = 1). First numbers: lighting ~4 ms, mod GPU alone ~3-6 ms per frame (both eyes).
- docs: README (Turbo / Foveated rows, dlaa.ini table, build with external/nvapi, third-party table, thanks to Breno Assis),
THIRD_PARTY.md (NVIDIA NVAPI MIT, OpenXR Toolkit MIT), docs/dlaa.ini.sample.
- tests/drawid_harness.cpp: S19 did_shadow = 1 | 2. Harness 136840 / 136840 passed at this commit.
Co-authored-by: Breno Assis <breno.assis@outlook.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Summary
Improve stability of the per-draw motion-vector path in VR-heavy city scenes by reducing render-thread disruption in the draw-id pipeline.
This change:
The goal is improved timing stability and less noticeable CPU hitching in dense VR scenes, even where average CPU cost does not drop dramatically.
Observed Issue
In VR, especially in dense city scenes with lots of traffic and geometry, the per-draw motion-vector path could introduce noticeable CPU timing instability. The issue was less about one large average cost and more about where the work landed on the render thread and how uneven that cost felt during play.
What Changed
Validation Notes
Runtime logs confirm that the shadowed record path is active:
Measured results suggest:
Testing
Tested on:
Scenario: