bevy_render/render_resource/
pipeline.rs1use crate::define_atomic_id;
2use crate::renderer::WgpuWrapper;
3use alloc::borrow::Cow;
4use bevy_asset::Handle;
5use bevy_mesh::VertexBufferLayout;
6use bevy_shader::{Shader, ShaderDefVal};
7use core::iter;
8use core::ops::Deref;
9use thiserror::Error;
10use wgpu::{
11 BindGroupLayoutEntry, ColorTargetState, DepthStencilState, MultisampleState, PrimitiveState,
12 PushConstantRange,
13};
14
15define_atomic_id!(RenderPipelineId);
16
17#[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#[derive(Clone, Debug)]
59pub struct ComputePipeline {
60 id: ComputePipelineId,
61 value: WgpuWrapper<wgpu::ComputePipeline>,
62}
63
64impl ComputePipeline {
65 #[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#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
91pub struct BindGroupLayoutDescriptor {
92 pub label: Cow<'static, str>,
94 pub entries: Vec<BindGroupLayoutEntry>,
95}
96
97impl BindGroupLayoutDescriptor {
98 pub fn new(label: impl Into<Cow<'static, str>>, entries: &[BindGroupLayoutEntry]) -> Self {
99 Self {
100 label: label.into(),
101 entries: entries.into(),
102 }
103 }
104}
105
106#[derive(Clone, Debug, PartialEq, Default)]
108pub struct RenderPipelineDescriptor {
109 pub label: Option<Cow<'static, str>>,
111 pub layout: Vec<BindGroupLayoutDescriptor>,
113 pub push_constant_ranges: Vec<PushConstantRange>,
116 pub vertex: VertexState,
118 pub primitive: PrimitiveState,
120 pub depth_stencil: Option<DepthStencilState>,
122 pub multisample: MultisampleState,
124 pub fragment: Option<FragmentState>,
126 pub zero_initialize_workgroup_memory: bool,
129}
130
131#[derive(Copy, Clone, Debug, Error)]
132#[error("RenderPipelineDescriptor has no FragmentState configured")]
133pub struct NoFragmentStateError;
134
135impl RenderPipelineDescriptor {
136 pub fn fragment_mut(&mut self) -> Result<&mut FragmentState, NoFragmentStateError> {
137 self.fragment.as_mut().ok_or(NoFragmentStateError)
138 }
139
140 pub fn set_layout(&mut self, index: usize, layout: BindGroupLayoutDescriptor) {
141 filling_set_at(&mut self.layout, index, bevy_utils::default(), layout);
142 }
143}
144
145#[derive(Clone, Debug, Eq, PartialEq, Default)]
146pub struct VertexState {
147 pub shader: Handle<Shader>,
149 pub shader_defs: Vec<ShaderDefVal>,
150 pub entry_point: Option<Cow<'static, str>>,
153 pub buffers: Vec<VertexBufferLayout>,
155}
156
157#[derive(Clone, Debug, PartialEq, Eq, Default)]
159pub struct FragmentState {
160 pub shader: Handle<Shader>,
162 pub shader_defs: Vec<ShaderDefVal>,
163 pub entry_point: Option<Cow<'static, str>>,
166 pub targets: Vec<Option<ColorTargetState>>,
168}
169
170impl FragmentState {
171 pub fn set_target(&mut self, index: usize, target: ColorTargetState) {
172 filling_set_at(&mut self.targets, index, None, Some(target));
173 }
174}
175
176#[derive(Clone, Debug, PartialEq, Eq, Default)]
178pub struct ComputePipelineDescriptor {
179 pub label: Option<Cow<'static, str>>,
180 pub layout: Vec<BindGroupLayoutDescriptor>,
181 pub push_constant_ranges: Vec<PushConstantRange>,
182 pub shader: Handle<Shader>,
184 pub shader_defs: Vec<ShaderDefVal>,
185 pub entry_point: Option<Cow<'static, str>>,
188 pub zero_initialize_workgroup_memory: bool,
191}
192
193fn filling_set_at<T: Clone>(vec: &mut Vec<T>, index: usize, filler: T, value: T) {
196 let num_to_fill = (index + 1).saturating_sub(vec.len());
197 vec.extend(iter::repeat_n(filler, num_to_fill));
198 vec[index] = value;
199}