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_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,

View file

@ -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);

View file

@ -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)) =

View file

@ -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);

View file

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

View file

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

View file

@ -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(

View file

@ -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());
}

View file

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

View file

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

View file

@ -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 {

View file

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

View file

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

View file

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

View file

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

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.
#[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,
}

View file

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

View file

@ -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 {

View file

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

View file

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

View file

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

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" }
# other
wgpu = "0.6"
wgpu = "0.7"
futures-lite = "1.4.0"
crossbeam-channel = "0.4.4"
crossbeam-utils = "0.7.2"

View file

@ -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()

View file

@ -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 {

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_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>) {

View file

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

View file

@ -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(),

View file

@ -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();
}
}