Skip to content

Performance optimizations for Intel iGPU (Panther Lake / unified memory) #2

Description

@HritwikSinghal

Tracking issue for performance work in this fork. Target: The Legend of Zelda: Breath of the Wild at 4K 60 FPS on an Intel Panther Lake B390 iGPU (Xe3, Mesa ANV, Arch Linux). Bottlenecks were identified via a systematic source survey plus the in-emulator instrumentation from #1.

Landed

  • Texture upload zero-fill (72d215d): the texture decode buffer was cleared after every upload, so every texture upload memset its entire buffer before the decoder overwrote it. Now kept at high-water mark with a 64 MiB release valve. (Metal backend has the same bug; not fixed here.)
  • Bounded blocking wait for the GPU emulation thread (4a10a44): the command processor busy-spun at 100% core when starved, stealing shared CPU/GPU power budget on an iGPU. Now: short spin, then a 200us-bounded condvar wait signaled by the ring-buffer producer (bounded because the emulated vsync is polled from that loop). The guest fence-wait loop also pauses and throttles its clock reads.
  • Persistent index cache (f94bcd1): the index-conversion cache held only 8 entries (~0% hit rate in BOTW), so nearly every draw re-ran SIMD index conversion + a synchronized allocation + a flush for static geometry. Now a cross-frame robin_hood map (2048-entry cap) with range invalidation + a sampled validation hash checked on every hit (explicit invalidation only ever covered the immediate-mode scratch buffer, so the hash is the primary staleness defense -- same model Cemu already uses for textures).

All three still need in-game verification (watch for geometry corruption from index-cache validation-hash misses) and profiling before/after numbers.

Backlog (data-gated, ordered by expected impact; details in claude/todo.md)

  • Register dirty-flag scheme: BOTW ends a draw sequence on almost any state change, forcing the slow first-draw path (3x descriptor-set state hash, full pipeline hash, full uniform re-gather/re-upload, full FBO re-derivation, full buffer re-sync) on most draws. One dirty-tracking scheme amortizes all five.
  • UMA zero-copy buffer cache: vertex/attribute data currently double-copies through a staging ring + vkCmdCopyBuffer on a unified-memory GPU.
  • Partial texture reloads: any detected change reloads every mip x slice of a texture (BOTW has a 1024x1024 x83-slice array hitting this).
  • Texture decode directly into staging memory (skip one full copy).
  • Occlusion queries: avoid renderpass splits per query and the GPU-side WAIT_BIT result copy.
  • Frame pacing: dedicated vsync timer thread; consider 2 frames in flight when GPU-bound.
  • Cheap wins: cached vkGetImageMemoryRequirements alignment, alignas(64) for per-core command state / ring indices, fused memcpy+hash in buffer cache page uploads.
  • Research spike: fp16 / RelaxedPrecision shader emission (large ALU+bandwidth win on iGPU, artifact risk).

Findings that were investigated and ruled out are recorded in claude/todo.md to avoid re-surveying.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions