Profile PRK.Client rendering slowdown outside Newland
Investigate the running development client's zone-dependent frame-rate loss, particularly outside Newland City. Capture managed thread/runtime and allocation evidence using Docker-hosted .NET diagnostics; correlate hot stacks with the rendering implementation and existing frame/GPU diagnostics. Test transparency sorting as a hypothesis, not an assumed cause. Constraints: do not alter or restart the running client without agreement. No GPU sorting or multi-threaded sorting solution; if sorting is material, propose a robust, simple, fast single-threaded CPU approach suitable for many semi-transparent objects. Distinguish managed active work, blocked/native calls, and GPU cost. Debug-build and capture-scene limitations must remain explicit. Acceptance: usable trace artifacts, ranked renderer hotspots with source correlation, evidence-based assessment of transparency sorting, and a concrete next-step plan with limitations. Implementation is a separate decision. Initial verified evidence (2026-10-12): attached Docker-hosted dotnet-trace/dotnet-counters 10.0.750501 to native client PID 4083286 without restart. Artifacts and temporary allocation analyzer: /tmp/prk-client-profile-20261012; capture-metadata.json records provenance and limits. Two 30s/20s EventPipe captures agree: render-thread sampled time culling 28–29%, whole draw-stream build ~11%, bucket/part emission including comparison sorts ~2%, translucent recording ~28% (second trace translucent mesh recording 23.38%). Visible comparison-sort stacks ~0.12%; inlining caveat applies. These are sampled thread time, not precise CPU or GPU percentages. All-thread topN is dominated by idle workers and must not drive conclusions. Source correlation: existing distance buckets and per-visual part sorting in DrawStreamBuilder already avoid a global comparison sort, but emit one draw per transparent part. Mesh.RecordVulkan repeatedly binds vertex/index buffers and borrows handles through allocator locks. Allocator borrow stacks account for ~5.28% of second render-thread samples; no claim that all is lock contention. Allocation ticks attribute ~530 MB over 20s to AnimatedRenderable.PrepareFrame -> Renderable.SetParentMatrix state copies/closures/delegates. Separate counters average ~32.8 MB/s total allocations and ~2.86 ms/s GC pause, so GC is not currently the dominant measured pause source. Native collect-linux probe succeeds but capture is denied by host permissions; host settings were not altered. User confirmed captures faced the bad Newland area. Engine Stats screenshot retained at /tmp/prk-client-profile-20261012/newland-engine-stats.png: 28.6 FPS / 34.95 ms, instance update 14.80 ms, shadow GPU pass 0.96 ms, 38 characters, 49,236 renderables; 23,301 transparent draws (22,117 blend-only; 1,184 alpha-test + blend), 23,299 transparent instances, only 105 transparent meshes / 30 materials, and 11,892 translucent material binds. Screenshot is not trace-synchronized and displayed draw/instance totals have small inconsistencies requiring validation. Triangles are a fixed-per-renderable estimate, not measured geometry. High repetition strengthens the case for order-preserving submission batching, not arbitrary material reordering of blended surfaces. Terrain grass uses default opaque alpha-tested material, so do not assume it explains the blend-only count. Same-process fast-scene comparison captured and validated: user faced a nearby different view in the same zone; nearby-fast-04.nettrace is a 30s same-profile capture, with nearby-fast-engine-stats.png and trace-comparison.json retained alongside earlier artifacts. Screenshot: 64.7 FPS / 15.46 ms, instance update 8.06 ms, shadow GPU pass 0.52 ms, 55 characters / 50,540 renderables, 3,523 transparent draws (3,433 blend-only), 1,861 translucent material binds. Fast render-thread samples: translucent recording 8.34% vs bad ~28%, bucket/part emission 0.729% vs ~2%, visible comparison-sort stacks 0.162% vs ~0.12%; culling 38.314%, instance update 52.153%. Do not interpret increased relative culling share as increased absolute per-frame cost. Camera/character counts differ and screenshots are point-in-time, not trace averages. Evidence does not support sorting as the primary cause; transparent submission volume and instance preparation are the priority candidates. Initial investigation acceptance is met: usable managed traces and allocation/runtime evidence, independently confirmed slow/fast scene comparison, source-correlated hotspot ranking, and a constrained next-step plan. This establishes candidate priorities, not a fully proven CPU/GPU bottleneck or completed optimization. Follow-up validation before optimization claims: same-camera Release runs, CPU phase timings and GPU scene/translucent timings, validated draw-stat accounting, and separate before/after tests preserving blend order and resource retirement safety. Prioritize safe redundant mesh-bind elimination and frame-lifetime-safe handle snapshots, order-preserving adjacent transparent draw coalescing where instance ranges permit, and attachment update allocation reduction; measure each independently. Audit cutout vs genuinely blended materials only with asset-semantic evidence—alpha testing alone does not make blending unnecessary. Preserve ordering and resource-retirement safety. If further evidence makes sorting material, benchmark an allocation-free single-threaded radix/key approach with deterministic ties and explicit invalidation rather than GPU or threaded sorting. No repository edits yet.
Checklist
0 of 0 completeNo checklist items.
- Area
- Project Rubi-Ka
- Project
- engines
- Kind
- Research
- Task ID
tsk_szb637np68- Updated