Prompt file imported from akspa0/parp-tools (
.codex/prompts/scene-culling-batching-performance-plan.md). Copyright stays with the author.
Implement the scene culling and batching performance slice in gillijimproject_refactor/src/MdxViewer with lower per-frame CPU work and more stable draw submission as the runtime goal.
Read First
gillijimproject_refactor/memory-bank/activeContext.mdgillijimproject_refactor/memory-bank/progress.mdgillijimproject_refactor/memory-bank/data-paths.mdgillijimproject_refactor/src/MdxViewer/memory-bank/activeContext.mdgillijimproject_refactor/documentation/wow-400-engine-performance-recovery-guide.mdgillijimproject_refactor/src/MdxViewer/Terrain/WorldScene.csgillijimproject_refactor/src/MdxViewer/Rendering/FrustumCuller.csgillijimproject_refactor/src/MdxViewer/Terrain/TerrainRenderer.csgillijimproject_refactor/src/MdxViewer/Rendering/WmoRenderer.cs
Goal
Reduce broad-phase visibility cost and unnecessary draw submission work in the main scene without regressing selection, PM4 debugging, or recent world-object fixes.
Why This Slice Exists
- The 4.0.0 client exposes
CWorldOccluder,CWorldAntiOccluder, andCWorldOcclusionVolume, which confirms that visibility is treated as a dedicated subsystem. - The active viewer already has frustum and distance culling, but much of the work still happens in large per-frame loops with repeated AABB checks and local state setup.
- The next useful slice is not “build a full occlusion engine.” It is to make the current broad-phase cheaper and the current submission path more stable.
Scope
- In scope:
WorldScenebroad-phase rejection and submission order- culling and batching behavior in terrain/WMO/MDX/PM4 passes
- counters or instrumentation that make the effect measurable
- preserving debug overlays as opt-in cost
- Out of scope unless direct evidence forces it:
- full occlusion-volume implementation
- terrain decode changes
- unrelated UI rewrites
Non-Negotiable Constraints
- Do not break PM4 picking, PM4 bounds, or other debug workflows while optimizing.
- Do not hide visible regressions behind more aggressive cull distances.
- Do not start with a speculative occlusion system when broad-phase and batching waste still exist.
- Keep the change minimal and measurable.
- Update memory-bank notes if culling behavior, counters, or known tradeoffs materially change.
Required Implementation Order
- Identify the hottest per-frame scene loops and the broad-phase checks they perform.
- Confirm whether the biggest cost is repeated culling, sorting, or draw submission fragmentation.
- Land the smallest change that removes one confirmed source of repeated work.
- Preserve existing correctness-sensitive exceptions such as nearby no-cull handling and PM4 debug visibility.
- Add or update counters so the impact is visible.
- Update memory-bank notes with the exact behavior change and remaining limitations.
Investigation Checklist
- Verify how often the same objects are re-tested in multiple passes.
- Verify whether expensive bounds transforms or sort keys can be reused per frame.
- Verify which debug overlays are still paying cost even when disabled.
- Check whether any current batching opportunity exists before deeper culling work.
- Prefer one confirmed hot path over a broad rewrite.
Validation Rules
- Build the changed viewer solution.
- If runtime validation on real data is not run, say so explicitly.
- If automated tests are not added or run, say so explicitly.
- Do not claim “occlusion” gains unless the change actually implements more than current frustum/distance rejection.
Deliverables
Return all items:
- exact culling/batching behavior changed
- files changed and why
- what repeated work was removed versus what remains
- build status
- automated-test status
- runtime-validation status
- memory-bank updates made
First Output
Start with:
- the current per-frame hot loop with the highest likely performance value
- what evidence from the engine and current code supports that choice
- what files will be changed first
- what visibility behavior must not regress during the pass
