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