bevy/crates/bevy_render/src/render_resource/pipeline.rs
Zhixing Zhang 16feb9acb7 Add push contant config to layout (#7681)
# Objective

Allow for creating pipelines that use push constants. To be able to use push constants. Fixes #4825

As of right now, trying to call `RenderPass::set_push_constants` will trigger the following error:

```
thread 'main' panicked at 'wgpu error: Validation Error

Caused by:
    In a RenderPass
      note: encoder = `<CommandBuffer-(0, 59, Vulkan)>`
    In a set_push_constant command
    provided push constant is for stage(s) VERTEX | FRAGMENT | VERTEX_FRAGMENT, however the pipeline layout has no push constant range for the stage(s) VERTEX | FRAGMENT | VERTEX_FRAGMENT
```
## Solution

Add a field push_constant_ranges to` RenderPipelineDescriptor` and `ComputePipelineDescriptor`.

This PR supersedes #4908 which now contains merge conflicts due to significant changes to `bevy_render`.

Meanwhile, this PR also made the `layout` field of `RenderPipelineDescriptor` and `ComputePipelineDescriptor` non-optional. If the user do not need to specify the bind group layouts, they can simply supply an empty vector here. No need for it to be optional.

---

## Changelog
- Add a field push_constant_ranges to RenderPipelineDescriptor and ComputePipelineDescriptor
- Made the `layout` field of RenderPipelineDescriptor and ComputePipelineDescriptor non-optional.


## Migration Guide

- Add push_constant_ranges: Vec::new() to every `RenderPipelineDescriptor` and `ComputePipelineDescriptor`
- Unwrap the optional values on the `layout` field of `RenderPipelineDescriptor` and `ComputePipelineDescriptor`. If the descriptor has no layout, supply an empty vector.


Co-authored-by: Zhixing Zhang <me@neoto.xin>
2023-02-17 06:20:16 +00:00

189 lines
6.5 KiB
Rust

use super::ShaderDefVal;
use crate::{
define_atomic_id,
render_resource::{resource_macros::render_resource_wrapper, BindGroupLayout, Shader},
};
use bevy_asset::Handle;
use std::{borrow::Cow, ops::Deref};
use wgpu::{
BufferAddress, ColorTargetState, DepthStencilState, MultisampleState, PrimitiveState,
PushConstantRange, VertexAttribute, VertexFormat, VertexStepMode,
};
define_atomic_id!(RenderPipelineId);
render_resource_wrapper!(ErasedRenderPipeline, wgpu::RenderPipeline);
/// A [`RenderPipeline`] represents a graphics pipeline and its stages (shaders), bindings and vertex buffers.
///
/// May be converted from and dereferences to a wgpu [`RenderPipeline`](wgpu::RenderPipeline).
/// Can be created via [`RenderDevice::create_render_pipeline`](crate::renderer::RenderDevice::create_render_pipeline).
#[derive(Clone, Debug)]
pub struct RenderPipeline {
id: RenderPipelineId,
value: ErasedRenderPipeline,
}
impl RenderPipeline {
#[inline]
pub fn id(&self) -> RenderPipelineId {
self.id
}
}
impl From<wgpu::RenderPipeline> for RenderPipeline {
fn from(value: wgpu::RenderPipeline) -> Self {
RenderPipeline {
id: RenderPipelineId::new(),
value: ErasedRenderPipeline::new(value),
}
}
}
impl Deref for RenderPipeline {
type Target = wgpu::RenderPipeline;
#[inline]
fn deref(&self) -> &Self::Target {
&self.value
}
}
define_atomic_id!(ComputePipelineId);
render_resource_wrapper!(ErasedComputePipeline, wgpu::ComputePipeline);
/// A [`ComputePipeline`] represents a compute pipeline and its single shader stage.
///
/// May be converted from and dereferences to a wgpu [`ComputePipeline`](wgpu::ComputePipeline).
/// Can be created via [`RenderDevice::create_compute_pipeline`](crate::renderer::RenderDevice::create_compute_pipeline).
#[derive(Clone, Debug)]
pub struct ComputePipeline {
id: ComputePipelineId,
value: ErasedComputePipeline,
}
impl ComputePipeline {
/// Returns the [`ComputePipelineId`].
#[inline]
pub fn id(&self) -> ComputePipelineId {
self.id
}
}
impl From<wgpu::ComputePipeline> for ComputePipeline {
fn from(value: wgpu::ComputePipeline) -> Self {
ComputePipeline {
id: ComputePipelineId::new(),
value: ErasedComputePipeline::new(value),
}
}
}
impl Deref for ComputePipeline {
type Target = wgpu::ComputePipeline;
#[inline]
fn deref(&self) -> &Self::Target {
&self.value
}
}
/// Describes a render (graphics) pipeline.
#[derive(Clone, Debug, PartialEq)]
pub struct RenderPipelineDescriptor {
/// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.
pub label: Option<Cow<'static, str>>,
/// The layout of bind groups for this pipeline.
pub layout: Vec<BindGroupLayout>,
/// The push constant ranges for this pipeline.
/// Supply an empty vector if the pipeline doesn't use push constants.
pub push_constant_ranges: Vec<PushConstantRange>,
/// The compiled vertex stage, its entry point, and the input buffers layout.
pub vertex: VertexState,
/// The properties of the pipeline at the primitive assembly and rasterization level.
pub primitive: PrimitiveState,
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
pub depth_stencil: Option<DepthStencilState>,
/// The multi-sampling properties of the pipeline.
pub multisample: MultisampleState,
/// The compiled fragment stage, its entry point, and the color targets.
pub fragment: Option<FragmentState>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VertexState {
/// The compiled shader module for this stage.
pub shader: Handle<Shader>,
pub shader_defs: Vec<ShaderDefVal>,
/// The name of the entry point in the compiled shader. There must be a
/// function with this name in the shader.
pub entry_point: Cow<'static, str>,
/// The format of any vertex buffers used with this pipeline.
pub buffers: Vec<VertexBufferLayout>,
}
/// Describes how the vertex buffer is interpreted.
#[derive(Default, Clone, Debug, Hash, Eq, PartialEq)]
pub struct VertexBufferLayout {
/// The stride, in bytes, between elements of this buffer.
pub array_stride: BufferAddress,
/// How often this vertex buffer is "stepped" forward.
pub step_mode: VertexStepMode,
/// The list of attributes which comprise a single vertex.
pub attributes: Vec<VertexAttribute>,
}
impl VertexBufferLayout {
/// Creates a new densely packed [`VertexBufferLayout`] from an iterator of vertex formats.
/// Iteration order determines the `shader_location` and `offset` of the [`VertexAttributes`](VertexAttribute).
/// The first iterated item will have a `shader_location` and `offset` of zero.
/// The `array_stride` is the sum of the size of the iterated [`VertexFormats`](VertexFormat) (in bytes).
pub fn from_vertex_formats<T: IntoIterator<Item = VertexFormat>>(
step_mode: VertexStepMode,
vertex_formats: T,
) -> Self {
let mut offset = 0;
let mut attributes = Vec::new();
for (shader_location, format) in vertex_formats.into_iter().enumerate() {
attributes.push(VertexAttribute {
format,
offset,
shader_location: shader_location as u32,
});
offset += format.size();
}
VertexBufferLayout {
array_stride: offset,
step_mode,
attributes,
}
}
}
/// Describes the fragment process in a render pipeline.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FragmentState {
/// The compiled shader module for this stage.
pub shader: Handle<Shader>,
pub shader_defs: Vec<ShaderDefVal>,
/// The name of the entry point in the compiled shader. There must be a
/// function with this name in the shader.
pub entry_point: Cow<'static, str>,
/// The color state of the render targets.
pub targets: Vec<Option<ColorTargetState>>,
}
/// Describes a compute pipeline.
#[derive(Clone, Debug)]
pub struct ComputePipelineDescriptor {
pub label: Option<Cow<'static, str>>,
pub layout: Vec<BindGroupLayout>,
pub push_constant_ranges: Vec<PushConstantRange>,
/// The compiled shader module for this stage.
pub shader: Handle<Shader>,
pub shader_defs: Vec<ShaderDefVal>,
/// The name of the entry point in the compiled shader. There must be a
/// function with this name in the shader.
pub entry_point: Cow<'static, str>,
}