Files
learn-wgpu/docs/TROUBLESHOOTING.md

8.9 KiB

Troubleshooting

1. cargo build fails with "no matching package"

Symptom: Build fails with could not find package for wgpu or winit.

Cause: Version typo in Cargo.toml. wgpu and winit have specific major versions.

Fix: Verify your dependency versions:

wgpu = "29"
winit = "0.30"
pollster = "0.4"
bytemuck = { version = "1", features = ["derive"] }
log = "0.4"
simple_logger = "5"

2. Window opens but shows black screen

Symptom: Window appears but is entirely black. No triangle visible.

Cause: One (or more) of several common rendering misconfigurations:

  • Pipeline not set: pass.set_pipeline() not called
  • Vertex buffer not bound: pass.set_vertex_buffer() not called
  • Draw call wrong: draw() arguments incorrect (must be draw(0..3, 0..1) — two ranges)
  • Triangle wound clockwise: FrontFace::Ccw requires counter-clockwise vertex order
  • Format mismatch: ColorTargetState::format must match SurfaceConfiguration::format
  • Present omitted: surface_texture.present() must be called to show rendered frame

Fix: Check each item above. Verify the pipeline is set, buffer is bound, draw uses two Range<u32> arguments, vertices are CCW, formats match, and present() is called.

3. Washed-out or wrong colors

Symptom: Triangle renders but colors look dull or incorrect.

Cause: SurfaceConfiguration::view_formats missing add_srgb_suffix(). Without sRGB gamma correction, colors appear washed out.

Fix: Ensure view_formats includes the sRGB variant:

view_formats: vec![format.add_srgb_suffix()],

4. "No adapter found"

Symptom: Program crashes or logs "No GPU adapter found" during startup.

Cause: wgpu cannot find a compatible graphics adapter. This can happen across all platforms for different reasons.

Fix:

  • Windows: Ensure your GPU supports DirectX 12 (WDDM 2.0+). Update GPU drivers from the manufacturer's website (NVIDIA, AMD, or Intel). Some integrated GPUs may require a Windows 10+ build. If DX12 is unavailable, install the LunarG Vulkan Runtime.
  • macOS: Metal is required. Ensure your GPU supports Metal (all Macs from 2012 onward). Update macOS to the latest version. If you're on Apple Silicon, wgpu will automatically use the Metal backend.
  • Linux: Install Vulkan drivers and tools:
    # Ubuntu/Debian
    sudo apt install vulkan-tools mesa-vulkan-drivers
    # Arch
    sudo pacman -S vulkan-tools vulkan-radeon  # or vulkan-intel / nvidia-utils
    vulkaninfo  # verify installation
    

5. "Adapter not compatible" (macOS / Metal)

Symptom: wgpu reports that no adapter is compatible with the surface.

Cause: On macOS, wgpu uses Metal exclusively. If the GPU does not support Metal (e.g., very old Mac hardware or a GPU below Metal 2.0), no adapter will be found.

Fix: Verify your Mac supports Metal. Check System Information > Graphics in macOS. If Metal is not supported, the GPU cannot be used with wgpu.

6. "Surface lost"

Symptom: Program crashes with a surface lost error during rendering, or the window renders blanks after being minimized/restored.

Cause: The display server or GPU context was reset. The Surface is permanently invalidated. Common triggers include:

  • Window minimized and restored (some display servers)
  • Display configuration changed (hotplug, external monitor connected/disconnected)
  • GPU driver reset
  • Compositor restart (Linux/Wayland)

Fix: Handle the CurrentSurfaceTexture::Lost variant gracefully. In the tutorial, this means the window may need to be reopened. In production code, set self.state = None, then on the next redraw event, re-run the full State::new() initialization chain to recreate all GPU resources.

7. Wayland surface crashes or doesn't render (Linux only)

Symptom: Program crashes or shows blank window on Wayland compositors (Sway, GNOME Shell, KDE Plasma, etc.).

Cause: winit's Wayland backend may have compatibility issues with certain compositors or Vulkan/Wayland interop layers.

