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