handoff(forge): parallel replay + recording A/B on engine a967d12b, occlusion A/B added

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018hSLRwirUk2NF4j1v2kH4Z
This commit is contained in:
ozanandClaude Opus 5.5 committed 2026-10-19 01:10:15 +01:00
1 parent bde94a1bca
commit 431d213451
1 file changed
+14 -5
@@ -1,19 +1,23 @@
# Forge: Windows A/B of parallel draw-list replay (engine 06ecc5df) # Forge: Windows A/B of parallel draw-list replay + recording (engine a967d12b)
Why: Windows sits at 45–50 fps with the RTX 5080 idle. The render thread is the limiter (10–13 ms wall, `end_frame` Why: Windows sits at 45–50 fps with the RTX 5080 idle. The render thread is the limiter (10–13 ms wall, `end_frame`
replay + submit 3.8–4.8 ms). The NVIDIA/WDDM driver path is paid serially on that thread for every `vkCmd*`. replay + submit 3.8–4.8 ms). The NVIDIA/WDDM driver path is paid serially on that thread for every `vkCmd*`.
Engine `06ecc5df` can cut large draw lists into chunks and record them into secondary command buffers on worker Engine `06ecc5df` can cut large draw lists into chunks and record them into secondary command buffers on worker
threads (Vulkan only, **default off**). Design + Mac results: engine `.agents/wiki/parallel-draw-replay.md`. threads (Vulkan only, **default off**). Design + Mac results: engine `.agents/wiki/parallel-draw-replay.md`.
Since then the engine also does **parallel recording** (Forward+ splits a pass's render list over worker threads, each
recording its own slice of the draw list; every driver; default off) — `gpucull record on|off|status`. It attacks the
other half of the render thread (Godot's per-draw bookkeeping before the driver). Same page, § Parallel recording.
Nothing is published or pinned for this yet. This is a test build on Forge only. Nothing is published or pinned for this yet. This is a test build on Forge only.
## 1. Build + oracle (Vulkan, Khronos layer) ## 1. Build + oracle (Vulkan, Khronos layer)
1. `git checkout 06ecc5df` in the engine, build the Windows editor with the `windows-x64` manifest flags. 1. `git checkout a967d12b` in the engine (replay + recording), build the Windows editor with the `windows-x64` manifest flags.
GodotSharp regen is not needed for the test: the game reaches the new API through `Call`. GodotSharp regen is not needed for the test: the game reaches the new API through `Call`.
2. With the Vulkan SDK's validation layer available (`--gpu-validation` turns it on): 2. With the Vulkan SDK's validation layer available (`--gpu-validation` turns it on):
`bash tests/gpu_oracle/parallel_draw_replay/run.sh <tinqs.windows.editor.x86_64.mono.exe> vulkan` `bash tests/gpu_oracle/parallel_draw_replay/run.sh <tinqs.windows.editor.x86_64.mono.exe> vulkan`
Expect `ORACLE: 6 passed, 0 failed`, exit 0, **zero `VUID` / validation lines** in the output. Paste the Expect `ORACLE: 10 passed, 0 failed`, exit 0, **zero `VUID` / validation lines** in the output. Paste the
output back. output back.
## 2. In-game A/B (box otherwise idle, one engine, nothing else running) ## 2. In-game A/B (box otherwise idle, one engine, nothing else running)
@@ -30,13 +34,18 @@ LOG="$APPDATA/Tinqs/app_userdata/Ariki/logs/godot.log"
OUT=.game-cli/replay-windows-$(date +%Y%m%d-%H%M) OUT=.game-cli/replay-windows-$(date +%Y%m%d-%H%M)
ARIKI_API=http://127.0.0.1:4328 python tools/render_thread_profile.py --log "$LOG" \ ARIKI_API=http://127.0.0.1:4328 python tools/render_thread_profile.py --log "$LOG" \
--poses tools/render_thread_poses.json --out "$OUT" --blocks 8 \ --poses tools/render_thread_poses.json --out "$OUT" --blocks 8 \
--states "replay off=gpucull:replay off" "replay on=gpucull:replay on" "replay on 32x8=gpucull:replay on 32 8" \ --states "both off=gpucull:replay off;gpucull:record off" "replay=gpucull:replay on;gpucull:record off" \
--restore "gpucull:replay off" "record=gpucull:replay off;gpucull:record on" "both on=gpucull:replay on;gpucull:record on" \
--restore "gpucull:replay off;gpucull:record off"
``` ```
Also take three `curl -s 127.0.0.1:4328/mainthread` reads with replay off and with replay on (from `e3582841a`). Also take three `curl -s 127.0.0.1:4328/mainthread` reads with replay off and with replay on (from `e3582841a`).
They show which thread paces the frame. They show which thread paces the frame.
Also: `curl -s -X POST 127.0.0.1:4328/command -d '{"command":"occlusion","value":"off"}'` vs `on` at the spawn pose
(5 `/perf` reads each) — the 1.2–1.3 ms "Update Occlusion Buffer" label decides whether CPU occlusion culling earns its
cost now that vegetation is GPU-culled.
Report per pose and state: frame ms, `_draw` wall, `end_frame`, render-CPU labels, fps p25, `/perf Report per pose and state: frame ms, `_draw` wall, `end_frame`, render-CPU labels, fps p25, `/perf
gpucullCounters.parallelReplay` (lists / chunks), pixel diff vs the A/A floor, and the full `results.json`. gpucullCounters.parallelReplay` (lists / chunks), pixel diff vs the A/A floor, and the full `results.json`.