wgpu/api/
render_pass.rs

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