Files
learn-wgpu/docs/TROUBLESHOOTING.md

6.5 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"
tokio = { version = "1", features = ["rt", "macros"] }
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. Panic: "No adapter found"

Symptom: Program crashes immediately with No GPU adapter found.

Cause: No Vulkan driver installed. wgpu on Linux requires Vulkan.

Fix:

sudo apt install libvulkan1 mesa-vulkan-drivers
vulkaninfo  # verify installation

5. Panic: "Surface lost"

Symptom: Program crashes with a surface lost error during rendering.

Cause: Display server restarted or GPU context was reset. The Surface is permanently invalidated.

Fix: In the tutorial, this means the window needs to be reopened. In production code, handle the Lost variant of CurrentSurfaceTexture by recreating the surface via Instance::create_surface().

6. Wayland surface crashes or doesn't render

Symptom: Program crashes or shows blank window on Wayland.

Cause: winit's Wayland backend may have compatibility issues with certain compositors.

Fix: Force X11 backend:

WINIT_UNIX_BACKEND=x11 cargo run

7. 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();
}

8. 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.

9. 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>

10. 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

11. 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

Additional Resources