docs: append S9-S11, add README and TROUBLESHOOTING
This commit is contained in:
@@ -1255,3 +1255,96 @@ succession. `surface.configure()` is fast enough to handle this — each call
|
|||||||
discards old buffers and allocates new ones. The GPU continues processing
|
discards old buffers and allocates new ones. The GPU continues processing
|
||||||
in-flight frames with the old buffer dimensions; there is no visual glitch
|
in-flight frames with the old buffer dimensions; there is no visual glitch
|
||||||
because the swapchain handles the transition seamlessly.
|
because the swapchain handles the transition seamlessly.
|
||||||
|
|
||||||
|
## S9: Where All the Code Goes
|
||||||
|
|
||||||
|
The full source is the codeblocks in sections S2–S8, assembled in order into
|
||||||
|
`src/main.rs` and `src/shader.wgsl`.
|
||||||
|
|
||||||
|
### File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── main.rs # Sections S2, S3, S5 (structs), S7 (render), S8 (resize)
|
||||||
|
├── shader.wgsl # Section S4 (the complete WGSL shader)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `main.rs` combines the winit event loop (S2), the init chain and `State`
|
||||||
|
struct (S3), the `Vertex` type and `VERTICES` constant (S5), the `render`
|
||||||
|
method (S7), and the `resize` method (S8).
|
||||||
|
- `shader.wgsl` is the single file from S4: vertex shader, fragment shader,
|
||||||
|
and the `VertexOutput` struct.
|
||||||
|
|
||||||
|
Refer to [concepts/GLOSSARY.md](concepts/GLOSSARY.md) for term definitions used
|
||||||
|
throughout these sections. See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for
|
||||||
|
common issues and their fixes.
|
||||||
|
|
||||||
|
## S10: Running It
|
||||||
|
|
||||||
|
Run the project:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo run
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected console output:** wgpu adapter info (GPU model, driver name), shader
|
||||||
|
module compilation log, pipeline creation messages, and the `simple_logger`
|
||||||
|
debug lines from surface status and device polling.
|
||||||
|
|
||||||
|
**Expected visual:** A dark gray background (from `LoadOp::Clear`) with a
|
||||||
|
rainbow triangle spanning most of the window. Red at the bottom-left corner,
|
||||||
|
blue at the bottom-right corner, green at the top vertex. Colors blend smoothly
|
||||||
|
across the triangle surface via hardware interpolation.
|
||||||
|
|
||||||
|
**Expected CPU usage:** 100% on one core due to `ControlFlow::Poll` driving a
|
||||||
|
continuous redraw loop. This is normal for a demo that redraws every vsync.
|
||||||
|
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for common issues.
|
||||||
|
|
||||||
|
## S11: What You've Learned and What's Next
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
|
||||||
|
You have built a complete GPU-rendered application from scratch. Here is what
|
||||||
|
each piece does:
|
||||||
|
|
||||||
|
- **The 5-layer wgpu [init chain](concepts/GLOSSARY.md#instance):**
|
||||||
|
[Instance](concepts/GLOSSARY.md#instance) →
|
||||||
|
[Surface](concepts/GLOSSARY.md#surface) →
|
||||||
|
[Adapter](concepts/GLOSSARY.md#adapter) →
|
||||||
|
[Device](concepts/GLOSSARY.md#device) + [Queue](concepts/GLOSSARY.md#queue) →
|
||||||
|
[SurfaceConfiguration](concepts/GLOSSARY.md#surface-configuration).
|
||||||
|
Each layer adds a capability: driver connection, window binding, GPU selection,
|
||||||
|
resource management, and swapchain allocation.
|
||||||
|
|
||||||
|
- **The [render pipeline](concepts/GLOSSARY.md#pipeline-render):** Shaders,
|
||||||
|
topology, and vertex layout compiled into a GPU configuration. Created once,
|
||||||
|
reused every frame. Expensive to create, cheap to execute.
|
||||||
|
|
||||||
|
- **The [command buffer](concepts/GLOSSARY.md#command-buffer) model:** Record
|
||||||
|
instructions on the CPU, submit atomically to the queue, GPU executes
|
||||||
|
asynchronously. No `.await` on a draw call.
|
||||||
|
|
||||||
|
- **The [swapchain](concepts/GLOSSARY.md#swapchain) and
|
||||||
|
[framebuffer](concepts/GLOSSARY.md#framebuffer):** Double-buffered rendering
|
||||||
|
through [PresentMode::Mailbox](concepts/GLOSSARY.md#present-mode). Acquire a
|
||||||
|
back buffer, render into it, present it to the display.
|
||||||
|
|
||||||
|
- **GPU [interpolation](concepts/GLOSSARY.md#interpolation):** Vertex attributes
|
||||||
|
automatically blended across triangle surfaces. You supply values at three
|
||||||
|
points; the rasterizer computes every value in between.
|
||||||
|
|
||||||
|
### What's Next
|
||||||
|
|
||||||
|
With the render loop and pipeline foundation in place, the next steps are:
|
||||||
|
|
||||||
|
- **Textures and [bind groups](concepts/GLOSSARY.md#bind-group)** — loading
|
||||||
|
images onto the GPU and sampling them in fragment shaders
|
||||||
|
- **Uniforms and 3D transforms** — projection, view, and model matrices for
|
||||||
|
positioning geometry in 3D space
|
||||||
|
- **Lighting and material models** — diffuse, specular, and PBR shading
|
||||||
|
- **Depth buffering and z-fighting** — per-pixel depth testing for correct
|
||||||
|
overlap ordering
|
||||||
|
- **[Compute shaders](concepts/GLOSSARY.md#compute-shader) and GPU compute
|
||||||
|
pipelines** — general-purpose GPU computation outside the graphics pipeline
|
||||||
|
|
||||||
|
Keep [concepts/GLOSSARY.md](concepts/GLOSSARY.md) handy as you move forward.
|
||||||
|
|||||||
28
docs/README.md
Normal file
28
docs/README.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# learn-wgpu
|
||||||
|
|
||||||
|
An educational book teaching Rust graphics programming with wgpu 29 + winit 0.30.
|
||||||
|
|
||||||
|
Built for backend/systems Rust developers who know Rust thoroughly but have zero
|
||||||
|
graphics programming experience. Every sentence teaches GPU concepts — not Rust syntax.
|
||||||
|
|
||||||
|
## Required Reading Order
|
||||||
|
|
||||||
|
1. [The Graphics Pipeline](concepts/graphics-pipeline.md) — GPU vs CPU, the 5-stage pipeline
|
||||||
|
2. [Coordinate Systems](concepts/coordinate-systems.md) — NDC, homogeneous coordinates, viewport
|
||||||
|
3. [Shader Basics](concepts/shader-basics.md) — WGSL, vertex/fragment shaders, interpolation
|
||||||
|
4. [Build a Rainbow Triangle](01-rainbow-triangle.md) — The complete step-by-step guide
|
||||||
|
5. [Troubleshooting](TROUBLESHOOTING.md) — Common errors and fixes (reference as needed)
|
||||||
|
6. [Glossary](concepts/GLOSSARY.md) — Every term defined (reference as needed)
|
||||||
|
|
||||||
|
> **Reading order matters:** Coordinate systems must be understood before shader basics,
|
||||||
|
> because the shader walkthrough references NDC coordinates.
|
||||||
|
|
||||||
|
## Guides
|
||||||
|
|
||||||
|
- **01 — Rainbow Triangle** — The minimal complete program: one triangle, smooth color interpolation
|
||||||
|
- More guides coming soon (textures, lighting, compute)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Rust stable (edition 2024)
|
||||||
|
- Linux x86_64 with Vulkan drivers (`libvulkan1`)
|
||||||
133
docs/TROUBLESHOOTING.md
Normal file
133
docs/TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# 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:
|
||||||
|
```toml
|
||||||
|
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:
|
||||||
|
```rust
|
||||||
|
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:**
|
||||||
|
```bash
|
||||||
|
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](concepts/GLOSSARY.md#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:
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
```rust
|
||||||
|
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](concepts/GLOSSARY.md#rasterizer) interpolates vertex colors automatically, but only if the fragment shader uses them.
|
||||||
|
|
||||||
|
**Fix:** Ensure fragment shader returns the interpolated vertex color:
|
||||||
|
```wgsl
|
||||||
|
@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):
|
||||||
|
```wgsl
|
||||||
|
return vec4<f32>(1.0, 1.0, 1.0, 1.0); // wrong: solid white
|
||||||
|
```
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Glossary](concepts/GLOSSARY.md) — Every term defined
|
||||||
|
- [Graphics Pipeline](concepts/graphics-pipeline.md) — Pipeline stage overview
|
||||||
|
- [Coordinate Systems](concepts/coordinate-systems.md) — NDC and transformation spaces
|
||||||
|
- [Shader Basics](concepts/shader-basics.md) — WGSL and shader concepts
|
||||||
|
- [wgpu documentation](https://docs.rs/wgpu/29.0.0/) — Official wgpu 29 API docs
|
||||||
|
- [wgpu repository](https://github.com/gfx-rs/wgpu) — Examples and issue tracker
|
||||||
Reference in New Issue
Block a user