bevy_render/render_resource/
pipeline.rs1use 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#[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, Default)]
92pub struct RenderPipelineDescriptor {
93 pub label: Option<Cow<'static, str>>,
95 pub layout: Vec<BindGroupLayout>,
97 pub push_constant_ranges: Vec<PushConstantRange>,
100 pub vertex: VertexState,
102 pub primitive: PrimitiveState,
104 pub depth_stencil: Option<DepthStencilState>,
106 pub multisample: MultisampleState,
108 pub fragment: Option<FragmentState>,
110 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 pub shader: Handle<Shader>,
133 pub shader_defs: Vec<ShaderDefVal>,
134 pub entry_point: Option<Cow<'static, str>>,
137 pub buffers: Vec<VertexBufferLayout>,
139}
140
141#[derive(Clone, Debug, PartialEq, Eq, Default)]
143pub struct FragmentState {
144 pub shader: Handle<Shader>,
146 pub shader_defs: Vec<ShaderDefVal>,
147 pub entry_point: Option<Cow<'static, str>>,
150 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#[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 pub shader: Handle<Shader>,
168 pub shader_defs: Vec<ShaderDefVal>,
169 pub entry_point: Option<Cow<'static, str>>,
172 pub zero_initialize_workgroup_memory: bool,
175}
176
177fn 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}