Update to wgpu-rs 0.7 (#542)

Update to wgpu-rs 0.7
This commit is contained in:
Zhixing Zhang 2021-01-31 23:06:42 -05:00 committed by GitHub
parent e6e23fdfa9
commit 81809c71ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 574 additions and 370 deletions

View file

@ -2,9 +2,8 @@ use bevy_asset::{Assets, HandleUntyped};
use bevy_reflect::TypeUuid; use bevy_reflect::TypeUuid;
use bevy_render::{ use bevy_render::{
pipeline::{ pipeline::{
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite, BlendFactor, BlendOperation, BlendState, ColorTargetState, ColorWrite, CompareFunction,
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, PipelineDescriptor, DepthBiasState, DepthStencilState, PipelineDescriptor, StencilFaceState, StencilState,
RasterizationStateDescriptor, StencilStateDescriptor, StencilStateFaceDescriptor,
}, },
shader::{Shader, ShaderStage, ShaderStages}, shader::{Shader, ShaderStage, ShaderStages},
texture::TextureFormat, texture::TextureFormat,
@ -15,33 +14,31 @@ pub const FORWARD_PIPELINE_HANDLE: HandleUntyped =
pub(crate) fn build_forward_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor { pub(crate) fn build_forward_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
PipelineDescriptor { PipelineDescriptor {
rasterization_state: Some(RasterizationStateDescriptor { depth_stencil: Some(DepthStencilState {
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 {
format: TextureFormat::Depth32Float, format: TextureFormat::Depth32Float,
depth_write_enabled: true, depth_write_enabled: true,
depth_compare: CompareFunction::Less, depth_compare: CompareFunction::Less,
stencil: StencilStateDescriptor { stencil: StencilState {
front: StencilStateFaceDescriptor::IGNORE, front: StencilFaceState::IGNORE,
back: StencilStateFaceDescriptor::IGNORE, back: StencilFaceState::IGNORE,
read_mask: 0, read_mask: 0,
write_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(), format: TextureFormat::default(),
color_blend: BlendDescriptor { color_blend: BlendState {
src_factor: BlendFactor::SrcAlpha, src_factor: BlendFactor::SrcAlpha,
dst_factor: BlendFactor::OneMinusSrcAlpha, dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
alpha_blend: BlendDescriptor { alpha_blend: BlendState {
src_factor: BlendFactor::One, src_factor: BlendFactor::One,
dst_factor: BlendFactor::One, dst_factor: BlendFactor::One,
operation: BlendOperation::Add, operation: BlendOperation::Add,

View file

@ -1,5 +1,7 @@
use crate::{ use crate::{
pipeline::{PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization}, pipeline::{
IndexFormat, PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization,
},
renderer::{ renderer::{
AssetRenderResourceBindings, BindGroup, BindGroupId, BufferId, RenderResource, AssetRenderResourceBindings, BindGroup, BindGroupId, BufferId, RenderResource,
RenderResourceBinding, RenderResourceBindings, RenderResourceContext, SharedBuffers, RenderResourceBinding, RenderResourceBindings, RenderResourceContext, SharedBuffers,
@ -26,6 +28,7 @@ pub enum RenderCommand {
SetIndexBuffer { SetIndexBuffer {
buffer: BufferId, buffer: BufferId,
offset: u64, offset: u64,
index_format: IndexFormat,
}, },
SetBindGroup { SetBindGroup {
index: u32, index: u32,
@ -95,8 +98,12 @@ impl Draw {
}); });
} }
pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64) { pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64, index_format: IndexFormat) {
self.render_command(RenderCommand::SetIndexBuffer { buffer, offset }); self.render_command(RenderCommand::SetIndexBuffer {
buffer,
offset,
index_format,
});
} }
pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup) { pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup) {
@ -325,8 +332,8 @@ impl<'a> DrawContext<'a> {
render_resource_bindings: &[&RenderResourceBindings], render_resource_bindings: &[&RenderResourceBindings],
) -> Result<(), DrawError> { ) -> Result<(), DrawError> {
for bindings in render_resource_bindings.iter() { for bindings in render_resource_bindings.iter() {
if let Some(index_buffer) = bindings.index_buffer { if let Some((index_buffer, index_format)) = bindings.index_buffer {
draw.set_index_buffer(index_buffer, 0); draw.set_index_buffer(index_buffer, 0, index_format);
} }
if let Some(main_vertex_buffer) = bindings.vertex_attribute_buffer { if let Some(main_vertex_buffer) = bindings.vertex_attribute_buffer {
draw.set_vertex_buffer(0, main_vertex_buffer, 0); draw.set_vertex_buffer(0, main_vertex_buffer, 0);

View file

@ -10,7 +10,7 @@ use bevy_math::*;
use bevy_reflect::TypeUuid; use bevy_reflect::TypeUuid;
use std::borrow::Cow; use std::borrow::Cow;
use crate::pipeline::{InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor}; use crate::pipeline::{InputStepMode, VertexAttribute, VertexBufferLayout};
use bevy_utils::{HashMap, HashSet}; use bevy_utils::{HashMap, HashSet};
pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; 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 attributes = Vec::new();
let mut accumulated_offset = 0; let mut accumulated_offset = 0;
for (attribute_name, attribute_values) in self.attributes.iter() { for (attribute_name, attribute_values) in self.attributes.iter() {
let vertex_format = VertexFormat::from(attribute_values); let vertex_format = VertexFormat::from(attribute_values);
attributes.push(VertexAttributeDescriptor { attributes.push(VertexAttribute {
name: attribute_name.clone(), name: attribute_name.clone(),
offset: accumulated_offset, offset: accumulated_offset,
format: vertex_format, format: vertex_format,
@ -270,7 +270,7 @@ impl Mesh {
accumulated_offset += vertex_format.get_size(); accumulated_offset += vertex_format.get_size();
} }
VertexBufferDescriptor { VertexBufferLayout {
name: Default::default(), name: Default::default(),
stride: accumulated_offset, stride: accumulated_offset,
step_mode: InputStepMode::Vertex, step_mode: InputStepMode::Vertex,
@ -453,21 +453,22 @@ fn update_entity_mesh(
for render_pipeline in render_pipelines.pipelines.iter_mut() { for render_pipeline in render_pipelines.pipelines.iter_mut() {
render_pipeline.specialization.primitive_topology = mesh.primitive_topology; render_pipeline.specialization.primitive_topology = mesh.primitive_topology;
// TODO: don't allocate a new vertex buffer descriptor for every entity // TODO: don't allocate a new vertex buffer descriptor for every entity
render_pipeline.specialization.vertex_buffer_descriptor = render_pipeline.specialization.vertex_buffer_layout = mesh.get_vertex_buffer_layout();
mesh.get_vertex_buffer_descriptor(); if let PrimitiveTopology::LineStrip | PrimitiveTopology::TriangleStrip =
render_pipeline.specialization.index_format = mesh mesh.primitive_topology
.indices() {
.map(|i| i.into()) render_pipeline.specialization.strip_index_format =
.unwrap_or(IndexFormat::Uint32); mesh.indices().map(|indices| indices.into());
}
} }
if let Some(RenderResourceId::Buffer(index_buffer_resource)) = if let Some(RenderResourceId::Buffer(index_buffer_resource)) =
render_resource_context.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX) render_resource_context.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX)
{ {
let index_format: IndexFormat = mesh.indices().unwrap().into();
// set index buffer into binding // set index buffer into binding
render_pipelines render_pipelines
.bindings .bindings
.set_index_buffer(index_buffer_resource); .set_index_buffer(index_buffer_resource, index_format);
} }
if let Some(RenderResourceId::Buffer(vertex_attribute_buffer_resource)) = if let Some(RenderResourceId::Buffer(vertex_attribute_buffer_resource)) =

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
pipeline::{BindGroupDescriptorId, PipelineDescriptor}, pipeline::{BindGroupDescriptorId, IndexFormat, PipelineDescriptor},
renderer::{BindGroupId, BufferId, RenderContext}, renderer::{BindGroupId, BufferId, RenderContext},
}; };
use bevy_asset::Handle; use bevy_asset::Handle;
@ -7,7 +7,7 @@ use std::ops::Range;
pub trait RenderPass { pub trait RenderPass {
fn get_render_context(&self) -> &dyn RenderContext; 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_vertex_buffer(&mut self, start_slot: u32, buffer: BufferId, offset: u64);
fn set_pipeline(&mut self, pipeline_handle: &Handle<PipelineDescriptor>); 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); fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32);

View file

@ -1,5 +1,7 @@
use super::UniformProperty; use super::UniformProperty;
use crate::texture::{TextureComponentType, TextureFormat, TextureViewDimension}; use crate::texture::{
StorageTextureAccess, TextureFormat, TextureSampleType, TextureViewDimension,
};
bitflags::bitflags! { bitflags::bitflags! {
pub struct BindingShaderStage: u32 { pub struct BindingShaderStage: u32 {
@ -20,25 +22,35 @@ pub struct BindingDescriptor {
#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum BindType { pub enum BindType {
Uniform { Uniform {
dynamic: bool, has_dynamic_offset: bool,
property: UniformProperty, property: UniformProperty,
}, },
StorageBuffer { StorageBuffer {
dynamic: bool, has_dynamic_offset: bool,
readonly: bool, readonly: bool,
}, },
Sampler { 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, comparison: bool,
}, },
SampledTexture { Texture {
multisampled: bool, multisampled: bool,
dimension: TextureViewDimension, view_dimension: TextureViewDimension,
component_type: TextureComponentType, sample_type: TextureSampleType,
}, },
StorageTexture { StorageTexture {
dimension: TextureViewDimension, /// Allowed access to this texture.
access: StorageTextureAccess,
/// Format of the texture.
format: TextureFormat, format: TextureFormat,
readonly: bool, /// Dimension of the texture view that is going to be sampled.
view_dimension: TextureViewDimension,
}, },
} }

View file

@ -1,12 +1,18 @@
use super::{ use super::{
state_descriptors::{ state_descriptors::{
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite, BlendFactor, BlendOperation, ColorWrite, CompareFunction, CullMode, FrontFace,
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat, PrimitiveTopology,
PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor,
}, },
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; use bevy_reflect::TypeUuid;
#[derive(Clone, Debug, TypeUuid)] #[derive(Clone, Debug, TypeUuid)]
@ -15,32 +21,12 @@ pub struct PipelineDescriptor {
pub name: Option<String>, pub name: Option<String>,
pub layout: Option<PipelineLayout>, pub layout: Option<PipelineLayout>,
pub shader_stages: ShaderStages, pub shader_stages: ShaderStages,
pub rasterization_state: Option<RasterizationStateDescriptor>, pub primitive: PrimitiveState,
pub depth_stencil: Option<DepthStencilState>,
/// The primitive topology used to interpret vertices. pub multisample: MultisampleState,
pub primitive_topology: PrimitiveTopology,
/// The effect of draw calls on the color aspect of the output target. /// The effect of draw calls on the color aspect of the output target.
pub color_states: Vec<ColorStateDescriptor>, pub color_target_states: Vec<ColorTargetState>,
/// 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,
} }
impl PipelineDescriptor { impl PipelineDescriptor {
@ -48,60 +34,71 @@ impl PipelineDescriptor {
PipelineDescriptor { PipelineDescriptor {
name: None, name: None,
layout: None, layout: None,
color_states: Vec::new(), color_target_states: Vec::new(),
depth_stencil_state: None, depth_stencil: None,
shader_stages, shader_stages,
rasterization_state: None, primitive: PrimitiveState {
primitive_topology: PrimitiveTopology::TriangleList, topology: PrimitiveTopology::TriangleList,
index_format: IndexFormat::Uint32, strip_index_format: None,
sample_count: 1, front_face: FrontFace::Ccw,
sample_mask: !0, cull_mode: CullMode::Back,
alpha_to_coverage_enabled: false, polygon_mode: PolygonMode::Fill,
},
multisample: MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
} }
} }
pub fn default_config(shader_stages: ShaderStages) -> Self { pub fn default_config(shader_stages: ShaderStages) -> Self {
PipelineDescriptor { PipelineDescriptor {
name: None, name: None,
primitive_topology: PrimitiveTopology::TriangleList, primitive: PrimitiveState {
layout: None, topology: PrimitiveTopology::TriangleList,
index_format: IndexFormat::Uint32, strip_index_format: None,
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
rasterization_state: Some(RasterizationStateDescriptor {
front_face: FrontFace::Ccw, front_face: FrontFace::Ccw,
cull_mode: CullMode::Back, cull_mode: CullMode::Back,
depth_bias: 0, polygon_mode: PolygonMode::Fill,
depth_bias_slope_scale: 0.0, },
depth_bias_clamp: 0.0, layout: None,
clamp_depth: false, depth_stencil: Some(DepthStencilState {
}),
depth_stencil_state: Some(DepthStencilStateDescriptor {
format: TextureFormat::Depth32Float, format: TextureFormat::Depth32Float,
depth_write_enabled: true, depth_write_enabled: true,
depth_compare: CompareFunction::Less, depth_compare: CompareFunction::Less,
stencil: StencilStateDescriptor { stencil: StencilState {
front: StencilStateFaceDescriptor::IGNORE, front: StencilFaceState::IGNORE,
back: StencilStateFaceDescriptor::IGNORE, back: StencilFaceState::IGNORE,
read_mask: 0, read_mask: 0,
write_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(), format: TextureFormat::default(),
color_blend: BlendDescriptor { color_blend: BlendState {
src_factor: BlendFactor::SrcAlpha, src_factor: BlendFactor::SrcAlpha,
dst_factor: BlendFactor::OneMinusSrcAlpha, dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
alpha_blend: BlendDescriptor { alpha_blend: BlendState {
src_factor: BlendFactor::One, src_factor: BlendFactor::One,
dst_factor: BlendFactor::One, dst_factor: BlendFactor::One,
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
write_mask: ColorWrite::ALL, write_mask: ColorWrite::ALL,
}], }],
multisample: MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
shader_stages, shader_stages,
} }
} }

View file

@ -1,6 +1,6 @@
use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor}; use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor};
use crate::{ use crate::{
pipeline::{BindType, InputStepMode, VertexBufferDescriptor}, pipeline::{BindType, InputStepMode, VertexBufferLayout},
renderer::RenderResourceContext, renderer::RenderResourceContext,
shader::{Shader, ShaderError}, shader::{Shader, ShaderError},
}; };
@ -15,8 +15,8 @@ pub struct PipelineSpecialization {
pub shader_specialization: ShaderSpecialization, pub shader_specialization: ShaderSpecialization,
pub primitive_topology: PrimitiveTopology, pub primitive_topology: PrimitiveTopology,
pub dynamic_bindings: HashSet<String>, pub dynamic_bindings: HashSet<String>,
pub index_format: IndexFormat, pub strip_index_format: Option<IndexFormat>,
pub vertex_buffer_descriptor: VertexBufferDescriptor, pub vertex_buffer_layout: VertexBufferLayout,
pub sample_count: u32, pub sample_count: u32,
} }
@ -24,11 +24,11 @@ impl Default for PipelineSpecialization {
fn default() -> Self { fn default() -> Self {
Self { Self {
sample_count: 1, sample_count: 1,
index_format: IndexFormat::Uint32, strip_index_format: None,
shader_specialization: Default::default(), shader_specialization: Default::default(),
primitive_topology: Default::default(), primitive_topology: Default::default(),
dynamic_bindings: 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) .any(|b| b == &binding.name)
{ {
if let BindType::Uniform { if let BindType::Uniform {
ref mut dynamic, .. ref mut has_dynamic_offset,
..
} = binding.bind_type } = binding.bind_type
{ {
*dynamic = true; *has_dynamic_offset = true;
binding_changed = 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 // 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(); let mut pipeline_layout = specialized_descriptor.layout.as_mut().unwrap();
// the vertex buffer descriptor of the mesh // 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 // 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, step_mode: InputStepMode::Vertex,
stride: mesh_vertex_buffer_descriptor.stride, stride: mesh_vertex_buffer_layout.stride,
..Default::default() ..Default::default()
}; };
@ -212,7 +213,7 @@ impl PipelineCompiler {
.get(0) .get(0)
.expect("Reflected layout has no attributes."); .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 .attributes
.iter() .iter()
.find(|x| x.name == shader_vertex_attribute.name) .find(|x| x.name == shader_vertex_attribute.name)
@ -233,13 +234,14 @@ impl PipelineCompiler {
} }
//TODO: add other buffers (like instancing) here //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); vertex_buffer_descriptors.push(compiled_vertex_buffer_descriptor);
pipeline_layout.vertex_buffer_descriptors = vertex_buffer_descriptors; pipeline_layout.vertex_buffer_descriptors = vertex_buffer_descriptors;
specialized_descriptor.sample_count = pipeline_specialization.sample_count; specialized_descriptor.multisample.count = pipeline_specialization.sample_count;
specialized_descriptor.primitive_topology = pipeline_specialization.primitive_topology; specialized_descriptor.primitive.topology = pipeline_specialization.primitive_topology;
specialized_descriptor.index_format = pipeline_specialization.index_format; specialized_descriptor.primitive.strip_index_format =
pipeline_specialization.strip_index_format;
let specialized_pipeline_handle = pipelines.add(specialized_descriptor); let specialized_pipeline_handle = pipelines.add(specialized_descriptor);
render_resource_context.create_render_pipeline( render_resource_context.create_render_pipeline(

View file

@ -1,4 +1,4 @@
use super::{BindGroupDescriptor, VertexBufferDescriptor}; use super::{BindGroupDescriptor, VertexBufferLayout};
use crate::shader::ShaderLayout; use crate::shader::ShaderLayout;
use bevy_utils::HashMap; use bevy_utils::HashMap;
use std::hash::Hash; use std::hash::Hash;
@ -6,7 +6,7 @@ use std::hash::Hash;
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct PipelineLayout { pub struct PipelineLayout {
pub bind_groups: Vec<BindGroupDescriptor>, pub bind_groups: Vec<BindGroupDescriptor>,
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>, pub vertex_buffer_descriptors: Vec<VertexBufferLayout>,
} }
impl PipelineLayout { 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()); vertex_buffer_descriptors.push(vertex_buffer_descriptor.clone());
} }

View file

@ -3,20 +3,48 @@ use bevy_reflect::Reflect;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DepthStencilStateDescriptor { pub struct DepthStencilState {
pub format: TextureFormat, pub format: TextureFormat,
pub depth_write_enabled: bool, pub depth_write_enabled: bool,
pub depth_compare: CompareFunction, pub depth_compare: CompareFunction,
pub stencil: StencilStateDescriptor, pub stencil: StencilState,
pub bias: DepthBiasState,
pub clamp_depth: bool,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct StencilStateDescriptor { pub struct StencilState {
pub front: StencilStateFaceDescriptor, pub front: StencilFaceState,
pub back: StencilStateFaceDescriptor, pub back: StencilFaceState,
pub read_mask: u32, pub read_mask: u32,
pub write_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)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum StencilOperation { pub enum StencilOperation {
@ -31,15 +59,15 @@ pub enum StencilOperation {
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct StencilStateFaceDescriptor { pub struct StencilFaceState {
pub compare: CompareFunction, pub compare: CompareFunction,
pub fail_op: StencilOperation, pub fail_op: StencilOperation,
pub depth_fail_op: StencilOperation, pub depth_fail_op: StencilOperation,
pub pass_op: StencilOperation, pub pass_op: StencilOperation,
} }
impl StencilStateFaceDescriptor { impl StencilFaceState {
pub const IGNORE: Self = StencilStateFaceDescriptor { pub const IGNORE: Self = StencilFaceState {
compare: CompareFunction::Always, compare: CompareFunction::Always,
fail_op: StencilOperation::Keep, fail_op: StencilOperation::Keep,
depth_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)] #[derive(Clone, Debug, Default)]
pub struct RasterizationStateDescriptor { pub struct PrimitiveState {
pub topology: PrimitiveTopology,
pub strip_index_format: Option<IndexFormat>,
pub front_face: FrontFace, pub front_face: FrontFace,
pub cull_mode: CullMode, pub cull_mode: CullMode,
pub depth_bias: i32, pub polygon_mode: PolygonMode,
pub depth_bias_slope_scale: f32,
pub depth_bias_clamp: f32,
pub clamp_depth: bool,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ColorStateDescriptor { pub struct ColorTargetState {
pub format: TextureFormat, pub format: TextureFormat,
pub alpha_blend: BlendDescriptor, pub alpha_blend: BlendState,
pub color_blend: BlendDescriptor, pub color_blend: BlendState,
pub write_mask: ColorWrite, pub write_mask: ColorWrite,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct BlendDescriptor { pub struct BlendState {
pub src_factor: BlendFactor, pub src_factor: BlendFactor,
pub dst_factor: BlendFactor, pub dst_factor: BlendFactor,
pub operation: BlendOperation, pub operation: BlendOperation,
} }
impl BlendDescriptor { impl BlendState {
pub const REPLACE: Self = BlendDescriptor { pub const REPLACE: Self = BlendState {
src_factor: BlendFactor::One, src_factor: BlendFactor::One,
dst_factor: BlendFactor::Zero, dst_factor: BlendFactor::Zero,
operation: BlendOperation::Add, operation: BlendOperation::Add,

View file

@ -8,23 +8,23 @@ use std::{
#[derive(Clone, Debug, Eq, PartialEq, Default, Reflect, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, Default, Reflect, Serialize, Deserialize)]
#[reflect_value(Serialize, Deserialize, PartialEq)] #[reflect_value(Serialize, Deserialize, PartialEq)]
pub struct VertexBufferDescriptor { pub struct VertexBufferLayout {
pub name: Cow<'static, str>, pub name: Cow<'static, str>,
pub stride: u64, pub stride: u64,
pub step_mode: InputStepMode, pub step_mode: InputStepMode,
pub attributes: Vec<VertexAttributeDescriptor>, pub attributes: Vec<VertexAttribute>,
} }
impl VertexBufferDescriptor { impl VertexBufferLayout {
pub fn new_from_attribute( pub fn new_from_attribute(
attribute: VertexAttributeDescriptor, attribute: VertexAttribute,
step_mode: InputStepMode, step_mode: InputStepMode,
) -> VertexBufferDescriptor { ) -> VertexBufferLayout {
VertexBufferDescriptor { VertexBufferLayout {
name: attribute.name.clone(), name: attribute.name.clone(),
stride: attribute.format.get_size(), stride: attribute.format.get_size(),
step_mode, 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)] #[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct VertexAttributeDescriptor { pub struct VertexAttribute {
pub name: Cow<'static, str>, pub name: Cow<'static, str>,
pub offset: u64,
pub format: VertexFormat, pub format: VertexFormat,
pub offset: u64,
pub shader_location: u32, pub shader_location: u32,
} }

View file

@ -3,8 +3,8 @@ use crate::{
draw::{Draw, RenderCommand}, draw::{Draw, RenderCommand},
pass::{ClearColor, LoadOp, PassDescriptor, TextureAttachment}, pass::{ClearColor, LoadOp, PassDescriptor, TextureAttachment},
pipeline::{ pipeline::{
BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, PipelineDescriptor, BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, IndexFormat,
UniformProperty, PipelineDescriptor, UniformProperty,
}, },
prelude::Visible, prelude::Visible,
render_graph::{Node, ResourceSlotInfo, ResourceSlots}, render_graph::{Node, ResourceSlotInfo, ResourceSlots},
@ -109,7 +109,7 @@ impl<Q: WorldQuery> PassNode<Q> {
name: "Camera".to_string(), name: "Camera".to_string(),
index: 0, index: 0,
bind_type: BindType::Uniform { bind_type: BindType::Uniform {
dynamic: false, has_dynamic_offset: false,
property: UniformProperty::Struct(vec![UniformProperty::Mat4]), property: UniformProperty::Struct(vec![UniformProperty::Mat4]),
}, },
shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT, shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT,
@ -301,12 +301,12 @@ where
render_pass.set_vertex_buffer(*slot, *buffer, *offset); render_pass.set_vertex_buffer(*slot, *buffer, *offset);
draw_state.set_vertex_buffer(*slot, *buffer, *offset); draw_state.set_vertex_buffer(*slot, *buffer, *offset);
} }
RenderCommand::SetIndexBuffer { buffer, offset } => { RenderCommand::SetIndexBuffer { buffer, offset, index_format } => {
if draw_state.is_index_buffer_set(*buffer, *offset) { if draw_state.is_index_buffer_set(*buffer, *offset, *index_format) {
continue; continue;
} }
render_pass.set_index_buffer(*buffer, *offset); render_pass.set_index_buffer(*buffer, *offset, *index_format);
draw_state.set_index_buffer(*buffer, *offset) draw_state.set_index_buffer(*buffer, *offset, *index_format);
} }
RenderCommand::SetBindGroup { RenderCommand::SetBindGroup {
index, index,
@ -344,7 +344,7 @@ struct DrawState {
pipeline: Option<Handle<PipelineDescriptor>>, pipeline: Option<Handle<PipelineDescriptor>>,
bind_groups: Vec<Option<BindGroupId>>, bind_groups: Vec<Option<BindGroupId>>,
vertex_buffers: Vec<Option<(BufferId, u64)>>, vertex_buffers: Vec<Option<(BufferId, u64)>>,
index_buffer: Option<(BufferId, u64)>, index_buffer: Option<(BufferId, u64, IndexFormat)>,
} }
impl DrawState { impl DrawState {
@ -364,12 +364,17 @@ impl DrawState {
self.vertex_buffers[index as usize] == Some((buffer, offset)) self.vertex_buffers[index as usize] == Some((buffer, offset))
} }
pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64) { pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64, index_format: IndexFormat) {
self.index_buffer = Some((buffer, offset)); self.index_buffer = Some((buffer, offset, index_format));
} }
pub fn is_index_buffer_set(&self, buffer: BufferId, offset: u64) -> bool { pub fn is_index_buffer_set(
self.index_buffer == Some((buffer, offset)) &self,
buffer: BufferId,
offset: u64,
index_format: IndexFormat,
) -> bool {
self.index_buffer == Some((buffer, offset, index_format))
} }
pub fn can_draw(&self) -> bool { pub fn can_draw(&self) -> bool {

View file

@ -1,6 +1,6 @@
use super::{BindGroup, BindGroupId, BufferId, SamplerId, TextureId}; use super::{BindGroup, BindGroupId, BufferId, SamplerId, TextureId};
use crate::{ use crate::{
pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor}, pipeline::{BindGroupDescriptor, BindGroupDescriptorId, IndexFormat, PipelineDescriptor},
renderer::RenderResourceContext, renderer::RenderResourceContext,
}; };
use bevy_asset::{Asset, Handle, HandleUntyped}; use bevy_asset::{Asset, Handle, HandleUntyped};
@ -69,7 +69,7 @@ pub struct RenderResourceBindings {
pub vertex_attribute_buffer: Option<BufferId>, 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. /// 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 vertex_fallback_buffer: Option<BufferId>,
pub index_buffer: Option<BufferId>, pub index_buffer: Option<(BufferId, IndexFormat)>,
assets: HashSet<(HandleUntyped, TypeId)>, assets: HashSet<(HandleUntyped, TypeId)>,
bind_groups: HashMap<BindGroupId, BindGroup>, bind_groups: HashMap<BindGroupId, BindGroup>,
bind_group_descriptors: HashMap<BindGroupDescriptorId, Option<BindGroupId>>, bind_group_descriptors: HashMap<BindGroupDescriptorId, Option<BindGroupId>>,
@ -116,8 +116,8 @@ impl RenderResourceBindings {
} }
} }
pub fn set_index_buffer(&mut self, index_buffer: BufferId) { pub fn set_index_buffer(&mut self, index_buffer: BufferId, index_format: IndexFormat) {
self.index_buffer = Some(index_buffer); self.index_buffer = Some((index_buffer, index_format));
} }
fn create_bind_group(&mut self, descriptor: &BindGroupDescriptor) -> BindGroupStatus { fn create_bind_group(&mut self, descriptor: &BindGroupDescriptor) -> BindGroupStatus {
@ -303,7 +303,7 @@ mod tests {
index: 0, index: 0,
name: "a".to_string(), name: "a".to_string(),
bind_type: BindType::Uniform { bind_type: BindType::Uniform {
dynamic: false, has_dynamic_offset: false,
property: UniformProperty::Struct(vec![UniformProperty::Mat4]), property: UniformProperty::Struct(vec![UniformProperty::Mat4]),
}, },
shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT, shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT,
@ -312,7 +312,7 @@ mod tests {
index: 1, index: 1,
name: "b".to_string(), name: "b".to_string(),
bind_type: BindType::Uniform { bind_type: BindType::Uniform {
dynamic: false, has_dynamic_offset: false,
property: UniformProperty::Float, property: UniformProperty::Float,
}, },
shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT, shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT,

View file

@ -11,13 +11,13 @@ pub use shader_defs::*;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub use shader_reflect::*; pub use shader_reflect::*;
use crate::pipeline::{BindGroupDescriptor, VertexBufferDescriptor}; use crate::pipeline::{BindGroupDescriptor, VertexBufferLayout};
/// Defines the memory layout of a shader /// Defines the memory layout of a shader
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct ShaderLayout { pub struct ShaderLayout {
pub bind_groups: Vec<BindGroupDescriptor>, pub bind_groups: Vec<BindGroupDescriptor>,
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>, pub vertex_buffer_layout: Vec<VertexBufferLayout>,
pub entry_point: String, pub entry_point: String,
} }

View file

@ -1,10 +1,10 @@
use crate::{ use crate::{
pipeline::{ pipeline::{
BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, InputStepMode, BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, InputStepMode,
UniformProperty, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, UniformProperty, VertexAttribute, VertexBufferLayout, VertexFormat,
}, },
shader::{ShaderLayout, GL_INSTANCE_INDEX, GL_VERTEX_INDEX}, shader::{ShaderLayout, GL_INSTANCE_INDEX, GL_VERTEX_INDEX},
texture::{TextureComponentType, TextureViewDimension}, texture::{TextureSampleType, TextureViewDimension},
}; };
use bevy_core::AsBytes; use bevy_core::AsBytes;
use spirv_reflect::{ use spirv_reflect::{
@ -29,7 +29,7 @@ impl ShaderLayout {
} }
// obtain attribute descriptors from reflection // 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() { for input_variable in module.enumerate_input_variables(None).unwrap() {
if input_variable.name == GL_VERTEX_INDEX if input_variable.name == GL_VERTEX_INDEX
|| input_variable.name == GL_INSTANCE_INDEX || input_variable.name == GL_INSTANCE_INDEX
@ -37,7 +37,7 @@ impl ShaderLayout {
continue; continue;
} }
// reflect vertex attribute descriptor and record it // reflect vertex attribute descriptor and record it
vertex_attribute_descriptors.push(VertexAttributeDescriptor { vertex_attributes.push(VertexAttribute {
name: input_variable.name.clone().into(), name: input_variable.name.clone().into(),
format: reflect_vertex_format( format: reflect_vertex_format(
input_variable.type_description.as_ref().unwrap(), input_variable.type_description.as_ref().unwrap(),
@ -47,20 +47,19 @@ impl ShaderLayout {
}); });
} }
vertex_attribute_descriptors vertex_attributes.sort_by(|a, b| a.shader_location.cmp(&b.shader_location));
.sort_by(|a, b| a.shader_location.cmp(&b.shader_location));
let mut vertex_buffer_descriptors = Vec::new(); let mut vertex_buffer_layout = Vec::new();
for vertex_attribute_descriptor in vertex_attribute_descriptors.drain(..) { for vertex_attribute in vertex_attributes.drain(..) {
let mut instance = false; let mut instance = false;
// obtain buffer name and instancing flag // obtain buffer name and instancing flag
let current_buffer_name = { let current_buffer_name = {
if bevy_conventions { if bevy_conventions {
if vertex_attribute_descriptor.name == GL_VERTEX_INDEX { if vertex_attribute.name == GL_VERTEX_INDEX {
GL_VERTEX_INDEX.to_string() GL_VERTEX_INDEX.to_string()
} else { } else {
instance = vertex_attribute_descriptor.name.starts_with("I_"); instance = vertex_attribute.name.starts_with("I_");
vertex_attribute_descriptor.name.to_string() vertex_attribute.name.to_string()
} }
} else { } else {
"DefaultVertex".to_string() "DefaultVertex".to_string()
@ -68,8 +67,8 @@ impl ShaderLayout {
}; };
// create a new buffer descriptor, per attribute! // create a new buffer descriptor, per attribute!
vertex_buffer_descriptors.push(VertexBufferDescriptor { vertex_buffer_layout.push(VertexBufferLayout {
attributes: vec![vertex_attribute_descriptor], attributes: vec![vertex_attribute],
name: current_buffer_name.into(), name: current_buffer_name.into(),
step_mode: if instance { step_mode: if instance {
InputStepMode::Instance InputStepMode::Instance
@ -82,7 +81,7 @@ impl ShaderLayout {
ShaderLayout { ShaderLayout {
bind_groups, bind_groups,
vertex_buffer_descriptors, vertex_buffer_layout,
entry_point: entry_point_name, entry_point: entry_point_name,
} }
} }
@ -123,27 +122,34 @@ fn reflect_binding(
ReflectDescriptorType::UniformBuffer => ( ReflectDescriptorType::UniformBuffer => (
&type_description.type_name, &type_description.type_name,
BindType::Uniform { BindType::Uniform {
dynamic: false, has_dynamic_offset: false,
property: reflect_uniform(type_description), property: reflect_uniform(type_description),
}, },
), ),
ReflectDescriptorType::SampledImage => ( ReflectDescriptorType::SampledImage => (
&binding.name, &binding.name,
BindType::SampledTexture { BindType::Texture {
dimension: reflect_dimension(type_description), view_dimension: reflect_dimension(type_description),
component_type: TextureComponentType::Float, sample_type: TextureSampleType::Float { filterable: true },
multisampled: false, multisampled: false,
}, },
), ),
ReflectDescriptorType::StorageBuffer => ( ReflectDescriptorType::StorageBuffer => (
&type_description.type_name, &type_description.type_name,
BindType::StorageBuffer { BindType::StorageBuffer {
dynamic: false, has_dynamic_offset: false,
readonly: true, readonly: true,
}, },
), ),
// TODO: detect comparison "true" case: https://github.com/gpuweb/gpuweb/issues/552 // 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), _ => panic!("Unsupported bind type {:?}.", binding.descriptor_type),
}; };
@ -302,8 +308,8 @@ mod tests {
use super::*; use super::*;
use crate::shader::{Shader, ShaderStage}; use crate::shader::{Shader, ShaderStage};
impl VertexBufferDescriptor { impl VertexBufferLayout {
pub fn test_zero_stride(mut self) -> VertexBufferDescriptor { pub fn test_zero_stride(mut self) -> VertexBufferLayout {
self.stride = 0; self.stride = 0;
self self
} }
@ -338,9 +344,9 @@ mod tests {
layout, layout,
ShaderLayout { ShaderLayout {
entry_point: "main".into(), entry_point: "main".into(),
vertex_buffer_descriptors: vec![ vertex_buffer_layout: vec![
VertexBufferDescriptor::new_from_attribute( VertexBufferLayout::new_from_attribute(
VertexAttributeDescriptor { VertexAttribute {
name: "Vertex_Position".into(), name: "Vertex_Position".into(),
format: VertexFormat::Float4, format: VertexFormat::Float4,
offset: 0, offset: 0,
@ -349,8 +355,8 @@ mod tests {
InputStepMode::Vertex InputStepMode::Vertex
) )
.test_zero_stride(), .test_zero_stride(),
VertexBufferDescriptor::new_from_attribute( VertexBufferLayout::new_from_attribute(
VertexAttributeDescriptor { VertexAttribute {
name: "Vertex_Normal".into(), name: "Vertex_Normal".into(),
format: VertexFormat::Uint4, format: VertexFormat::Uint4,
offset: 0, offset: 0,
@ -359,8 +365,8 @@ mod tests {
InputStepMode::Vertex InputStepMode::Vertex
) )
.test_zero_stride(), .test_zero_stride(),
VertexBufferDescriptor::new_from_attribute( VertexBufferLayout::new_from_attribute(
VertexAttributeDescriptor { VertexAttribute {
name: "I_TestInstancing_Property".into(), name: "I_TestInstancing_Property".into(),
format: VertexFormat::Uint4, format: VertexFormat::Uint4,
offset: 0, offset: 0,
@ -377,7 +383,7 @@ mod tests {
index: 0, index: 0,
name: "Camera".into(), name: "Camera".into(),
bind_type: BindType::Uniform { bind_type: BindType::Uniform {
dynamic: false, has_dynamic_offset: false,
property: UniformProperty::Struct(vec![UniformProperty::Mat4]), property: UniformProperty::Struct(vec![UniformProperty::Mat4]),
}, },
shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT, shader_stage: BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT,
@ -388,10 +394,10 @@ mod tests {
vec![BindingDescriptor { vec![BindingDescriptor {
index: 0, index: 0,
name: "Texture".into(), name: "Texture".into(),
bind_type: BindType::SampledTexture { bind_type: BindType::Texture {
multisampled: false, multisampled: false,
dimension: TextureViewDimension::D2, view_dimension: TextureViewDimension::D2,
component_type: TextureComponentType::Float, sample_type: TextureSampleType::Float { filterable: true }
}, },
shader_stage: BindingShaderStage::VERTEX, shader_stage: BindingShaderStage::VERTEX,
}] }]

View file

@ -14,6 +14,7 @@ pub struct SamplerDescriptor {
pub lod_max_clamp: f32, pub lod_max_clamp: f32,
pub compare_function: Option<CompareFunction>, pub compare_function: Option<CompareFunction>,
pub anisotropy_clamp: Option<NonZeroU8>, pub anisotropy_clamp: Option<NonZeroU8>,
pub border_color: Option<SamplerBorderColor>,
} }
impl SamplerDescriptor { impl SamplerDescriptor {
@ -38,6 +39,7 @@ impl Default for SamplerDescriptor {
lod_max_clamp: std::f32::MAX, lod_max_clamp: std::f32::MAX,
compare_function: None, compare_function: None,
anisotropy_clamp: None, anisotropy_clamp: None,
border_color: None,
} }
} }
} }
@ -68,3 +70,10 @@ impl Default for FilterMode {
FilterMode::Nearest FilterMode::Nearest
} }
} }
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum SamplerBorderColor {
TransparentBlack,
OpaqueBlack,
OpaqueWhite,
}

View file

@ -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,
}

View file

@ -49,9 +49,41 @@ impl Extent3d {
/// Type of data shaders will read from a texture. /// Type of data shaders will read from a texture.
#[derive(Copy, Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[derive(Copy, Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum TextureComponentType { pub enum TextureSampleType {
Float, /// 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, Sint,
/// Sampling returns unsigned integers.
///
/// Example GLSL syntax:
/// ```cpp,ignore
/// layout(binding = 0)
/// uniform utexture2D t;
/// ```
Uint, Uint,
} }

View file

@ -4,9 +4,8 @@ use bevy_ecs::Resources;
use bevy_reflect::TypeUuid; use bevy_reflect::TypeUuid;
use bevy_render::{ use bevy_render::{
pipeline::{ pipeline::{
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite, BlendFactor, BlendOperation, BlendState, ColorTargetState, ColorWrite, CompareFunction,
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, PipelineDescriptor, DepthBiasState, DepthStencilState, PipelineDescriptor, StencilFaceState, StencilState,
RasterizationStateDescriptor, StencilStateDescriptor, StencilStateFaceDescriptor,
}, },
render_graph::{base, AssetRenderResourcesNode, RenderGraph, RenderResourcesNode}, render_graph::{base, AssetRenderResourcesNode, RenderGraph, RenderResourcesNode},
shader::{Shader, ShaderStage, ShaderStages}, 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 { pub fn build_sprite_sheet_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
PipelineDescriptor { PipelineDescriptor {
rasterization_state: Some(RasterizationStateDescriptor { depth_stencil: Some(DepthStencilState {
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 {
format: TextureFormat::Depth32Float, format: TextureFormat::Depth32Float,
depth_write_enabled: true, depth_write_enabled: true,
depth_compare: CompareFunction::LessEqual, depth_compare: CompareFunction::LessEqual,
stencil: StencilStateDescriptor { stencil: StencilState {
front: StencilStateFaceDescriptor::IGNORE, front: StencilFaceState::IGNORE,
back: StencilStateFaceDescriptor::IGNORE, back: StencilFaceState::IGNORE,
read_mask: 0, read_mask: 0,
write_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(), format: TextureFormat::default(),
color_blend: BlendDescriptor { color_blend: BlendState {
src_factor: BlendFactor::SrcAlpha, src_factor: BlendFactor::SrcAlpha,
dst_factor: BlendFactor::OneMinusSrcAlpha, dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
alpha_blend: BlendDescriptor { alpha_blend: BlendState {
src_factor: BlendFactor::One, src_factor: BlendFactor::One,
dst_factor: BlendFactor::One, dst_factor: BlendFactor::One,
operation: BlendOperation::Add, 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 { pub fn build_sprite_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
PipelineDescriptor { PipelineDescriptor {
rasterization_state: Some(RasterizationStateDescriptor { depth_stencil: Some(DepthStencilState {
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 {
format: TextureFormat::Depth32Float, format: TextureFormat::Depth32Float,
depth_write_enabled: true, depth_write_enabled: true,
depth_compare: CompareFunction::LessEqual, depth_compare: CompareFunction::LessEqual,
stencil: StencilStateDescriptor { stencil: StencilState {
front: StencilStateFaceDescriptor::IGNORE, front: StencilFaceState::IGNORE,
back: StencilStateFaceDescriptor::IGNORE, back: StencilFaceState::IGNORE,
read_mask: 0, read_mask: 0,
write_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(), format: TextureFormat::default(),
color_blend: BlendDescriptor { color_blend: BlendState {
src_factor: BlendFactor::SrcAlpha, src_factor: BlendFactor::SrcAlpha,
dst_factor: BlendFactor::OneMinusSrcAlpha, dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
alpha_blend: BlendDescriptor { alpha_blend: BlendState {
src_factor: BlendFactor::One, src_factor: BlendFactor::One,
dst_factor: BlendFactor::One, dst_factor: BlendFactor::One,
operation: BlendOperation::Add, operation: BlendOperation::Add,

View file

@ -3,13 +3,14 @@ use bevy_render::{
draw::{Draw, DrawContext, DrawError, Drawable}, draw::{Draw, DrawContext, DrawError, Drawable},
mesh, mesh,
mesh::Mesh, mesh::Mesh,
pipeline::{PipelineSpecialization, VertexBufferDescriptor}, pipeline::{PipelineSpecialization, VertexBufferLayout},
prelude::Msaa, prelude::Msaa,
renderer::{BindGroup, RenderResourceBindings, RenderResourceId}, renderer::{BindGroup, RenderResourceBindings, RenderResourceId},
}; };
use bevy_sprite::TextureAtlasSprite; use bevy_sprite::TextureAtlasSprite;
use crate::{PositionedGlyph, TextSection}; use crate::{PositionedGlyph, TextSection};
use bevy_render::pipeline::IndexFormat;
pub struct DrawableText<'a> { pub struct DrawableText<'a> {
pub render_resource_bindings: &'a mut RenderResourceBindings, pub render_resource_bindings: &'a mut RenderResourceBindings,
@ -18,7 +19,7 @@ pub struct DrawableText<'a> {
pub sections: &'a [TextSection], pub sections: &'a [TextSection],
pub text_glyphs: &'a Vec<PositionedGlyph>, pub text_glyphs: &'a Vec<PositionedGlyph>,
pub msaa: &'a Msaa, pub msaa: &'a Msaa,
pub font_quad_vertex_descriptor: &'a VertexBufferDescriptor, pub font_quad_vertex_layout: &'a VertexBufferLayout,
} }
impl<'a> Drawable for DrawableText<'a> { impl<'a> Drawable for DrawableText<'a> {
@ -28,7 +29,7 @@ impl<'a> Drawable for DrawableText<'a> {
&bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE.typed(), &bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE.typed(),
&PipelineSpecialization { &PipelineSpecialization {
sample_count: self.msaa.samples, 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() ..Default::default()
}, },
)?; )?;
@ -53,7 +54,7 @@ impl<'a> Drawable for DrawableText<'a> {
mesh::INDEX_BUFFER_ASSET_INDEX, 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) { if let Some(buffer_info) = render_resource_context.get_buffer_info(quad_index_buffer) {
indices = 0..(buffer_info.size / 4) as u32; indices = 0..(buffer_info.size / 4) as u32;
} else { } else {

View file

@ -73,7 +73,7 @@ pub fn draw_text2d_system(
>, >,
) { ) {
let font_quad = meshes.get(&QUAD_HANDLE).unwrap(); 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() { let scale_factor = if let Some(window) = windows.get_primary() {
window.scale_factor() as f32 window.scale_factor() as f32
@ -106,7 +106,7 @@ pub fn draw_text2d_system(
position, position,
msaa: &msaa, msaa: &msaa,
text_glyphs: &text_glyphs.glyphs, text_glyphs: &text_glyphs.glyphs,
font_quad_vertex_descriptor: &vertex_buffer_descriptor, font_quad_vertex_layout: &font_quad_vertex_layout,
scale_factor, scale_factor,
sections: &text.sections, sections: &text.sections,
}; };

View file

@ -23,33 +23,31 @@ pub const UI_PIPELINE_HANDLE: HandleUntyped =
pub fn build_ui_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor { pub fn build_ui_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
PipelineDescriptor { PipelineDescriptor {
rasterization_state: Some(RasterizationStateDescriptor { depth_stencil: Some(DepthStencilState {
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 {
format: TextureFormat::Depth32Float, format: TextureFormat::Depth32Float,
depth_write_enabled: true, depth_write_enabled: true,
depth_compare: CompareFunction::Less, depth_compare: CompareFunction::Less,
stencil: StencilStateDescriptor { stencil: StencilState {
front: StencilStateFaceDescriptor::IGNORE, front: StencilFaceState::IGNORE,
back: StencilStateFaceDescriptor::IGNORE, back: StencilFaceState::IGNORE,
read_mask: 0, read_mask: 0,
write_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(), format: TextureFormat::default(),
color_blend: BlendDescriptor { color_blend: BlendState {
src_factor: BlendFactor::SrcAlpha, src_factor: BlendFactor::SrcAlpha,
dst_factor: BlendFactor::OneMinusSrcAlpha, dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add, operation: BlendOperation::Add,
}, },
alpha_blend: BlendDescriptor { alpha_blend: BlendState {
src_factor: BlendFactor::One, src_factor: BlendFactor::One,
dst_factor: BlendFactor::One, dst_factor: BlendFactor::One,
operation: BlendOperation::Add, operation: BlendOperation::Add,

View file

@ -142,7 +142,7 @@ pub fn draw_text_system(
}; };
let font_quad = meshes.get(&QUAD_HANDLE).unwrap(); 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() { for (entity, mut draw, visible, text, node, global_transform) in query.iter_mut() {
if !visible.is_visible { if !visible.is_visible {
@ -158,7 +158,7 @@ pub fn draw_text_system(
scale_factor: scale_factor as f32, scale_factor: scale_factor as f32,
msaa: &msaa, msaa: &msaa,
text_glyphs: &text_glyphs.glyphs, text_glyphs: &text_glyphs.glyphs,
font_quad_vertex_descriptor: &vertex_buffer_descriptor, font_quad_vertex_layout: &vertex_buffer_layout,
sections: &text.sections, sections: &text.sections,
}; };

View file

@ -29,7 +29,7 @@ bevy_winit = { path = "../bevy_winit", optional = true, version = "0.4.0" }
bevy_utils = { path = "../bevy_utils", version = "0.4.0" } bevy_utils = { path = "../bevy_utils", version = "0.4.0" }
# other # other
wgpu = "0.6" wgpu = "0.7"
futures-lite = "1.4.0" futures-lite = "1.4.0"
crossbeam-channel = "0.4.4" crossbeam-channel = "0.4.4"
crossbeam-utils = "0.7.2" crossbeam-utils = "0.7.2"

View file

@ -206,6 +206,7 @@ pub fn create_render_pass<'a, 'b>(
encoder: &'a mut wgpu::CommandEncoder, encoder: &'a mut wgpu::CommandEncoder,
) -> wgpu::RenderPass<'a> { ) -> wgpu::RenderPass<'a> {
encoder.begin_render_pass(&wgpu::RenderPassDescriptor { encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &pass_descriptor color_attachments: &pass_descriptor
.color_attachments .color_attachments
.iter() .iter()

View file

@ -1,8 +1,6 @@
use crate::{ use crate::{wgpu_type_converter::WgpuInto, WgpuBindGroupInfo, WgpuResources};
wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto},
WgpuBindGroupInfo, WgpuResources,
};
use crate::wgpu_type_converter::OwnedWgpuVertexBufferLayout;
use bevy_asset::{Assets, Handle, HandleUntyped}; use bevy_asset::{Assets, Handle, HandleUntyped};
use bevy_render::{ use bevy_render::{
pipeline::{ pipeline::{
@ -18,7 +16,7 @@ use bevy_render::{
use bevy_utils::tracing::trace; use bevy_utils::tracing::trace;
use bevy_window::{Window, WindowId}; use bevy_window::{Window, WindowId};
use futures_lite::future; 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; use wgpu::util::DeviceExt;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -331,7 +329,11 @@ impl RenderResourceContext for WgpuRenderResourceContext {
let spirv: Cow<[u32]> = shader.get_spirv(None).unwrap().into(); let spirv: Cow<[u32]> = shader.get_spirv(None).unwrap().into();
let shader_module = self let shader_module = self
.device .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); shader_modules.insert(shader_handle.clone_weak(), shader_module);
} }
@ -453,13 +455,13 @@ impl RenderResourceContext for WgpuRenderResourceContext {
.vertex_buffer_descriptors .vertex_buffer_descriptors
.iter() .iter()
.map(|v| v.wgpu_into()) .map(|v| v.wgpu_into())
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>(); .collect::<Vec<OwnedWgpuVertexBufferLayout>>();
let color_states = pipeline_descriptor let color_states = pipeline_descriptor
.color_states .color_target_states
.iter() .iter()
.map(|c| c.wgpu_into()) .map(|c| c.wgpu_into())
.collect::<Vec<wgpu::ColorStateDescriptor>>(); .collect::<Vec<wgpu::ColorTargetState>>();
self.create_shader_module(&pipeline_descriptor.shader_stages.vertex, shaders); 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()), Some(ref fragment_handle) => Some(shader_modules.get(fragment_handle).unwrap()),
None => None, None => None,
}; };
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor { let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
label: None, label: None,
layout: Some(&pipeline_layout), layout: Some(&pipeline_layout),
vertex_stage: wgpu::ProgrammableStageDescriptor { vertex: wgpu::VertexState {
module: &vertex_shader_module, module: &vertex_shader_module,
entry_point: "main", 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 { fragment: match pipeline_descriptor.shader_stages.fragment {
Some(_) => Some(wgpu::ProgrammableStageDescriptor { Some(_) => Some(wgpu::FragmentState {
entry_point: "main", entry_point: "main",
module: fragment_shader_module.as_ref().unwrap(), module: fragment_shader_module.as_ref().unwrap(),
targets: color_states.as_slice(),
}), }),
None => None, None => None,
}, },
rasterization_state: pipeline_descriptor primitive: pipeline_descriptor.primitive.clone().wgpu_into(),
.rasterization_state depth_stencil: pipeline_descriptor
.as_ref() .depth_stencil
.map(|r| r.wgpu_into()), .clone()
primitive_topology: pipeline_descriptor.primitive_topology.wgpu_into(), .map(|depth_stencil| depth_stencil.wgpu_into()),
color_states: &color_states, multisample: pipeline_descriptor.multisample.clone().wgpu_into(),
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,
}; };
let render_pipeline = self let render_pipeline = self
@ -564,7 +556,13 @@ impl RenderResourceContext for WgpuRenderResourceContext {
} }
RenderResourceBinding::Buffer { buffer, range, .. } => { RenderResourceBinding::Buffer { buffer, range, .. } => {
let wgpu_buffer = buffers.get(&buffer).unwrap(); 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 { wgpu::BindGroupEntry {

View file

@ -1,8 +1,8 @@
use crate::{renderer::WgpuRenderContext, WgpuResourceRefs}; use crate::{renderer::WgpuRenderContext, wgpu_type_converter::WgpuInto, WgpuResourceRefs};
use bevy_asset::Handle; use bevy_asset::Handle;
use bevy_render::{ use bevy_render::{
pass::RenderPass, pass::RenderPass,
pipeline::{BindGroupDescriptorId, PipelineDescriptor}, pipeline::{BindGroupDescriptorId, IndexFormat, PipelineDescriptor},
renderer::{BindGroupId, BufferId, RenderContext}, renderer::{BindGroupId, BufferId, RenderContext},
}; };
use bevy_utils::tracing::trace; use bevy_utils::tracing::trace;
@ -40,9 +40,10 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
self.render_pass.set_stencil_reference(reference); 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(); 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>) { fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {

View file

@ -37,7 +37,7 @@ impl WgpuRenderer {
.request_adapter(&wgpu::RequestAdapterOptions { .request_adapter(&wgpu::RequestAdapterOptions {
power_preference: match options.power_pref { power_preference: match options.power_pref {
WgpuPowerOptions::HighPerformance => wgpu::PowerPreference::HighPerformance, WgpuPowerOptions::HighPerformance => wgpu::PowerPreference::HighPerformance,
WgpuPowerOptions::Adaptive => wgpu::PowerPreference::Default, WgpuPowerOptions::Adaptive => wgpu::PowerPreference::LowPower,
WgpuPowerOptions::LowPower => wgpu::PowerPreference::LowPower, WgpuPowerOptions::LowPower => wgpu::PowerPreference::LowPower,
}, },
compatible_surface: None, compatible_surface: None,
@ -53,9 +53,9 @@ impl WgpuRenderer {
let (device, queue) = adapter let (device, queue) = adapter
.request_device( .request_device(
&wgpu::DeviceDescriptor { &wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(), features: wgpu::Features::empty(),
limits: wgpu::Limits::default(), limits: wgpu::Limits::default(),
shader_validation: true,
}, },
trace_path, trace_path,
) )

View file

@ -2,19 +2,21 @@ use bevy_render::{
color::Color, color::Color,
pass::{LoadOp, Operations}, pass::{LoadOp, Operations},
pipeline::{ pipeline::{
BindType, BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite, BindType, BlendFactor, BlendOperation, BlendState, ColorTargetState, ColorWrite,
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat, CompareFunction, CullMode, DepthBiasState, DepthStencilState, FrontFace, IndexFormat,
InputStepMode, PrimitiveTopology, RasterizationStateDescriptor, StencilOperation, InputStepMode, MultisampleState, PolygonMode, PrimitiveState, PrimitiveTopology,
StencilStateDescriptor, StencilStateFaceDescriptor, VertexAttributeDescriptor, StencilFaceState, StencilOperation, StencilState, VertexAttribute, VertexBufferLayout,
VertexBufferDescriptor, VertexFormat, VertexFormat,
}, },
renderer::BufferUsage, renderer::BufferUsage,
texture::{ texture::{
AddressMode, Extent3d, FilterMode, SamplerDescriptor, TextureComponentType, AddressMode, Extent3d, FilterMode, SamplerBorderColor, SamplerDescriptor,
TextureDescriptor, TextureDimension, TextureFormat, TextureUsage, TextureViewDimension, StorageTextureAccess, TextureDescriptor, TextureDimension, TextureFormat,
TextureSampleType, TextureUsage, TextureViewDimension,
}, },
}; };
use bevy_window::Window; use bevy_window::Window;
use wgpu::BufferBindingType;
pub trait WgpuFrom<T> { pub trait WgpuFrom<T> {
fn from(val: T) -> Self; fn from(val: T) -> Self;
@ -70,9 +72,9 @@ impl WgpuFrom<VertexFormat> for wgpu::VertexFormat {
} }
} }
impl WgpuFrom<&VertexAttributeDescriptor> for wgpu::VertexAttributeDescriptor { impl WgpuFrom<&VertexAttribute> for wgpu::VertexAttribute {
fn from(val: &VertexAttributeDescriptor) -> Self { fn from(val: &VertexAttribute) -> Self {
wgpu::VertexAttributeDescriptor { wgpu::VertexAttribute {
format: val.format.wgpu_into(), format: val.format.wgpu_into(),
offset: val.offset, offset: val.offset,
shader_location: val.shader_location, shader_location: val.shader_location,
@ -90,34 +92,34 @@ impl WgpuFrom<InputStepMode> for wgpu::InputStepMode {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct OwnedWgpuVertexBufferDescriptor { pub struct OwnedWgpuVertexBufferLayout {
pub stride: wgpu::BufferAddress, pub array_stride: wgpu::BufferAddress,
pub step_mode: wgpu::InputStepMode, pub step_mode: wgpu::InputStepMode,
pub attributes: Vec<wgpu::VertexAttributeDescriptor>, pub attributes: Vec<wgpu::VertexAttribute>,
} }
impl WgpuFrom<&VertexBufferDescriptor> for OwnedWgpuVertexBufferDescriptor { impl WgpuFrom<&VertexBufferLayout> for OwnedWgpuVertexBufferLayout {
fn from(val: &VertexBufferDescriptor) -> OwnedWgpuVertexBufferDescriptor { fn from(val: &VertexBufferLayout) -> OwnedWgpuVertexBufferLayout {
let attributes = val let attributes = val
.attributes .attributes
.iter() .iter()
.map(|a| a.wgpu_into()) .map(|a| a.wgpu_into())
.collect::<Vec<wgpu::VertexAttributeDescriptor>>(); .collect::<Vec<wgpu::VertexAttribute>>();
OwnedWgpuVertexBufferDescriptor { OwnedWgpuVertexBufferLayout {
step_mode: val.step_mode.wgpu_into(), step_mode: val.step_mode.wgpu_into(),
stride: val.stride, array_stride: val.stride,
attributes, attributes,
} }
} }
} }
impl<'a> From<&'a OwnedWgpuVertexBufferDescriptor> for wgpu::VertexBufferDescriptor<'a> { impl<'a> From<&'a OwnedWgpuVertexBufferLayout> for wgpu::VertexBufferLayout<'a> {
fn from(val: &'a OwnedWgpuVertexBufferDescriptor) -> Self { fn from(val: &'a OwnedWgpuVertexBufferLayout) -> Self {
wgpu::VertexBufferDescriptor { wgpu::VertexBufferLayout {
attributes: &val.attributes, attributes: &val.attributes,
step_mode: val.step_mode, step_mode: val.step_mode,
stride: val.stride, array_stride: val.array_stride,
} }
} }
} }
@ -181,46 +183,71 @@ where
impl WgpuFrom<&BindType> for wgpu::BindingType { impl WgpuFrom<&BindType> for wgpu::BindingType {
fn from(bind_type: &BindType) -> Self { fn from(bind_type: &BindType) -> Self {
match bind_type { match bind_type {
BindType::Uniform { dynamic, .. } => wgpu::BindingType::UniformBuffer { BindType::Uniform {
dynamic: *dynamic, 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), min_binding_size: bind_type.get_uniform_size().and_then(wgpu::BufferSize::new),
}, },
BindType::StorageBuffer { dynamic, readonly } => wgpu::BindingType::StorageBuffer { BindType::StorageBuffer {
dynamic: *dynamic, has_dynamic_offset,
readonly: *readonly, 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), min_binding_size: bind_type.get_uniform_size().and_then(wgpu::BufferSize::new),
}, },
BindType::SampledTexture { BindType::Texture {
dimension, view_dimension,
multisampled, multisampled,
component_type, sample_type,
} => wgpu::BindingType::SampledTexture { } => wgpu::BindingType::Texture {
dimension: (*dimension).wgpu_into(), view_dimension: (*view_dimension).wgpu_into(),
multisampled: *multisampled, 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, comparison: *comparison,
}, },
BindType::StorageTexture { BindType::StorageTexture {
dimension, view_dimension,
format, format,
readonly, access,
} => wgpu::BindingType::StorageTexture { } => wgpu::BindingType::StorageTexture {
dimension: (*dimension).wgpu_into(), access: (*access).wgpu_into(),
view_dimension: (*view_dimension).wgpu_into(),
format: (*format).wgpu_into(), format: (*format).wgpu_into(),
readonly: *readonly,
}, },
} }
} }
} }
impl WgpuFrom<TextureComponentType> for wgpu::TextureComponentType { impl WgpuFrom<TextureSampleType> for wgpu::TextureSampleType {
fn from(texture_component_type: TextureComponentType) -> Self { fn from(texture_component_type: TextureSampleType) -> Self {
match texture_component_type { match texture_component_type {
TextureComponentType::Float => wgpu::TextureComponentType::Float, TextureSampleType::Float { filterable } => {
TextureComponentType::Sint => wgpu::TextureComponentType::Sint, wgpu::TextureSampleType::Float { filterable }
TextureComponentType::Uint => wgpu::TextureComponentType::Uint, }
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 { impl WgpuFrom<&StencilState> for wgpu::StencilState {
fn from(val: &StencilStateDescriptor) -> Self { fn from(val: &StencilState) -> Self {
wgpu::StencilStateDescriptor { wgpu::StencilState {
back: (&val.back).wgpu_into(), back: (&val.back).wgpu_into(),
front: (&val.front).wgpu_into(), front: (&val.front).wgpu_into(),
read_mask: val.read_mask, read_mask: val.read_mask,
@ -334,20 +361,32 @@ impl WgpuFrom<&StencilStateDescriptor> for wgpu::StencilStateDescriptor {
} }
} }
impl WgpuFrom<&DepthStencilStateDescriptor> for wgpu::DepthStencilStateDescriptor { impl WgpuFrom<DepthStencilState> for wgpu::DepthStencilState {
fn from(val: &DepthStencilStateDescriptor) -> Self { fn from(val: DepthStencilState) -> Self {
wgpu::DepthStencilStateDescriptor { wgpu::DepthStencilState {
depth_compare: val.depth_compare.wgpu_into(), depth_compare: val.depth_compare.wgpu_into(),
depth_write_enabled: val.depth_write_enabled, depth_write_enabled: val.depth_write_enabled,
format: val.format.wgpu_into(), format: val.format.wgpu_into(),
stencil: (&val.stencil).wgpu_into(), stencil: (&val.stencil).wgpu_into(),
bias: val.bias.wgpu_into(),
clamp_depth: val.clamp_depth,
} }
} }
} }
impl WgpuFrom<&StencilStateFaceDescriptor> for wgpu::StencilStateFaceDescriptor { impl WgpuFrom<MultisampleState> for wgpu::MultisampleState {
fn from(val: &StencilStateFaceDescriptor) -> Self { fn from(val: MultisampleState) -> Self {
wgpu::StencilStateFaceDescriptor { 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(), compare: val.compare.wgpu_into(),
depth_fail_op: val.depth_fail_op.wgpu_into(), depth_fail_op: val.depth_fail_op.wgpu_into(),
fail_op: val.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 { impl WgpuFrom<PolygonMode> for wgpu::PolygonMode {
fn from(val: &RasterizationStateDescriptor) -> Self { fn from(val: PolygonMode) -> wgpu::PolygonMode {
wgpu::RasterizationStateDescriptor { match val {
front_face: val.front_face.wgpu_into(), PolygonMode::Fill => wgpu::PolygonMode::Fill,
cull_mode: val.cull_mode.wgpu_into(), PolygonMode::Line => wgpu::PolygonMode::Line,
depth_bias: val.depth_bias, PolygonMode::Point => wgpu::PolygonMode::Point,
depth_bias_slope_scale: val.depth_bias_slope_scale,
depth_bias_clamp: val.depth_bias_clamp,
clamp_depth: val.clamp_depth,
} }
} }
} }
impl WgpuFrom<&ColorStateDescriptor> for wgpu::ColorStateDescriptor { impl WgpuFrom<DepthBiasState> for wgpu::DepthBiasState {
fn from(val: &ColorStateDescriptor) -> Self { fn from(val: DepthBiasState) -> Self {
wgpu::ColorStateDescriptor { 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(), format: val.format.wgpu_into(),
alpha_blend: (&val.alpha_blend).wgpu_into(), alpha_blend: (&val.alpha_blend).wgpu_into(),
color_blend: (&val.color_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 { impl WgpuFrom<ColorWrite> for wgpu::ColorWrite {
fn from(val: ColorWrite) -> Self { fn from(val: ColorWrite) -> Self {
wgpu::ColorWrite::from_bits(val.bits()).unwrap() wgpu::ColorWrite::from_bits(val.bits()).unwrap()
} }
} }
impl WgpuFrom<&BlendDescriptor> for wgpu::BlendDescriptor { impl WgpuFrom<&BlendState> for wgpu::BlendState {
fn from(val: &BlendDescriptor) -> Self { fn from(val: &BlendState) -> Self {
wgpu::BlendDescriptor { wgpu::BlendState {
src_factor: val.src_factor.wgpu_into(), src_factor: val.src_factor.wgpu_into(),
dst_factor: val.dst_factor.wgpu_into(), dst_factor: val.dst_factor.wgpu_into(),
operation: val.operation.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, lod_max_clamp: sampler_descriptor.lod_max_clamp,
compare: sampler_descriptor.compare_function.map(|c| c.wgpu_into()), compare: sampler_descriptor.compare_function.map(|c| c.wgpu_into()),
anisotropy_clamp: sampler_descriptor.anisotropy_clamp, 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 { impl WgpuFrom<&Window> for wgpu::SwapChainDescriptor {
fn from(window: &Window) -> Self { fn from(window: &Window) -> Self {
wgpu::SwapChainDescriptor { wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: TextureFormat::default().wgpu_into(), format: TextureFormat::default().wgpu_into(),
width: window.physical_width(), width: window.physical_width(),
height: window.physical_height(), height: window.physical_height(),

View file

@ -9,7 +9,7 @@ fn main() {
.add_stage_after(stage::UPDATE, STAGE, StateStage::<AppState>::default()) .add_stage_after(stage::UPDATE, STAGE, StateStage::<AppState>::default())
.on_state_enter(STAGE, AppState::Setup, load_textures.system()) .on_state_enter(STAGE, AppState::Setup, load_textures.system())
.on_state_update(STAGE, AppState::Setup, check_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(); .run();
} }
@ -18,7 +18,7 @@ const STAGE: &str = "app_state";
#[derive(Clone)] #[derive(Clone)]
enum AppState { enum AppState {
Setup, Setup,
Finshed, Finished,
} }
#[derive(Default)] #[derive(Default)]
@ -38,7 +38,7 @@ fn check_textures(
if let LoadState::Loaded = if let LoadState::Loaded =
asset_server.get_group_load_state(rpg_sprite_handles.handles.iter().map(|handle| handle.id)) 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();
} }
} }