Replace Engine Stats with developer-only client profiler
Build a reusable client profiler, replacing Engine Stats without rendering optimizations. Reuse retained UI/window composition, Vulkan timestamp conversion, renderer counters and allocator diagnostics. Bounded per-frame history with CPU phase timings, separately frame-associated GPU pass results, culling/work counters, memory/resource diagnostics, history graphs, pause/frame selection, baseline comparison and JSON export. Developer instrumentation, UI and assets must be compiled out with existing EnableDevClient/PRK_DEVCLIENT mechanism, including graphics engine; publishing developer builds remains forbidden. Collectors are engine-thread-owned, allocation-free after warmup; GPU results read only after completion without additional waits. Clear measurement semantics (inclusive/overlapping phases, missing vs zero GPU samples, frame interval vs CPU duration, estimated geometry not real triangle counts). Normal development configuration is the baseline; Release is not assumed to be a performance fix. User refined UI requirements: all detail panels use the existing sortable/resizable list-mode UiTable. Remove persistent annotation/caveat paragraphs; retain measurement semantics in tooltips and capture metadata. Memory/resources must use separate numeric values rather than old slash-delimited text: Memory rows with value/unit, Categories with active/pending MiB and counts, Latency with median/p95/max milliseconds, samples and failures. Acceptance: profiler explains CPU phases and scene workload with frame history and inspectable captures; replaced window retains useful existing memory/resource metrics; baseline comparison/export works and bounded history/selection/delayed GPU association have regression tests; production assemblies/assets exclude profiler; developer and production builds and appropriate tests pass. Rendering semantics, sorting, culling policy and GPU resource lifetime remain unchanged. Real UI visual validation without restarting the user's running client or using their gameplay session. Implementation milestone: feature/client-developer-profiler replaces Diagnostics.xml/DiagnosticsPresenter with Profiler.xml and presenter/details/resources/graph components; no rendering optimizations. Engine-thread collector holds 1,200 frames, warmed collection and plotted-history copying allocate zero objects. CPU scopes cover update/profiler UI/render waits/culling/stream/upload/recording/submit/present/pacing; detailed lighting/sort/off-screen near probes are fixed per frame. GPU queries cover shadow/body-shadow/reflection/scene/translucent/composite, read after existing completed slot fence and attached to original frame IDs. Counts separate reflection/effects and real static indexed triangle recordings from legacy estimates. Verified so far: 57 focused developer tests (including numeric resources, frozen history/table behavior, graph-click selection after ring eviction and source-generated export with JSON reflection explicitly disabled); 28 production-gate/related UI tests; two actual Vulkan timestamp tests using container software Vulkan with synchronization validation and no errors. Developer and EnableDevClient=false assemblies build separately under .dev-data/profiler-build; production client output contains no Profiler.xml or deleted Diagnostics.xml, and assembly reflection verifies no profiler types/property. Rendered and inspected CPU/GPU/work/memory/categories/latency previews through real retained GUI/Skia tests; artifacts under .dev-data/profiler-build/dev/bin/PRK.GraphicsEngine.Tests/debug/profiler-preview-*.png. Patch-scoped static review found three material issues, now fixed and regression-tested: graph clicks froze current ring instead of plotted snapshot; VisibleFlags sampled before reconciliation; reflection-based JSON export could fail in dev builds with PublishAot defaults. Fixed with bounded reusable plotted snapshot, post-reconciliation counter sample, and a small typed/source-generated export envelope (not broader AOT profiler support). Review coverage was partial; all three verified findings are fixed with targeted regressions. Final broader run: 196 passed, 20 environment-dependent native-window/original-asset tests skipped, zero failures. Production run: 28 passed, zero failures; software-Vulkan query/synchronization suite: two passed, zero validation errors. Both client and graphics publish guards reject PRK_DEVCLIENT as expected. git diff --check passes. Production client output has neither profiler nor retired diagnostics layout, and production assemblies exclude profiler types. No full native AOT publish, AMD hardware/gameplay profiling, or skipped display/install-asset tests claimed. Final UI refinement verified: clean Profiler title, compact CPU/GPU graphs, no persistent developer/GPU/probe caveat text. Semantics remain in row/header/control tooltips and export metadata. Memory/resources now has three list-mode subpanels with separate typed numeric columns: Memory value+unit rows, Categories active/pending MiB and resource counts, Latency median/p95/max in fixed milliseconds plus samples/failures. Numeric sorting and representative render previews pass. Capture export uses a small typed/generated JSON context and passes with reflection explicitly disabled, without enabling profiler in published AOT builds. Implemented on feature/client-developer-profiler and committed as 9fb6bf3d9 (`feature: Replace Engine Stats with a developer profiler`). PR preparation was paused for user-reported observer overhead: live profiler updates occasionally cost ~12.73 ms, with additional shared UI prepare cost. New acceptance target is under 1 ms p95 for a warmed profiler update on this machine with full 1,200-frame retained history and the normal visible viewport. User approved a zoomed-in default (150 frames), wheel-anchored zoom and drag-to-pan frozen history; tables summarize the visible range and Resume follows newest frames. Preserve raw measurements rather than subtracting incomplete observer costs. Reproduce refresh cost, eliminate frozen redraws and hidden-panel work, batch/downsample graph rendering without hiding spikes or bridging GPU gaps, and benchmark normal development builds. Report presenter and shared GUI/layout/paint boundaries separately; JSON export remains explicit action work. Refresh cost verified: an opt-in full-history Debug benchmark reproduced ~14–15 ms/refresh and ~1.78 MB managed allocation per refresh, including repeated frozen redraws. New bounded double-buffered refresh prepares CPU graph on one callback, then GPU graph and the visible table on the next; images/data publish from the same snapshot. Exact quantiles use reusable spans, labels and baseline summaries are cached, hidden panels are not rebuilt, frozen graphs are not regenerated, and process resident sampling uses Environment.WorkingSet. Graph rendering preserves per-pixel min/max peaks, gaps and full raw history; viewport and pointer selection tests pass. Final local benchmark under concurrent desktop/game load: CPU median 0.8090/p95 0.8904 ms, GPU 0.7003/0.9321, work 0.7328/0.8831, memory 0.5546/0.8592. One max was 1.0888 ms, so no hard real-time maximum guarantee. User live empty-scene capture independently shows Profiler UI p95 0.43/max 0.76 ms. Important separate limitation: user screenshot still shows UI Prepare spikes around 19 ms. Controlled retained-GUI benchmark with original AO skin reproduces paint median 15.60/p95 16.03 ms at 2x scale; layout median ~0.03 ms. Graph-only paint is much cheaper, and a tested transparent-fill shortcut was slower and was not applied. New UI Layout/Paint/Stage/Cursor scopes expose this shared painter cost. No blanket subtraction, GUI renderer rewrite, or claim that end-to-end observer overhead is under 1 ms. The client had exited before an attempted live trace; no live trace was captured. Latest verification: 201 focused developer tests passed with 20 display/asset-dependent skips, 28 production tests and two synchronization-validated software-Vulkan tests passed. Zoom/pan/frozen rendering, exact statistics, and peak/gap preservation have new regressions; the final post-snapshot-copy run passed all 201 focused tests with the same 20 environment-dependent skips. Final refresh benchmark passed the <1 ms p95 budget for every default-viewport panel, with shared-paint limitations explicitly preserved. Branch pushed with a clean working tree. All scoped implementation/checklist criteria are verified. Pull request #2646: https://git.project-rk.com/prk/engines/pulls/2646 Head feature/client-developer-profiler → develop. Open, ready for review and mergeable; no unrelated performance work included. User independently launched the client and supplied live UI feedback; assistant has not driven a gameplay session or modified/restarted that client.
Checklist
4 of 4 complete- Bounded frame collector, statistics, capture comparison/export and exclusion tests verified
- CPU/GPU/culling instrumentation and delayed frame association verified without behavior changes
- Profiler replaces Engine Stats, graphs and controls validated; developer/production builds pass
- Profiler update p95 below 1 ms with full retained history/default viewport; frozen/hidden work, zoom/pan, exact statistics and graph peak/gap regressions verified; shared GUI paint limitation recorded
- Area
- Project Rubi-Ka
- Project
- engines
- Kind
- Feature
- Task ID
tsk_rgmq8x8q8c- Updated