Fix: Temporarily force the X11 backend:

WINIT_UNIX_BACKEND=x11 cargo run

If X11 works but Wayland does not, check your compositor version and winit version. This is a Linux-specific issue and does not affect Windows or macOS.

8. Window won't close

Symptom: Clicking the X button or pressing Escape doesn't close the window.

Cause: ApplicationHandler::exiting() not implemented, or event_loop_ctl.exit() not called.

Fix: Ensure exiting() (note: NOT closing()) is implemented:

fn exiting(&mut self, event_loop_ctl: &ActiveEventLoop) {
    event_loop_ctl.exit();
}

9. CPU at 100%

Symptom: One CPU core at 100% usage.

Cause: ControlFlow::Poll drives RedrawRequested events continuously. Every frame renders and queues another redraw. This is the expected behavior for a ControlFlow::Poll render loop.

Fix: No fix needed — this is expected for a continuous redraw demo. For production, switch to ControlFlow::Wait and call request_redraw() only when state changes.

10. Shader compilation or pipeline creation error

Symptom: Program panics during create_render_pipeline with a shader validation error.

Cause: @location numbers in WGSL don't match shader_location numbers in Rust's VertexAttribute, or @builtin(position) is missing from vertex shader output.

Fix: Check the log output for validation messages. Verify:

  • WGSL @location(0) matches Rust shader_location: 0
  • WGSL @location(1) matches Rust shader_location: 1
  • Vertex shader outputs @builtin(position) clip_position: vec4<f32>

11. Triangle shows one solid color instead of gradient

Symptom: Triangle renders but is a single uniform color instead of smoothly blending.

Cause: Fragment shader returns a constant color instead of passing through input.vertex_color. The rasterizer interpolates vertex colors automatically, but only if the fragment shader uses them.

Fix: Ensure fragment shader returns the interpolated vertex color:

@fragment
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
    return vec4<f32>(input.vertex_color, 1.0);
}

Not this (which returns a solid color):

return vec4<f32>(1.0, 1.0, 1.0, 1.0);  // wrong: solid white

12. WGSL shader compilation errors

Symptom: Program panics or logs errors during device.create_shader_module() or create_render_pipeline() with messages referencing WGSL validation failures.

Cause: wgpu validates WGSL shaders at pipeline creation time, not at runtime. Errors surface immediately when the shader module is created or when the render pipeline references it. Common causes include:

  • Syntax errors: typos in WGSL (missing semicolons, mismatched braces, incorrect keywords)
  • Type mismatches: passing vec2<f32> where vec4<f32> is expected, or mixing signed/unsigned types
  • Missing @location or @builtin attributes: vertex/fragment shader I/O without proper decoration
  • Entry point not found: the @vertex or @fragment function name doesn't match the pipeline descriptor's entry_point field

Fix: Read wgpu's error messages carefully — they include the shader source line and column where the issue was detected. Follow this checklist:

  • Check the reported line/column in your WGSL source for syntax issues
  • Verify all type signatures match between vertex shader output and fragment shader input
  • Ensure every varying uses @location(N) and position output uses @builtin(position)
  • Confirm the function name in your @vertex/@fragment declaration matches the string you pass to ProgrammableStage::entry_point
  • If the error message is unclear, try compiling the shader in isolation to isolate syntax vs. pipeline-binding issues

13. GPU debugging with RenderDoc

Symptom: Rendering issues that are difficult to diagnose (artifacts, wrong output, silent failures).

Cause: GPU debugging is hard with standard tools. Graphics pipeline state, shader execution, and buffer contents are not easily inspectable at runtime.

Fix: Use RenderDoc — a standalone GPU debugging tool supporting frame capture, pipeline state inspection, and shader debugging. It works with Vulkan (Linux), DX12/DX11 (Windows), and Metal (macOS). Launch RenderDoc, attach to your wgpu process, and capture frames to inspect the full graphics pipeline step by step. On macOS, RenderDoc supports Metal 2.0+ devices.

Additional Resources