wgpu/api/render_pass.rs
1use core::{num::NonZeroU32, ops::Range};
2
3use crate::{
4 api::{impl_deferred_command_buffer_actions, SharedDeferredCommandBufferActions},
5 *,
6};
7pub use wgt::{LoadOp, Operations, StoreOp};
8
9/// In-progress recording of a render pass: a list of render commands in a [`CommandEncoder`].
10///
11/// It can be created with [`CommandEncoder::begin_render_pass()`], whose [`RenderPassDescriptor`]
12/// specifies the attachments (textures) that will be rendered to.
13///
14/// Most of the methods on `RenderPass` serve one of two purposes, identifiable by their names:
15///
16/// * `draw_*()`: Drawing (that is, encoding a render command, which, when executed by the GPU, will
17/// rasterize something and execute shaders).
18/// * `set_*()`: Setting part of the [render state](https://gpuweb.github.io/gpuweb/#renderstate)
19/// for future drawing commands.
20///
21/// A render pass may contain any number of drawing commands, and before/between each command the
22/// render state may be updated however you wish; each drawing command will be executed using the
23/// render state that has been set when the `draw_*()` function is called.
24///
25/// Corresponds to [WebGPU `GPURenderPassEncoder`](
26/// https://gpuweb.github.io/gpuweb/#render-pass-encoder).
27#[derive(Debug)]
28pub struct RenderPass<'encoder> {
29 pub(crate) inner: dispatch::DispatchRenderPass,
30 pub(crate) actions: SharedDeferredCommandBufferActions,
31
32 /// This lifetime is used to protect the [`CommandEncoder`] from being used
33 /// while the pass is alive. This needs to be PhantomDrop to prevent the lifetime
34 /// from being shortened.
35 pub(crate) _encoder_guard: PhantomDrop<&'encoder ()>,
36}
37
38#[cfg(send_sync)]
39static_assertions::assert_impl_all!(RenderPass<'_>: Send, Sync);
40
41crate::cmp::impl_eq_ord_hash_proxy!(RenderPass<'_> => .inner);
42
43impl RenderPass<'_> {
44 /// Drops the lifetime relationship to the parent command encoder, making usage of
45 /// the encoder while this pass is recorded a run-time error instead.
46 ///
47 /// Attention: As long as the render pass has not been ended, any mutating operation on the parent
48 /// command encoder will cause a run-time error and invalidate it!
49 /// By default, the lifetime constraint prevents this, but it can be useful
50 /// to handle this at run time, such as when storing the pass and encoder in the same
51 /// data structure.
52 ///
53 /// This operation has no effect on pass recording.
54 /// It's a safe operation, since [`CommandEncoder`] is in a locked state as long as the pass is active
55 /// regardless of the lifetime constraint or its absence.
56 pub fn forget_lifetime(self) -> RenderPass<'static> {
57 RenderPass {
58 inner: self.inner,
59 actions: self.actions,
60 _encoder_guard: crate::api::PhantomDrop::default(),
61 }
62 }
63
64 /// Sets the active bind group for a given bind group index. The bind group layout
65 /// in the active pipeline when any `draw_*()` method is called must match the layout of
66 /// this bind group.
67 ///
68 /// If the bind group have dynamic offsets, provide them in binding order.
69 /// These offsets have to be aligned to [`Limits::min_uniform_buffer_offset_alignment`]
70 /// or [`Limits::min_storage_buffer_offset_alignment`] appropriately.
71 ///
72 /// Subsequent draw calls’ shader executions will be able to access data in these bind groups.
73 pub fn set_bind_group<'a, BG>(&mut self, index: u32, bind_group: BG, offsets: &[DynamicOffset])
74 where
75 Option<&'a BindGroup>: From<BG>,
76 {
77 let bg: Option<&'a BindGroup> = bind_group.into();
78 let bg = bg.map(|bg| &bg.inner);
79
80 self.inner.set_bind_group(index, bg, offsets);
81 }
82
83 /// Sets the active render pipeline.
84 ///
85 /// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
86 pub fn set_pipeline(&mut self, pipeline: &RenderPipeline) {
87 self.inner.set_pipeline(&pipeline.inner);
88 }
89
90 /// Sets the blend color as used by some of the blending modes.
91 ///
92 /// Subsequent blending tests will test against this value.
93 /// If this method has not been called, the blend constant defaults to [`Color::TRANSPARENT`]
94 /// (all components zero).
95 pub fn set_blend_constant(&mut self, color: Color) {
96 self.inner.set_blend_constant(color);
97 }
98
99 /// Sets the active index buffer.
100 ///
101 /// Subsequent calls to [`draw_indexed`](RenderPass::draw_indexed) on this [`RenderPass`] will
102 /// use `buffer` as the source index buffer.
103 ///
104 /// # Panics
105 ///
106 /// - If the buffer slice length is 0.
107 pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'_>, index_format: IndexFormat) {
108 self.inner.set_index_buffer(
109 &buffer_slice.buffer.inner,
110 index_format,
111 buffer_slice.offset,
112 Some(buffer_slice.size),
113 );
114 }
115
116 /// Assign a vertex buffer to a slot.
117 ///
118 /// Subsequent calls to [`draw`] and [`draw_indexed`] on this
119 /// [`RenderPass`] will use `buffer` as one of the source vertex buffers.
120 /// The format of the data in the buffer is specified by the [`VertexBufferLayout`] in the
121 /// pipeline's [`VertexState`].
122 ///
123 /// The `slot` refers to the index of the matching descriptor in
124 /// [`VertexState::buffers`].
125 ///
126 /// [`draw`]: RenderPass::draw
127 /// [`draw_indexed`]: RenderPass::draw_indexed
128 ///
129 /// # Panics
130 ///
131 /// - If the buffer slice length is 0.
132 pub fn set_vertex_buffer<'b, B>(&mut self, slot: u32, buffer_slice: B)
133 where
134 Option<BufferSlice<'b>>: From<B>,
135 {
136 let buffer_slice: Option<BufferSlice<'b>> = buffer_slice.into();
137 if let Some(buffer_slice) = buffer_slice {
138 self.inner.set_vertex_buffer(
139 slot,
140 Some(&buffer_slice.buffer.inner),
141 buffer_slice.offset,
142 Some(buffer_slice.size),
143 );
144 } else {
145 self.inner.set_vertex_buffer(slot, None, 0, None);
146 }
147 }
148
149 /// Sets the scissor rectangle used during the rasterization stage.
150 /// After transformation into [viewport coordinates](https://www.w3.org/TR/webgpu/#viewport-coordinates).
151 ///
152 /// Subsequent draw calls will discard any fragments which fall outside the scissor rectangle.
153 /// If this method has not been called, the scissor rectangle defaults to the entire bounds of
154 /// the render targets.
155 ///
156 /// The function of the scissor rectangle resembles [`set_viewport()`](Self::set_viewport),
157 /// but it does not affect the coordinate system, only which fragments are discarded.
158 pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
159 self.inner.set_scissor_rect(x, y, width, height);
160 }
161
162 /// Sets the viewport used during the rasterization stage to linearly map
163 /// from [normalized device coordinates](https://www.w3.org/TR/webgpu/#ndc) to [viewport coordinates](https://www.w3.org/TR/webgpu/#viewport-coordinates).
164 ///
165 /// Subsequent draw calls will only draw within this region.
166 /// If this method has not been called, the viewport defaults to the entire bounds of the render
167 /// targets.
168 pub fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) {
169 self.inner.set_viewport(x, y, w, h, min_depth, max_depth);
170 }
171
172 /// Sets the stencil reference.
173 ///
174 /// Subsequent stencil tests will test against this value.
175 /// If this method has not been called, the stencil reference value defaults to `0`.
176 pub fn set_stencil_reference(&mut self, reference: u32) {
177 self.inner.set_stencil_reference(reference);
178 }
179
180 /// Inserts debug marker.
181 pub fn insert_debug_marker(&mut self, label: &str) {
182 self.inner.insert_debug_marker(label);
183 }
184
185 /// Start record commands and group it into debug marker group.
186 pub fn push_debug_group(&mut self, label: &str) {
187 self.inner.push_debug_group(label);
188 }
189
190 /// Stops command recording and creates debug group.
191 pub fn pop_debug_group(&mut self) {
192 self.inner.pop_debug_group();
193 }
194
195 /// Draws primitives from the active vertex buffer(s).
196 ///
197 /// The active vertex buffer(s) can be set with [`RenderPass::set_vertex_buffer`].
198 /// This does not use an index buffer. If you need indexed drawing, see [`RenderPass::draw_indexed`]
199 ///
200 /// Panics if `vertices` range is outside of the range of the vertices range of any set vertex buffer.
201 ///
202 /// - `vertices`: The range of vertices to draw.
203 /// - `instances`: Range of instances to draw. Use `0..1` if instance buffers are not used.
204 ///
205 /// E.g.of how its used internally
206 /// ```rust ignore
207 /// for instance_id in instance_range {
208 /// for vertex_id in vertex_range {
209 /// let vertex = vertex[vertex_id];
210 /// vertex_shader(vertex, vertex_id, instance_id);
211 /// }
212 /// }
213 /// ```
214 ///
215 /// This drawing command uses the current render state, as set by preceding `set_*()` methods.
216 /// It is not affected by changes to the state that are performed after it is called.
217 pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
218 self.inner.draw(vertices, instances);
219 }
220
221 /// Draws indexed primitives using the active index buffer and the active vertex buffers.
222 ///
223 /// The active index buffer can be set with [`RenderPass::set_index_buffer`]
224 /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
225 ///
226 /// Panics if `indices` range is outside of the range of the indices range of the set index buffer.
227 ///
228 /// - `indices`: The range of indices to draw.
229 /// - `base_vertex`: value added to each index value before indexing into the vertex buffers.
230 /// - `instances`: Range of instances to draw. Use `0..1` if instance buffers are not used.
231 ///
232 /// E.g.of how its used internally
233 /// ```rust ignore
234 /// for instance_id in instance_range {
235 /// for index_index in index_range {
236 /// let vertex_id = index_buffer[index_index];
237 /// let adjusted_vertex_id = vertex_id + base_vertex;
238 /// let vertex = vertex[adjusted_vertex_id];
239 /// vertex_shader(vertex, adjusted_vertex_id, instance_id);
240 /// }
241 /// }
242 /// ```
243 ///
244 /// This drawing command uses the current render state, as set by preceding `set_*()` methods.
245 /// It is not affected by changes to the state that are performed after it is called.
246 pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
247 self.inner.draw_indexed(indices, base_vertex, instances);
248 }
249
250 /// Draws using a mesh pipeline.
251 ///
252 /// The current pipeline must be a mesh pipeline.
253 ///
254 /// If the current pipeline has a task shader, run it with an workgroup for
255 /// every `vec3<u32>(i, j, k)` where `i`, `j`, and `k` are between `0` and
256 /// `group_count_x`, `group_count_y`, and `group_count_z`. The invocation with
257 /// index zero in each group is responsible for determining the mesh shader dispatch.
258 /// Its return value indicates the number of workgroups of mesh shaders to invoke. It also
259 /// passes a payload value for them to consume. Because each task workgroup is essentially
260 /// a mesh shader draw call, mesh workgroups dispatched by different task workgroups
261 /// cannot interact in any way, and `workgroup_id` corresponds to its location in the
262 /// calling specific task shader's dispatch group.
263 ///
264 /// If the current pipeline lacks a task shader, run its mesh shader with a
265 /// workgroup for every `vec3<u32>(i, j, k)` where `i`, `j`, and `k` are
266 /// between `0` and `group_count_x`, `group_count_y`, and `group_count_z`.
267 ///
268 /// Each mesh shader workgroup outputs a set of vertices and indices for primitives.
269 /// The indices outputted correspond to the vertices outputted by that same workgroup;
270 /// there is no global vertex buffer. These primitives are passed to the rasterizer and
271 /// essentially treated like a vertex shader output, except that the mesh shader may
272 /// choose to cull specific primitives or pass per-primitive non-interpolated values
273 /// to the fragment shader. As such, each primitive is then rendered with the current
274 /// pipeline's fragment shader, if present. Otherwise, [No Color Output mode] is used.
275 ///
276 /// [No Color Output mode]: https://www.w3.org/TR/webgpu/#no-color-output
277 pub fn draw_mesh_tasks(&mut self, group_count_x: u32, group_count_y: u32, group_count_z: u32) {
278 self.inner
279 .draw_mesh_tasks(group_count_x, group_count_y, group_count_z);
280 }
281
282 /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
283 ///
284 /// This is like calling [`RenderPass::draw`] but the contents of the call are specified in the `indirect_buffer`.
285 /// The structure expected in `indirect_buffer` must conform to [`DrawIndirectArgs`](crate::util::DrawIndirectArgs).
286 ///
287 /// Calling this requires the device support [`DownlevelFlags::INDIRECT_EXECUTION`].
288 pub fn draw_indirect(&mut self, indirect_buffer: &Buffer, indirect_offset: BufferAddress) {
289 self.inner
290 .draw_indirect(&indirect_buffer.inner, indirect_offset);
291 }
292
293 /// Draws indexed primitives using the active index buffer and the active vertex buffers,
294 /// based on the contents of the `indirect_buffer`.
295 ///
296 /// This is like calling [`RenderPass::draw_indexed`] but the contents of the call are specified in the `indirect_buffer`.
297 /// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirectArgs`](crate::util::DrawIndexedIndirectArgs).
298 ///
299 /// Calling this requires the device support [`DownlevelFlags::INDIRECT_EXECUTION`].
300 pub fn draw_indexed_indirect(
301 &mut self,
302 indirect_buffer: &Buffer,
303 indirect_offset: BufferAddress,
304 ) {
305 self.inner
306 .draw_indexed_indirect(&indirect_buffer.inner, indirect_offset);
307 }
308
309 /// Draws using a mesh pipeline,
310 /// based on the contents of the `indirect_buffer`
311 ///
312 /// This is like calling [`RenderPass::draw_mesh_tasks`] but the contents of the call are specified in the `indirect_buffer`.
313 /// The structure expected in the `indirect_buffer` must conform to [`DispatchIndirectArgs`](crate::util::DispatchIndirectArgs).
314 ///
315 /// Indirect drawing has some caveats depending on the features available. We are not currently able to validate
316 /// these and issue an error.
317 ///
318 /// See details on the individual flags for more information.
319 pub fn draw_mesh_tasks_indirect(
320 &mut self,
321 indirect_buffer: &Buffer,
322 indirect_offset: BufferAddress,
323 ) {
324 self.inner
325 .draw_mesh_tasks_indirect(&indirect_buffer.inner, indirect_offset);
326 }
327
328 impl_deferred_command_buffer_actions!();
329
330 /// Execute a [render bundle][RenderBundle], which is a set of pre-recorded commands
331 /// that can be run together.
332 ///
333 /// Commands in the bundle do not inherit this render pass's current render state, and after the
334 /// bundle has executed, the state is **cleared** (reset to defaults, not the previous state).
335 pub fn execute_bundles<'a, I: IntoIterator<Item = &'a RenderBundle>>(
336 &mut self,
337 render_bundles: I,
338 ) {
339 let mut render_bundles = render_bundles.into_iter().map(|rb| &rb.inner);
340
341 self.inner.execute_bundles(&mut render_bundles);
342 }
343
344 /// Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
345 /// `count` draw calls are issued.
346 ///
347 /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
348 ///
349 /// The structure expected in `indirect_buffer` must conform to [`DrawIndirectArgs`](crate::util::DrawIndirectArgs).
350 /// These draw structures are expected to be tightly packed.
351 ///
352 /// Calling this requires the device support [`DownlevelFlags::INDIRECT_EXECUTION`].
353 ///
354 /// This drawing command uses the current render state, as set by preceding `set_*()` methods.
355 /// It is not affected by changes to the state that are performed after it is called.
356 pub fn multi_draw_indirect(
357 &mut self,
358 indirect_buffer: &Buffer,
359 indirect_offset: BufferAddress,
360 count: u32,
361 ) {
362 self.inner
363 .multi_draw_indirect(&indirect_buffer.inner, indirect_offset, count);
364 }
365
366 /// Dispatches multiple draw calls from the active index buffer and the active vertex buffers,
367 /// based on the contents of the `indirect_buffer`. `count` draw calls are issued.
368 ///
369 /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
370 /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
371 ///
372 /// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirectArgs`](crate::util::DrawIndexedIndirectArgs).
373 /// These draw structures are expected to be tightly packed.
374 ///
375 /// Calling this requires the device support [`DownlevelFlags::INDIRECT_EXECUTION`].
376 ///
377 /// This drawing command uses the current render state, as set by preceding `set_*()` methods.
378 /// It is not affected by changes to the state that are performed after it is called.
379 pub fn multi_draw_indexed_indirect(
380 &mut self,
381 indirect_buffer: &Buffer,
382 indirect_offset: BufferAddress,
383 count: u32,
384 ) {
385 self.inner
386 .multi_draw_indexed_indirect(&indirect_buffer.inner, indirect_offset, count);
387 }
388
389 /// Dispatches multiple draw calls based on the contents of the `indirect_buffer`.
390 /// `count` draw calls are issued.
391 ///
392 /// The structure expected in the `indirect_buffer` must conform to [`DispatchIndirectArgs`](crate::util::DispatchIndirectArgs).
393 ///
394 /// This drawing command uses the current render state, as set by preceding `set_*()` methods.
395 /// It is not affected by changes to the state that are performed after it is called.
396 pub fn multi_draw_mesh_tasks_indirect(
397 &mut self,
398 indirect_buffer: &Buffer,
399 indirect_offset: BufferAddress,
400 count: u32,
401 ) {
402 self.inner
403 .multi_draw_mesh_tasks_indirect(&indirect_buffer.inner, indirect_offset, count);
404 }
405
406 #[cfg(custom)]
407 /// Returns custom implementation of RenderPass (if custom backend and is internally T)
408 pub fn as_custom<T: custom::RenderPassInterface>(&self) -> Option<&T> {
409 self.inner.as_custom()
410 }
411}
412
413/// [`Features::MULTI_DRAW_INDIRECT_COUNT`] must be enabled on the device in order to call these functions.
414impl RenderPass<'_> {
415 /// Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
416 /// The count buffer is read to determine how many draws to issue.
417 ///
418 /// The indirect buffer must be long enough to account for `max_count` draws, however only `count`
419 /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
420 ///
421 /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
422 ///
423 /// The structure expected in `indirect_buffer` must conform to [`DrawIndirectArgs`](crate::util::DrawIndirectArgs).
424 /// These draw structures are expected to be tightly packed.
425 ///
426 /// The structure expected in `count_buffer` is the following:
427 ///
428 /// ```rust
429 /// #[repr(C)]
430 /// struct DrawIndirectCount {
431 /// count: u32, // Number of draw calls to issue.
432 /// }
433 /// ```
434 ///
435 /// This drawing command uses the current render state, as set by preceding `set_*()` methods.
436 /// It is not affected by changes to the state that are performed after it is called.
437 pub fn multi_draw_indirect_count(
438 &mut self,
439 indirect_buffer: &Buffer,
440 indirect_offset: BufferAddress,
441 count_buffer: &Buffer,
442 count_offset: BufferAddress,
443 max_count: u32,
444 ) {
445 self.inner.multi_draw_indirect_count(
446 &indirect_buffer.inner,
447 indirect_offset,
448 &count_buffer.inner,
449 count_offset,
450 max_count,
451 );
452 }
453
454 /// Dispatches multiple draw calls from the active index buffer and the active vertex buffers,
455 /// based on the contents of the `indirect_buffer`. The count buffer is read to determine how many draws to issue.
456 ///
457 /// The indirect buffer must be long enough to account for `max_count` draws, however only `count`
458 /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
459 ///
460 /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
461 /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
462 ///
463 /// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirectArgs`](crate::util::DrawIndexedIndirectArgs).
464 ///
465 /// These draw structures are expected to be tightly packed.
466 ///
467 /// The structure expected in `count_buffer` is the following:
468 ///
469 /// ```rust
470 /// #[repr(C)]
471 /// struct DrawIndexedIndirectCount {
472 /// count: u32, // Number of draw calls to issue.
473 /// }
474 /// ```
475 ///
476 /// This drawing command uses the current render state, as set by preceding `set_*()` methods.
477 /// It is not affected by changes to the state that are performed after it is called.
478 pub fn multi_draw_indexed_indirect_count(
479 &mut self,
480 indirect_buffer: &Buffer,
481 indirect_offset: BufferAddress,
482 count_buffer: &Buffer,
483 count_offset: BufferAddress,
484 max_count: u32,
485 ) {
486 self.inner.multi_draw_indexed_indirect_count(
487 &indirect_buffer.inner,
488 indirect_offset,
489 &count_buffer.inner,
490 count_offset,
491 max_count,
492 );
493 }
494
495 /// Dispatches multiple draw calls based on the contents of the `indirect_buffer`. The count buffer is read to determine how many draws to issue.
496 ///
497 /// The indirect buffer must be long enough to account for `max_count` draws, however only `count`
498 /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
499 ///
500 /// The structure expected in the `indirect_buffer` must conform to [`DispatchIndirectArgs`](crate::util::DispatchIndirectArgs).
501 ///
502 /// These draw structures are expected to be tightly packed.
503 ///
504 /// This drawing command uses the current render state, as set by preceding `set_*()` methods.
505 /// It is not affected by changes to the state that are performed after it is called.
506 pub fn multi_draw_mesh_tasks_indirect_count(
507 &mut self,
508 indirect_buffer: &Buffer,
509 indirect_offset: BufferAddress,
510 count_buffer: &Buffer,
511 count_offset: BufferAddress,
512 max_count: u32,
513 ) {
514 self.inner.multi_draw_mesh_tasks_indirect_count(
515 &indirect_buffer.inner,
516 indirect_offset,
517 &count_buffer.inner,
518 count_offset,
519 max_count,
520 );
521 }
522}
523
524/// [`Features::IMMEDIATES`] must be enabled on the device in order to call these functions.
525impl RenderPass<'_> {
526 /// Set immediate data for subsequent draw calls.
527 ///
528 /// Write the bytes in `data` at offset `offset` within immediate data
529 /// storage. Both `offset` and the length of `data` must be
530 /// multiples of [`crate::IMMEDIATE_DATA_ALIGNMENT`], which is always 4.
531 ///
532 /// For example, if `offset` is `4` and `data` is eight bytes long, this
533 /// call will write `data` to bytes `4..12` of immediate data storage.
534 pub fn set_immediates(&mut self, offset: u32, data: &[u8]) {
535 self.inner.set_immediates(offset, data);
536 }
537}
538
539/// [`Features::TIMESTAMP_QUERY_INSIDE_PASSES`] must be enabled on the device in order to call these functions.
540impl RenderPass<'_> {
541 /// Issue a timestamp command at this point in the queue. The
542 /// timestamp will be written to the specified query set, at the specified index.
543 ///
544 /// Must be multiplied by [`Queue::get_timestamp_period`] to get
545 /// the value in nanoseconds. Absolute values have no meaning,
546 /// but timestamps can be subtracted to get the time it takes
547 /// for a string of operations to complete.
548 pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) {
549 self.inner.write_timestamp(&query_set.inner, query_index);
550 }
551}
552
553impl RenderPass<'_> {
554 /// Start a occlusion query on this render pass. It can be ended with
555 /// [`end_occlusion_query`](Self::end_occlusion_query).
556 /// Occlusion queries may not be nested.
557 pub fn begin_occlusion_query(&mut self, query_index: u32) {
558 self.inner.begin_occlusion_query(query_index);
559 }
560
561 /// End the occlusion query on this render pass. It can be started with
562 /// [`begin_occlusion_query`](Self::begin_occlusion_query).
563 /// Occlusion queries may not be nested.
564 pub fn end_occlusion_query(&mut self) {
565 self.inner.end_occlusion_query();
566 }
567}
568
569/// [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled on the device in order to call these functions.
570impl RenderPass<'_> {
571 /// Start a pipeline statistics query on this render pass. It can be ended with
572 /// [`end_pipeline_statistics_query`](Self::end_pipeline_statistics_query).
573 /// Pipeline statistics queries may not be nested.
574 ///
575 /// The amount of information collected by this query, and the space occupied in the query set,
576 /// is determined by the [`PipelineStatisticsTypes`] the query set was created with.
577 /// `query_index` is the index of the first query result slot that will be written to, and
578 /// `query_set` must have sufficient size to hold all results written starting at that slot.
579 pub fn begin_pipeline_statistics_query(&mut self, query_set: &QuerySet, query_index: u32) {
580 self.inner
581 .begin_pipeline_statistics_query(&query_set.inner, query_index);
582 }
583
584 /// End the pipeline statistics query on this render pass. It can be started with
585 /// [`begin_pipeline_statistics_query`](Self::begin_pipeline_statistics_query).
586 /// Pipeline statistics queries may not be nested.
587 pub fn end_pipeline_statistics_query(&mut self) {
588 self.inner.end_pipeline_statistics_query();
589 }
590}
591
592/// Describes the timestamp writes of a render pass.
593///
594/// For use with [`RenderPassDescriptor`].
595/// At least one of [`Self::beginning_of_pass_write_index`] and [`Self::end_of_pass_write_index`]
596/// must be `Some`.
597///
598/// Corresponds to [WebGPU `GPURenderPassTimestampWrite`](
599/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderpasstimestampwrites).
600#[derive(Clone, Debug)]
601pub struct RenderPassTimestampWrites<'a> {
602 /// The query set to write to.
603 pub query_set: &'a QuerySet,
604 /// The index of the query set at which a start timestamp of this pass is written, if any.
605 pub beginning_of_pass_write_index: Option<u32>,
606 /// The index of the query set at which an end timestamp of this pass is written, if any.
607 pub end_of_pass_write_index: Option<u32>,
608}
609#[cfg(send_sync)]
610static_assertions::assert_impl_all!(RenderPassTimestampWrites<'_>: Send, Sync);
611
612/// Describes a color attachment to a [`RenderPass`].
613///
614/// For use with [`RenderPassDescriptor`].
615///
616/// Corresponds to [WebGPU `GPURenderPassColorAttachment`](
617/// https://gpuweb.github.io/gpuweb/#color-attachments).
618#[derive(Clone, Debug)]
619pub struct RenderPassColorAttachment<'tex> {
620 /// The view to use as an attachment.
621 pub view: &'tex TextureView,
622 /// The depth slice index of a 3D view. It must not be provided if the view is not 3D.
623 pub depth_slice: Option<u32>,
624 /// The view that will receive the resolved output if multisampling is used.
625 ///
626 /// If set, it is always written to, regardless of how [`Self::ops`] is configured.
627 pub resolve_target: Option<&'tex TextureView>,
628 /// What operations will be performed on this color attachment.
629 pub ops: Operations<Color>,
630}
631#[cfg(send_sync)]
632static_assertions::assert_impl_all!(RenderPassColorAttachment<'_>: Send, Sync);
633
634/// Describes a depth/stencil attachment to a [`RenderPass`].
635///
636/// For use with [`RenderPassDescriptor`].
637///
638/// Corresponds to [WebGPU `GPURenderPassDepthStencilAttachment`](
639/// https://gpuweb.github.io/gpuweb/#depth-stencil-attachments).
640#[derive(Clone, Debug)]
641pub struct RenderPassDepthStencilAttachment<'tex> {
642 /// The view to use as an attachment.
643 pub view: &'tex TextureView,
644 /// What operations will be performed on the depth part of the attachment.
645 pub depth_ops: Option<Operations<f32>>,
646 /// What operations will be performed on the stencil part of the attachment.
647 pub stencil_ops: Option<Operations<u32>>,
648}
649#[cfg(send_sync)]
650static_assertions::assert_impl_all!(RenderPassDepthStencilAttachment<'_>: Send, Sync);
651
652/// Describes the attachments of a render pass.
653///
654/// For use with [`CommandEncoder::begin_render_pass`].
655///
656/// Corresponds to [WebGPU `GPURenderPassDescriptor`](
657/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderpassdescriptor).
658#[derive(Clone, Debug, Default)]
659pub struct RenderPassDescriptor<'a> {
660 /// Debug label of the render pass. This will show up in graphics debuggers for easy identification.
661 pub label: Label<'a>,
662 /// The color attachments of the render pass.
663 pub color_attachments: &'a [Option<RenderPassColorAttachment<'a>>],
664 /// The depth and stencil attachment of the render pass, if any.
665 pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachment<'a>>,
666 /// Defines which timestamp values will be written for this pass, and where to write them to.
667 ///
668 /// Requires [`Features::TIMESTAMP_QUERY`] to be enabled.
669 pub timestamp_writes: Option<RenderPassTimestampWrites<'a>>,
670 /// Defines where the occlusion query results will be stored for this pass.
671 pub occlusion_query_set: Option<&'a QuerySet>,
672 /// The mask of multiview image layers to use for this render pass. For example, if you wish
673 /// to render to the first 2 layers, you would use 3=0b11. If you wanted ro render to only the
674 /// 2nd layer, you would use 2=0b10. If you aren't using multiview this should be `None`.
675 ///
676 /// Note that setting bits higher than the number of texture layers is a validation error.
677 ///
678 /// This doesn't influence load/store/clear/etc operations, as those are defined for attachments,
679 /// therefore affecting all attachments. Meaning, this affects only any shaders executed on the `RenderPass`.
680 pub multiview_mask: Option<NonZeroU32>,
681}
682#[cfg(send_sync)]
683static_assertions::assert_impl_all!(RenderPassDescriptor<'_>: Send, Sync);