Implement properly integrated ambient occlusion in PRK.Client
Implementation authorized. Work in /home/mathias/Projects/worktrees/engines-client-ambient-occlusion on feature/client-ambient-occlusion. User-requested baseline checkpoint committed as 76385892c (feature: Add ambient occlusion with live quality controls); baseline checkpoint is preserved. Optimization committed as 5a8e34cde (perf: Skip zero-weight foliage occlusion samples), containing zero-falloff foliage rejection and the Vulkan optimization-regression/A-B harness. User accepts current performance for now; AO worktree is clean. Baseline implementation remains 76385892c. Pull request #2650: https://git.project-rk.com/prk/engines/pulls/2650 — feature/client-ambient-occlusion → develop, pushed at 5a8e34cde. Merge simulation against origin/develop 6cc9f7da9 succeeds. Static patch review inspected all 47 diffs but hit its context budget on dependency follow-up; no verified findings does not constitute a clean approval. PR description preserves validation limits, including sequential multi-instance Vulkan abort and untested platforms. User requests removal of one-off GPU/end-to-end verification scaffolding from the PR, retaining fast deterministic CPU regressions and the pre-existing Vulkan/CI coverage. CI inspection confirms new default AO/grass GPU readbacks require shader assets not configured in the headless Release job. Remove those new harnesses and restore prior lifecycle/context tests rather than adding skips or broader CI setup. License and verification-scaffolding cleanup completed and pushed in 4cfe9bb1d and 73c4a7e03; PR #2650 updated. One-off AO/grass GPU readback, A/B benchmark and live-quality harnesses removed, existing lifecycle/context tests restored exactly to pre-AO baseline, deterministic CPU regressions retained. Canonical license texts moved to PRK.Client/Licenses; package and client export general licenses/ with XeGTAO and all audio/dependency notices. Package recipe, rebuildable recipe defaults, publish mapping/guard and docs updated. Verification: CPU suite 3655 passed/52 skipped; headless Release lavapipe Vulkan suite 13 passed (rerun after cleanup); CMake packaging/exported-recipe configuration and managed linux-x64 Release publish passed with warnings as errors. All four relocated license texts byte-identical; all ten packaged notices match published output and have unique resolved publish destinations; obsolete exports absent; missing XeGTAO rejected by publish guard. Merge simulation against fetched origin/develop succeeds; worktree clean. No new AOT publish or full window-suite rerun for this follow-up. Broad hardware/scene acceptance gaps remain open. Supplied partial-review findings addressed and pushed in 7ae721795 (release precompilation) and d1988f39d (unchanged-settings fallback); PR #2650 has a follow-up summary and validation comment. Both release precompilers now emit default compute, all three estimator tiers and AO/geometry graphics artifacts into publish output. Windows build variants are grouped into all/default, graphics-only and estimator-only sets. GraphicsOptionsModel prepares unchanged AO using the latest running quality (wired from Engine.RenderFeatures), preserves saved/overridden preferences, and still passes explicit AO changes through normal validation. Added four deterministic CPU cases; both saved-High and overridden-High fallback cases failed before the fix and pass afterward. Extended the existing RequiresInstall published-shader test rather than adding GPU/end-to-end harnesses. Verification: final CPU suite 3659 passed/52 skipped; production Release build zero warnings/errors; Bash and PowerShell release scripts executed on Linux with real glslc and generated the same 174 artifacts byte-for-byte; existing published-shader load test passed without recompilation. MSBuild source groups select 31 default/28 graphics/1 estimator source; actual PrecompileShaders target executed with Windows-host evaluation on Linux and a compiler invocation recorder:174 calls versus279 previously, exactly three quality-estimator calls, zero calls on incremental rerun. No native Windows/macOS build, runtime or GPU validation was performed. Automated follow-up review was unavailable because the review tool selected the main worktree rather than this uncommitted worktree; no independent review approval is claimed. AO worktree is clean and synchronized with origin/feature/client-ambient-occlusion at d1988f39d. Review remains partial and is not release approval. Experimental compiler, gather, arithmetic and mask-integration variants remain in /tmp and are not included in the checkpoint. Implement ambient occlusion as a first-class Vulkan rendering feature, not a final-colour darkening overlay. Original profiler worktree remains untouched. AO worktree is now rebased onto origin/develop bbbf3cba3, including the released developer profiler. Uncommitted AO changes were preserved and reapplied; a backup stash remains available. AO CPU/GPU timing and draw counters are integrated into the profiler; Scene GPU time includes material AO sampling. HDR work is deferred and will restart later; no coordination with or dependency on that branch. Initial inspection: RendererVulkan uses forward scene shading, scene colour/depth copies for translucency, and a final composite pass. RenderTargets owns per-frame sampled D32 depth, but there is no dedicated normal target or AO pass. shader_fragment.glsl currently combines ambient, direct sun, local/probe light and vertex colour before material response, body shadows and fog. AO integration must distinguish indirect light from direct/emissive contributions. Intended approach: establish shared geometry coverage/depth-normal inputs for opaque and alpha-tested static and animated geometry, including terrain and grass; compute GTAO with edge-aware filtering/upscaling and evaluate temporal accumulation only with correct reprojection/history invalidation. Consume AO in linear-light indirect shading before fog/transparency/output conversion, preserving direct and emissive light. Explicitly decide transparency and reflection policy. Reuse render-target ownership, draw streams, shader variants, capability checks and frame retirement rather than creating a parallel renderer. Acceptance: correct Vulkan formats, descriptors, barriers, per-frame ownership, resize/recreation and teardown; consistent geometry coverage across passes; Off/quality options apply live without restarting. Reuse the existing transactional lighting-settings transition to prepare AO resources/shader variants, preserve the old configuration on refusal, and safely release old resources after GPU completion. Debug views; deterministic CPU/shader tests and real Vulkan validation plus indoor/outdoor/animated/foliage/water visual checks; performance is a first-class acceptance criterion across a broad range of platforms while retaining cutting-edge high-end quality. Establish measured CPU/GPU time, bandwidth and VRAM budgets for representative hardware and resolutions before choosing defaults; benchmark the full pipeline cost including geometry inputs, filtering and any temporal work, not just the AO kernel. Provide scalable resolution/sample quality tiers with capability-aware selection, avoid unnecessary copies and synchronization, and ensure AO-only passes/resources are skipped when disabled. Verify measured GPU cost and no visual/performance regression with AO disabled; disclose hardware coverage gaps. Current engine-native compute tiers: Low half-resolution 1 slice/2 steps per side (4 depth samples/AO pixel); Medium native-resolution 2/2 (8 samples); High native-resolution 3/3 (18 samples). All use a five-level FP32 linear-depth pyramid, static Hilbert/R2 angle/step noise and two connectivity-aware denoise passes, with bilateral upsample only for Low. Effective sampling support remains 1.5 m. Default remains Off pending broader performance validation. RX 9070 synthetic-plane timings for the geometry prepass + depth preparation + AO + denoise are Low 0.21/0.73 ms, Medium 0.56–0.58/2.19–2.50 ms, High 0.82/3.16 ms at 1080p/4K. These exclude scene-material AO sampling and are limited synthetic measurements, not representative scene budgets. Native High image memory is approximately 531 MB for three 4K frame slots (FP32 pyramid and RGBA8 AO ping-pong included); memory/format optimization and broad device coverage remain important. CPU tests excluding install dependencies passed before live changes (3552); focused live-settings/configuration tests passed (21), builds pass without warnings. Headless synchronization-validation/readback tests pass across small/odd/1080p/4K extents with 1–3 frame slots. A single hidden X11 renderer passes live Off/Low/Medium/High changes with simultaneous shadow toggles, streamed geometry, resize and cleanup; AO requires no restart. Sequential multi-instance window tests still abort with an invalid physical-device handle and need diagnosis. Construction rollback/shutdown now discard stale deferred debug names exposed by those tests. Foliage now uses finite angular visibility intervals unioned in bitmasks instead of solid horizons, with effective thickness carried in normal alpha and material-aware filtering/upscaling. Solid-geometry horizon behavior remains unchanged. Grass has two-sided indirect probe lighting, root shading combined with ambient AO rather than multiplied, and no root attenuation of direct light; this material correction also applies with AO disabled. Initial uniform 3 cm thickness looked too weak in the user's scene. Current tuning models tuft volumes: 18 cm effective view-ray thickness at roots, tapering to 6 cm at tips. GPU readbacks verify denser roots occlude more than tips, foliage remains weaker than solid walls, and solid-foliage/receive-only diagnostics work. Diagnostic controls: PRK_AO_FOLIAGE_MODE=Thin|ReceiveOnly|Solid and PRK_AO_DISABLE_GRASS_ROOT=true (with AO enabled). Developer and non-developer release builds pass without warnings; current non-install CPU suite passes 3654 tests (52 skipped). Six Vulkan readback/profiler tests and the single-renderer live-quality/resize/cleanup test pass, including compute dispatch counters. GPU coverage includes 1×1/tiny/odd/1080p/4K extents, linear-depth mip readback, thin-footprint flags, planar radiometric invariance, one-pixel foreground/contact preservation, foliage root/tip differences and diagnostic modes. The engine retains resource ownership, transactional settings and profiler integration; obsolete fragment-based AO/filter shaders were removed. FP32 and core storage formats avoid optional half-precision/extended-format requirements. Negative depth magnitude is an explicit PRK metadata encoding for conservative thin coverage; mixed footprints fall back to mip zero to avoid treating grass as opaque geometry. PRK also normalizes against the unobstructed hemisphere to correct view-angle-dependent baseline darkening found by the 1080p tests. These are documented extensions, not a bit-identical XeGTAO port. Intel MIT attribution/license is included. No native dependency was added. Validation uses private asset snapshots after shared output includes disappeared during one run; the rerun passed. User accepts the appearance of the new XeGTAO-style result. Real-scene exported profile analysis: /home/mathias/.local/share/PRK/profiles/profile-20261013-054236-b6901917184842679f4c8f0c0a5d2dd9.json is High; profile-20261013-054257-b6043a5fa62343abae3d54b9a2bcf4c7.json is labelled Off but contains 911 enabled frames (IDs 2548–3458) followed by only 288 Off frames (3459–3746). The first capture contains startup/streaming and a different workload, so the best comparison is within the second capture: last 300 enabled frames versus Off after 20 transition frames. Median AO GPU 5.249 ms (p95 5.513), CPU recording 0.754 ms; timed non-overlapping GPU spans total 9.203 ms enabled versus 5.256 ms Off. Both measured update-to-pacing wall times remain 11.089 ms, with pacing about 6.365 versus 7.263 ms, so apparent minimal FPS impact is paced/capped rather than negligible GPU cost. Scene GPU time rises from 3.129 ms enabled to 4.117 ms Off; clocks/cache effects are hypotheses, not established causes, and scope sums are not whole-frame GPU or presentation measurements. Scene draw count stays roughly 1150 versus 1143; enabling AO adds about 1100 prepass draws and eight dispatches. Render-target active allocation drops by 354309120 bytes (~338 MiB) when Off; no pending owners, allocator creation failures or retry failures in snapshots. Captures are Debug, probes disabled, and omit resolution/quality metadata; quality labels are user-provided. AO timing is now split into geometry prepass, depth preparation, estimation and denoising on both CPU and GPU, with the existing inclusive aggregate retained. Metric indices are append-only; UI labels and exports identify overlap, and GpuMetricParents supports machine-readable exclusion of child spans from totals. Disabled phases remain absent and GPU results stay associated with original frames; no additional fence/query waits are introduced. Eleven focused profiler tests plus three Vulkan profiler/live-settings tests pass. User requests a linux-x64 Native AOT Release development artifact with profiler enabled after validation, and its run command using PRK_OPENAL_LIBRARY=/mnt/games/PRK-NEW/client/libopenal.so.1 and PRK_DATAROOT=/mnt/games/PRK-NEW/client/. Add explicit AllowDevClientPublish=true opt-in while keeping production publish rejection by default; publish to a separate AO worktree .dev-data directory, never overwrite the game install. Publish guard behavior is verified for blocked dev builds, opted-in dev builds and normal production. Published linux-x64 Native AOT Release profiler-enabled artifact at /home/mathias/Projects/worktrees/engines-client-ambient-occlusion/.dev-data/ao-profiler-aot-20261013-0632/. Publish used EnableDevClient=true, AllowDevClientPublish=true and the existing native-audio license/source package; default production publish guards remain verified. Native ELF is 26 MB, full bundle about 50 MB, with profiler layout and XeGTAO attribution; no managed DLL/runtimeconfig/deps files at output root. Precompiled 179 graphics/compute shader artifacts to avoid cold shader compilation in profiles. Executable SHA256: 924bf73bf44d174c8c5d5c6ab849197a67ec291d9ca41e576d80cb7760c147e5. Native CLI startup/argument parsing succeeds with the user's PRK_OPENAL_LIBRARY and PRK_DATAROOT environment; GUI/gameplay of this AOT artifact was not launched. Full non-install CPU suite passes 3655 tests (52 skipped), focused profiler suite 11 tests, and Vulkan query/live-phase suite three tests; live GPU phase spans are positive, contained within aggregate, original-frame-associated, and absent with AO Off. New UI rows are AO Total, AO Geometry Prepass, AO Depth Preparation, AO Estimation and AO Denoising. User confirms all AOT Release quality captures were recorded at 3840×2160 (4K): Off 064721, Low 064730, Medium 064738, High 064746 under ~/.local/share/PRK/profiles/profile-20261013-0647*.json. Native Medium/High evaluate 8,294,400 AO pixels/frame; High has up to 149,299,200 depth samples/frame before boundary/radius rejection. User authorizes estimation optimizations without reducing samples or fidelity. Benchmarked baseline versus candidates with alternating reference/candidate order, identical 4K resolution, all quality tiers, static geometry and final AO/edge readback. Adopted only early rejection of thin samples with zero falloff before normal fetch/backface angle/mask calculations; opaque path remains branch-free and output is byte-identical across 4K plane, solid step and dense-foliage cases for Low/Medium/High. Dense-foliage stress estimation improves about 4–7% in repeated all-tier measurements (Medium ~5.17→4.83 ms; High ~10.53–10.73→10.09–10.15 ms); these stress costs are not representative of the user's ~2.92 ms High game profile. Opaque gains/regressions remain within small-run variability; do not promise a universal speedup. Rejected contiguous-run mask integration (maximum integral error ~1e-6 but no speed gain), constant-weight lookup (no reliable speed gain), loop hints (no extra gain), blanket -O (rare final byte changes up to14), scalar arithmetic reassociation (up to2) and native gather rewrite (initially promising but not consistently beneficial across all-tier repeats). Compiler strategy/sample counts/resolution/radius/denoise unchanged. Added GPU 65,536 mask/angle comparison plus explicit opt-in all-tier A/B timing/image tests. CPU suite passes3655 (52 skipped), final Vulkan readback/profiler tests7 plus live-settings1 pass; all-tier A/B tests3 pass. Shader-only optimized AOT profiler bundle staged at .dev-data/ao-profiler-estimation-opt-20261013/ using the exact baseline AOT executable (same SHA256) with recompiled Low/Medium/High estimator SPIR-V; original published bundle preserved. New user exports 084707 (Off) and 084738 (High) each contain 1199 pure-state frames, ~13.34–13.37 seconds of retained history, with 1197 completed GPU samples. They validate Off-versus-High overhead, not baseline-versus-optimized improvement. High GPU median/p95: total1.985/1.997 ms, prepass.554/.559, depth.041/.042, estimate1.261/1.267, denoise.108/.108; CPU AO recording.434/.493 ms. Non-overlapping timed GPU sums Off2.168/2.188 versus High4.345/4.389 ms; Scene1.518→1.713 ms. Measured paced wall time stays11.084 ms. Workload between pair is mostly stable (scene847→840draws, transparent703constant; characters13→11), but differs materially from prior captures (about7390ready objects rather than4238). Render-target AO allocation increment is99,491,840bytes (~94.88MiB), much smaller than prior confirmed4K338MiB, while image counts still indicate two slots; resolution or target configuration therefore needs user confirmation before comparing to earlier4K runs. No pending owners or allocator failures. Both are Release/dev; build/shader hash and resolution are not captured. User provided matched dense-scene, stationary 4K captures 085635 (earlier A) and 085729 (later B), both High with 1199 frames/1197 completed GPU samples (~13.34–13.37 seconds retained). User confirms 085635 is baseline and 085729 is optimized; both are the same stationary dense scene at4K. Both have exactly stable workload counters: characters6, ready7799, candidates3677, submitted3262, scene862draws, transparent750draws, triangles5,206,317, AOprepass812draws/eight dispatches; render-target allocations743,060,480bytes/count26 match prior4K configuration. GPU median/p95 A→B: estimation4.844/5.405→4.048/4.257ms, AO total5.978/6.514→5.229/5.499ms, non-overlapping timed GPU sum9.574/9.941→9.089/9.531ms. Later capture estimates ~0.796ms faster (16.4%), AO total~0.749ms faster (12.5%), and timed GPU sum~0.485ms lower (5.1%). Unchanged stages differ: prepass.702→.755ms, Scene2.843→3.133ms, denoise.254→.271ms, so device clocks/background conditions may affect aggregate gain; no cause established. CPU AO~.317→.312ms and paced wall11.096ms unchanged. Real-scene optimization benefit is now user-confirmed: estimation16.4% lower, AO total12.5% lower, timed GPU spans5.1% lower in this matched pair. This validates keeping zero-falloff thin-sample rejection without quality changes; no universal hardware/workload speedup is claimed. Do not compare against different-location/lower-target-memory0847pair or claim 4.08→1.98ms as an optimization result. Histories overlap and contain prior tiers; merged by original frame ID, inferred sustained tier boundaries from distinct estimation-time clusters (quality is not explicitly exported): Off 2188–2961, Low 2962–3665, Medium 3666–4311, High 4312–4424 plus two pending GPU frames. After excluding the first 20 frames of each phase, GPU medians/p95 ms are: Low total 1.180/1.190, prepass .650/.657, depth .124/.130, estimate .288/.291, denoise .103/.103 (684 frames); Medium total 2.845/2.862, prepass .649/.654, depth .122/.124, estimate 1.669/1.677, denoise .386/.392 (626 frames); High total 4.084/4.161, prepass .645/.651, depth .126/.130, estimate 2.917/2.970, denoise .380/.391 (93 frames, only ~1.08 seconds, so tail confidence is limited). Parent-minus-children GPU overhead is ~.015–.020 ms; no double counting was used. AO CPU aggregate is ~.53–.54 ms, of which prepass is ~.525–.536 ms; compute command recording is only ~.004–.005 ms. Workload stays ~30 characters and 1127 scene draws, with High ~29/1119, and enabling AO adds ~1077/1069 prepass draws. All qualities remain at ~11.09 ms update-to-pacing wall time. Timed non-overlapping GPU pass sums are Off4.457, Low6.852, Medium7.727, High8.911 ms; Scene GPU differs by tier, so sums are not precise causal AO overhead. Low Scene median is 4.845 ms versus Medium 4.058 ms and High 4.013 ms; source confirms Low performs depth/normal-guided four-tap upsampling in each shaded fragment while native tiers use a direct AO fetch. This is a plausible measurable Low-tier shading penalty, not yet isolated proof. If optimizing Low, assess dedicated/fused bilateral reconstruction versus repeated forward-shader sampling, with its additional full-resolution target memory tradeoff; compare total Scene+AO cost rather than the AO total row alone. Render-target memory increments versus Off are Low244.15 MiB, Medium/High337.90 MiB; allocator snapshots have no pending owners or creation/retry failures. Highest-priority GPU optimization is the estimation shader (71% of High AO time); inspect arithmetic and thin-mask integration before changing samples or visual response. CPU optimization priority is prepass recording/binds. Depth preparation is already small (~.12 ms), so prioritize neither fusion nor extra complexity there. Compact working/depth formats with safe capability/precision fallbacks remain a separate VRAM optimization. Longer settled High/Release runs and broad hardware tests remain needed. Assess optional compact formats/VRAM and follow with longer settled Release captures. Broad hardware/scene coverage and independent review remain outstanding. XeGTAO-style reimplementation is implemented in C#/Vulkan/GLSL, with no native library or external rendering framework. Adapt the MIT reference at a5b1686c7ea37788eeb3576b5be47f7c03db532c with attribution. Keep the existing geometry/material inputs, transactional live settings and profiler; introduce native engine compute pipelines for linear-depth mip preparation, audited sampling and connectivity-aware denoising. Maintain the current 1.5 m effective sampling support while isolating estimator/filter changes. Preserve foliage as an explicitly tested extension, with material-consistent depth mip sampling. Research basis: Intel XeGTAO (MIT, archived April 2024) provides linear-depth mip prefilter, near-field quadratic sample distribution with independent low-discrepancy angle/step noise, and packed slope-aware cardinal edge connectivity with symmetric denoising. Its High preset is full-resolution 3 slices × 3 steps per side = 18 depth samples/pixel; the former High prototype was half-resolution 4 × 8 × 2 = 64 samples/AO pixel, about 16 samples per native pixel but lower evaluation detail. The native-resolution core is now benchmarked; preserve reference equations/attribution and explicitly test PRK extensions rather than claiming bit-identical behavior. Keep radius/look tuning separate from estimator and filtering changes; current radius is fixed at 1.5 m. AMD CACAO 1.4 is a credible alternate/reference for native/downsampled modes, importance-driven adaptive sampling and bilateral upsample. The visibility-bitmask paper/author code supports finite-thickness occlusion, but the public example uses unweighted sector counts and has no quantitative performance proof; our cosine-weighted solid/thin hybrid is custom and needs independent/reference validation. Reuse material metadata and AO resource ownership, but do not keep tuning constants in place of proper depth hierarchy, sampling and denoising. Temporal AO is optional later and requires trustworthy reprojection/disocclusion handling for characters and animated grass; XeGTAO works spatially without TAA. Ray-traced AO is an optional future tier/reference, not a cross-platform baseline. Primary sources: https://github.com/GameTechDev/XeGTAO ; https://raw.githubusercontent.com/GameTechDev/XeGTAO/master/Source/Rendering/Shaders/vaGTAO.hlsl ; https://raw.githubusercontent.com/GameTechDev/XeGTAO/master/Source/Rendering/Shaders/XeGTAO.hlsli ; https://gpuopen.com/manuals/fidelityfx_sdk/techniques/combined-adaptive-compute-ambient-occlusion/ ; https://arxiv.org/abs/2301.11376 ; https://cdrinmatane.github.io/posts/ssaovb-code/ ; https://github.com/NVIDIA-RTX/NRD . Real indoor/outdoor/animated/foliage/water visual checks, broad hardware/platform coverage, full shading-overhead benchmarks and independent patch review remain outstanding. Do not treat current validation as release approval. A full deferred renderer conversion is not assumed necessary.
Checklist
1 of 3 complete- Isolate implementation in its own worktree and settle pass ordering, lighting separation and hardware-tier performance budgets; HDR work is deferred.
- Implement consistent geometry inputs, GTAO/filtering and indirect-light integration with complete Vulkan resource lifecycle.
- Verify scalable quality controls, shader/CPU tests, Vulkan validation and visual correctness; benchmark full-pipeline CPU/GPU cost and VRAM across representative hardware/resolutions, including AO disabled, and record coverage gaps.
- Area
- Project Rubi-Ka
- Project
- engines
- Kind
- Feature
- Task ID
tsk_mynbvmrb8s- Updated