# Performance Budget & Profiling Methodology > **Target hardware:** GTX 1050 / RX 560 class (2 GB VRAM) > **Engine:** Godot 4.7 Forward+ renderer > **Frame target:** 60 fps (16.6 ms per frame) --- ## 1. Frame Budget (16.6 ms) | Phase | Budget | Notes | |---------------|--------|-------| | GPU total | 8.0 ms | Forward+ opaque pass, transparent, sky, tonemap | | CPU — physics | 1.5 ms | 128-tick, capsule sweep, raycasts | | CPU — render | 1.5 ms | Culling, sorting, draw-call submission | | CPU — gameplay| 3.0 ms | Input, animation, network interpolation | | **Headroom** | **2.6 ms** | Buffer for frametime variance (≈15%) | ### Bottleneck detection thresholds | Metric | Green | Yellow | Red | |----------------|------------|---------------|---------------| | GPU frame ms | < 5.0 | 5.0–7.5 | > 7.5 | | CPU frame ms | < 10.0 | 10.0–13.0 | > 13.0 | | Draw calls | < 1200 | 1200–1800 | > 2000 | | Triangles / frame | < 300K | 300K–600K | > 1M | | VRAM used | < 1.2 GB | 1.2–1.7 GB | > 1.8 GB | | Main RAM used | < 2.0 GB | 2.0–3.0 GB | > 3.5 GB | --- ## 2. Rendering Budget ### Triangle Count | Asset type | LOD0 tris | LOD1 tris (50%) | LOD2 tris (25%) | Instances/map | |-----------------|-----------|-----------------|-----------------|---------------| | Wall panel | 800 | 400 | 200 | ~600 | | Floor slab | 800 | 400 | 200 | ~400 | | Pillar | 400 | 200 | 100 | ~80 | | Doorway / window| 1200 | 600 | 300 | ~60 | | Accent panel | 400 | 200 | 100 | ~40 | **Budget calculation** (max visible): - Walls ≈ 50 visible × 800 = 40K (LOD0) - Floors ≈ 20 visible × 800 = 16K (LOD0) - Details ≈ 30 visible × 400 = 12K (LOD0) - **Total LOD0 tris ≈ 68K** — well within budget - With LOD + occlusion, visible tris on target GPU < 200K ### Draw Calls | Pass | Draw calls | Notes | |---------------|------------|-------| | Opaque solids | 600–800 | Per-object, one per visible piece | | Shadows | 200–400 | Single directional cascade | | Transparent | 50–100 | Reflection probes, lightmap | | UI | 100–200 | HUD, minimap, scoreboard | | **Total** | **950–1500** | Well within 2000 target | ### VRAM Budget | Category | Size | Notes | |----------------------|----------|-------| | Texture pool (1K × 7 mats) | 75 MB | 28 PBR maps | | Lightmap atlas | 64–128 MB| 2048 × 2048, DXT5 | | Shadow map | 16 MB | 2048 × 2048 atlas | | Mesh geometry | 20–40 MB | LOD0–LOD2 | | Reflection probe cubemaps | 8 MB | 8 × 512 cubemaps | | Audio + misc | 50 MB | | | **Total base** | **~300 MB** | | | **Headroom** | **1.7 GB** | For gameplay assets, streaming | --- ## 3. LOD Strategy ### CSG-based pieces (current) Since the modular kit uses CSG nodes (procedural geometry), traditional mesh LOD is not directly supported. The equivalent optimizations are: | Technique | Benefit | How | |----------------------------|---------|-----| | **Visibility ranges** | Skip rendering past cutoff | `visibility_range_end` on each CSGBox3D/Combiner | | **Occlusion culling** | Skip behind-occluder geometry | OccluderInstance3D on major walls | | **CSG → Mesh baking** | Replace procedural with static mesh | `convert_csg_to_mesh.gd` tool script | | **Mesh LOD after baking** | Traditional LOD on static meshes | Godot ImporterMesh LOD | ### Visibility Range Thresholds (CSG phase) | Asset | Hide beyond | Rationale | |---------------------|-------------|-----------| | Wall panels | 50 m | OC sightlines rarely exceed 40 m | | Floor slabs | 60 m | Visible as ground plane further | | Pillars | 30 m | Thin silhouette, cull earlier | | Beams | 30 m | Ceiling detail, only visible indoors | | Accent panels | 20 m | Small team-color decals | | Doorway / window | 40 m | Opening shapes visible at medium range | ### Mesh LOD Targets (baked mesh phase) | LOD | Distance | Tris % | Notes | |-----|----------|--------|-------| | 0 | 0–15 m | 100% | Full detail, panel gaps | | 1 | 15–40 m | 50% | Collapse bevels, remove small holes | | 2 | 40–80 m | 25% | Planar collapse, aggressive decimate | | 3 | 80 m+ | CULL | Not visible at competitive sightlines | --- ## 4. Occlusion Culling ### Implementation - **OccluderInstance3D** nodes auto-generated from wall CSGBox3D geometry - **Voxel resolution**: 128³ (good balance of accuracy vs memory) - **Generation script**: `client/scripts/generate_occluders.gd` — `@tool` script - Activation: Scene tree → Add OccluderInstance3D → Set occluder shape to box matching wall extents ### Occluder Coverage | Occluder origin | Covers | Shape | |----------------------|-----------------------|--------| | Exterior walls | Block view of outdoor | Box | | Interior dividers | Lane separation | Box | | Pillar clusters | Mid-range detail | Box | Expected culling benefit: **30–50% reduction in visible geometry** on a 3-lane map with interior dividers. --- ## 5. Profiling Methodology ### Toolchain | Tool | Use | |------|-----| | Godot Editor Debugger | Real-time frame profiler, monitor, 3D scene debug | | `profile_scene.gd` | Headless frame-time capture | | GPU vendor tools (NVIDIA NSight / Radeon GPA) | GPU-bound profiling | | Frame debugger (Godot built-in) | Draw-call inspection | ### Profiling Workflow 1. **CPU baseline**: Run `profile_scene.gd --headless` on target hardware 2. **GPU baseline**: Capture 1000+ frames with editor profiler, record p50/p95/p99 3. **Draw call audit**: Use frame debugger to count and classify draw calls 4. **Occlusion test**: Toggle OccluderInstance3D visibility, measure FPS delta 5. **LOD validation**: Check LOD transitions with debug visualization 6. **Thermal test**: 30-minute continuous gameplay, log frame-time variance ### Pass/Fail Criteria - **PASS**: holds 60 fps on target hardware for 95% of frames across all 3 maps - **ACCEPTABLE**: drops to 45–55 fps during intense firefights but recovers within 2 s - **FAIL**: sustained < 45 fps or > 100 ms frame-time spike --- ## 6. Reference Frames ### `kit_demo.tscn` (indoor single-room, 5.12 × 5.12 m) - ~11 CSG pieces, 8 materials - Estimated draw calls: ~20–30 - Estimated triangles: ~8K–12K - VRAM: ~80 MB (materials + lightmap) - **Expected: > 200 fps on GTX 1050** ### `template_map.tscn` (3-lane showroom, 20 × 16 m) - ~25 CSG pieces + prefabs - Estimated draw calls: ~150–250 - Estimated triangles: ~40K–60K - VRAM: ~200 MB (materials + lightmap + probes) - **Expected: 90–120 fps on GTX 1050** ### Full competitive map (target, ~80 × 60 m) - ~800 CSG pieces (when built from modular kit) - Estimated draw calls: ~1500 (with LOD + occlusion) - Estimated triangles: ~200K–400K - VRAM: ~500 MB - **Target: 60 fps on GTX 1050**