Skip to main content

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);