1use alloc::borrow::Cow;
2use bevy_asset::Handle;
3use bevy_derive::Deref;
4use bevy_mesh::VertexBufferLayout;
5use bevy_shader::{CachedPipelineId, Shader, ShaderDefVal};
6use core::iter;
7use thiserror::Error;
8use wgpu_types::{
9 BindGroupLayoutEntry, ColorTargetState, DepthStencilState, MultisampleState, PrimitiveState,
10};
11
12#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
13pub struct BindGroupLayoutDescriptor {
14 pub label: Cow<'static, str>,
16 pub entries: Vec<BindGroupLayoutEntry>,
17}
18
19impl BindGroupLayoutDescriptor {
20 pub fn new(label: impl Into<Cow<'static, str>>, entries: &[BindGroupLayoutEntry]) -> Self {
21 Self {
22 label: label.into(),
23 entries: entries.into(),
24 }
25 }
26}
27
28#[derive(Clone, Debug, PartialEq, Default)]
30pub struct RenderPipelineDescriptor {
31 pub label: Option<Cow<'static, str>>,
33 pub layout: Vec<BindGroupLayoutDescriptor>,
35 pub immediate_size: u32,
38 pub vertex: VertexState,
40 pub primitive: PrimitiveState,
42 pub depth_stencil: Option<DepthStencilState>,
44 pub multisample: MultisampleState,
46 pub fragment: Option<FragmentState>,
48 pub zero_initialize_workgroup_memory: bool,
51}
52
53#[derive(Copy, Clone, Debug, Error)]
54#[error("RenderPipelineDescriptor has no FragmentState configured")]
55pub struct NoFragmentStateError;
56
57impl RenderPipelineDescriptor {
58 pub fn fragment_mut(&mut self) -> Result<&mut FragmentState, NoFragmentStateError> {
59 self.fragment.as_mut().ok_or(NoFragmentStateError)
60 }
61
62 pub fn set_layout(&mut self, index: usize, layout: BindGroupLayoutDescriptor) {
63 filling_set_at(&mut self.layout, index, bevy_utils::default(), layout);
64 }
65}
66
67#[derive(Clone, Debug, PartialEq, Default)]
68pub struct VertexState {
69 pub shader: Handle<Shader>,
71 pub shader_defs: Vec<ShaderDefVal>,
72 pub entry_point: Option<Cow<'static, str>>,
75 pub buffers: Vec<VertexBufferLayout>,
77 pub constants: Vec<(Cow<'static, str>, f64)>,
79}
80
81#[derive(Clone, Debug, PartialEq, Default)]
83pub struct FragmentState {
84 pub shader: Handle<Shader>,
86 pub shader_defs: Vec<ShaderDefVal>,
87 pub entry_point: Option<Cow<'static, str>>,
90 pub targets: Vec<Option<ColorTargetState>>,
92 pub constants: Vec<(Cow<'static, str>, f64)>,
94}
95
96impl FragmentState {
97 pub fn set_target(&mut self, index: usize, target: ColorTargetState) {
98 filling_set_at(&mut self.targets, index, None, Some(target));
99 }
100}
101
102#[derive(Clone, Debug, PartialEq, Default)]
104pub struct ComputePipelineDescriptor {
105 pub label: Option<Cow<'static, str>>,
106 pub layout: Vec<BindGroupLayoutDescriptor>,
107 pub immediate_size: u32,
108 pub shader: Handle<Shader>,
110 pub shader_defs: Vec<ShaderDefVal>,
111 pub entry_point: Option<Cow<'static, str>>,
114 pub zero_initialize_workgroup_memory: bool,
117 pub constants: Vec<(Cow<'static, str>, f64)>,
119}
120
121fn filling_set_at<T: Clone>(vec: &mut Vec<T>, index: usize, filler: T, value: T) {
124 let num_to_fill = (index + 1).saturating_sub(vec.len());
125 vec.extend(iter::repeat_n(filler, num_to_fill));
126 vec[index] = value;
127}
128
129#[derive(Debug)]
133pub enum PipelineDescriptor {
134 RenderPipelineDescriptor(Box<RenderPipelineDescriptor>),
135 ComputePipelineDescriptor(Box<ComputePipelineDescriptor>),
136 MeshPipelineDescriptor(Box<MeshPipelineDescriptor>),
137}
138
139#[derive(Clone, Debug, PartialEq, Default)]
141pub struct MeshPipelineDescriptor {
142 pub label: Option<Cow<'static, str>>,
144 pub layout: Vec<BindGroupLayoutDescriptor>,
146 pub immediate_size: u32,
149 pub task: Option<TaskState>,
151 pub mesh: MeshState,
153 pub primitive: PrimitiveState,
155 pub depth_stencil: Option<DepthStencilState>,
157 pub multisample: MultisampleState,
159 pub fragment: Option<FragmentState>,
161 pub zero_initialize_workgroup_memory: bool,
164}
165
166#[derive(Clone, Debug, PartialEq, Default)]
167pub struct TaskState {
168 pub shader: Handle<Shader>,
170 pub shader_defs: Vec<ShaderDefVal>,
171 pub entry_point: Option<Cow<'static, str>>,
174 pub constants: Vec<(Cow<'static, str>, f64)>,
176}
177
178#[derive(Clone, Debug, PartialEq, Default)]
179pub struct MeshState {
180 pub shader: Handle<Shader>,
182 pub shader_defs: Vec<ShaderDefVal>,
183 pub entry_point: Option<Cow<'static, str>>,
186 pub constants: Vec<(Cow<'static, str>, f64)>,
188}
189
190#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Deref)]
192pub struct CachedRenderPipelineId(CachedPipelineId);
193
194impl CachedRenderPipelineId {
195 pub const INVALID: Self = CachedRenderPipelineId(usize::MAX);
197
198 #[inline]
199 pub fn new(id: usize) -> Self {
200 Self(id)
201 }
202
203 #[inline]
204 pub fn id(&self) -> usize {
205 self.0
206 }
207}
208
209#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
211pub struct CachedComputePipelineId(CachedPipelineId);
212
213impl CachedComputePipelineId {
214 pub const INVALID: Self = CachedComputePipelineId(usize::MAX);
216
217 #[inline]
218 pub fn new(id: usize) -> Self {
219 Self(id)
220 }
221
222 #[inline]
223 pub fn id(&self) -> usize {
224 self.0
225 }
226}