Skip to content

Commit 8083977

Browse files
author
Matthieu Pizenberg
committed
Document example 02
1 parent 277d7d4 commit 8083977

File tree

2 files changed

+62
-34
lines changed

2 files changed

+62
-34
lines changed

example_01_triangle/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
//! - the fragment shader
1414
//! - the primitive type (triangle list)
1515
//! 6. Define our command encoder:
16-
//! 6.1. Start by defining our render pass:
16+
//! 1. Start by defining our render pass:
1717
//! - Link to the texture output
1818
//! - Link to the pipeline
1919
//! - Draw the primitive (provide vertices indices)
20-
//! 6.2. Add a command to copy the texture output to the output buffer
20+
//! 2. Add a command to copy the texture output to the output buffer
2121
//! 7. Submit our commands to the device queue
2222
//! 8. (async) Transfer the output buffer into an image we can save to disk
2323

example_02_buffer/src/main.rs

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
//! This example aims at showing vertex buffer usage in a minimal wgpu setup.
2+
//!
3+
//! The corner coordinates of the triangle are provided via a vertex buffer
4+
//! and the vertex indices in the face are provided as an index buffer.
5+
//! The steps of this minimal program are the following.
6+
//!
7+
//! 1. (async) Initialize the connection with the GPU device
8+
//! 2. Initialize a wgpu Texture object that will serve as a write target for our pipeline
9+
//! 3. Initialize a wgpu Buffer where the Texture output will be transferred to
10+
//! 4. **(new)** Create and initialize a vertex buffer containing the triangle coordinates
11+
//! 5. **(new)** Create and initialize an index buffer containing the vertex indices in the face
12+
//! 6. Load the shader module, containing both the vertex and fragment shaders
13+
//! 7. Define our render pipeline, including:
14+
//! - the vertex shader: **(new)** include our vertex buffer layout
15+
//! - the fragment shader
16+
//! - the primitive type (triangle list)
17+
//! 8. Define our command encoder:
18+
//! 1. Start by defining our render pass:
19+
//! - Link to the texture output
20+
//! - Link to the pipeline
21+
//! - **(new)** Provide vertex buffer and index buffer
22+
//! - Draw the primitive
23+
//! 2. Add a command to copy the texture output to the output buffer
24+
//! 9. Submit our commands to the device queue
25+
//! 10. (async) Transfer the output buffer into an image we can save to disk
26+
127
use wgpu::util::DeviceExt; // Utility trait to create and initialize buffers with device.create_buffer_init()
228

329
fn main() {
@@ -6,35 +32,41 @@ fn main() {
632
}
733

834
async fn run() {
9-
// Initializing WebGPU
35+
// (1) Initializing WebGPU
1036
println!("Initializing WebGPU ...");
1137
let (device, queue) = init_wgpu_device().await.unwrap();
1238

13-
// Initialize the output texture
39+
// (2) Initialize the output texture
1440
let texture = init_output_texture(&device, 256);
1541
let texture_view = texture.create_view(&Default::default());
1642

17-
// Create and initialize the vertex buffer for the triangle vertices
43+
// (3) Initialize a buffer for the texture output
44+
let output_buffer_desc = create_texture_buffer_descriptor(&texture);
45+
let output_buffer = device.create_buffer(&output_buffer_desc);
46+
47+
// (4) Create and initialize the vertex buffer for the triangle vertices
1848
// (needs the DeviceExt trait)
1949
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
2050
label: Some("Vertex Buffer"),
2151
contents: bytemuck::cast_slice(VERTICES),
2252
usage: wgpu::BufferUsages::VERTEX,
2353
});
2454

25-
// Create and initialize the index buffer for the indices of the triangle face
55+
// (5) Create and initialize the index buffer for the indices of the triangle face
2656
// (needs the DeviceExt trait)
2757
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
2858
label: Some("Index Buffer"),
2959
contents: bytemuck::cast_slice(INDICES),
3060
usage: wgpu::BufferUsages::INDEX,
3161
});
3262

