Skip to content

ENG2-P0-01: Add GPU timestamp queries (wgpu QuerySet) for shadow/render/submit phases #741

Description

@aram-devdocs

Parent

  • Program: ENG2 — GoudEngine v2 Rebuild (see the pinned master tracking issue)
  • Phase / Milestone: Phase 0 — Instrumentation & Truth (eng2-p0-truth)
  • Batch / Group: Batch 0.1 — Instrumentation core, Group A
  • Runbook spec: docs/src/runbook/phases/phase-0.md (committed with the roadmap)

Summary

Add wgpu QuerySet-based GPU timestamp queries around the shadow pass, main render pass, and submit call so GPU-side phase costs (gpu_shadow, gpu_render, gpu_submit) are measured directly instead of inferred from CPU record time.

Architecture Context

Layer: Libs (Layer 2) — libs/graphics/backend/wgpu_backend/.
Modules/types touched:

  • goud_engine/src/libs/graphics/backend/wgpu_backend/frame.rstimestamp_writes: None at line 148; CPU-only phase timers at lines 18-127
  • goud_engine/src/libs/graphics/backend/wgpu_backend/shadow_pass.rstimestamp_writes: None at lines 76 and 382

Boundary constraints (only those that apply):

  • Raw GPU calls stay in libs/graphics/backend/ — this work already lives there; do not leak wgpu:: types out of the backend module boundary.

Pattern to follow: Existing CPU phase-timer bracketing pattern in frame.rs (Instant::now() before/after each phase) — mirror the same phase boundaries but back them with QuerySet begin/end.

Scope

  • Add a wgpu::QuerySet (timestamp type) sized for shadow/render/submit phase pairs
  • Wire timestamp_writes: Some(...) into the shadow pass descriptor (shadow_pass.rs:76,382) and main render pass descriptor (frame.rs:148)
  • Resolve query results and expose new gpu_shadow/gpu_render/gpu_submit phase counters distinct from the existing CPU-record phases
  • Tests: spec test asserting the query set is populated and resolved without panicking on the wgpu backend
  • Docs/rules updates if this invalidates .agents/rules/graphics-patterns.md's testing guidance

Acceptance Criteria

  • gpu_shadow, gpu_render, gpu_submit report non-zero timings on a real GPU-backed capture (S1 scene)
  • PERF (area:performance): S1 capture attributes shadow/render/submit cost distinctly instead of the current always-CPU-record-time values; feeds the Phase 0 gate item "S1 capture: gpu_shadow, gpu_render, gpu_submit report non-zero"
  • cargo check && cargo fmt --all -- --check && cargo clippy -- -D warnings clean; cargo test green; ./codegen.sh && git diff --exit-code (drift gate)

Breaking Change & Throne Follow-up

None — additive/internal.

Blocked By

None.

Files Likely Touched

  • Modified: goud_engine/src/libs/graphics/backend/wgpu_backend/frame.rs, .../shadow_pass.rs
  • New: possibly a query-set helper module under backend/wgpu_backend/

Agent Notes

  • timestamp_writes: None at backend/wgpu_backend/frame.rs:148 and shadow_pass.rs:76,382 — no GPU timing exists today; all phases are Instant::now() CPU record-time (frame.rs:18-127).
  • Add QuerySet begin/end around shadow, main pass, submit; new gpu_shadow/gpu_render/gpu_submit phases distinct from CPU-record phases.
  • This is why shadow_pass reports 0 µs while Metal stalls 300–600 ms (perf: BeginFrame + EndFrame stall 300-600ms when shadows enabled with 1.4k+ scene instances (macOS Metal) #677 evidence) — the counter, not the GPU, is silent.
  • This issue blocks ENG2-P0-02 (surfacing the counters via FFI/MCP), ENG2-P0-07 (scene harness capture), and ENG2-P2-10 (root-causing the Metal shadow stall).

Verification

cargo check && cargo fmt --all -- --check && cargo clippy -- -D warnings
cargo test
./codegen.sh && git diff --exit-code

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions