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
+
1
27
use wgpu:: util:: DeviceExt ; // Utility trait to create and initialize buffers with device.create_buffer_init()
2
28
3
29
fn main ( ) {
@@ -6,35 +32,41 @@ fn main() {
6
32
}
7
33
8
34
async fn run ( ) {
9
- // Initializing WebGPU
35
+ // (1) Initializing WebGPU
10
36
println ! ( "Initializing WebGPU ..." ) ;
11
37
let ( device, queue) = init_wgpu_device ( ) . await . unwrap ( ) ;
12
38
13
- // Initialize the output texture
39
+ // (2) Initialize the output texture
14
40
let texture = init_output_texture ( & device, 256 ) ;
15
41
let texture_view = texture. create_view ( & Default :: default ( ) ) ;
16
42
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
18
48
// (needs the DeviceExt trait)
19
49
let vertex_buffer = device. create_buffer_init ( & wgpu:: util:: BufferInitDescriptor {
20
50
label : Some ( "Vertex Buffer" ) ,
21
51
contents : bytemuck:: cast_slice ( VERTICES ) ,
22
52
usage : wgpu:: BufferUsages :: VERTEX ,
23
53
} ) ;
24
54
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
26
56
// (needs the DeviceExt trait)
27
57
let index_buffer = device. create_buffer_init ( & wgpu:: util:: BufferInitDescriptor {
28
58
label : Some ( "Index Buffer" ) ,
29
59
contents : bytemuck:: cast_slice ( INDICES ) ,
30
60
usage : wgpu:: BufferUsages :: INDEX ,
31
61
} ) ;
32
62
33
- // Define our pipeline
63
+ // (6) Load the shader module, containing both the vertex and fragment shaders
34
64
let shader_module = device. create_shader_module ( wgpu:: ShaderModuleDescriptor {
35
65
label : Some ( "triangle_shader" ) ,
36
66
source : wgpu:: ShaderSource :: Wgsl ( include_str ! ( "triangle.wgsl" ) . into ( ) ) ,
37
67
} ) ;
68
+
69
+ // (7) Define our pipeline
38
70
let pipeline = build_simple_pipeline (
39
71
& device,
40
72
& shader_module,
@@ -45,7 +77,7 @@ async fn run() {
45
77
// Initialize a command encoder
46
78
let mut encoder = device. create_command_encoder ( & Default :: default ( ) ) ;
47
79
48
- // Draw our pipeline (add render pass to the command encoder)
80
+ // (8.1) Draw our pipeline (add render pass to the command encoder)
49
81
// This needs to be inside {...} or a function so that the &pipeline lifetime works.
50
82
draw_pipeline (
51
83
& mut encoder,
@@ -56,18 +88,14 @@ async fn run() {
56
88
INDICES . len ( ) as u32 ,
57
89
) ;
58
90
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
64
92
copy_texture_to_buffer ( & mut encoder, & texture, & output_buffer) ;
65
93
66
- // Finalize the command encoder and send it to the queue
94
+ // (9) Finalize the command encoder and send it to the queue
67
95
println ! ( "Submitting commands to the queue ..." ) ;
68
96
queue. submit ( Some ( encoder. finish ( ) ) ) ;
69
97
70
- // Transfer the texture output buffer into an image buffer
98
+ // (10) Transfer the texture output buffer into an image buffer
71
99
println ! ( "Saving the GPU output into an image ..." ) ;
72
100
let img = to_image ( & device, & output_buffer, texture. width ( ) , texture. height ( ) ) . await ;
73
101
@@ -80,7 +108,7 @@ async fn run() {
80
108
println ! ( "Terminating the program ..." )
81
109
}
82
110
83
- /// Initializing WebGPU
111
+ /// (1) Initializing WebGPU
84
112
async fn init_wgpu_device ( ) -> Result < ( wgpu:: Device , wgpu:: Queue ) , wgpu:: RequestDeviceError > {
85
113
// Start an "Instance", which is the context for all things wgpu.
86
114
let instance = wgpu:: Instance :: new ( wgpu:: InstanceDescriptor {
@@ -104,7 +132,7 @@ async fn init_wgpu_device() -> Result<(wgpu::Device, wgpu::Queue), wgpu::Request
104
132
adapter. request_device ( & Default :: default ( ) , None ) . await
105
133
}
106
134
107
- /// Initialize the output texture
135
+ /// (2) Initialize the output texture
108
136
fn init_output_texture ( device : & wgpu:: Device , texture_size : u32 ) -> wgpu:: Texture {
109
137
let texture_desc = wgpu:: TextureDescriptor {
110
138
label : Some ( "output_texture" ) ,
@@ -128,6 +156,19 @@ fn init_output_texture(device: &wgpu::Device, texture_size: u32) -> wgpu::Textur
128
156
device. create_texture ( & texture_desc)
129
157
}
130
158
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
+
131
172
/// Each corner of the triangle is a Vertex with the following properties
132
173
/// Bytemuck is used to enable easy casting to a &[u8].
133
174
#[ repr( C ) ]
@@ -179,7 +220,7 @@ impl Vertex {
179
220
}
180
221
}
181
222
182
- /// Define our simple render pipeline
223
+ /// (7) Define our simple render pipeline
183
224
fn build_simple_pipeline (
184
225
device : & wgpu:: Device ,
185
226
shader_module : & wgpu:: ShaderModule ,
@@ -230,7 +271,7 @@ fn build_simple_pipeline(
230
271
} )
231
272
}
232
273
233
- /// Draw our pipeline (add render pass to the command encoder).
274
+ /// (8.1) Draw our pipeline (add render pass to the command encoder).
234
275
fn draw_pipeline (
235
276
encoder : & mut wgpu:: CommandEncoder ,
236
277
pipeline : & wgpu:: RenderPipeline ,
@@ -268,20 +309,7 @@ fn draw_pipeline(
268
309
render_pass. draw_indexed ( 0 ..num_indices, 0 , 0 ..1 ) ;
269
310
}
270
311
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
285
313
fn copy_texture_to_buffer (
286
314
encoder : & mut wgpu:: CommandEncoder ,
287
315
texture : & wgpu:: Texture ,
@@ -310,7 +338,7 @@ fn copy_texture_to_buffer(
310
338
) ;
311
339
}
312
340
313
- /// Copy the texture output buffer into an image buffer
341
+ /// (10) Copy the texture output buffer into an image buffer
314
342
async fn to_image (
315
343
device : & wgpu:: Device ,
316
344
texture_buffer : & wgpu:: Buffer ,
0 commit comments