33-
// Define our pipeline
63+
// (6) Load the shader module, containing both the vertex and fragment shaders
3464
let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
3565
label: Some("triangle_shader"),
3666
source: wgpu::ShaderSource::Wgsl(include_str!("triangle.wgsl").into()),
3767
});
68+
69+
// (7) Define our pipeline
3870
let pipeline = build_simple_pipeline(
3971
&device,
4072
&shader_module,
@@ -45,7 +77,7 @@ async fn run() {
4577
// Initialize a command encoder
4678
let mut encoder = device.create_command_encoder(&Default::default());
4779

48-
// Draw our pipeline (add render pass to the command encoder)
80+
// (8.1) Draw our pipeline (add render pass to the command encoder)
4981
// This needs to be inside {...} or a function so that the &pipeline lifetime works.
5082
draw_pipeline(
5183
&mut encoder,
@@ -56,18 +88,14 @@ async fn run() {
5688
INDICES.len() as u32,
5789
);
5890

59-
// Initialize a buffer for the texture output
60-
let output_buffer_desc = create_texture_buffer_descriptor(&texture);
61-
let output_buffer = device.create_buffer(&output_buffer_desc);
62-
63-
// Copy the texture output into a buffer
91+
// (8.2) Copy the texture output into a buffer
6492
copy_texture_to_buffer(&mut encoder, &texture, &output_buffer);
6593

66-
// Finalize the command encoder and send it to the queue
94+
// (9) Finalize the command encoder and send it to the queue
6795
println!("Submitting commands to the queue ...");
6896
queue.submit(Some(encoder.finish()));
6997

70-
// Transfer the texture output buffer into an image buffer
98+
// (10) Transfer the texture output buffer into an image buffer
7199
println!("Saving the GPU output into an image ...");
72100
let img = to_image(&device, &output_buffer, texture.width(), texture.height()).await;
73101

@@ -80,7 +108,7 @@ async fn run() {
80108
println!("Terminating the program ...")
81109
}
82110

83-
/// Initializing WebGPU
111+
/// (1) Initializing WebGPU
84112
async fn init_wgpu_device() -> Result<(wgpu::Device, wgpu::Queue), wgpu::RequestDeviceError> {
85113
// Start an "Instance", which is the context for all things wgpu.
86114
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
@@ -104,7 +132,7 @@ async fn init_wgpu_device() -> Result<(wgpu::Device, wgpu::Queue), wgpu::Request
104132
adapter.request_device(&Default::default(), None).await
105133
}
106134

107-
/// Initialize the output texture
135+
/// (2) Initialize the output texture
108136
fn init_output_texture(device: &wgpu::Device, texture_size: u32) -> wgpu::Texture {
109137
let texture_desc = wgpu::TextureDescriptor {
110138
label: Some("output_texture"),
@@ -128,6 +156,19 @@ fn init_output_texture(device: &wgpu::Device, texture_size: u32) -> wgpu::Textur
128156
device.create_texture(&texture_desc)
129157
}
130158

159+
/// (3) Create a buffer descriptor of the correct size for the texture
160+
fn create_texture_buffer_descriptor(texture: &wgpu::Texture) -> wgpu::BufferDescriptor {
161+
let texel_size = texture.format().block_copy_size(None).unwrap();
162+
wgpu::BufferDescriptor {
163+
size: (texel_size * texture.width() * texture.height()).into(),
164+
usage: wgpu::BufferUsages::COPY_DST
165+
// this tells wpgu that we want to read this buffer from the cpu
166+
| wgpu::BufferUsages::MAP_READ,
167+
label: None,
168+
mapped_at_creation: false,
169+
}
170+
}
171+
131172
/// Each corner of the triangle is a Vertex with the following properties
132173
/// Bytemuck is used to enable easy casting to a &[u8].
133174
#[repr(C)]
@@ -179,7 +220,7 @@ impl Vertex {
179220
}
180221
}
181222

182-
/// Define our simple render pipeline
223+
/// (7) Define our simple render pipeline
183224
fn build_simple_pipeline(
184225
device: &wgpu::Device,
185226
shader_module: &wgpu::ShaderModule,
@@ -230,7 +271,7 @@ fn build_simple_pipeline(
230271
})
231272
}
232273

233-
/// Draw our pipeline (add render pass to the command encoder).
274+
/// (8.1) Draw our pipeline (add render pass to the command encoder).
234275
fn draw_pipeline(
235276
encoder: &mut wgpu::CommandEncoder,
236277
pipeline: &wgpu::RenderPipeline,
@@ -268,20 +309,7 @@ fn draw_pipeline(
268309
render_pass.draw_indexed(0..num_indices, 0, 0..1);
269310
}
270311

271-
/// Create a buffer descriptor of the correct size for the texture
272-
fn create_texture_buffer_descriptor(texture: &wgpu::Texture) -> wgpu::BufferDescriptor {
273-
let texel_size = texture.format().block_copy_size(None).unwrap();
274-
wgpu::BufferDescriptor {
275-
size: (texel_size * texture.width() * texture.height()).into(),
276-
usage: wgpu::BufferUsages::COPY_DST
277-
// this tells wpgu that we want to read this buffer from the cpu
278-
| wgpu::BufferUsages::MAP_READ,
279-
label: None,
280-
mapped_at_creation: false,
281-
}
282-
}
283-
284-
/// Copy the texture output into a buffer
312+
/// (8.2) Copy the texture output into a buffer
285313
fn copy_texture_to_buffer(
286314
encoder: &mut wgpu::CommandEncoder,
287315
texture: &wgpu::Texture,
@@ -310,7 +338,7 @@ fn copy_texture_to_buffer(
310338
);
311339
}
312340

313-
/// Copy the texture output buffer into an image buffer
341+
/// (10) Copy the texture output buffer into an image buffer
314342
async fn to_image(
315343
device: &wgpu::Device,
316344
texture_buffer: &wgpu::Buffer,

0 commit comments

Comments
 (0)