bevy_render/render_resource/
pipeline.rs

1use super::empty_bind_group_layout;
2use crate::renderer::WgpuWrapper;
3use crate::{define_atomic_id, render_resource::BindGroupLayout};
4use alloc::borrow::Cow;
5use bevy_asset::Handle;
6use bevy_mesh::VertexBufferLayout;
7use bevy_shader::{Shader, ShaderDefVal};
8use core::iter;
9use core::ops::Deref;
10use thiserror::Error;
11use wgpu::{
12    ColorTargetState, DepthStencilState, MultisampleState, PrimitiveState, PushConstantRange,
13};
14
15define_atomic_id!(RenderPipelineId);
16
17/// A [`RenderPipeline`] represents a graphics pipeline and its stages (shaders), bindings and vertex buffers.
18///
19/// May be converted from and dereferences to a wgpu [`RenderPipeline`](wgpu::RenderPipeline).
20/// Can be created via [`RenderDevice::create_render_pipeline`](crate::renderer::RenderDevice::create_render_pipeline).
21#[derive(Clone, Debug)]
22pub struct RenderPipeline {
23    id: RenderPipelineId,
24    value: WgpuWrapper<wgpu::RenderPipeline>,
25}
26
27impl RenderPipeline {
28    #[inline]
29    pub fn id(&self) -> RenderPipelineId {
30        self.id
31    }
32}
33
34impl From<wgpu::RenderPipeline> for RenderPipeline {
35    fn from(value: wgpu::RenderPipeline) -> Self {
36        RenderPipeline {
37            id: RenderPipelineId::new(),
38            value: WgpuWrapper::new(value),
39        }
40    }
41}
42
43impl Deref for RenderPipeline {
44    type Target = wgpu::RenderPipeline;
45
46    #[inline]
47    fn deref(&self) -> &Self::Target {
48        &self.value
49    }
50}
51
52define_atomic_id!(ComputePipelineId);
53
54/// A [`ComputePipeline`] represents a compute pipeline and its single shader stage.
55///
56/// May be converted from and dereferences to a wgpu [`ComputePipeline`](wgpu::ComputePipeline).
57/// Can be created via [`RenderDevice::create_compute_pipeline`](crate::renderer::RenderDevice::create_compute_pipeline).
58#[derive(Clone, Debug)]
59pub struct ComputePipeline {
60    id: ComputePipelineId,
61    value: WgpuWrapper<wgpu::ComputePipeline>,
62}
63
64impl ComputePipeline {
65    /// Returns the [`ComputePipelineId`].
66    #[inline]
67    pub fn id(&self) -> ComputePipelineId {
68        self.id
69    }
70}
71
72impl From<wgpu::ComputePipeline> for ComputePipeline {
73    fn from(value: wgpu::ComputePipeline) -> Self {
74        ComputePipeline {
75            id: ComputePipelineId::new(),
76            value: WgpuWrapper::new(value),
77        }
78    }
79}
80
81impl Deref for ComputePipeline {
82    type Target = wgpu::ComputePipeline;
83
84    #[inline]
85    fn deref(&self) -> &Self::Target {
86        &self.value
87    }
88}
89
90/// Describes a render (graphics) pipeline.
91#[derive(Clone, Debug, PartialEq, Default)]
92pub struct RenderPipelineDescriptor {
93    /// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.
94    pub label: Option<Cow<'static, str>>,
95    /// The layout of bind groups for this pipeline.
96    pub layout: Vec<BindGroupLayout>,
97    /// The push constant ranges for this pipeline.
98    /// Supply an empty vector if the pipeline doesn't use push constants.
99    pub push_constant_ranges: Vec<PushConstantRange>,
100    /// The compiled vertex stage, its entry point, and the input buffers layout.
101    pub vertex: VertexState,
102    /// The properties of the pipeline at the primitive assembly and rasterization level.
103    pub primitive: PrimitiveState,
104    /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
105    pub depth_stencil: Option<DepthStencilState>,
106    /// The multi-sampling properties of the pipeline.
107    pub multisample: MultisampleState,
108    /// The compiled fragment stage, its entry point, and the color targets.
109    pub fragment: Option<FragmentState>,
110    /// Whether to zero-initialize workgroup memory by default. If you're not sure, set this to true.
111    /// If this is false, reading from workgroup variables before writing to them will result in garbage values.
112    pub zero_initialize_workgroup_memory: bool,
113}
114
115#[derive(Copy, Clone, Debug, Error)]
116#[error("RenderPipelineDescriptor has no FragmentState configured")]
117pub struct NoFragmentStateError;
118
119impl RenderPipelineDescriptor {
120    pub fn fragment_mut(&mut self) -> Result<&mut FragmentState, NoFragmentStateError> {
121        self.fragment.as_mut().ok_or(NoFragmentStateError)
122    }
123
124    pub fn set_layout(&mut self, index: usize, layout: BindGroupLayout) {
125        filling_set_at(&mut self.layout, index, empty_bind_group_layout(), layout);
126    }
127}
128
129#[derive(Clone, Debug, Eq, PartialEq, Default)]
130pub struct VertexState {
131    /// The compiled shader module for this stage.
132    pub shader: Handle<Shader>,
133    pub shader_defs: Vec<ShaderDefVal>,
134    /// The name of the entry point in the compiled shader, or `None` if the default entry point
135    /// is used.
136    pub entry_point: Option<Cow<'static, str>>,
137    /// The format of any vertex buffers used with this pipeline.
138    pub buffers: Vec<VertexBufferLayout>,
139}
140
141/// Describes the fragment process in a render pipeline.
142#[derive(Clone, Debug, PartialEq, Eq, Default)]
143pub struct FragmentState {
144    /// The compiled shader module for this stage.
145    pub shader: Handle<Shader>,
146    pub shader_defs: Vec<ShaderDefVal>,
147    /// The name of the entry point in the compiled shader, or `None` if the default entry point
148    /// is used.
149    pub entry_point: Option<Cow<'static, str>>,
150    /// The color state of the render targets.
151    pub targets: Vec<Option<ColorTargetState>>,
152}
153
154impl FragmentState {
155    pub fn set_target(&mut self, index: usize, target: ColorTargetState) {
156        filling_set_at(&mut self.targets, index, None, Some(target));
157    }
158}
159
160/// Describes a compute pipeline.
161#[derive(Clone, Debug, PartialEq, Eq, Default)]
162pub struct ComputePipelineDescriptor {
163    pub label: Option<Cow<'static, str>>,
164    pub layout: Vec<BindGroupLayout>,
165    pub push_constant_ranges: Vec<PushConstantRange>,
166    /// The compiled shader module for this stage.
167    pub shader: Handle<Shader>,
168    pub shader_defs: Vec<ShaderDefVal>,
169    /// The name of the entry point in the compiled shader, or `None` if the default entry point
170    /// is used.
171    pub entry_point: Option<Cow<'static, str>>,
172    /// Whether to zero-initialize workgroup memory by default. If you're not sure, set this to true.
173    /// If this is false, reading from workgroup variables before writing to them will result in garbage values.
174    pub zero_initialize_workgroup_memory: bool,
175}
176
177// utility function to set a value at the specified index, extending with
178// a filler value if the index is out of bounds.
179fn filling_set_at<T: Clone>(vec: &mut Vec<T>, index: usize, filler: T, value: T) {
180    let num_to_fill = (index + 1).saturating_sub(vec.len());
181    vec.extend(iter::repeat_n(filler, num_to_fill));
182    vec[index] = value;
183}