WebGPU Debugging System

A comprehensive debugging and performance monitoring system for WebGPU demos, designed to help identify performance bottlenecks and analyze rendering behavior without impacting runtime performance.

Architecture

The debugging system consists of two main components:

This separation keeps the main demo classes clean while providing powerful debugging capabilities.

Quick Start

Console Access

Once a WebGPU demo is running, you can access debugging features through the global webgpuDemo object:

// Show all available commands
webgpuDemo.help()

// Quick performance check
webgpuDemo.debugQuick()

// Start continuous monitoring
webgpuDemo.startMonitoring()

Debug Utilities

Additional utilities are available via webgpuDebugUtils:

// Quick setup
webgpuDebugUtils.quickDebug()

// Start monitoring with defaults
webgpuDebugUtils.startQuickMonitoring()

// Create performance alerts
const stopAlert = webgpuDebugUtils.createPerformanceAlert(20) // 20ms threshold

Available Commands

Performance Analysis

debugTiming()

Comprehensive frame performance breakdown with detailed table output. ⚠️ Warning: Uses console.table() which can impact performance.

webgpuDemo.debugTiming()

debugTimingLite()

Lightweight single-line timing information - performance friendly.

webgpuDemo.debugTimingLite()
// Output: ⚡ Frame: 2.45ms | Reset: 0.12ms | Behaviors: 0.34ms | ...

debugQuick()

Ultra-quick performance summary for continuous monitoring.

webgpuDemo.debugQuick()
// Output: 🚀 2.5ms | 12 objects | 2.1ms avg

debugPerformanceBar()

Visual performance breakdown using emoji bar charts.

webgpuDemo.debugPerformanceBar()

Render Analysis

debugRenderOrder()

Detailed render order and uniform offset analysis with tables. ⚠️ Warning: Uses console.table() which can impact performance.

debugRenderOrderLite()

Lightweight render order summary.

webgpuDemo.debugRenderOrderLite()
// Output: 👁️ Visible: 8 objects | 🙈 Hidden: 2 objects

Comprehensive Analysis

debugAll()

Lightweight comprehensive debug information (recommended).

debugAllDetailed()

Comprehensive debug with detailed tables (slower).

Continuous Monitoring

startMonitoring(intervalMs?)

Start continuous performance monitoring.

webgpuDemo.startMonitoring(500) // Monitor every 500ms

stopMonitoring()

Stop continuous monitoring.

toggleMonitoring()

Pause/resume monitoring without stopping the timer.

Transparency Debugging

debugTransparency()

Comprehensive transparency sorting and culling analysis for all objects in the scene.

webgpuDemo.debugTransparency()

Shows:

debugTransparencyLite()

Lightweight transparency summary.

webgpuDemo.debugTransparencyLite()
// Output: 🔮 Transparency: 3 transparent, 5 opaque, 3 no-cull

debugTransparentCulling()

Test transparent material culling behavior with various material configurations.

webgpuDemo.debugTransparentCulling()

Tests culling modes for:

Advanced Features

Performance Alerts

Set up automatic alerts when frame times exceed thresholds:

const stopAlert = webgpuDebugUtils.createPerformanceAlert(16.67) // 60fps threshold
// Automatically stops after calling stopAlert()

Debug Sessions

Record performance data over time for analysis:

const session = new webgpuDebugUtils.DebugSession()

session.start(100) // Record every 100ms
// ... let it run ...
session.stop()
session.analyze() // Get statistical analysis
const data = session.export() // Export raw data

Performance Snapshots

Get performance data programmatically:

const snapshot = webgpuDebugUtils.getPerformanceSnapshot()
if (snapshot) {
  console.log(`Frame time: ${snapshot.frameTime}ms`)
  console.log(`Objects: ${snapshot.objectCount}`)
}

Performance Considerations

Lightweight vs Heavy Methods

Method Type Performance Impact Use Case
*Lite() methods Minimal Frequent debugging, continuous monitoring
debugQuick() Minimal Real-time monitoring
debug*() with tables High Detailed analysis, one-time debugging

Best Practices

  1. Use lightweight methods for frequent debugging

    webgpuDemo.debugQuick() // ✅ Good for frequent use
    webgpuDemo.debugTiming() // ❌ Avoid in loops/frequent calls
    
  2. Continuous monitoring with appropriate intervals

    webgpuDemo.startMonitoring(1000) // ✅ Good for general monitoring
    webgpuDemo.startMonitoring(16)   // ❌ Too frequent, impacts performance
    
  3. Clean up monitoring

    webgpuDemo.stopMonitoring() // Always stop when done
    

Frame Timing Breakdown

The system measures these key performance metrics:

Troubleshooting

No Demo Instance Found

❌ No WebGPU demo instance found. Make sure a demo is running.

Solution: Ensure a WebGPU demo is loaded and initialized. The webgpuDemo global is only available after demo initialization.

No Timing Data Available

❌ No timing data

Solution: Wait for at least one frame to render. Timing data is only available after the first render call.

Performance Impact

If debugging methods are impacting performance:

  1. Use *Lite() versions of methods
  2. Reduce monitoring frequency
  3. Avoid console.table() methods (debugTiming(), debugRenderOrder())
  4. Stop monitoring when not needed

Implementation Details

WebGPUDebugTarget Interface

Demo classes implement this interface to expose necessary data:

interface WebGPUDebugTarget {
  lastFrameTiming: FrameTimingData | null;
  smoothedFrameTime: number;
  canvasWidth: number;
  canvasHeight: number;
  isInitialized: boolean;
  sceneState?: SceneState;
  resourceManager?: ResourceManager;
  camera?: Camera;
}

Frame Timing Data Structure

interface FrameTimingData {
  resetRingBuffers: number;
  applyBehaviors: number;
  updateTransforms: number;
  renderPassSetup: number;
  renderLoop: number;
  totalRenderFunction: number;
  objectCount: number;
  debugInfo?: Array<{
    id: number;
    name: string;
    visible: boolean;
    offset: number;
  }>;
}

Examples

Basic Performance Monitoring

// Quick check
webgpuDemo.debugQuick()

// Start background monitoring
webgpuDemo.startMonitoring(1000)

// Check detailed breakdown when needed
webgpuDemo.debugTimingLite()

Performance Investigation

// Record a session
const session = new webgpuDebugUtils.DebugSession()
session.start(50) // High frequency for detailed analysis

// Run your test scenario...
// (interact with demo, change settings, etc.)

session.stop()
session.analyze() // Get statistics

Alert-Based Monitoring

// Set up alerts for different scenarios
const renderAlert = webgpuDebugUtils.createPerformanceAlert(16.67) // 60fps
const targetAlert = webgpuDebugUtils.createPerformanceAlert(8.33)  // 120fps

// Run your demo...

// Clean up
renderAlert()
targetAlert()

Contributing

When adding new debugging features:

  1. Add lightweight versions for frequent use
  2. Document performance impact
  3. Follow the pattern of delegating from demo classes to WebGPUDebugger
  4. Update this README with new features