wgpu/api/
compute_pass.rs

1use crate::{
2    api::{impl_deferred_command_buffer_actions, SharedDeferredCommandBufferActions},
3    *,
4};
5
6/// In-progress recording of a compute pass.
7///
8/// It can be created with [`CommandEncoder::begin_compute_pass`].
9///
10/// Corresponds to [WebGPU `GPUComputePassEncoder`](
11/// https://gpuweb.github.io/gpuweb/#compute-pass-encoder).
12#[derive(Debug)]
13pub struct ComputePass<'encoder> {
14    pub(crate) inner: dispatch::DispatchComputePass,
15
16    /// Shared with CommandEncoder to enqueue deferred actions from within a pass.
17    pub(crate) actions: SharedDeferredCommandBufferActions,
18
19    /// This lifetime is used to protect the [`CommandEncoder`] from being used
20    /// while the pass is alive. This needs to be PhantomDrop to prevent the lifetime
21    /// from being shortened.
22    pub(crate) _encoder_guard: crate::api::PhantomDrop<&'encoder ()>,
23}
24
25#[cfg(send_sync)]
26static_assertions::assert_impl_all!(ComputePass<'_>: Send, Sync);
27
28crate::cmp::impl_eq_ord_hash_proxy!(ComputePass<'_> => .inner);
29
30impl ComputePass<'_> {
31    /// Drops the lifetime relationship to the parent command encoder, making usage of
32    /// the encoder while this pass is recorded a run-time error instead.
33    ///
34    /// Attention: As long as the compute pass has not been ended, any mutating operation on the parent
35    /// command encoder will cause a run-time error and invalidate it!
36    /// By default, the lifetime constraint prevents this, but it can be useful
37    /// to handle this at run time, such as when storing the pass and encoder in the same
38    /// data structure.
39    ///
40    /// This operation has no effect on pass recording.
41    /// It's a safe operation, since [`CommandEncoder`] is in a locked state as long as the pass is active
42    /// regardless of the lifetime constraint or its absence.
43    pub fn forget_lifetime(self) -> ComputePass<'static> {
44        ComputePass {
45            inner: self.inner,
46            actions: self.actions,
47            _encoder_guard: crate::api::PhantomDrop::default(),
48        }
49    }
50
51    /// Sets the active bind group for a given bind group index. The bind group layout
52    /// in the active pipeline when the `dispatch_workgroups()` function is called must match the layout of this bind group.
53    ///
54    /// If the bind group have dynamic offsets, provide them in the binding order.
55    /// These offsets have to be aligned to [`Limits::min_uniform_buffer_offset_alignment`]
56    /// or [`Limits::min_storage_buffer_offset_alignment`] appropriately.
57    pub fn set_bind_group<'a, BG>(&mut self, index: u32, bind_group: BG, offsets: &[DynamicOffset])
58    where
59        Option<&'a BindGroup>: From<BG>,
60    {
61        let bg: Option<&BindGroup> = bind_group.into();
62        let bg = bg.map(|bg| &bg.inner);
63        self.inner.set_bind_group(index, bg, offsets);
64    }
65
66    /// Sets the active compute pipeline.
67    pub fn set_pipeline(&mut self, pipeline: &ComputePipeline) {
68        self.inner.set_pipeline(&pipeline.inner);
69    }
70
71    /// Inserts debug marker.
72    pub fn insert_debug_marker(&mut self, label: &str) {
73        self.inner.insert_debug_marker(label);
74    }
75
76    /// Start record commands and group it into debug marker group.
77    pub fn push_debug_group(&mut self, label: &str) {
78        self.inner.push_debug_group(label);
79    }
80
81    /// Stops command recording and creates debug group.
82    pub fn pop_debug_group(&mut self) {
83        self.inner.pop_debug_group();
84    }
85
86    /// Dispatches compute work operations.
87    ///
88    /// `x`, `y` and `z` denote the number of work groups to dispatch in each dimension.
89    pub fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) {
90        self.inner.dispatch_workgroups(x, y, z);
91    }
92
93    /// Dispatches compute work operations, based on the contents of the `indirect_buffer`.
94    ///
95    /// The structure expected in `indirect_buffer` must conform to [`DispatchIndirectArgs`](crate::util::DispatchIndirectArgs).
96    pub fn dispatch_workgroups_indirect(
97        &mut self,
98        indirect_buffer: &Buffer,
99        indirect_offset: BufferAddress,
100    ) {
101        self.inner
102            .dispatch_workgroups_indirect(&indirect_buffer.inner, indirect_offset);
103    }
104
105    /// Transition resources to an underlying hal resource state. Compute pass version of
106    /// [`CommandEncoder::transition_resources`].
107    ///
108    /// This is an advanced, native-only API (no-op on web). Useful for native interoperability.
109    ///
110    /// A user wanting to interoperate with the underlying native graphics APIs (Vulkan, DirectX12, Metal, etc)
111    /// can use this API to generate barriers between wgpu commands and the native API commands,
112    /// for synchronization and resource state transition purposes.
113    /// Unlike [`CommandEncoder::transition_resources`], this does not require ending the pass and will
114    /// use the same semantics and granularity as the automatic barriers inserted for bindings.
115    ///
116    /// For example, users might want to pass buffer device addresses into a SPIR-V passthrough shader.
117    /// These resources cannot be tracked by wgpu since they do not appear in the bindings and will
118    /// cause data races if not handled - this function allows marking the underlying buffers behind
119    /// the address as used:
120    ///
121    /// ```ignore
122    /// let buffer_transitions =
123    ///     custom_resources
124    ///         .iter()
125    ///         .map(|resource| wgpu::BufferTransition {
126    ///             buffer: &resource.buffer,
127    ///             state: wgpu::BufferUses::STORAGE_READ_WRITE,
128    ///         });
129    /// pass.transition_resources(buffer_transitions, iter::empty())
130    ///
131    /// pass.dispatch_workgroups(x, y, z);
132    /// ```
133    ///
134    pub fn transition_resources<'a>(
135        &mut self,
136        buffer_transitions: impl Iterator<Item = wgt::BufferTransition<&'a Buffer>>,
137        texture_transitions: impl Iterator<Item = wgt::TextureTransition<&'a TextureView>>,
138    ) {
139        self.inner.transition_resources(
140            &mut buffer_transitions.map(|t| wgt::BufferTransition {
141                buffer: &t.buffer.inner,
142                state: t.state,
143            }),
144            &mut texture_transitions.map(|t| wgt::TextureTransition {
145                texture: &t.texture.inner,
146                selector: t.selector,
147                state: t.state,
148            }),
149        );
150    }
151
152    impl_deferred_command_buffer_actions!();
153
154    #[cfg(custom)]
155    /// Returns custom implementation of ComputePass (if custom backend and is internally T)
156    pub fn as_custom<T: custom::ComputePassInterface>(&self) -> Option<&T> {
157        self.inner.as_custom()
158    }
159}
160
161/// [`Features::IMMEDIATES`] must be enabled on the device in order to call these functions.
162impl ComputePass<'_> {
163    /// Set immediate data for subsequent dispatch calls.
164    ///
165    /// Write the bytes in `data` at offset `offset` within immediate data
166    /// storage.  Both `offset` and the length of `data` must be
167    /// multiples of [`crate::IMMEDIATE_DATA_ALIGNMENT`], which is always 4.
168    ///
169    /// For example, if `offset` is `4` and `data` is eight bytes long, this
170    /// call will write `data` to bytes `4..12` of immediate data storage.
171    pub fn set_immediates(&mut self, offset: u32, data: &[u8]) {
172        self.inner.set_immediates(offset, data);
173    }
174}
175
176/// [`Features::TIMESTAMP_QUERY_INSIDE_PASSES`] must be enabled on the device in order to call these functions.
177impl ComputePass<'_> {
178    /// Issue a timestamp command at this point in the queue. The timestamp will be written to the specified query set, at the specified index.
179    ///
180    /// Must be multiplied by [`Queue::get_timestamp_period`] to get
181    /// the value in nanoseconds. Absolute values have no meaning,
182    /// but timestamps can be subtracted to get the time it takes
183    /// for a string of operations to complete.
184    pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) {
185        self.inner.write_timestamp(&query_set.inner, query_index);
186    }
187}
188
189/// [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled on the device in order to call these functions.
190impl ComputePass<'_> {
191    /// Start a pipeline statistics query on this compute pass. It can be ended with
192    /// `end_pipeline_statistics_query`. Pipeline statistics queries may not be nested.
193    ///
194    /// The amount of information collected by this query, and the space occupied in the query set,
195    /// is determined by the [`PipelineStatisticsTypes`] the query set was created with.
196    /// `query_index` is the index of the first query result slot that will be written to, and
197    /// `query_set` must have sufficient size to hold all results written starting at that slot.
198    pub fn begin_pipeline_statistics_query(&mut self, query_set: &QuerySet, query_index: u32) {
199        self.inner
200            .begin_pipeline_statistics_query(&query_set.inner, query_index);
201    }
202
203    /// End the pipeline statistics query on this compute pass. It can be started with
204    /// `begin_pipeline_statistics_query`. Pipeline statistics queries may not be nested.
205    pub fn end_pipeline_statistics_query(&mut self) {
206        self.inner.end_pipeline_statistics_query();
207    }
208}
209
210/// Describes the timestamp writes of a compute pass.
211///
212/// For use with [`ComputePassDescriptor`].
213/// At least one of `beginning_of_pass_write_index` and `end_of_pass_write_index` must be `Some`.
214///
215/// Corresponds to [WebGPU `GPUComputePassTimestampWrites`](
216/// https://gpuweb.github.io/gpuweb/#dictdef-gpucomputepasstimestampwrites).
217#[derive(Clone, Debug)]
218pub struct ComputePassTimestampWrites<'a> {
219    /// The query set to write to.
220    pub query_set: &'a QuerySet,
221    /// The index of the query set at which a start timestamp of this pass is written, if any.
222    pub beginning_of_pass_write_index: Option<u32>,
223    /// The index of the query set at which an end timestamp of this pass is written, if any.
224    pub end_of_pass_write_index: Option<u32>,
225}
226#[cfg(send_sync)]
227static_assertions::assert_impl_all!(ComputePassTimestampWrites<'_>: Send, Sync);
228
229/// Describes the attachments of a compute pass.
230///
231/// For use with [`CommandEncoder::begin_compute_pass`].
232///
233/// Corresponds to [WebGPU `GPUComputePassDescriptor`](
234/// https://gpuweb.github.io/gpuweb/#dictdef-gpucomputepassdescriptor).
235#[derive(Clone, Default, Debug)]
236pub struct ComputePassDescriptor<'a> {
237    /// Debug label of the compute pass. This will show up in graphics debuggers for easy identification.
238    pub label: Label<'a>,
239    /// Defines which timestamp values will be written for this pass, and where to write them to.
240    ///
241    /// Requires [`Features::TIMESTAMP_QUERY`] to be enabled.
242    pub timestamp_writes: Option<ComputePassTimestampWrites<'a>>,
243}
244#[cfg(send_sync)]
245static_assertions::assert_impl_all!(ComputePassDescriptor<'_>: Send, Sync);