Path: blob/main/crates/bevy_render/src/render_resource/pipeline.rs
6596 views
use super::empty_bind_group_layout;1use crate::renderer::WgpuWrapper;2use crate::{define_atomic_id, render_resource::BindGroupLayout};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::{11ColorTargetState, DepthStencilState, MultisampleState, PrimitiveState, PushConstantRange,12};1314define_atomic_id!(RenderPipelineId);1516/// A [`RenderPipeline`] represents a graphics pipeline and its stages (shaders), bindings and vertex buffers.17///18/// May be converted from and dereferences to a wgpu [`RenderPipeline`](wgpu::RenderPipeline).19/// Can be created via [`RenderDevice::create_render_pipeline`](crate::renderer::RenderDevice::create_render_pipeline).20#[derive(Clone, Debug)]21pub struct RenderPipeline {22id: RenderPipelineId,23value: WgpuWrapper<wgpu::RenderPipeline>,24}2526impl RenderPipeline {27#[inline]28pub fn id(&self) -> RenderPipelineId {29self.id30}31}3233impl From<wgpu::RenderPipeline> for RenderPipeline {34fn from(value: wgpu::RenderPipeline) -> Self {35RenderPipeline {36id: RenderPipelineId::new(),37value: WgpuWrapper::new(value),38}39}40}4142impl Deref for RenderPipeline {43type Target = wgpu::RenderPipeline;4445#[inline]46fn deref(&self) -> &Self::Target {47&self.value48}49}5051define_atomic_id!(ComputePipelineId);5253/// A [`ComputePipeline`] represents a compute pipeline and its single shader stage.54///55/// May be converted from and dereferences to a wgpu [`ComputePipeline`](wgpu::ComputePipeline).56/// Can be created via [`RenderDevice::create_compute_pipeline`](crate::renderer::RenderDevice::create_compute_pipeline).57#[derive(Clone, Debug)]58pub struct ComputePipeline {59id: ComputePipelineId,60value: WgpuWrapper<wgpu::ComputePipeline>,61}6263impl ComputePipeline {64/// Returns the [`ComputePipelineId`].65#[inline]66pub fn id(&self) -> ComputePipelineId {67self.id68}69}7071impl From<wgpu::ComputePipeline> for ComputePipeline {72fn from(value: wgpu::ComputePipeline) -> Self {73ComputePipeline {74id: ComputePipelineId::new(),75value: WgpuWrapper::new(value),76}77}78}7980impl Deref for ComputePipeline {81type Target = wgpu::ComputePipeline;8283#[inline]84fn deref(&self) -> &Self::Target {85&self.value86}87}8889/// Describes a render (graphics) pipeline.90#[derive(Clone, Debug, PartialEq, Default)]91pub struct RenderPipelineDescriptor {92/// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.93pub label: Option<Cow<'static, str>>,94/// The layout of bind groups for this pipeline.95pub layout: Vec<BindGroupLayout>,96/// The push constant ranges for this pipeline.97/// Supply an empty vector if the pipeline doesn't use push constants.98pub push_constant_ranges: Vec<PushConstantRange>,99/// The compiled vertex stage, its entry point, and the input buffers layout.100pub vertex: VertexState,101/// The properties of the pipeline at the primitive assembly and rasterization level.102pub primitive: PrimitiveState,103/// The effect of draw calls on the depth and stencil aspects of the output target, if any.104pub depth_stencil: Option<DepthStencilState>,105/// The multi-sampling properties of the pipeline.106pub multisample: MultisampleState,107/// The compiled fragment stage, its entry point, and the color targets.108pub fragment: Option<FragmentState>,109/// Whether to zero-initialize workgroup memory by default. If you're not sure, set this to true.110/// If this is false, reading from workgroup variables before writing to them will result in garbage values.111pub zero_initialize_workgroup_memory: bool,112}113114#[derive(Copy, Clone, Debug, Error)]115#[error("RenderPipelineDescriptor has no FragmentState configured")]116pub struct NoFragmentStateError;117118impl RenderPipelineDescriptor {119pub fn fragment_mut(&mut self) -> Result<&mut FragmentState, NoFragmentStateError> {120self.fragment.as_mut().ok_or(NoFragmentStateError)121}122123pub fn set_layout(&mut self, index: usize, layout: BindGroupLayout) {124filling_set_at(&mut self.layout, index, empty_bind_group_layout(), layout);125}126}127128#[derive(Clone, Debug, Eq, PartialEq, Default)]129pub struct VertexState {130/// The compiled shader module for this stage.131pub shader: Handle<Shader>,132pub shader_defs: Vec<ShaderDefVal>,133/// The name of the entry point in the compiled shader, or `None` if the default entry point134/// is used.135pub entry_point: Option<Cow<'static, str>>,136/// The format of any vertex buffers used with this pipeline.137pub buffers: Vec<VertexBufferLayout>,138}139140/// Describes the fragment process in a render pipeline.141#[derive(Clone, Debug, PartialEq, Eq, Default)]142pub struct FragmentState {143/// The compiled shader module for this stage.144pub shader: Handle<Shader>,145pub shader_defs: Vec<ShaderDefVal>,146/// The name of the entry point in the compiled shader, or `None` if the default entry point147/// is used.148pub entry_point: Option<Cow<'static, str>>,149/// The color state of the render targets.150pub targets: Vec<Option<ColorTargetState>>,151}152153impl FragmentState {154pub fn set_target(&mut self, index: usize, target: ColorTargetState) {155filling_set_at(&mut self.targets, index, None, Some(target));156}157}158159/// Describes a compute pipeline.160#[derive(Clone, Debug, PartialEq, Eq, Default)]161pub struct ComputePipelineDescriptor {162pub label: Option<Cow<'static, str>>,163pub layout: Vec<BindGroupLayout>,164pub push_constant_ranges: Vec<PushConstantRange>,165/// The compiled shader module for this stage.166pub shader: Handle<Shader>,167pub shader_defs: Vec<ShaderDefVal>,168/// The name of the entry point in the compiled shader, or `None` if the default entry point169/// is used.170pub entry_point: Option<Cow<'static, str>>,171/// Whether to zero-initialize workgroup memory by default. If you're not sure, set this to true.172/// If this is false, reading from workgroup variables before writing to them will result in garbage values.173pub zero_initialize_workgroup_memory: bool,174}175176// utility function to set a value at the specified index, extending with177// a filler value if the index is out of bounds.178fn filling_set_at<T: Clone>(vec: &mut Vec<T>, index: usize, filler: T, value: T) {179let num_to_fill = (index + 1).saturating_sub(vec.len());180vec.extend(iter::repeat_n(filler, num_to_fill));181vec[index] = value;182}183184185