Skip to main content

wgpu/api/
render_pipeline.rs

1use core::num::NonZeroU32;
2
3use crate::*;
4
5/// Handle to a rendering (graphics) pipeline.
6///
7/// A `RenderPipeline` object represents a graphics pipeline and its stages, bindings, vertex
8/// buffers and targets. It can be created with [`Device::create_render_pipeline`].
9///
10/// Corresponds to [WebGPU `GPURenderPipeline`](https://gpuweb.github.io/gpuweb/#render-pipeline).
11#[derive(Debug, Clone)]
12pub struct RenderPipeline {
13    pub(crate) inner: dispatch::DispatchRenderPipeline,
14}
15#[cfg(send_sync)]
16static_assertions::assert_impl_all!(RenderPipeline: Send, Sync);
17
18crate::cmp::impl_eq_ord_hash_proxy!(RenderPipeline => .inner);
19
20impl RenderPipeline {
21    /// Get an object representing the bind group layout at a given index.
22    ///
23    /// If this pipeline was created with a [default layout][RenderPipelineDescriptor::layout], then
24    /// bind groups created with the returned `BindGroupLayout` can only be used with this pipeline.
25    ///
26    /// This method will raise a validation error if there is no bind group layout at `index`.
27    pub fn get_bind_group_layout(&self, index: u32) -> BindGroupLayout {
28        let layout = self.inner.get_bind_group_layout(index);
29        BindGroupLayout { inner: layout }
30    }
31
32    #[cfg(custom)]
33    /// Returns custom implementation of RenderPipeline (if custom backend and is internally T)
34    pub fn as_custom<T: custom::RenderPipelineInterface>(&self) -> Option<&T> {
35        self.inner.as_custom()
36    }
37}
38
39#[cfg(wgpu_core)]
40impl RenderPipeline {
41    /// Create a new render pipeline of wgpu from a wgpu-core render pipeline.
42    ///
43    /// # Arguments
44    ///
45    /// - `core_render_pipeline` - wgpu-core render pipeline.
46    pub fn from_core(
47        core_render_pipeline: alloc::sync::Arc<wgc::pipeline::RenderPipeline>,
48    ) -> Self {
49        Self {
50            inner: crate::backend::wgpu_core::CoreRenderPipeline::from_core(core_render_pipeline)
51                .into(),
52        }
53    }
54
55    /// Returns the underlying wgpu-core render pipeline if this `RenderPipeline` is on the wgpu-core backend, otherwise `None`.
56    pub fn as_core(&self) -> Option<alloc::sync::Arc<wgc::pipeline::RenderPipeline>> {
57        self.inner.as_core_opt().map(|rp| rp.as_core())
58    }
59}
60
61/// Specifies an interpretation of the bytes of a vertex buffer as vertex attributes.
62///
63/// Use this in a [`RenderPipelineDescriptor`] to describe the format of the vertex buffers that
64/// are passed to [`RenderPass::set_vertex_buffer()`].
65///
66/// Corresponds to [WebGPU `GPUVertexBufferLayout`](
67/// https://gpuweb.github.io/gpuweb/#dictdef-gpuvertexbufferlayout).
68///
69/// # Example
70///
71/// The following example defines a `struct` with three fields,
72/// and a [`VertexBufferLayout`] that contains [`VertexAttribute`]s for each field,
73/// using the [`vertex_attr_array!`] macro to compute attribute offsets:
74///
75/// ```
76/// #[repr(C, packed)]
77/// struct Vertex {
78///     foo: [f32; 2],
79///     bar: f32,
80///     baz: [u16; 4],
81/// }
82///
83/// impl Vertex {
84///     /// Layout to use with a buffer whose contents are a `[Vertex]`.
85///     pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout {
86///         array_stride: size_of::<Self>() as wgpu::BufferAddress,
87///         step_mode: wgpu::VertexStepMode::Vertex,
88///         attributes: &wgpu::vertex_attr_array![
89///             0 => Float32x2,
90///             1 => Float32,
91///             2 => Uint16x4,
92///         ],
93///     };
94/// }
95///
96/// # assert_eq!(Vertex::LAYOUT.attributes[2].offset, Vertex::LAYOUT.array_stride - 2 * 4);
97#[derive(Clone, Debug, Hash, Eq, PartialEq)]
98pub struct VertexBufferLayout<'a> {
99    /// The stride, in bytes, between elements of this buffer (between vertices).
100    ///
101    /// This must be a multiple of [`VERTEX_ALIGNMENT`].
102    pub array_stride: BufferAddress,
103    /// How often this vertex buffer is "stepped" forward.
104    pub step_mode: VertexStepMode,
105    /// The list of attributes which comprise a single vertex.
106    pub attributes: &'a [VertexAttribute],
107}
108static_assertions::assert_impl_all!(VertexBufferLayout<'_>: Send, Sync);
109
110/// Describes the vertex processing in a render pipeline.
111///
112/// For use in [`RenderPipelineDescriptor`].
113///
114/// Corresponds to [WebGPU `GPUVertexState`](
115/// https://gpuweb.github.io/gpuweb/#dictdef-gpuvertexstate).
116#[derive(Clone, Debug)]
117pub struct VertexState<'a> {
118    /// The compiled shader module for this stage.
119    pub module: &'a ShaderModule,
120    /// The name of the entry point in the compiled shader to use.
121    ///
122    /// If [`Some`], there must be a vertex-stage shader entry point with this name in `module`.
123    /// Otherwise, expect exactly one vertex-stage entry point in `module`, which will be
124    /// selected.
125    // NOTE: keep phrasing in sync. with `ComputePipelineDescriptor::entry_point`
126    // NOTE: keep phrasing in sync. with `FragmentState::entry_point`
127    pub entry_point: Option<&'a str>,
128    /// Advanced options for when this pipeline is compiled
129    ///
130    /// This implements `Default`, and for most users can be set to `Default::default()`
131    pub compilation_options: PipelineCompilationOptions<'a>,
132    /// The format of any vertex buffers used with this pipeline via
133    /// [`RenderPass::set_vertex_buffer()`].
134    ///
135    /// The attribute locations and types specified in this layout must match the
136    /// locations and types of the inputs to the `entry_point` function.
137    pub buffers: &'a [Option<VertexBufferLayout<'a>>],
138}
139#[cfg(send_sync)]
140static_assertions::assert_impl_all!(VertexState<'_>: Send, Sync);
141
142/// Describes the fragment processing in a render pipeline.
143///
144/// For use in [`RenderPipelineDescriptor`].
145///
146/// Corresponds to [WebGPU `GPUFragmentState`](
147/// https://gpuweb.github.io/gpuweb/#dictdef-gpufragmentstate).
148#[derive(Clone, Debug)]
149pub struct FragmentState<'a> {
150    /// The compiled shader module for this stage.
151    pub module: &'a ShaderModule,
152    /// The name of the entry point in the compiled shader to use.
153    ///
154    /// If [`Some`], there must be a `@fragment` shader entry point with this name in `module`.
155    /// Otherwise, expect exactly one fragment-stage entry point in `module`, which will be
156    /// selected.
157    // NOTE: keep phrasing in sync. with `ComputePipelineDescriptor::entry_point`
158    // NOTE: keep phrasing in sync. with `VertexState::entry_point`
159    pub entry_point: Option<&'a str>,
160    /// Advanced options for when this pipeline is compiled
161    ///
162    /// This implements `Default`, and for most users can be set to `Default::default()`
163    pub compilation_options: PipelineCompilationOptions<'a>,
164    /// The color state of the render targets.
165    pub targets: &'a [Option<ColorTargetState>],
166}
167#[cfg(send_sync)]
168static_assertions::assert_impl_all!(FragmentState<'_>: Send, Sync);
169
170/// Describes the task shader stage in a mesh shader pipeline.
171///
172/// For use in [`MeshPipelineDescriptor`]
173#[derive(Clone, Debug)]
174pub struct TaskState<'a> {
175    /// The compiled shader module for this stage.
176    pub module: &'a ShaderModule,
177
178    /// The name of the task shader entry point in the shader module to use.
179    ///
180    /// If [`Some`], there must be a task shader entry point with the given name
181    /// in `module`. Otherwise, there must be exactly one task shader entry
182    /// point in `module`, which will be selected.
183    pub entry_point: Option<&'a str>,
184
185    /// Advanced options for when this pipeline is compiled.
186    ///
187    /// This implements `Default`, and for most users can be set to `Default::default()`
188    pub compilation_options: PipelineCompilationOptions<'a>,
189}
190#[cfg(send_sync)]
191static_assertions::assert_impl_all!(TaskState<'_>: Send, Sync);
192
193/// Describes the mesh shader stage in a mesh shader pipeline.
194///
195/// For use in [`MeshPipelineDescriptor`]
196#[derive(Clone, Debug)]
197pub struct MeshState<'a> {
198    /// The compiled shader module for this stage.
199    pub module: &'a ShaderModule,
200    /// The name of the entry point in the compiled shader to use.
201    ///
202    /// If [`Some`], there must be a vertex-stage shader entry point with this name in `module`.
203    /// Otherwise, expect exactly one vertex-stage entry point in `module`, which will be
204    /// selected.
205    pub entry_point: Option<&'a str>,
206    /// Advanced options for when this pipeline is compiled
207    ///
208    /// This implements `Default`, and for most users can be set to `Default::default()`
209    pub compilation_options: PipelineCompilationOptions<'a>,
210}
211#[cfg(send_sync)]
212static_assertions::assert_impl_all!(MeshState<'_>: Send, Sync);
213
214/// Describes a render (graphics) pipeline.
215///
216/// For use with [`Device::create_render_pipeline`].
217///
218/// Corresponds to [WebGPU `GPURenderPipelineDescriptor`](
219/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderpipelinedescriptor).
220#[derive(Clone, Debug)]
221pub struct RenderPipelineDescriptor<'a> {
222    /// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.
223    pub label: Label<'a>,
224    /// The layout of bind groups for this pipeline.
225    ///
226    /// If this is set, then [`Device::create_render_pipeline`] will raise a validation error if
227    /// the layout doesn't match what the shader module(s) expect.
228    ///
229    /// Using the same [`PipelineLayout`] for many [`RenderPipeline`] or [`ComputePipeline`]
230    /// pipelines guarantees that you don't have to rebind any resources when switching between
231    /// those pipelines.
232    ///
233    /// ## Default pipeline layout
234    ///
235    /// If `layout` is `None`, then the pipeline has a [default layout] created and used instead.
236    /// The default layout is deduced from the shader modules.
237    ///
238    /// You can use [`RenderPipeline::get_bind_group_layout`] to create bind groups for use with the
239    /// default layout. However, these bind groups cannot be used with any other pipelines. This is
240    /// convenient for simple pipelines, but using an explicit layout is recommended in most cases.
241    ///
242    /// [default layout]: https://www.w3.org/TR/webgpu/#default-pipeline-layout
243    pub layout: Option<&'a PipelineLayout>,
244    /// The compiled vertex stage, its entry point, and the input buffers layout.
245    pub vertex: VertexState<'a>,
246    /// The properties of the pipeline at the primitive assembly and rasterization level.
247    pub primitive: PrimitiveState,
248    /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
249    pub depth_stencil: Option<DepthStencilState>,
250    /// The multi-sampling properties of the pipeline.
251    pub multisample: MultisampleState,
252    /// The compiled fragment stage, its entry point, and the color targets.
253    pub fragment: Option<FragmentState<'a>>,
254    /// If the pipeline will be used with a multiview render pass, this indicates what multiview
255    /// mask the render pass will be used with. The masks must match exactly.
256    ///
257    /// For example, if you wish to render to the first 2 layers, you would use 3=0b11. If you
258    /// wanted to render to only the 2nd layer, you would use 2=0b10. If you aren't using
259    /// multiview this should be `None`.
260    pub multiview_mask: Option<NonZeroU32>,
261    /// The pipeline cache to use when creating this pipeline.
262    pub cache: Option<&'a PipelineCache>,
263}
264#[cfg(send_sync)]
265static_assertions::assert_impl_all!(RenderPipelineDescriptor<'_>: Send, Sync);
266
267/// Describes a mesh shader (graphics) pipeline.
268///
269/// For use with [`Device::create_mesh_pipeline`]. A mesh pipeline is very much
270/// like a render pipeline, except that instead of [`RenderPass::draw`] it is
271/// invoked with [`RenderPass::draw_mesh_tasks`], and instead of a vertex shader
272/// and a fragment shader:
273///
274/// - [`task`] specifies an optional task shader entry point, which determines how
275///   many groups of mesh shaders to dispatch.
276///
277/// - [`mesh`] specifies a mesh shader entry point, which generates groups of
278///   primitives to draw
279///
280/// - [`fragment`] specifies as fragment shader for drawing those primitives,
281///   just like in an ordinary render pipeline.
282///
283/// The key difference is that, whereas a vertex shader is invoked on the
284/// elements of vertex buffers, the task shader gets to decide how many mesh
285/// shader workgroups to make, and then each mesh shader workgroup gets to
286/// decide which primitives it wants to generate, and what their vertex
287/// attributes are. Task and mesh shaders can use whatever they please as
288/// inputs, like a compute shader. However, they cannot use specialized vertex
289/// or index buffers.
290///
291/// A mesh pipeline is invoked by [`RenderPass::draw_mesh_tasks`], which looks
292/// like a compute shader dispatch with [`ComputePass::dispatch_workgroups`]:
293/// you pass `x`, `y`, and `z` values indicating the number of task shaders to
294/// invoke in parallel. The output value of the first thread in a task shader
295/// workgroup determines how many mesh workgroups should be dispatched from there.
296/// Those mesh workgroups also get a special payload passed from the task shader.
297///
298/// If the task shader is omitted, then the (`x`, `y`, `z`) parameters to
299/// `draw_mesh_tasks` are used to decide how many invocations of the mesh shader
300/// to invoke directly, without a task payload.
301///
302/// [vertex formats]: wgpu_types::VertexFormat
303/// [`task`]: Self::task
304/// [`mesh`]: Self::mesh
305/// [`fragment`]: Self::fragment
306#[derive(Clone, Debug)]
307pub struct MeshPipelineDescriptor<'a> {
308    /// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.
309    pub label: Label<'a>,
310    /// The layout of bind groups for this pipeline.
311    ///
312    /// If this is set, then [`Device::create_render_pipeline`] will raise a validation error if
313    /// the layout doesn't match what the shader module(s) expect.
314    ///
315    /// Using the same [`PipelineLayout`] for many [`RenderPipeline`] or [`ComputePipeline`]
316    /// pipelines guarantees that you don't have to rebind any resources when switching between
317    /// those pipelines.
318    ///
319    /// ## Default pipeline layout
320    ///
321    /// If `layout` is `None`, then the pipeline has a [default layout] created and used instead.
322    /// The default layout is deduced from the shader modules.
323    ///
324    /// You can use [`RenderPipeline::get_bind_group_layout`] to create bind groups for use with the
325    /// default layout. However, these bind groups cannot be used with any other pipelines. This is
326    /// convenient for simple pipelines, but using an explicit layout is recommended in most cases.
327    ///
328    /// [default layout]: https://www.w3.org/TR/webgpu/#default-pipeline-layout
329    pub layout: Option<&'a PipelineLayout>,
330
331    /// The mesh pipeline's task shader.
332    ///
333    /// If this is `None`, the mesh pipeline has no task shader. Executing a
334    /// mesh drawing command simply dispatches a grid of mesh shaders directly.
335    ///
336    /// [`draw_mesh_tasks`]: RenderPass::draw_mesh_tasks
337    pub task: Option<TaskState<'a>>,
338
339    /// The compiled mesh stage and its entry point
340    pub mesh: MeshState<'a>,
341    /// The properties of the pipeline at the primitive assembly and rasterization level.
342    pub primitive: PrimitiveState,
343    /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
344    pub depth_stencil: Option<DepthStencilState>,
345    /// The multi-sampling properties of the pipeline.
346    pub multisample: MultisampleState,
347    /// The compiled fragment stage, its entry point, and the color targets.
348    pub fragment: Option<FragmentState<'a>>,
349    /// If the pipeline will be used with a multiview render pass, this indicates how many array
350    /// layers the attachments will have.
351    pub multiview: Option<NonZeroU32>,
352    /// The pipeline cache to use when creating this pipeline.
353    pub cache: Option<&'a PipelineCache>,
354}
355#[cfg(send_sync)]
356static_assertions::assert_impl_all!(MeshPipelineDescriptor<'_>: Send, Sync);