mirror of
https://github.com/bevyengine/bevy
synced 2024-09-20 14:32:06 +00:00
parent
e6e23fdfa9
commit
81809c71ce
29 changed files with 574 additions and 370 deletions
|
@ -2,9 +2,8 @@ use bevy_asset::{Assets, HandleUntyped};
|
|||
use bevy_reflect::TypeUuid;
|
||||
use bevy_render::{
|
||||
pipeline::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, PipelineDescriptor,
|
||||
RasterizationStateDescriptor, StencilStateDescriptor, StencilStateFaceDescriptor,
|
||||
BlendFactor, BlendOperation, BlendState, ColorTargetState, ColorWrite, CompareFunction,
|
||||
DepthBiasState, DepthStencilState, PipelineDescriptor, StencilFaceState, StencilState,
|
||||
},
|
||||
shader::{Shader, ShaderStage, ShaderStages},
|
||||
texture::TextureFormat,
|
||||
|
@ -15,33 +14,31 @@ pub const FORWARD_PIPELINE_HANDLE: HandleUntyped =
|
|||
|
||||
pub(crate) fn build_forward_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
||||
PipelineDescriptor {
|
||||
rasterization_state: Some(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
clamp_depth: false,
|
||||
}),
|
||||
depth_stencil_state: Some(DepthStencilStateDescriptor {
|
||||
depth_stencil: Some(DepthStencilState {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil: StencilStateDescriptor {
|
||||
front: StencilStateFaceDescriptor::IGNORE,
|
||||
back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil: StencilState {
|
||||
front: StencilFaceState::IGNORE,
|
||||
back: StencilFaceState::IGNORE,
|
||||
read_mask: 0,
|
||||
write_mask: 0,
|
||||
},
|
||||
bias: DepthBiasState {
|
||||
constant: 0,
|
||||
slope_scale: 0.0,
|
||||
clamp: 0.0,
|
||||
},
|
||||
clamp_depth: false,
|
||||
}),
|
||||
color_states: vec![ColorStateDescriptor {
|
||||
color_target_states: vec![ColorTargetState {
|
||||
format: TextureFormat::default(),
|
||||
color_blend: BlendDescriptor {
|
||||
color_blend: BlendState {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
alpha_blend: BlendState {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::{
|
||||
pipeline::{PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization},
|
||||
pipeline::{
|
||||
IndexFormat, PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization,
|
||||
},
|
||||
renderer::{
|
||||
AssetRenderResourceBindings, BindGroup, BindGroupId, BufferId, RenderResource,
|
||||
RenderResourceBinding, RenderResourceBindings, RenderResourceContext, SharedBuffers,
|
||||
|
@ -26,6 +28,7 @@ pub enum RenderCommand {
|
|||
SetIndexBuffer {
|
||||
buffer: BufferId,
|
||||
offset: u64,
|
||||
index_format: IndexFormat,
|
||||
},
|
||||
SetBindGroup {
|
||||
index: u32,
|
||||
|
@ -95,8 +98,12 @@ impl Draw {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64) {
|
||||
self.render_command(RenderCommand::SetIndexBuffer { buffer, offset });
|
||||
pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64, index_format: IndexFormat) {
|
||||
self.render_command(RenderCommand::SetIndexBuffer {
|
||||
buffer,
|
||||
offset,
|
||||
index_format,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup) {
|
||||
|
@ -325,8 +332,8 @@ impl<'a> DrawContext<'a> {
|
|||
render_resource_bindings: &[&RenderResourceBindings],
|
||||
) -> Result<(), DrawError> {
|
||||
for bindings in render_resource_bindings.iter() {
|
||||
if let Some(index_buffer) = bindings.index_buffer {
|
||||
draw.set_index_buffer(index_buffer, 0);
|
||||
if let Some((index_buffer, index_format)) = bindings.index_buffer {
|
||||
draw.set_index_buffer(index_buffer, 0, index_format);
|
||||
}
|
||||
if let Some(main_vertex_buffer) = bindings.vertex_attribute_buffer {
|
||||
draw.set_vertex_buffer(0, main_vertex_buffer, 0);
|
||||
|
|
|
@ -10,7 +10,7 @@ use bevy_math::*;
|
|||
use bevy_reflect::TypeUuid;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::pipeline::{InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor};
|
||||
use crate::pipeline::{InputStepMode, VertexAttribute, VertexBufferLayout};
|
||||
use bevy_utils::{HashMap, HashSet};
|
||||
|
||||
pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
|
||||
|
@ -256,12 +256,12 @@ impl Mesh {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn get_vertex_buffer_descriptor(&self) -> VertexBufferDescriptor {
|
||||
pub fn get_vertex_buffer_layout(&self) -> VertexBufferLayout {
|
||||
let mut attributes = Vec::new();
|
||||
let mut accumulated_offset = 0;
|
||||
for (attribute_name, attribute_values) in self.attributes.iter() {
|
||||
let vertex_format = VertexFormat::from(attribute_values);
|
||||
attributes.push(VertexAttributeDescriptor {
|
||||
attributes.push(VertexAttribute {
|
||||
name: attribute_name.clone(),
|
||||
offset: accumulated_offset,
|
||||
format: vertex_format,
|
||||
|
@ -270,7 +270,7 @@ impl Mesh {
|
|||
accumulated_offset += vertex_format.get_size();
|
||||
}
|
||||
|
||||
VertexBufferDescriptor {
|
||||
VertexBufferLayout {
|
||||
name: Default::default(),
|
||||
stride: accumulated_offset,
|
||||
step_mode: InputStepMode::Vertex,
|
||||
|
@ -453,21 +453,22 @@ fn update_entity_mesh(
|
|||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||
render_pipeline.specialization.primitive_topology = mesh.primitive_topology;
|
||||
// TODO: don't allocate a new vertex buffer descriptor for every entity
|
||||
render_pipeline.specialization.vertex_buffer_descriptor =
|
||||
mesh.get_vertex_buffer_descriptor();
|
||||
render_pipeline.specialization.index_format = mesh
|
||||
.indices()
|
||||
.map(|i| i.into())
|
||||
.unwrap_or(IndexFormat::Uint32);
|
||||
render_pipeline.specialization.vertex_buffer_layout = mesh.get_vertex_buffer_layout();
|
||||
if let PrimitiveTopology::LineStrip | PrimitiveTopology::TriangleStrip =
|
||||
mesh.primitive_topology
|
||||
{
|
||||
render_pipeline.specialization.strip_index_format =
|
||||
mesh.indices().map(|indices| indices.into());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(RenderResourceId::Buffer(index_buffer_resource)) =
|
||||
render_resource_context.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX)
|
||||
{
|
||||
let index_format: IndexFormat = mesh.indices().unwrap().into();
|
||||
// set index buffer into binding
|
||||
render_pipelines
|
||||
.bindings
|
||||
.set_index_buffer(index_buffer_resource);
|
||||
.set_index_buffer(index_buffer_resource, index_format);
|
||||
}
|
||||
|
||||
if let Some(RenderResourceId::Buffer(vertex_attribute_buffer_resource)) =
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
||||
pipeline::{BindGroupDescriptorId, IndexFormat, PipelineDescriptor},
|
||||
renderer::{BindGroupId, BufferId, RenderContext},
|
||||
};
|
||||
use bevy_asset::Handle;
|
||||
|
@ -7,7 +7,7 @@ use std::ops::Range;
|
|||
|
||||
pub trait RenderPass {
|
||||
fn get_render_context(&self) -> &dyn RenderContext;
|
||||
fn set_index_buffer(&mut self, buffer: BufferId, offset: u64);
|
||||
fn set_index_buffer(&mut self, buffer: BufferId, offset: u64, index_format: IndexFormat);
|
||||
fn set_vertex_buffer(&mut self, start_slot: u32, buffer: BufferId, offset: u64);
|
||||
fn set_pipeline(&mut self, pipeline_handle: &Handle<PipelineDescriptor>);
|
||||
fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use super::UniformProperty;
|
||||
use crate::texture::{TextureComponentType, TextureFormat, TextureViewDimension};
|
||||
use crate::texture::{
|
||||
StorageTextureAccess, TextureFormat, TextureSampleType, TextureViewDimension,
|
||||
};
|
||||
|
||||
bitflags::bitflags! {
|
||||
pub struct BindingShaderStage: u32 {
|
||||
|
@ -20,25 +22,35 @@ pub struct BindingDescriptor {
|
|||
#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum BindType {
|
||||
Uniform {
|
||||
dynamic: bool,
|
||||
has_dynamic_offset: bool,
|
||||
property: UniformProperty,
|
||||
},
|
||||
StorageBuffer {
|
||||
dynamic: bool,
|
||||
has_dynamic_offset: bool,
|
||||
readonly: bool,
|
||||
},
|
||||
Sampler {
|
||||
/// The sampling result is produced based on more than a single color sample from a texture,
|
||||
/// e.g. when bilinear interpolation is enabled.
|
||||
///
|
||||
/// A filtering sampler can only be used with a filterable texture.
|
||||
filtering: bool,
|
||||
/// Use as a comparison sampler instead of a normal sampler.
|
||||
/// For more info take a look at the analogous functionality in OpenGL: https://www.khronos.org/opengl/wiki/Sampler_Object#Comparison_mode.
|
||||
comparison: bool,
|
||||
},
|
||||
SampledTexture {
|
||||
Texture {
|
||||
multisampled: bool,
|
||||
dimension: TextureViewDimension,
|
||||
component_type: TextureComponentType,
|
||||
view_dimension: TextureViewDimension,
|
||||
sample_type: TextureSampleType,
|
||||
},
|
||||
StorageTexture {
|
||||
dimension: TextureViewDimension,
|
||||
/// Allowed access to this texture.
|
||||
access: StorageTextureAccess,
|
||||
/// Format of the texture.
|
||||
format: TextureFormat,
|
||||
readonly: bool,
|
||||
/// Dimension of the texture view that is going to be sampled.
|
||||
view_dimension: TextureViewDimension,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
use super::{
|
||||
state_descriptors::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat,
|
||||
PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
BlendFactor, BlendOperation, ColorWrite, CompareFunction, CullMode, FrontFace,
|
||||
PrimitiveTopology,
|
||||
},
|
||||
PipelineLayout, StencilStateDescriptor,
|
||||
PipelineLayout,
|
||||
};
|
||||
use crate::{
|
||||
pipeline::{
|
||||
BlendState, ColorTargetState, DepthBiasState, DepthStencilState, MultisampleState,
|
||||
PolygonMode, PrimitiveState, StencilFaceState, StencilState,
|
||||
},
|
||||
shader::ShaderStages,
|
||||
texture::TextureFormat,
|
||||
};
|
||||
use crate::{shader::ShaderStages, texture::TextureFormat};
|
||||
use bevy_reflect::TypeUuid;
|
||||
|
||||
#[derive(Clone, Debug, TypeUuid)]
|
||||
|
@ -15,32 +21,12 @@ pub struct PipelineDescriptor {
|
|||
pub name: Option<String>,
|
||||
pub layout: Option<PipelineLayout>,
|
||||
pub shader_stages: ShaderStages,
|
||||
pub rasterization_state: Option<RasterizationStateDescriptor>,
|
||||
|
||||
/// The primitive topology used to interpret vertices.
|
||||
pub primitive_topology: PrimitiveTopology,
|
||||
pub primitive: PrimitiveState,
|
||||
pub depth_stencil: Option<DepthStencilState>,
|
||||
pub multisample: MultisampleState,
|
||||
|
||||
/// The effect of draw calls on the color aspect of the output target.
|
||||
pub color_states: Vec<ColorStateDescriptor>,
|
||||
|
||||
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
|
||||
pub depth_stencil_state: Option<DepthStencilStateDescriptor>,
|
||||
|
||||
/// The format of any index buffers used with this pipeline.
|
||||
pub index_format: IndexFormat,
|
||||
|
||||
/// The number of samples calculated per pixel (for MSAA).
|
||||
pub sample_count: u32,
|
||||
|
||||
/// Bitmask that restricts the samples of a pixel modified by this pipeline.
|
||||
pub sample_mask: u32,
|
||||
|
||||
/// When enabled, produces another sample mask per pixel based on the alpha output value, that
|
||||
/// is AND-ed with the sample_mask and the primitive coverage to restrict the set of samples
|
||||
/// affected by a primitive.
|
||||
/// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
|
||||
/// is guaranteed to be all 1-s.
|
||||
pub alpha_to_coverage_enabled: bool,
|
||||
pub color_target_states: Vec<ColorTargetState>,
|
||||
}
|
||||
|
||||
impl PipelineDescriptor {
|
||||
|
@ -48,60 +34,71 @@ impl PipelineDescriptor {
|
|||
PipelineDescriptor {
|
||||
name: None,
|
||||
layout: None,
|
||||
color_states: Vec::new(),
|
||||
depth_stencil_state: None,
|
||||
color_target_states: Vec::new(),
|
||||
depth_stencil: None,
|
||||
shader_stages,
|
||||
rasterization_state: None,
|
||||
primitive_topology: PrimitiveTopology::TriangleList,
|
||||
index_format: IndexFormat::Uint32,
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
primitive: PrimitiveState {
|
||||
topology: PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
polygon_mode: PolygonMode::Fill,
|
||||
},
|
||||
multisample: MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_config(shader_stages: ShaderStages) -> Self {
|
||||
PipelineDescriptor {
|
||||
name: None,
|
||||
primitive_topology: PrimitiveTopology::TriangleList,
|
||||
layout: None,
|
||||
index_format: IndexFormat::Uint32,
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
rasterization_state: Some(RasterizationStateDescriptor {
|
||||
primitive: PrimitiveState {
|
||||
topology: PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
clamp_depth: false,
|
||||
}),
|
||||
depth_stencil_state: Some(DepthStencilStateDescriptor {
|
||||
polygon_mode: PolygonMode::Fill,
|
||||
},
|
||||
layout: None,
|
||||
depth_stencil: Some(DepthStencilState {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil: StencilStateDescriptor {
|
||||
front: StencilStateFaceDescriptor::IGNORE,
|
||||
back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil: StencilState {
|
||||
front: StencilFaceState::IGNORE,
|
||||
back: StencilFaceState::IGNORE,
|
||||
read_mask: 0,
|
||||
write_mask: 0,
|
||||
},
|
||||
bias: DepthBiasState {
|
||||
constant: 0,
|
||||
slope_scale: 0.0,
|
||||
clamp: 0.0,
|
||||
},
|
||||
clamp_depth: false,
|
||||
}),
|
||||
color_states: vec![ColorStateDescriptor {
|
||||
color_target_states: vec![ColorTargetState {
|
||||
format: TextureFormat::default(),
|
||||
color_blend: BlendDescriptor {
|
||||
color_blend: BlendState {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
alpha_blend: BlendState {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
}],
|
||||
multisample: MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
shader_stages,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor};
|
||||
use crate::{
|
||||
pipeline::{BindType, InputStepMode, VertexBufferDescriptor},
|
||||
pipeline::{BindType, InputStepMode, VertexBufferLayout},
|
||||
renderer::RenderResourceContext,
|
||||
shader::{Shader, ShaderError},
|
||||
};
|
||||
|
@ -15,8 +15,8 @@ pub struct PipelineSpecialization {
|
|||
pub shader_specialization: ShaderSpecialization,
|
||||
pub primitive_topology: PrimitiveTopology,
|
||||
pub dynamic_bindings: HashSet<String>,
|
||||
pub index_format: IndexFormat,
|
||||
pub vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||
pub strip_index_format: Option<IndexFormat>,
|
||||
pub vertex_buffer_layout: VertexBufferLayout,
|
||||
pub sample_count: u32,
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,11 @@ impl Default for PipelineSpecialization {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
sample_count: 1,
|
||||
index_format: IndexFormat::Uint32,
|
||||
strip_index_format: None,
|
||||
shader_specialization: Default::default(),
|
||||
primitive_topology: Default::default(),
|
||||
dynamic_bindings: Default::default(),
|
||||
vertex_buffer_descriptor: Default::default(),
|
||||
vertex_buffer_layout: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,10 +178,11 @@ impl PipelineCompiler {
|
|||
.any(|b| b == &binding.name)
|
||||
{
|
||||
if let BindType::Uniform {
|
||||
ref mut dynamic, ..
|
||||
ref mut has_dynamic_offset,
|
||||
..
|
||||
} = binding.bind_type
|
||||
{
|
||||
*dynamic = true;
|
||||
*has_dynamic_offset = true;
|
||||
binding_changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -197,12 +198,12 @@ impl PipelineCompiler {
|
|||
// create a vertex layout that provides all attributes from either the specialized vertex buffers or a zero buffer
|
||||
let mut pipeline_layout = specialized_descriptor.layout.as_mut().unwrap();
|
||||
// the vertex buffer descriptor of the mesh
|
||||
let mesh_vertex_buffer_descriptor = &pipeline_specialization.vertex_buffer_descriptor;
|
||||
let mesh_vertex_buffer_layout = &pipeline_specialization.vertex_buffer_layout;
|
||||
|
||||
// the vertex buffer descriptor that will be used for this pipeline
|
||||
let mut compiled_vertex_buffer_descriptor = VertexBufferDescriptor {
|
||||
let mut compiled_vertex_buffer_descriptor = VertexBufferLayout {
|
||||
step_mode: InputStepMode::Vertex,
|
||||
stride: mesh_vertex_buffer_descriptor.stride,
|
||||
stride: mesh_vertex_buffer_layout.stride,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -212,7 +213,7 @@ impl PipelineCompiler {
|
|||
.get(0)
|
||||
.expect("Reflected layout has no attributes.");
|
||||
|
||||
if let Some(target_vertex_attribute) = mesh_vertex_buffer_descriptor
|
||||
if let Some(target_vertex_attribute) = mesh_vertex_buffer_layout
|
||||
.attributes
|
||||
.iter()
|
||||
.find(|x| x.name == shader_vertex_attribute.name)
|
||||
|
@ -233,13 +234,14 @@ impl PipelineCompiler {
|
|||
}
|
||||
|
||||
//TODO: add other buffers (like instancing) here
|
||||
let mut vertex_buffer_descriptors = Vec::<VertexBufferDescriptor>::default();
|
||||
let mut vertex_buffer_descriptors = Vec::<VertexBufferLayout>::default();
|
||||
vertex_buffer_descriptors.push(compiled_vertex_buffer_descriptor);
|
||||
|
||||
pipeline_layout.vertex_buffer_descriptors = vertex_buffer_descriptors;
|
||||
specialized_descriptor.sample_count = pipeline_specialization.sample_count;
|
||||
specialized_descriptor.primitive_topology = pipeline_specialization.primitive_topology;
|
||||
specialized_descriptor.index_format = pipeline_specialization.index_format;
|
||||
specialized_descriptor.multisample.count = pipeline_specialization.sample_count;
|
||||
specialized_descriptor.primitive.topology = pipeline_specialization.primitive_topology;
|
||||
specialized_descriptor.primitive.strip_index_format =
|
||||
pipeline_specialization.strip_index_format;
|
||||
|
||||
let specialized_pipeline_handle = pipelines.add(specialized_descriptor);
|
||||
render_resource_context.create_render_pipeline(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{BindGroupDescriptor, VertexBufferDescriptor};
|
||||
use super::{BindGroupDescriptor, VertexBufferLayout};
|
||||
use crate::shader::ShaderLayout;
|
||||
use bevy_utils::HashMap;
|
||||
use std::hash::Hash;
|
||||
|
@ -6,7 +6,7 @@ use std::hash::Hash;
|
|||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PipelineLayout {
|
||||
pub bind_groups: Vec<BindGroupDescriptor>,
|
||||
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
|
||||
pub vertex_buffer_descriptors: Vec<VertexBufferLayout>,
|
||||
}
|
||||
|
||||
impl PipelineLayout {
|
||||
|
@ -49,7 +49,7 @@ impl PipelineLayout {
|
|||
}
|
||||
}
|
||||
|
||||
for vertex_buffer_descriptor in shader_layouts[0].vertex_buffer_descriptors.iter() {
|
||||
for vertex_buffer_descriptor in shader_layouts[0].vertex_buffer_layout.iter() {
|
||||
vertex_buffer_descriptors.push(vertex_buffer_descriptor.clone());
|
||||
}
|
||||
|
||||
|
|
|
@ -3,20 +3,48 @@ use bevy_reflect::Reflect;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DepthStencilStateDescriptor {
|
||||
pub struct DepthStencilState {
|
||||
pub format: TextureFormat,
|
||||
pub depth_write_enabled: bool,
|
||||
pub depth_compare: CompareFunction,
|
||||
pub stencil: StencilStateDescriptor,
|
||||
pub stencil: StencilState,
|
||||
pub bias: DepthBiasState,
|
||||
pub clamp_depth: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StencilStateDescriptor {
|
||||
pub front: StencilStateFaceDescriptor,
|
||||
pub back: StencilStateFaceDescriptor,
|
||||
pub struct StencilState {
|
||||
pub front: StencilFaceState,
|
||||
pub back: StencilFaceState,
|
||||
pub read_mask: u32,
|
||||
pub write_mask: u32,
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MultisampleState {
|
||||
/// The number of samples calculated per pixel (for MSAA). For non-multisampled textures,
|
||||
/// this should be `1`
|
||||
pub count: u32,
|
||||
/// Bitmask that restricts the samples of a pixel modified by this pipeline. All samples
|
||||
/// can be enabled using the value `!0`
|
||||
pub mask: u64,
|
||||
/// When enabled, produces another sample mask per pixel based on the alpha output value, that
|
||||
/// is ANDed with the sample_mask and the primitive coverage to restrict the set of samples
|
||||
/// affected by a primitive.
|
||||
///
|
||||
/// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
|
||||
/// is guaranteed to be all 1-s.
|
||||
pub alpha_to_coverage_enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DepthBiasState {
|
||||
/// Constant depth biasing factor, in basic units of the depth format.
|
||||
pub constant: i32,
|
||||
/// Slope depth biasing factor.
|
||||
pub slope_scale: f32,
|
||||
/// Depth bias clamp value (absolute).
|
||||
pub clamp: f32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum StencilOperation {
|
||||
|
@ -31,15 +59,15 @@ pub enum StencilOperation {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct StencilStateFaceDescriptor {
|
||||
pub struct StencilFaceState {
|
||||
pub compare: CompareFunction,
|
||||
pub fail_op: StencilOperation,
|
||||
pub depth_fail_op: StencilOperation,
|
||||
pub pass_op: StencilOperation,
|
||||
}
|
||||
|
||||
impl StencilStateFaceDescriptor {
|
||||
pub const IGNORE: Self = StencilStateFaceDescriptor {
|
||||
impl StencilFaceState {
|
||||
pub const IGNORE: Self = StencilFaceState {
|
||||
compare: CompareFunction::Always,
|
||||
fail_op: StencilOperation::Keep,
|
||||
depth_fail_op: StencilOperation::Keep,
|
||||
|
@ -99,33 +127,48 @@ impl Default for CullMode {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum PolygonMode {
|
||||
/// Polygons are filled
|
||||
Fill = 0,
|
||||
/// Polygons are draw as line segments
|
||||
Line = 1,
|
||||
/// Polygons are draw as points
|
||||
Point = 2,
|
||||
}
|
||||
|
||||
impl Default for PolygonMode {
|
||||
fn default() -> Self {
|
||||
PolygonMode::Fill
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct RasterizationStateDescriptor {
|
||||
pub struct PrimitiveState {
|
||||
pub topology: PrimitiveTopology,
|
||||
pub strip_index_format: Option<IndexFormat>,
|
||||
pub front_face: FrontFace,
|
||||
pub cull_mode: CullMode,
|
||||
pub depth_bias: i32,
|
||||
pub depth_bias_slope_scale: f32,
|
||||
pub depth_bias_clamp: f32,
|
||||
pub clamp_depth: bool,
|
||||
pub polygon_mode: PolygonMode,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ColorStateDescriptor {
|
||||
pub struct ColorTargetState {
|
||||
pub format: TextureFormat,
|
||||
pub alpha_blend: BlendDescriptor,
|
||||
pub color_blend: BlendDescriptor,
|
||||
pub alpha_blend: BlendState,
|
||||
pub color_blend: BlendState,
|
||||
pub write_mask: ColorWrite,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BlendDescriptor {
|
||||
pub struct BlendState {
|
||||
pub src_factor: BlendFactor,
|
||||
pub dst_factor: BlendFactor,
|
||||
pub operation: BlendOperation,
|
||||
}
|
||||
|
||||
impl BlendDescriptor {
|
||||
pub const REPLACE: Self = BlendDescriptor {
|
||||
impl BlendState {
|
||||
pub const REPLACE: Self = BlendState {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::Zero,
|
||||
operation: BlendOperation::Add,
|
||||
|
|
|
@ -8,23 +8,23 @@ use std::{
|
|||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Default, Reflect, Serialize, Deserialize)]
|
||||
#[reflect_value(Serialize, Deserialize, PartialEq)]
|
||||
pub struct VertexBufferDescriptor {
|
||||
pub struct VertexBufferLayout {
|
||||
pub name: Cow<'static, str>,
|
||||
pub stride: u64,
|
||||
pub step_mode: InputStepMode,
|
||||
pub attributes: Vec<VertexAttributeDescriptor>,
|
||||
pub attributes: Vec<VertexAttribute>,
|
||||
}
|
||||
|
||||
impl VertexBufferDescriptor {
|
||||
impl VertexBufferLayout {
|
||||
pub fn new_from_attribute(
|
||||
attribute: VertexAttributeDescriptor,
|
||||
attribute: VertexAttribute,
|
||||
step_mode: InputStepMode,
|
||||
) -> VertexBufferDescriptor {
|
||||
VertexBufferDescriptor {
|
||||
) -> VertexBufferLayout {
|
||||
VertexBufferLayout {
|
||||
name: attribute.name.clone(),
|
||||
stride: attribute.format.get_size(),
|
||||
step_mode,
|
||||
attributes: vec![attribute.clone()],
|
||||
attributes: vec![attribute],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,10 +41,10 @@ impl Default for InputStepMode {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct VertexAttributeDescriptor {
|
||||
pub struct VertexAttribute {
|
||||
pub name: Cow<'static, str>,
|
||||
pub offset: u64,
|
||||
pub format: VertexFormat,
|
||||
pub offset: u64,
|
||||
pub shader_location: u32,
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ use crate::{
|
|||
draw::{Draw, RenderCommand},
|
||||
pass::{ClearColor, LoadOp, PassDescriptor, TextureAttachment},
|
||||
pipeline::{
|
||||
BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, PipelineDescriptor,
|
||||
UniformProperty,
|
||||
BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, IndexFormat,
|
||||
PipelineDescriptor, UniformProperty,
|
||||
},
|
||||
prelude::Visible,
|
||||
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
|
||||
|
@ -109,7 +109,7 @@ impl<Q: WorldQuery> PassNode<Q> {
|
|||
name: "Camera".to_string(),
|
||||
index: 0,
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
has_dynamic_offset: false,
|
||||
property: UniformProperty::Struct(vec![UniformProperty::Mat4]),
|
||||
},
|
||||
shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT,
|
||||
|
@ -301,12 +301,12 @@ where
|
|||
render_pass.set_vertex_buffer(*slot, *buffer, *offset);
|
||||
draw_state.set_vertex_buffer(*slot, *buffer, *offset);
|
||||
}
|
||||
RenderCommand::SetIndexBuffer { buffer, offset } => {
|
||||
if draw_state.is_index_buffer_set(*buffer, *offset) {
|
||||
RenderCommand::SetIndexBuffer { buffer, offset, index_format } => {
|
||||
if draw_state.is_index_buffer_set(*buffer, *offset, *index_format) {
|
||||
continue;
|
||||
}
|
||||
render_pass.set_index_buffer(*buffer, *offset);
|
||||
draw_state.set_index_buffer(*buffer, *offset)
|
||||
render_pass.set_index_buffer(*buffer, *offset, *index_format);
|
||||
draw_state.set_index_buffer(*buffer, *offset, *index_format);
|
||||
}
|
||||
RenderCommand::SetBindGroup {
|
||||
index,
|
||||
|
@ -344,7 +344,7 @@ struct DrawState {
|
|||
pipeline: Option<Handle<PipelineDescriptor>>,
|
||||
bind_groups: Vec<Option<BindGroupId>>,
|
||||
vertex_buffers: Vec<Option<(BufferId, u64)>>,
|
||||
index_buffer: Option<(BufferId, u64)>,
|
||||
index_buffer: Option<(BufferId, u64, IndexFormat)>,
|
||||
}
|
||||
|
||||
impl DrawState {
|
||||
|
@ -364,12 +364,17 @@ impl DrawState {
|
|||
self.vertex_buffers[index as usize] == Some((buffer, offset))
|
||||
}
|
||||
|
||||
pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64) {
|
||||
self.index_buffer = Some((buffer, offset));
|
||||
pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64, index_format: IndexFormat) {
|
||||
self.index_buffer = Some((buffer, offset, index_format));
|
||||
}
|
||||
|
||||
pub fn is_index_buffer_set(&self, buffer: BufferId, offset: u64) -> bool {
|
||||
self.index_buffer == Some((buffer, offset))
|
||||
pub fn is_index_buffer_set(
|
||||
&self,
|
||||
buffer: BufferId,
|
||||
offset: u64,
|
||||
index_format: IndexFormat,
|
||||
) -> bool {
|
||||
self.index_buffer == Some((buffer, offset, index_format))
|
||||
}
|
||||
|
||||
pub fn can_draw(&self) -> bool {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{BindGroup, BindGroupId, BufferId, SamplerId, TextureId};
|
||||
use crate::{
|
||||
pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor},
|
||||
pipeline::{BindGroupDescriptor, BindGroupDescriptorId, IndexFormat, PipelineDescriptor},
|
||||
renderer::RenderResourceContext,
|
||||
};
|
||||
use bevy_asset::{Asset, Handle, HandleUntyped};
|
||||
|
@ -69,7 +69,7 @@ pub struct RenderResourceBindings {
|
|||
pub vertex_attribute_buffer: Option<BufferId>,
|
||||
/// A Buffer that is filled with zeros that will be used for attributes required by the shader, but undefined by the mesh.
|
||||
pub vertex_fallback_buffer: Option<BufferId>,
|
||||
pub index_buffer: Option<BufferId>,
|
||||
pub index_buffer: Option<(BufferId, IndexFormat)>,
|
||||
assets: HashSet<(HandleUntyped, TypeId)>,
|
||||
bind_groups: HashMap<BindGroupId, BindGroup>,
|
||||
bind_group_descriptors: HashMap<BindGroupDescriptorId, Option<BindGroupId>>,
|
||||
|
@ -116,8 +116,8 @@ impl RenderResourceBindings {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_index_buffer(&mut self, index_buffer: BufferId) {
|
||||
self.index_buffer = Some(index_buffer);
|
||||
pub fn set_index_buffer(&mut self, index_buffer: BufferId, index_format: IndexFormat) {
|
||||
self.index_buffer = Some((index_buffer, index_format));
|
||||
}
|
||||
|
||||
fn create_bind_group(&mut self, descriptor: &BindGroupDescriptor) -> BindGroupStatus {
|
||||
|
@ -303,7 +303,7 @@ mod tests {
|
|||
index: 0,
|
||||
name: "a".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
has_dynamic_offset: false,
|
||||
property: UniformProperty::Struct(vec![UniformProperty::Mat4]),
|
||||
},
|
||||
shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT,
|
||||
|
@ -312,7 +312,7 @@ mod tests {
|
|||
index: 1,
|
||||
name: "b".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
has_dynamic_offset: false,
|
||||
property: UniformProperty::Float,
|
||||
},
|
||||
shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT,
|
||||
|
|
|
@ -11,13 +11,13 @@ pub use shader_defs::*;
|
|||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub use shader_reflect::*;
|
||||
|
||||
use crate::pipeline::{BindGroupDescriptor, VertexBufferDescriptor};
|
||||
use crate::pipeline::{BindGroupDescriptor, VertexBufferLayout};
|
||||
|
||||
/// Defines the memory layout of a shader
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ShaderLayout {
|
||||
pub bind_groups: Vec<BindGroupDescriptor>,
|
||||
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
|
||||
pub vertex_buffer_layout: Vec<VertexBufferLayout>,
|
||||
pub entry_point: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::{
|
||||
pipeline::{
|
||||
BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, InputStepMode,
|
||||
UniformProperty, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
|
||||
UniformProperty, VertexAttribute, VertexBufferLayout, VertexFormat,
|
||||
},
|
||||
shader::{ShaderLayout, GL_INSTANCE_INDEX, GL_VERTEX_INDEX},
|
||||
texture::{TextureComponentType, TextureViewDimension},
|
||||
texture::{TextureSampleType, TextureViewDimension},
|
||||
};
|
||||
use bevy_core::AsBytes;
|
||||
use spirv_reflect::{
|
||||
|
@ -29,7 +29,7 @@ impl ShaderLayout {
|
|||
}
|
||||
|
||||
// obtain attribute descriptors from reflection
|
||||
let mut vertex_attribute_descriptors = Vec::new();
|
||||
let mut vertex_attributes = Vec::new();
|
||||
for input_variable in module.enumerate_input_variables(None).unwrap() {
|
||||
if input_variable.name == GL_VERTEX_INDEX
|
||||
|| input_variable.name == GL_INSTANCE_INDEX
|
||||
|
@ -37,7 +37,7 @@ impl ShaderLayout {
|
|||
continue;
|
||||
}
|
||||
// reflect vertex attribute descriptor and record it
|
||||
vertex_attribute_descriptors.push(VertexAttributeDescriptor {
|
||||
vertex_attributes.push(VertexAttribute {
|
||||
name: input_variable.name.clone().into(),
|
||||
format: reflect_vertex_format(
|
||||
input_variable.type_description.as_ref().unwrap(),
|
||||
|
@ -47,20 +47,19 @@ impl ShaderLayout {
|
|||
});
|
||||
}
|
||||
|
||||
vertex_attribute_descriptors
|
||||
.sort_by(|a, b| a.shader_location.cmp(&b.shader_location));
|
||||
vertex_attributes.sort_by(|a, b| a.shader_location.cmp(&b.shader_location));
|
||||
|
||||
let mut vertex_buffer_descriptors = Vec::new();
|
||||
for vertex_attribute_descriptor in vertex_attribute_descriptors.drain(..) {
|
||||
let mut vertex_buffer_layout = Vec::new();
|
||||
for vertex_attribute in vertex_attributes.drain(..) {
|
||||
let mut instance = false;
|
||||
// obtain buffer name and instancing flag
|
||||
let current_buffer_name = {
|
||||
if bevy_conventions {
|
||||
if vertex_attribute_descriptor.name == GL_VERTEX_INDEX {
|
||||
if vertex_attribute.name == GL_VERTEX_INDEX {
|
||||
GL_VERTEX_INDEX.to_string()
|
||||
} else {
|
||||
instance = vertex_attribute_descriptor.name.starts_with("I_");
|
||||
vertex_attribute_descriptor.name.to_string()
|
||||
instance = vertex_attribute.name.starts_with("I_");
|
||||
vertex_attribute.name.to_string()
|
||||
}
|
||||
} else {
|
||||
"DefaultVertex".to_string()
|
||||
|
@ -68,8 +67,8 @@ impl ShaderLayout {
|
|||
};
|
||||
|
||||
// create a new buffer descriptor, per attribute!
|
||||
vertex_buffer_descriptors.push(VertexBufferDescriptor {
|
||||
attributes: vec![vertex_attribute_descriptor],
|
||||
vertex_buffer_layout.push(VertexBufferLayout {
|
||||
attributes: vec![vertex_attribute],
|
||||
name: current_buffer_name.into(),
|
||||
step_mode: if instance {
|
||||
InputStepMode::Instance
|
||||
|
@ -82,7 +81,7 @@ impl ShaderLayout {
|
|||
|
||||
ShaderLayout {
|
||||
bind_groups,
|
||||
vertex_buffer_descriptors,
|
||||
vertex_buffer_layout,
|
||||
entry_point: entry_point_name,
|
||||
}
|
||||
}
|
||||
|
@ -123,27 +122,34 @@ fn reflect_binding(
|
|||
ReflectDescriptorType::UniformBuffer => (
|
||||
&type_description.type_name,
|
||||
BindType::Uniform {
|
||||
dynamic: false,
|
||||
has_dynamic_offset: false,
|
||||
property: reflect_uniform(type_description),
|
||||
},
|
||||
),
|
||||
ReflectDescriptorType::SampledImage => (
|
||||
&binding.name,
|
||||
BindType::SampledTexture {
|
||||
dimension: reflect_dimension(type_description),
|
||||
component_type: TextureComponentType::Float,
|
||||
BindType::Texture {
|
||||
view_dimension: reflect_dimension(type_description),
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
multisampled: false,
|
||||
},
|
||||
),
|
||||
ReflectDescriptorType::StorageBuffer => (
|
||||
&type_description.type_name,
|
||||
BindType::StorageBuffer {
|
||||
dynamic: false,
|
||||
has_dynamic_offset: false,
|
||||
readonly: true,
|
||||
},
|
||||
),
|
||||
// TODO: detect comparison "true" case: https://github.com/gpuweb/gpuweb/issues/552
|
||||
ReflectDescriptorType::Sampler => (&binding.name, BindType::Sampler { comparison: false }),
|
||||
// TODO: detect filtering "true" case
|
||||
ReflectDescriptorType::Sampler => (
|
||||
&binding.name,
|
||||
BindType::Sampler {
|
||||
comparison: false,
|
||||
filtering: false,
|
||||
},
|
||||
),
|
||||
_ => panic!("Unsupported bind type {:?}.", binding.descriptor_type),
|
||||
};
|
||||
|
||||
|
@ -302,8 +308,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::shader::{Shader, ShaderStage};
|
||||
|
||||
impl VertexBufferDescriptor {
|
||||
pub fn test_zero_stride(mut self) -> VertexBufferDescriptor {
|
||||
impl VertexBufferLayout {
|
||||
pub fn test_zero_stride(mut self) -> VertexBufferLayout {
|
||||
self.stride = 0;
|
||||
self
|
||||
}
|
||||
|
@ -338,9 +344,9 @@ mod tests {
|
|||
layout,
|
||||
ShaderLayout {
|
||||
entry_point: "main".into(),
|
||||
vertex_buffer_descriptors: vec![
|
||||
VertexBufferDescriptor::new_from_attribute(
|
||||
VertexAttributeDescriptor {
|
||||
vertex_buffer_layout: vec![
|
||||
VertexBufferLayout::new_from_attribute(
|
||||
VertexAttribute {
|
||||
name: "Vertex_Position".into(),
|
||||
format: VertexFormat::Float4,
|
||||
offset: 0,
|
||||
|
@ -349,8 +355,8 @@ mod tests {
|
|||
InputStepMode::Vertex
|
||||
)
|
||||
.test_zero_stride(),
|
||||
VertexBufferDescriptor::new_from_attribute(
|
||||
VertexAttributeDescriptor {
|
||||
VertexBufferLayout::new_from_attribute(
|
||||
VertexAttribute {
|
||||
name: "Vertex_Normal".into(),
|
||||
format: VertexFormat::Uint4,
|
||||
offset: 0,
|
||||
|
@ -359,8 +365,8 @@ mod tests {
|
|||
InputStepMode::Vertex
|
||||
)
|
||||
.test_zero_stride(),
|
||||
VertexBufferDescriptor::new_from_attribute(
|
||||
VertexAttributeDescriptor {
|
||||
VertexBufferLayout::new_from_attribute(
|
||||
VertexAttribute {
|
||||
name: "I_TestInstancing_Property".into(),
|
||||
format: VertexFormat::Uint4,
|
||||
offset: 0,
|
||||
|
@ -377,7 +383,7 @@ mod tests {
|
|||
index: 0,
|
||||
name: "Camera".into(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
has_dynamic_offset: false,
|
||||
property: UniformProperty::Struct(vec![UniformProperty::Mat4]),
|
||||
},
|
||||
shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT,
|
||||
|
@ -388,10 +394,10 @@ mod tests {
|
|||
vec![BindingDescriptor {
|
||||
index: 0,
|
||||
name: "Texture".into(),
|
||||
bind_type: BindType::SampledTexture {
|
||||
bind_type: BindType::Texture {
|
||||
multisampled: false,
|
||||
dimension: TextureViewDimension::D2,
|
||||
component_type: TextureComponentType::Float,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
sample_type: TextureSampleType::Float { filterable: true }
|
||||
},
|
||||
shader_stage: BindingShaderStage::VERTEX,
|
||||
}]
|
||||
|
|
|
@ -14,6 +14,7 @@ pub struct SamplerDescriptor {
|
|||
pub lod_max_clamp: f32,
|
||||
pub compare_function: Option<CompareFunction>,
|
||||
pub anisotropy_clamp: Option<NonZeroU8>,
|
||||
pub border_color: Option<SamplerBorderColor>,
|
||||
}
|
||||
|
||||
impl SamplerDescriptor {
|
||||
|
@ -38,6 +39,7 @@ impl Default for SamplerDescriptor {
|
|||
lod_max_clamp: std::f32::MAX,
|
||||
compare_function: None,
|
||||
anisotropy_clamp: None,
|
||||
border_color: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,3 +70,10 @@ impl Default for FilterMode {
|
|||
FilterMode::Nearest
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum SamplerBorderColor {
|
||||
TransparentBlack,
|
||||
OpaqueBlack,
|
||||
OpaqueWhite,
|
||||
}
|
||||
|
|
|
@ -40,3 +40,29 @@ impl Default for TextureDescriptor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum StorageTextureAccess {
|
||||
/// The texture can only be read in the shader and it must be annotated with `readonly`.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(set=0, binding=0, r32f) readonly uniform image2D myStorageImage;
|
||||
/// ```
|
||||
ReadOnly,
|
||||
/// The texture can only be written in the shader and it must be annotated with `writeonly`.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(set=0, binding=0, r32f) writeonly uniform image2D myStorageImage;
|
||||
/// ```
|
||||
WriteOnly,
|
||||
/// The texture can be both read and written in the shader.
|
||||
/// [`Features::STORAGE_TEXTURE_ACCESS_READ_WRITE`] must be enabled to use this access mode.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(set=0, binding=0, r32f) uniform image2D myStorageImage;
|
||||
/// ```
|
||||
ReadWrite,
|
||||
}
|
||||
|
|
|
@ -49,9 +49,41 @@ impl Extent3d {
|
|||
|
||||
/// Type of data shaders will read from a texture.
|
||||
#[derive(Copy, Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum TextureComponentType {
|
||||
Float,
|
||||
pub enum TextureSampleType {
|
||||
/// Sampling returns floats.
|
||||
///
|
||||
/// If `filterable` is false, the texture can't be sampled with
|
||||
/// a filtering sampler.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform texture2D t;
|
||||
/// ```
|
||||
Float { filterable: bool },
|
||||
/// Sampling does the depth reference comparison.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform texture2DShadow t;
|
||||
/// ```
|
||||
Depth,
|
||||
/// Sampling returns signed integers.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform itexture2D t;
|
||||
/// ```
|
||||
Sint,
|
||||
/// Sampling returns unsigned integers.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform utexture2D t;
|
||||
/// ```
|
||||
Uint,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,8 @@ use bevy_ecs::Resources;
|
|||
use bevy_reflect::TypeUuid;
|
||||
use bevy_render::{
|
||||
pipeline::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, PipelineDescriptor,
|
||||
RasterizationStateDescriptor, StencilStateDescriptor, StencilStateFaceDescriptor,
|
||||
BlendFactor, BlendOperation, BlendState, ColorTargetState, ColorWrite, CompareFunction,
|
||||
DepthBiasState, DepthStencilState, PipelineDescriptor, StencilFaceState, StencilState,
|
||||
},
|
||||
render_graph::{base, AssetRenderResourcesNode, RenderGraph, RenderResourcesNode},
|
||||
shader::{Shader, ShaderStage, ShaderStages},
|
||||
|
@ -21,33 +20,31 @@ pub const SPRITE_SHEET_PIPELINE_HANDLE: HandleUntyped =
|
|||
|
||||
pub fn build_sprite_sheet_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
||||
PipelineDescriptor {
|
||||
rasterization_state: Some(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::None,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
clamp_depth: false,
|
||||
}),
|
||||
depth_stencil_state: Some(DepthStencilStateDescriptor {
|
||||
depth_stencil: Some(DepthStencilState {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::LessEqual,
|
||||
stencil: StencilStateDescriptor {
|
||||
front: StencilStateFaceDescriptor::IGNORE,
|
||||
back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil: StencilState {
|
||||
front: StencilFaceState::IGNORE,
|
||||
back: StencilFaceState::IGNORE,
|
||||
read_mask: 0,
|
||||
write_mask: 0,
|
||||
},
|
||||
bias: DepthBiasState {
|
||||
constant: 0,
|
||||
slope_scale: 0.0,
|
||||
clamp: 0.0,
|
||||
},
|
||||
clamp_depth: false,
|
||||
}),
|
||||
color_states: vec![ColorStateDescriptor {
|
||||
color_target_states: vec![ColorTargetState {
|
||||
format: TextureFormat::default(),
|
||||
color_blend: BlendDescriptor {
|
||||
color_blend: BlendState {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
alpha_blend: BlendState {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
|
@ -69,33 +66,31 @@ pub fn build_sprite_sheet_pipeline(shaders: &mut Assets<Shader>) -> PipelineDesc
|
|||
|
||||
pub fn build_sprite_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
||||
PipelineDescriptor {
|
||||
rasterization_state: Some(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::None,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
clamp_depth: false,
|
||||
}),
|
||||
depth_stencil_state: Some(DepthStencilStateDescriptor {
|
||||
depth_stencil: Some(DepthStencilState {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::LessEqual,
|
||||
stencil: StencilStateDescriptor {
|
||||
front: StencilStateFaceDescriptor::IGNORE,
|
||||
back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil: StencilState {
|
||||
front: StencilFaceState::IGNORE,
|
||||
back: StencilFaceState::IGNORE,
|
||||
read_mask: 0,
|
||||
write_mask: 0,
|
||||
},
|
||||
bias: DepthBiasState {
|
||||
constant: 0,
|
||||
slope_scale: 0.0,
|
||||
clamp: 0.0,
|
||||
},
|
||||
clamp_depth: false,
|
||||
}),
|
||||
color_states: vec![ColorStateDescriptor {
|
||||
color_target_states: vec![ColorTargetState {
|
||||
format: TextureFormat::default(),
|
||||
color_blend: BlendDescriptor {
|
||||
color_blend: BlendState {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
alpha_blend: BlendState {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
|
|
|
@ -3,13 +3,14 @@ use bevy_render::{
|
|||
draw::{Draw, DrawContext, DrawError, Drawable},
|
||||
mesh,
|
||||
mesh::Mesh,
|
||||
pipeline::{PipelineSpecialization, VertexBufferDescriptor},
|
||||
pipeline::{PipelineSpecialization, VertexBufferLayout},
|
||||
prelude::Msaa,
|
||||
renderer::{BindGroup, RenderResourceBindings, RenderResourceId},
|
||||
};
|
||||
use bevy_sprite::TextureAtlasSprite;
|
||||
|
||||
use crate::{PositionedGlyph, TextSection};
|
||||
use bevy_render::pipeline::IndexFormat;
|
||||
|
||||
pub struct DrawableText<'a> {
|
||||
pub render_resource_bindings: &'a mut RenderResourceBindings,
|
||||
|
@ -18,7 +19,7 @@ pub struct DrawableText<'a> {
|
|||
pub sections: &'a [TextSection],
|
||||
pub text_glyphs: &'a Vec<PositionedGlyph>,
|
||||
pub msaa: &'a Msaa,
|
||||
pub font_quad_vertex_descriptor: &'a VertexBufferDescriptor,
|
||||
pub font_quad_vertex_layout: &'a VertexBufferLayout,
|
||||
}
|
||||
|
||||
impl<'a> Drawable for DrawableText<'a> {
|
||||
|
@ -28,7 +29,7 @@ impl<'a> Drawable for DrawableText<'a> {
|
|||
&bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE.typed(),
|
||||
&PipelineSpecialization {
|
||||
sample_count: self.msaa.samples,
|
||||
vertex_buffer_descriptor: self.font_quad_vertex_descriptor.clone(),
|
||||
vertex_buffer_layout: self.font_quad_vertex_layout.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
@ -53,7 +54,7 @@ impl<'a> Drawable for DrawableText<'a> {
|
|||
mesh::INDEX_BUFFER_ASSET_INDEX,
|
||||
)
|
||||
{
|
||||
draw.set_index_buffer(quad_index_buffer, 0);
|
||||
draw.set_index_buffer(quad_index_buffer, 0, IndexFormat::Uint32);
|
||||
if let Some(buffer_info) = render_resource_context.get_buffer_info(quad_index_buffer) {
|
||||
indices = 0..(buffer_info.size / 4) as u32;
|
||||
} else {
|
||||
|
|
|
@ -73,7 +73,7 @@ pub fn draw_text2d_system(
|
|||
>,
|
||||
) {
|
||||
let font_quad = meshes.get(&QUAD_HANDLE).unwrap();
|
||||
let vertex_buffer_descriptor = font_quad.get_vertex_buffer_descriptor();
|
||||
let font_quad_vertex_layout = font_quad.get_vertex_buffer_layout();
|
||||
|
||||
let scale_factor = if let Some(window) = windows.get_primary() {
|
||||
window.scale_factor() as f32
|
||||
|
@ -106,7 +106,7 @@ pub fn draw_text2d_system(
|
|||
position,
|
||||
msaa: &msaa,
|
||||
text_glyphs: &text_glyphs.glyphs,
|
||||
font_quad_vertex_descriptor: &vertex_buffer_descriptor,
|
||||
font_quad_vertex_layout: &font_quad_vertex_layout,
|
||||
scale_factor,
|
||||
sections: &text.sections,
|
||||
};
|
||||
|
|
|
@ -23,33 +23,31 @@ pub const UI_PIPELINE_HANDLE: HandleUntyped =
|
|||
|
||||
pub fn build_ui_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
||||
PipelineDescriptor {
|
||||
rasterization_state: Some(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
clamp_depth: false,
|
||||
}),
|
||||
depth_stencil_state: Some(DepthStencilStateDescriptor {
|
||||
depth_stencil: Some(DepthStencilState {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil: StencilStateDescriptor {
|
||||
front: StencilStateFaceDescriptor::IGNORE,
|
||||
back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil: StencilState {
|
||||
front: StencilFaceState::IGNORE,
|
||||
back: StencilFaceState::IGNORE,
|
||||
read_mask: 0,
|
||||
write_mask: 0,
|
||||
},
|
||||
bias: DepthBiasState {
|
||||
constant: 0,
|
||||
slope_scale: 0.0,
|
||||
clamp: 0.0,
|
||||
},
|
||||
clamp_depth: false,
|
||||
}),
|
||||
color_states: vec![ColorStateDescriptor {
|
||||
color_target_states: vec![ColorTargetState {
|
||||
format: TextureFormat::default(),
|
||||
color_blend: BlendDescriptor {
|
||||
color_blend: BlendState {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
alpha_blend: BlendState {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
|
|
|
@ -142,7 +142,7 @@ pub fn draw_text_system(
|
|||
};
|
||||
|
||||
let font_quad = meshes.get(&QUAD_HANDLE).unwrap();
|
||||
let vertex_buffer_descriptor = font_quad.get_vertex_buffer_descriptor();
|
||||
let vertex_buffer_layout = font_quad.get_vertex_buffer_layout();
|
||||
|
||||
for (entity, mut draw, visible, text, node, global_transform) in query.iter_mut() {
|
||||
if !visible.is_visible {
|
||||
|
@ -158,7 +158,7 @@ pub fn draw_text_system(
|
|||
scale_factor: scale_factor as f32,
|
||||
msaa: &msaa,
|
||||
text_glyphs: &text_glyphs.glyphs,
|
||||
font_quad_vertex_descriptor: &vertex_buffer_descriptor,
|
||||
font_quad_vertex_layout: &vertex_buffer_layout,
|
||||
sections: &text.sections,
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ bevy_winit = { path = "../bevy_winit", optional = true, version = "0.4.0" }
|
|||
bevy_utils = { path = "../bevy_utils", version = "0.4.0" }
|
||||
|
||||
# other
|
||||
wgpu = "0.6"
|
||||
wgpu = "0.7"
|
||||
futures-lite = "1.4.0"
|
||||
crossbeam-channel = "0.4.4"
|
||||
crossbeam-utils = "0.7.2"
|
||||
|
|
|
@ -206,6 +206,7 @@ pub fn create_render_pass<'a, 'b>(
|
|||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
) -> wgpu::RenderPass<'a> {
|
||||
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: None,
|
||||
color_attachments: &pass_descriptor
|
||||
.color_attachments
|
||||
.iter()
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use crate::{
|
||||
wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto},
|
||||
WgpuBindGroupInfo, WgpuResources,
|
||||
};
|
||||
use crate::{wgpu_type_converter::WgpuInto, WgpuBindGroupInfo, WgpuResources};
|
||||
|
||||
use crate::wgpu_type_converter::OwnedWgpuVertexBufferLayout;
|
||||
use bevy_asset::{Assets, Handle, HandleUntyped};
|
||||
use bevy_render::{
|
||||
pipeline::{
|
||||
|
@ -18,7 +16,7 @@ use bevy_render::{
|
|||
use bevy_utils::tracing::trace;
|
||||
use bevy_window::{Window, WindowId};
|
||||
use futures_lite::future;
|
||||
use std::{borrow::Cow, ops::Range, sync::Arc};
|
||||
use std::{borrow::Cow, num::NonZeroU64, ops::Range, sync::Arc};
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -331,7 +329,11 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
let spirv: Cow<[u32]> = shader.get_spirv(None).unwrap().into();
|
||||
let shader_module = self
|
||||
.device
|
||||
.create_shader_module(wgpu::ShaderModuleSource::SpirV(spirv));
|
||||
.create_shader_module(&wgpu::ShaderModuleDescriptor {
|
||||
label: None,
|
||||
source: wgpu::ShaderSource::SpirV(spirv),
|
||||
flags: Default::default(),
|
||||
});
|
||||
shader_modules.insert(shader_handle.clone_weak(), shader_module);
|
||||
}
|
||||
|
||||
|
@ -453,13 +455,13 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
.vertex_buffer_descriptors
|
||||
.iter()
|
||||
.map(|v| v.wgpu_into())
|
||||
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
|
||||
.collect::<Vec<OwnedWgpuVertexBufferLayout>>();
|
||||
|
||||
let color_states = pipeline_descriptor
|
||||
.color_states
|
||||
.color_target_states
|
||||
.iter()
|
||||
.map(|c| c.wgpu_into())
|
||||
.collect::<Vec<wgpu::ColorStateDescriptor>>();
|
||||
.collect::<Vec<wgpu::ColorTargetState>>();
|
||||
|
||||
self.create_shader_module(&pipeline_descriptor.shader_stages.vertex, shaders);
|
||||
|
||||
|
@ -476,41 +478,31 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
Some(ref fragment_handle) => Some(shader_modules.get(fragment_handle).unwrap()),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
||||
label: None,
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
vertex: wgpu::VertexState {
|
||||
module: &vertex_shader_module,
|
||||
entry_point: "main",
|
||||
buffers: &owned_vertex_buffer_descriptors
|
||||
.iter()
|
||||
.map(|v| v.into())
|
||||
.collect::<Vec<wgpu::VertexBufferLayout>>(),
|
||||
},
|
||||
fragment_stage: match pipeline_descriptor.shader_stages.fragment {
|
||||
Some(_) => Some(wgpu::ProgrammableStageDescriptor {
|
||||
fragment: match pipeline_descriptor.shader_stages.fragment {
|
||||
Some(_) => Some(wgpu::FragmentState {
|
||||
entry_point: "main",
|
||||
module: fragment_shader_module.as_ref().unwrap(),
|
||||
targets: color_states.as_slice(),
|
||||
}),
|
||||
None => None,
|
||||
},
|
||||
rasterization_state: pipeline_descriptor
|
||||
.rasterization_state
|
||||
.as_ref()
|
||||
.map(|r| r.wgpu_into()),
|
||||
primitive_topology: pipeline_descriptor.primitive_topology.wgpu_into(),
|
||||
color_states: &color_states,
|
||||
depth_stencil_state: pipeline_descriptor
|
||||
.depth_stencil_state
|
||||
.as_ref()
|
||||
.map(|d| d.wgpu_into()),
|
||||
vertex_state: wgpu::VertexStateDescriptor {
|
||||
index_format: pipeline_descriptor.index_format.wgpu_into(),
|
||||
vertex_buffers: &owned_vertex_buffer_descriptors
|
||||
.iter()
|
||||
.map(|v| v.into())
|
||||
.collect::<Vec<wgpu::VertexBufferDescriptor>>(),
|
||||
},
|
||||
sample_count: pipeline_descriptor.sample_count,
|
||||
sample_mask: pipeline_descriptor.sample_mask,
|
||||
alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled,
|
||||
primitive: pipeline_descriptor.primitive.clone().wgpu_into(),
|
||||
depth_stencil: pipeline_descriptor
|
||||
.depth_stencil
|
||||
.clone()
|
||||
.map(|depth_stencil| depth_stencil.wgpu_into()),
|
||||
multisample: pipeline_descriptor.multisample.clone().wgpu_into(),
|
||||
};
|
||||
|
||||
let render_pipeline = self
|
||||
|
@ -564,7 +556,13 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
}
|
||||
RenderResourceBinding::Buffer { buffer, range, .. } => {
|
||||
let wgpu_buffer = buffers.get(&buffer).unwrap();
|
||||
wgpu::BindingResource::Buffer(wgpu_buffer.slice(range.clone()))
|
||||
let size = NonZeroU64::new(range.end - range.start)
|
||||
.expect("Size of the buffer needs to be greater than 0!");
|
||||
wgpu::BindingResource::Buffer {
|
||||
buffer: wgpu_buffer,
|
||||
offset: range.start,
|
||||
size: Some(size),
|
||||
}
|
||||
}
|
||||
};
|
||||
wgpu::BindGroupEntry {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{renderer::WgpuRenderContext, WgpuResourceRefs};
|
||||
use crate::{renderer::WgpuRenderContext, wgpu_type_converter::WgpuInto, WgpuResourceRefs};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_render::{
|
||||
pass::RenderPass,
|
||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
||||
pipeline::{BindGroupDescriptorId, IndexFormat, PipelineDescriptor},
|
||||
renderer::{BindGroupId, BufferId, RenderContext},
|
||||
};
|
||||
use bevy_utils::tracing::trace;
|
||||
|
@ -40,9 +40,10 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
|
|||
self.render_pass.set_stencil_reference(reference);
|
||||
}
|
||||
|
||||
fn set_index_buffer(&mut self, buffer_id: BufferId, offset: u64) {
|
||||
fn set_index_buffer(&mut self, buffer_id: BufferId, offset: u64, index_format: IndexFormat) {
|
||||
let buffer = self.wgpu_resources.buffers.get(&buffer_id).unwrap();
|
||||
self.render_pass.set_index_buffer(buffer.slice(offset..));
|
||||
self.render_pass
|
||||
.set_index_buffer(buffer.slice(offset..), index_format.wgpu_into());
|
||||
}
|
||||
|
||||
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
|
||||
|
|
|
@ -37,7 +37,7 @@ impl WgpuRenderer {
|
|||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: match options.power_pref {
|
||||
WgpuPowerOptions::HighPerformance => wgpu::PowerPreference::HighPerformance,
|
||||
WgpuPowerOptions::Adaptive => wgpu::PowerPreference::Default,
|
||||
WgpuPowerOptions::Adaptive => wgpu::PowerPreference::LowPower,
|
||||
WgpuPowerOptions::LowPower => wgpu::PowerPreference::LowPower,
|
||||
},
|
||||
compatible_surface: None,
|
||||
|
@ -53,9 +53,9 @@ impl WgpuRenderer {
|
|||
let (device, queue) = adapter
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: None,
|
||||
features: wgpu::Features::empty(),
|
||||
limits: wgpu::Limits::default(),
|
||||
shader_validation: true,
|
||||
},
|
||||
trace_path,
|
||||
)
|
||||
|
|
|
@ -2,19 +2,21 @@ use bevy_render::{
|
|||
color::Color,
|
||||
pass::{LoadOp, Operations},
|
||||
pipeline::{
|
||||
BindType, BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat,
|
||||
InputStepMode, PrimitiveTopology, RasterizationStateDescriptor, StencilOperation,
|
||||
StencilStateDescriptor, StencilStateFaceDescriptor, VertexAttributeDescriptor,
|
||||
VertexBufferDescriptor, VertexFormat,
|
||||
BindType, BlendFactor, BlendOperation, BlendState, ColorTargetState, ColorWrite,
|
||||
CompareFunction, CullMode, DepthBiasState, DepthStencilState, FrontFace, IndexFormat,
|
||||
InputStepMode, MultisampleState, PolygonMode, PrimitiveState, PrimitiveTopology,
|
||||
StencilFaceState, StencilOperation, StencilState, VertexAttribute, VertexBufferLayout,
|
||||
VertexFormat,
|
||||
},
|
||||
renderer::BufferUsage,
|
||||
texture::{
|
||||
AddressMode, Extent3d, FilterMode, SamplerDescriptor, TextureComponentType,
|
||||
TextureDescriptor, TextureDimension, TextureFormat, TextureUsage, TextureViewDimension,
|
||||
AddressMode, Extent3d, FilterMode, SamplerBorderColor, SamplerDescriptor,
|
||||
StorageTextureAccess, TextureDescriptor, TextureDimension, TextureFormat,
|
||||
TextureSampleType, TextureUsage, TextureViewDimension,
|
||||
},
|
||||
};
|
||||
use bevy_window::Window;
|
||||
use wgpu::BufferBindingType;
|
||||
|
||||
pub trait WgpuFrom<T> {
|
||||
fn from(val: T) -> Self;
|
||||
|
@ -70,9 +72,9 @@ impl WgpuFrom<VertexFormat> for wgpu::VertexFormat {
|
|||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&VertexAttributeDescriptor> for wgpu::VertexAttributeDescriptor {
|
||||
fn from(val: &VertexAttributeDescriptor) -> Self {
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
impl WgpuFrom<&VertexAttribute> for wgpu::VertexAttribute {
|
||||
fn from(val: &VertexAttribute) -> Self {
|
||||
wgpu::VertexAttribute {
|
||||
format: val.format.wgpu_into(),
|
||||
offset: val.offset,
|
||||
shader_location: val.shader_location,
|
||||
|
@ -90,34 +92,34 @@ impl WgpuFrom<InputStepMode> for wgpu::InputStepMode {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedWgpuVertexBufferDescriptor {
|
||||
pub stride: wgpu::BufferAddress,
|
||||
pub struct OwnedWgpuVertexBufferLayout {
|
||||
pub array_stride: wgpu::BufferAddress,
|
||||
pub step_mode: wgpu::InputStepMode,
|
||||
pub attributes: Vec<wgpu::VertexAttributeDescriptor>,
|
||||
pub attributes: Vec<wgpu::VertexAttribute>,
|
||||
}
|
||||
|
||||
impl WgpuFrom<&VertexBufferDescriptor> for OwnedWgpuVertexBufferDescriptor {
|
||||
fn from(val: &VertexBufferDescriptor) -> OwnedWgpuVertexBufferDescriptor {
|
||||
impl WgpuFrom<&VertexBufferLayout> for OwnedWgpuVertexBufferLayout {
|
||||
fn from(val: &VertexBufferLayout) -> OwnedWgpuVertexBufferLayout {
|
||||
let attributes = val
|
||||
.attributes
|
||||
.iter()
|
||||
.map(|a| a.wgpu_into())
|
||||
.collect::<Vec<wgpu::VertexAttributeDescriptor>>();
|
||||
.collect::<Vec<wgpu::VertexAttribute>>();
|
||||
|
||||
OwnedWgpuVertexBufferDescriptor {
|
||||
OwnedWgpuVertexBufferLayout {
|
||||
step_mode: val.step_mode.wgpu_into(),
|
||||
stride: val.stride,
|
||||
array_stride: val.stride,
|
||||
attributes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a OwnedWgpuVertexBufferDescriptor> for wgpu::VertexBufferDescriptor<'a> {
|
||||
fn from(val: &'a OwnedWgpuVertexBufferDescriptor) -> Self {
|
||||
wgpu::VertexBufferDescriptor {
|
||||
impl<'a> From<&'a OwnedWgpuVertexBufferLayout> for wgpu::VertexBufferLayout<'a> {
|
||||
fn from(val: &'a OwnedWgpuVertexBufferLayout) -> Self {
|
||||
wgpu::VertexBufferLayout {
|
||||
attributes: &val.attributes,
|
||||
step_mode: val.step_mode,
|
||||
stride: val.stride,
|
||||
array_stride: val.array_stride,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -181,46 +183,71 @@ where
|
|||
impl WgpuFrom<&BindType> for wgpu::BindingType {
|
||||
fn from(bind_type: &BindType) -> Self {
|
||||
match bind_type {
|
||||
BindType::Uniform { dynamic, .. } => wgpu::BindingType::UniformBuffer {
|
||||
dynamic: *dynamic,
|
||||
BindType::Uniform {
|
||||
has_dynamic_offset, ..
|
||||
} => wgpu::BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: *has_dynamic_offset,
|
||||
min_binding_size: bind_type.get_uniform_size().and_then(wgpu::BufferSize::new),
|
||||
},
|
||||
BindType::StorageBuffer { dynamic, readonly } => wgpu::BindingType::StorageBuffer {
|
||||
dynamic: *dynamic,
|
||||
readonly: *readonly,
|
||||
BindType::StorageBuffer {
|
||||
has_dynamic_offset,
|
||||
readonly,
|
||||
} => wgpu::BindingType::Buffer {
|
||||
ty: BufferBindingType::Storage {
|
||||
read_only: *readonly,
|
||||
},
|
||||
has_dynamic_offset: *has_dynamic_offset,
|
||||
min_binding_size: bind_type.get_uniform_size().and_then(wgpu::BufferSize::new),
|
||||
},
|
||||
BindType::SampledTexture {
|
||||
dimension,
|
||||
BindType::Texture {
|
||||
view_dimension,
|
||||
multisampled,
|
||||
component_type,
|
||||
} => wgpu::BindingType::SampledTexture {
|
||||
dimension: (*dimension).wgpu_into(),
|
||||
sample_type,
|
||||
} => wgpu::BindingType::Texture {
|
||||
view_dimension: (*view_dimension).wgpu_into(),
|
||||
multisampled: *multisampled,
|
||||
component_type: (*component_type).wgpu_into(),
|
||||
sample_type: (*sample_type).wgpu_into(),
|
||||
},
|
||||
BindType::Sampler { comparison } => wgpu::BindingType::Sampler {
|
||||
BindType::Sampler {
|
||||
comparison,
|
||||
filtering,
|
||||
} => wgpu::BindingType::Sampler {
|
||||
filtering: *filtering,
|
||||
comparison: *comparison,
|
||||
},
|
||||
BindType::StorageTexture {
|
||||
dimension,
|
||||
view_dimension,
|
||||
format,
|
||||
readonly,
|
||||
access,
|
||||
} => wgpu::BindingType::StorageTexture {
|
||||
dimension: (*dimension).wgpu_into(),
|
||||
access: (*access).wgpu_into(),
|
||||
view_dimension: (*view_dimension).wgpu_into(),
|
||||
format: (*format).wgpu_into(),
|
||||
readonly: *readonly,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<TextureComponentType> for wgpu::TextureComponentType {
|
||||
fn from(texture_component_type: TextureComponentType) -> Self {
|
||||
impl WgpuFrom<TextureSampleType> for wgpu::TextureSampleType {
|
||||
fn from(texture_component_type: TextureSampleType) -> Self {
|
||||
match texture_component_type {
|
||||
TextureComponentType::Float => wgpu::TextureComponentType::Float,
|
||||
TextureComponentType::Sint => wgpu::TextureComponentType::Sint,
|
||||
TextureComponentType::Uint => wgpu::TextureComponentType::Uint,
|
||||
TextureSampleType::Float { filterable } => {
|
||||
wgpu::TextureSampleType::Float { filterable }
|
||||
}
|
||||
TextureSampleType::Sint => wgpu::TextureSampleType::Sint,
|
||||
TextureSampleType::Uint => wgpu::TextureSampleType::Uint,
|
||||
TextureSampleType::Depth => wgpu::TextureSampleType::Depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<StorageTextureAccess> for wgpu::StorageTextureAccess {
|
||||
fn from(storage_texture_access: StorageTextureAccess) -> Self {
|
||||
match storage_texture_access {
|
||||
StorageTextureAccess::ReadOnly => wgpu::StorageTextureAccess::ReadOnly,
|
||||
StorageTextureAccess::WriteOnly => wgpu::StorageTextureAccess::WriteOnly,
|
||||
StorageTextureAccess::ReadWrite => wgpu::StorageTextureAccess::ReadWrite,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -323,9 +350,9 @@ impl WgpuFrom<TextureUsage> for wgpu::TextureUsage {
|
|||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&StencilStateDescriptor> for wgpu::StencilStateDescriptor {
|
||||
fn from(val: &StencilStateDescriptor) -> Self {
|
||||
wgpu::StencilStateDescriptor {
|
||||
impl WgpuFrom<&StencilState> for wgpu::StencilState {
|
||||
fn from(val: &StencilState) -> Self {
|
||||
wgpu::StencilState {
|
||||
back: (&val.back).wgpu_into(),
|
||||
front: (&val.front).wgpu_into(),
|
||||
read_mask: val.read_mask,
|
||||
|
@ -334,20 +361,32 @@ impl WgpuFrom<&StencilStateDescriptor> for wgpu::StencilStateDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&DepthStencilStateDescriptor> for wgpu::DepthStencilStateDescriptor {
|
||||
fn from(val: &DepthStencilStateDescriptor) -> Self {
|
||||
wgpu::DepthStencilStateDescriptor {
|
||||
impl WgpuFrom<DepthStencilState> for wgpu::DepthStencilState {
|
||||
fn from(val: DepthStencilState) -> Self {
|
||||
wgpu::DepthStencilState {
|
||||
depth_compare: val.depth_compare.wgpu_into(),
|
||||
depth_write_enabled: val.depth_write_enabled,
|
||||
format: val.format.wgpu_into(),
|
||||
stencil: (&val.stencil).wgpu_into(),
|
||||
bias: val.bias.wgpu_into(),
|
||||
clamp_depth: val.clamp_depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&StencilStateFaceDescriptor> for wgpu::StencilStateFaceDescriptor {
|
||||
fn from(val: &StencilStateFaceDescriptor) -> Self {
|
||||
wgpu::StencilStateFaceDescriptor {
|
||||
impl WgpuFrom<MultisampleState> for wgpu::MultisampleState {
|
||||
fn from(val: MultisampleState) -> Self {
|
||||
wgpu::MultisampleState {
|
||||
count: val.count,
|
||||
mask: val.mask,
|
||||
alpha_to_coverage_enabled: val.alpha_to_coverage_enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&StencilFaceState> for wgpu::StencilFaceState {
|
||||
fn from(val: &StencilFaceState) -> Self {
|
||||
wgpu::StencilFaceState {
|
||||
compare: val.compare.wgpu_into(),
|
||||
depth_fail_op: val.depth_fail_op.wgpu_into(),
|
||||
fail_op: val.fail_op.wgpu_into(),
|
||||
|
@ -441,22 +480,29 @@ impl WgpuFrom<CullMode> for wgpu::CullMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&RasterizationStateDescriptor> for wgpu::RasterizationStateDescriptor {
|
||||
fn from(val: &RasterizationStateDescriptor) -> Self {
|
||||
wgpu::RasterizationStateDescriptor {
|
||||
front_face: val.front_face.wgpu_into(),
|
||||
cull_mode: val.cull_mode.wgpu_into(),
|
||||
depth_bias: val.depth_bias,
|
||||
depth_bias_slope_scale: val.depth_bias_slope_scale,
|
||||
depth_bias_clamp: val.depth_bias_clamp,
|
||||
clamp_depth: val.clamp_depth,
|
||||
impl WgpuFrom<PolygonMode> for wgpu::PolygonMode {
|
||||
fn from(val: PolygonMode) -> wgpu::PolygonMode {
|
||||
match val {
|
||||
PolygonMode::Fill => wgpu::PolygonMode::Fill,
|
||||
PolygonMode::Line => wgpu::PolygonMode::Line,
|
||||
PolygonMode::Point => wgpu::PolygonMode::Point,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&ColorStateDescriptor> for wgpu::ColorStateDescriptor {
|
||||
fn from(val: &ColorStateDescriptor) -> Self {
|
||||
wgpu::ColorStateDescriptor {
|
||||
impl WgpuFrom<DepthBiasState> for wgpu::DepthBiasState {
|
||||
fn from(val: DepthBiasState) -> Self {
|
||||
wgpu::DepthBiasState {
|
||||
constant: val.constant,
|
||||
slope_scale: val.slope_scale,
|
||||
clamp: val.clamp,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&ColorTargetState> for wgpu::ColorTargetState {
|
||||
fn from(val: &ColorTargetState) -> Self {
|
||||
wgpu::ColorTargetState {
|
||||
format: val.format.wgpu_into(),
|
||||
alpha_blend: (&val.alpha_blend).wgpu_into(),
|
||||
color_blend: (&val.color_blend).wgpu_into(),
|
||||
|
@ -465,15 +511,29 @@ impl WgpuFrom<&ColorStateDescriptor> for wgpu::ColorStateDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<PrimitiveState> for wgpu::PrimitiveState {
|
||||
fn from(val: PrimitiveState) -> Self {
|
||||
wgpu::PrimitiveState {
|
||||
topology: val.topology.wgpu_into(),
|
||||
strip_index_format: val
|
||||
.strip_index_format
|
||||
.map(|index_format| index_format.wgpu_into()),
|
||||
front_face: val.front_face.wgpu_into(),
|
||||
cull_mode: val.cull_mode.wgpu_into(),
|
||||
polygon_mode: val.polygon_mode.wgpu_into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<ColorWrite> for wgpu::ColorWrite {
|
||||
fn from(val: ColorWrite) -> Self {
|
||||
wgpu::ColorWrite::from_bits(val.bits()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&BlendDescriptor> for wgpu::BlendDescriptor {
|
||||
fn from(val: &BlendDescriptor) -> Self {
|
||||
wgpu::BlendDescriptor {
|
||||
impl WgpuFrom<&BlendState> for wgpu::BlendState {
|
||||
fn from(val: &BlendState) -> Self {
|
||||
wgpu::BlendState {
|
||||
src_factor: val.src_factor.wgpu_into(),
|
||||
dst_factor: val.dst_factor.wgpu_into(),
|
||||
operation: val.operation.wgpu_into(),
|
||||
|
@ -536,6 +596,9 @@ impl WgpuFrom<SamplerDescriptor> for wgpu::SamplerDescriptor<'_> {
|
|||
lod_max_clamp: sampler_descriptor.lod_max_clamp,
|
||||
compare: sampler_descriptor.compare_function.map(|c| c.wgpu_into()),
|
||||
anisotropy_clamp: sampler_descriptor.anisotropy_clamp,
|
||||
border_color: sampler_descriptor
|
||||
.border_color
|
||||
.map(|border_color| border_color.wgpu_into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -559,10 +622,20 @@ impl WgpuFrom<FilterMode> for wgpu::FilterMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<SamplerBorderColor> for wgpu::SamplerBorderColor {
|
||||
fn from(val: SamplerBorderColor) -> Self {
|
||||
match val {
|
||||
SamplerBorderColor::TransparentBlack => wgpu::SamplerBorderColor::TransparentBlack,
|
||||
SamplerBorderColor::OpaqueBlack => wgpu::SamplerBorderColor::OpaqueBlack,
|
||||
SamplerBorderColor::OpaqueWhite => wgpu::SamplerBorderColor::OpaqueWhite,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuFrom<&Window> for wgpu::SwapChainDescriptor {
|
||||
fn from(window: &Window) -> Self {
|
||||
wgpu::SwapChainDescriptor {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
|
||||
format: TextureFormat::default().wgpu_into(),
|
||||
width: window.physical_width(),
|
||||
height: window.physical_height(),
|
||||
|
|
|
@ -9,7 +9,7 @@ fn main() {
|
|||
.add_stage_after(stage::UPDATE, STAGE, StateStage::<AppState>::default())
|
||||
.on_state_enter(STAGE, AppState::Setup, load_textures.system())
|
||||
.on_state_update(STAGE, AppState::Setup, check_textures.system())
|
||||
.on_state_enter(STAGE, AppState::Finshed, setup.system())
|
||||
.on_state_enter(STAGE, AppState::Finished, setup.system())
|
||||
.run();
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ const STAGE: &str = "app_state";
|
|||
#[derive(Clone)]
|
||||
enum AppState {
|
||||
Setup,
|
||||
Finshed,
|
||||
Finished,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -38,7 +38,7 @@ fn check_textures(
|
|||
if let LoadState::Loaded =
|
||||
asset_server.get_group_load_state(rpg_sprite_handles.handles.iter().map(|handle| handle.id))
|
||||
{
|
||||
state.set_next(AppState::Finshed).unwrap();
|
||||
state.set_next(AppState::Finished).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue