Profile 4K ambient occlusion cost with Wayrender
Capture the current PRK.Client with Wayrender using local .env authentication without exposing secrets. Establish matched stationary 3840x2160 AO Off/Low/Medium/High measurements, inspect GPU regions and draw/dispatch state, and trace dominant costs to renderer/shaders. Preserve capture overhead, warmup, workload and hardware limitations. User now authorizes implementation of a reusable offline benchmark system before AO optimization, in isolated worktree /home/mathias/Projects/worktrees/engines-ao-estimation on perf/ao-estimation. Preserve main checkout and its untracked captures. Benchmark location: playfield567 Newland, Earsnest Forest, game coordinates997.2,375.8,height32.4 (verify conversion to renderer XYZ from existing code). Reuse existing --offline scene loader, screenshot capture and --profile-out instead of a parallel harness. Establish explicit scene/camera/hour/resolution/features, warmup, reproducible animation/loading controls where supported, baseline/candidate ordering, manifests with build/shader/settings identities, built-in profile export and separate Wayrender runs. No game login or credentials. Offline benchmark implemented in Tools/ClientBenchmark/{benchmark.py,newland.json,README.md}. Adds developer-only --profile-size and --profile-static, isolated preference root, settled-world readiness followed by explicit warmup, fixed simulation/render deltas, fixed developer hour and camera, actual output/settings metadata, and export failure exit status. Reuses existing offline scene/profile/screenshot paths and native Wayrender target/range tooling. Runner records fixture, source/patch/runner/build/shader identities, optional Vulkan/driver/compiler inventory, CPU/GPU summaries, and workload invariants; supports reversed baseline/candidate order, AO/foliage modes, separate screenshot/debug-view and targeted Wayrender runs. Failures and changing counters reject comparisons. Linux process-group timeout cleanup is implemented. Initial actual screenshot caught offline world entering login-orbit scene despite loading Newland; fixed ScreenDerivation to keep offline sessions InGame. New camera-routing regression failed before fix (expected InGame, got Login) and passes after. Initial size/readiness/workload checks correctly rejected wrong-size/no-grass and changing-counter runs rather than accepting them. Verified screenshot /tmp/ao-benchmark-visual-03/01-baseline-High-Thin/scene.png shows dense grass/trees at native4K; camera is explicitly 1.6m above supplied feet position, yaw0/pitch-15, fixed hour14. Six fresh-process 600-frame diagnostics with order Thin/ReceiveOnly/Solid then reverse all pass with exactly identical workload counters:ready43385,candidates10120,submitted3554,scene729,reflection3284,transparent2557,triangles5239126,groundcover2377,AO681draws/8dispatches. Per-run estimator medians ms:Thin3.81044/3.81916;ReceiveOnly1.89190/1.85590;Solid1.91644/1.91168. Diagnostic modes change appearance and demonstrate custom thin path overhead (~1.9ms), not an equivalent-quality optimization. Four A/A control runs baseline/control then control/baseline (same executable) all pass counters; baseline medians3.80692/3.86980 versus control3.86756/3.87982ms (~0.9% difference between across-run medians with no implementation change), so small timing gains need stronger evidence. AO-Off control /tmp/ao-benchmark-off-01 passes and retains matching base workload; AO counters0 and expected triangle drop. Two targeted Wayrender runs pass with complete9-stage sibling counts,632retained intervals,no warnings,clean shutdown,statistics disabled. Final artifact /tmp/ao-benchmark-wayrender-final/01-baseline-High-Thin/trace.wrtrace:600-frame median/p95 explicit AO4.79964/4.96880ms,estimate3.79862/3.96996,geometry.62236/.63108,depth.10908/.11024,denoise.26204/.26776. Final built-in estimate3.79910/3.97044ms. Native trace and built-in frame IDs are not exactly correlated; instrumentation suites remain separate. CPU validation:client4612passed/42skipped,graphics741passed/1skipped; developer and production Release builds pass with warnings-as-errors, zero warnings/errors; Python syntax and git diff --check pass. Main checkout untouched except existing captures; worktree changes uncommitted. Final timing artifact follows removal of unnecessary per-frame camera Resize; all measurements remain controlled static managed Release developer runs on RX9070, not production Native AOT/gameplay or broad hardware validation. Estimator experiments now authorized and in progress. Immutable baseline copied to /tmp/ao-estimation-experiments/baseline (estimator SPIR-V SHA2569a5bdbc74f58c0fba1d2984876b8229ea0655a4262f67af5e0be2ac36759ae39). Completed reversed 30s/600-frame diagnostics show baseline3.88948/3.88912ms versus mask-only3.61060/3.60762ms; mask-only keeps sample/mask construction alive via output blue but removes integration. Subsequent baseline3.88898/3.80750, angles-only3.59308/3.59592, normals-only3.58242/3.58330ms. Valid single-pass settled screening: baseline3.87034,distance-only1.92002,depth-only1.89620,tile16x4 remap4.09766,tile32x2 remap4.17288ms. All completed valid runs retain the same workload counters; diagnostic images intentionally differ and their stage differences are approximate compiler-sensitive cost isolation, not equivalent-quality gains. These results point strongly to the scattered per-sample thickness fetch, not bitmask integration, as dominant overhead. Pixel remapping variants regress and are not being adopted. Short10s warmup screening changed counters and was rejected/stopped; retained fixture remains30s. Horizon-clip screening failed on temporary-storage quota and has no usable timing. PI then crashed; recovery verified no benchmark/build process remained and found packed candidate copy incomplete. Removed only generated duplicated diagnostic runtimes, preserving shader/SPIR-V artifacts and profiles; kept immutable baseline. /tmp usage fell13GB→7.8GB. Further candidate bundles and results use ignored worktree .dev-data/ao-estimation on disk. Packed-thickness prototype modifies AmbientOcclusionRenderer plus ao_depth_compute/ao_main_compute: depth mip0 packs2x2 existing RGBA8 normal-alpha bytes into RGBA channels of existing denoise scratch; estimator samples packed scratch instead of full normals for thickness; scratch is reused by denoise after explicit write/read/write dependencies. No additional AO images or image-byte allocation, and no sample-count/resolution/radius/filter or optional format-capability changes. Extra descriptor metadata is outside the image-memory claim. Adds second storage binding7; existing descriptor pool capacity remains sufficient. Build passes zero warnings/errors. First whole-image A/A check exposed random procedural clouds and reflected sky despite frozen time (1,764,159 changed pixels); this was not accepted or cropped away. Skybox now accepts an optional procedural seed; only static-profile startup passes seed0 to independent cloud/star/front-end streams, leaving normal gameplay unseeded. Actual seed is exported and the runner rejects unseeded static profiles. Rebuilt both immutable baseline and packed bundles with the exact same seeded client DLL while retaining baseline versus packed renderer/shaders. Seeded 3840x2160 High visibility images are byte-identical for A/A and A/B across all decoded RGBA pixels. Initial Vulkan validation passed; a second baseline/packed validation suite using VK_LAYER_VALIDATE_SYNC=1 and VK_LAYER_SYNCVAL_SHADER_ACCESSES_HEURISTIC=1 also passed with no VUID/synchronization errors or validation warnings. These are separate non-performance runs; existing layer shader-access heuristic limitations remain. All Low/Medium/High 801x601 AO-debug image comparisons also have zero changed pixels, including half-resolution Low and odd borders. All twelve 4K normal-shading timing runs pass and preserve identical per-tier workload counters. Across two reversed-order per-run medians (600 completed GPU frames/run,30s warmup), baseline→packed estimator ms:Low.32599→.26968(-17.3%),Medium1.97144→1.62522(-17.6%),High3.82611→3.08837(-19.3%). Inclusive AO total:Low1.18652→1.15041(-3.0%),Medium2.93813→2.62892(-10.5%),High4.83038→4.12630(-14.6%). Packing adds~.022ms to depth preparation and is included in the net gain. Main command-buffer Frame GPU median High11.13358→10.52505ms(-5.5%), excludes shadow command buffer and is not end-to-end FPS. Low Frame8.62444→8.62073ms is within variability; no meaningful Low whole-frame gain claimed. Scene time differs slightly; clocks/cache causes remain unmeasured. Candidate bundle .dev-data/ao-estimation/bundles/packed-thickness. Whole-image decoded RGBA comparison utility added at Tools/ClientBenchmark/compare_images.py (Pillow); self-equality and exact one-pixel/one-byte detection checks pass. Seeded bundles live at .dev-data/ao-estimation/bundles/{baseline-seeded,packed-seeded}; image artifacts at images-high-seeded with zero-difference reports; validation artifacts at validation-shader-access. CPU suites after the prototype/seed fix:client4612passed/42skipped,graphics742passed/0skipped. Completed separate targeted Wayrender High cross-check at wayrender-high:baseline→packed estimator3.80610→3.07806ms and explicit AO sibling sum4.80686→4.10598ms, clean shutdown/no warnings/complete600-frame ranges with1+5+1+2 stage counts. Targeted timing scopes contain no dispatch snapshots when queried, so no captured descriptor-introspection proof claimed. Existing 4K Medium Vulkan resize/rollback/shutdown cases all4passed for1/3frame slots, with sync/shader-access validation settings. Final production Release build passes zero warnings/errors; all three estimator SPIR-V tiers plus depth shader compile and pass spirv-val (depth capabilities only Shader/ImageQuery). Seeded AO-Off control baseline/packed both pass identical counters,0AOdraws/dispatches and absent GPU AO phases;Frame8.43916/8.44198ms, within variability. Full-source/header benchmark instructions and whole-image comparison utility remain in Tools/ClientBenchmark; no comments/RE-derived content introduced. User requested a pull request excluding the benchmark and excessive test coverage. Prepared clean worktree /home/mathias/Projects/worktrees/engines-ao-thickness-pr on perf/pack-ao-thickness from freshly fetched origin/develop9782ee6c7. Only AmbientOcclusionRenderer.cs, ao_depth_compute.glsl and ao_main_compute.glsl are included; all benchmark/offline-viewer/sky-seeding/test changes remain local in the original perf/ao-estimation worktree. Commit3615b474e (perf: Pack ambient occlusion thickness into scratch storage), pushed with upstream origin/perf/pack-ao-thickness. Isolated PR validation:production Release build zero warnings/errors; existing client4617passed/42skipped;graphics741passed/1skipped;four existing Vulkan resize/cleanup cases passed with sync/shader-access settings;git diff --check passes. No test or benchmark files added to the PR. Final machine-readable evidence and copied build/test logs: .dev-data/ao-estimation/verification/summary.json; immutable seeded bundles and performance/image/validation/Wayrender suites retained alongside. Screenshot timing is excluded. Validation is limited to this static scene on RX9070 managed Release; other GPUs/platforms, production Native AOT, dynamic gameplay and broad resolutions remain untested. Odd-size image runs are fidelity checks, not small-resolution performance claims. This completes the controlled profiling/initial optimization round, not broad release approval. Verify actual offline rendering and workload consistency before using performance comparisons; diagnose missing determinism rather than hiding it. Retain an estimator change only after baseline-image stability, equivalent AO output, matched repeated total-pipeline timings, all-tier/odd-extent checks and Vulkan validation pass; otherwise revert the candidate while preserving findings. User supplied /tmp/captures/trace_07_11_22_07.wrtrace for read-only analysis with /home/mathias/Projects/wayrender/target/release/wayrender. Trace: clean shutdown, no dropped events, 510 frames over ~38.05 s, RX 9070 RADV GFX1201, Debug/net10.0 client, High estimator hash aa6d1ed77ec427a2. Geometry extent 3840x2160 and estimator dispatch 480x270x1 with current 8x8 source confirm native 4K. Full-capture averages mix startup/loading and workload variation; use final 60 frames (451–510, ~4.42 s) for relatively stable timing, not a claimed stationary matched benchmark. Medians/p95 ms: geometry .76612/.77460; five depth dispatch labels summed per frame .12102/.12376; estimator 1.97838/1.99528; two denoisers summed .40114/.40828; explicit nonoverlapping AO label sum 3.26616/3.29032. Median queue GPU work 11.56524 ms. These completion intervals include adjacent synchronization and capture perturbation, not isolated utilization or end-to-end latency. Frame 300 geometry event1684/scope8:1851 draws,1,956,020 input triangles,2,882,429 vertex invocations,18,904,761 fragment invocations (not unique pixels). Full draw inventory: static952draws/177376triangles, grass420/1670400, animated479/108244; grass ~85.4% input triangles, not measured time attribution. Current source estimator has18 nominal depth samples/pixel (~149.3M at4K before rejection), thin coarse-depth fallback to mip0, additional normal/thickness reads and angle/mask work, and up to32 occupied sectors per side/slice in variable-length cosine-weighted integration. Shader-level bottleneck (ALU/memory/divergence) remains unmeasured. Source match was initially unestablished; subsequent v5 capture closes this gap as detailed below. Denoisers each read9 AO plus5 normal/material texels per native pixel in source. AO prepass repeats static/grass/animated geometry; native main shading additionally samples AO outside the explicit scopes. No Off control in supplied capture; no causal total AO overhead or optimization speedup claimed. New user capture /tmp/captures/trace_07_11_23_30.wrtrace (v5):1280 frames, clean shutdown,0 dropped events,no warnings, Debug RX9070, work instrumentation with pass statistics. New dispatch inspection confirms pipeline43541c3d99e0599a, shaderaa6d1ed77ec427a2,8x8x1 local size,480x270x1 groups,8,294,400 invocations, no specialization, push0. Image descriptors complete:4K D32 depth, RGBA8 normals, five-mip R32 depth pyramid, RGBA8 output. Captured shader exported to /tmp/ao-captured-aa6d1ed77ec427a2.spv, passes spirv-val; current source compiled with3/3 defines is byte-identical (SHA2569a5bdbc74f58c0fba1d2984876b8229ea0655a4262f67af5e0be2ac36759ae39). SPIR-V confirms variable-length thin-mask integration with FindILsb and arc trig, but this is not driver ISA, occupancy or runtime instruction profiling. Native range tool successfully aggregates9 sibling AO labels without parent overlap and reports complete60/60 samples. Frames1221–1280 median/p95 ms:geometry1.07314/1.08152,estimate3.73612/4.37884,depth.15966/.16332,denoise.39820/.55264,totalAO5.37290/6.16496. Tail varies substantially (AO4.46056–6.18448ms); not a stationary benchmark. Longer ranges:401–600 totalAO4.063/4.32312,estimate2.68270/2.83820;1001–1200 totalAO5.56938/6.02784,estimate3.94182/4.25760. Last17frames totalAO6.15456/6.18448,estimate4.37080/4.38456, too short for benchmark claims. Frame1250 geometry932draws,1,624,262input triangles,29,263,989fragment invocations, versus previous frame3001851draws/18,904,761fragment invocations; draw counts alone do not establish equal workload. Shader identity matches previous capture; scene/workload and scheduling cause remains unisolated, no regression claimed. Updated Wayrender cannot read prior v4 trace (unsupported binary container version), so native cross-capture compare failed; prior recorded results remain available, not a matched comparison. No Off or Thin/Solid diagnostic controls, GPU clocks or hardware bottleneck counters available. New artifacts /tmp/ao-new-*.json and /tmp/ao-captured-*.spvasm. Next: matched stationary Release Off/High control and diagnostic Thin/ReceiveOnly/Solid estimator comparisons with unchanged geometry, then shader-level profiling and image-validated candidate experiments. Raw inspect JSON and summaries saved under /tmp/ao-*; no repository files changed. Acceptance: evidence-backed pass breakdown and matched AO-disabled control, or concrete capture blockers documented. Pull request #3021: https://git.project-rk.com/prk/engines/pulls/3021 — perf/pack-ao-thickness → develop. Opened with the optimization only; benchmark and test additions excluded. Existing completion state is unchanged.
Checklist
4 of 4 complete- Capture settled matched 4K AO-enabled and AO-disabled controls with hardware/settings metadata.
- Inspect dominant regions and draws/dispatches, relate costs to source, and report verified findings and limitations.
- Implement and validate reusable login-free Newland benchmark with fixed workload settings, built-in profiling, Wayrender capture and comparison manifests.
- Evaluate equivalent-quality thin-foliage estimator candidates using the validated offline fixture, alternating matched timings and AO/debug-image comparisons; retain only verified improvements.
- Area
- Project Rubi-Ka
- Project
- engines
- Kind
- Research
- Task ID
tsk_yex422vbzv- Updated