pipeline specialization (support different primitive topologies within the same pipeline)

This commit is contained in:
Carter Anderson 2020-04-19 19:06:41 -07:00
parent 86d0ae6470
commit 7fe2288814
13 changed files with 172 additions and 118 deletions

View File

@ -118,7 +118,7 @@ impl<T> AssetStorage<T> {
AssetStorage { AssetStorage {
assets: HashMap::new(), assets: HashMap::new(),
names: HashMap::new(), names: HashMap::new(),
current_index: 1, current_index: DEFAULT_HANDLE_ID + 1, // ensure we don't start on the default handle id
} }
} }

View File

@ -39,7 +39,7 @@ use self::{
}, },
render_graph::RenderGraph, render_graph::RenderGraph,
render_resource::{ render_resource::{
build_entity_render_resource_assignments_system, entity_render_resource_assignments_system,
resource_providers::{ resource_providers::{
Camera2dResourceProvider, CameraResourceProvider, LightResourceProvider, Camera2dResourceProvider, CameraResourceProvider, LightResourceProvider,
UniformResourceProvider, UniformResourceProvider,
@ -111,8 +111,12 @@ impl AppPlugin for RenderPlugin {
.add_resource(EntityRenderResourceAssignments::default()) .add_resource(EntityRenderResourceAssignments::default())
.add_resource(asset_batchers) .add_resource(asset_batchers)
// core systems // core systems
.add_system(build_entity_render_resource_assignments_system()) .add_system(entity_render_resource_assignments_system())
.add_system_to_stage_init(stage::POST_UPDATE, camera::camera_update_system) .add_system_to_stage_init(stage::POST_UPDATE, camera::camera_update_system)
.add_system_to_stage(
stage::POST_UPDATE,
mesh::mesh_specializer_system(),
)
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system()) .add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system())
.add_system_to_stage( .add_system_to_stage(
stage::POST_UPDATE, stage::POST_UPDATE,

View File

@ -6,7 +6,7 @@ use crate::{
render_resource::AssetBatchers, render_resource::AssetBatchers,
Renderable, Renderable,
}; };
use bevy_asset::Handle; use bevy_asset::{AssetStorage, Handle};
use glam::*; use glam::*;
use legion::prelude::*; use legion::prelude::*;
use std::borrow::Cow; use std::borrow::Cow;
@ -224,7 +224,7 @@ pub mod shape {
]; ];
Mesh { Mesh {
primitive_topology: PrimitiveTopology::TriangleStrip, primitive_topology: PrimitiveTopology::TriangleList,
attributes: vec![ attributes: vec![
VertexAttribute::position(positions), VertexAttribute::position(positions),
VertexAttribute::normal(normals), VertexAttribute::normal(normals),
@ -283,7 +283,7 @@ pub mod shape {
} }
Mesh { Mesh {
primitive_topology: PrimitiveTopology::TriangleStrip, primitive_topology: PrimitiveTopology::TriangleList,
attributes: vec![ attributes: vec![
VertexAttribute::position(positions), VertexAttribute::position(positions),
VertexAttribute::normal(normals), VertexAttribute::normal(normals),
@ -321,6 +321,20 @@ pub fn mesh_batcher_system() -> Box<dyn Schedulable> {
}) })
} }
pub fn mesh_specializer_system() -> Box<dyn Schedulable> {
SystemBuilder::new("mesh_batcher")
.read_resource::<AssetStorage<Mesh>>()
.with_query(
<(Read<Handle<Mesh>>, Write<Renderable>)>::query().filter(changed::<Handle<Mesh>>() | changed::<Renderable>()),
)
.build(|_, world, meshes, query| {
for (mesh_handle, mut renderable) in query.iter_mut(world) {
let mesh = meshes.get(&mesh_handle).unwrap();
renderable.render_resource_assignments.pipeline_specialization.primitive_topology = mesh.primitive_topology;
}
})
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{Vertex, pipeline::state_descriptors::PrimitiveTopology, shader::AsUniforms}; use crate::{Vertex, pipeline::state_descriptors::PrimitiveTopology, shader::AsUniforms};

View File

@ -1,5 +1,6 @@
use super::{ use super::{
BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType, VertexBufferDescriptors, state_descriptors::PrimitiveTopology, BindType, PipelineDescriptor, PipelineLayout,
PipelineLayoutType, VertexBufferDescriptors,
}; };
use crate::{ use crate::{
render_resource::{ render_resource::{
@ -14,11 +15,25 @@ use std::collections::{HashMap, HashSet};
use legion::prelude::*; use legion::prelude::*;
#[derive(Clone, Eq, PartialEq, Debug, Default)]
pub struct PipelineSpecialization {
pub shader_specialization: ShaderSpecialization,
pub primitive_topology: PrimitiveTopology,
}
#[derive(Clone, Eq, PartialEq, Debug, Default)]
pub struct ShaderSpecialization {
pub shader_defs: HashSet<String>,
}
// TODO: consider using (Typeid, fieldinfo.index) in place of string for hashes // TODO: consider using (Typeid, fieldinfo.index) in place of string for hashes
pub struct PipelineCompiler { pub struct PipelineCompiler {
pub shader_source_to_compiled: HashMap<Handle<Shader>, Vec<(HashSet<String>, Handle<Shader>)>>, pub shader_source_to_compiled:
pub pipeline_source_to_compiled: HashMap<Handle<Shader>, Vec<(ShaderSpecialization, Handle<Shader>)>>,
HashMap<Handle<PipelineDescriptor>, Vec<(HashSet<String>, Handle<PipelineDescriptor>)>>, pub pipeline_source_to_compiled: HashMap<
Handle<PipelineDescriptor>,
Vec<(PipelineSpecialization, Handle<PipelineDescriptor>)>,
>,
} }
impl PipelineCompiler { impl PipelineCompiler {
@ -86,7 +101,7 @@ impl PipelineCompiler {
&mut self, &mut self,
shader_storage: &mut AssetStorage<Shader>, shader_storage: &mut AssetStorage<Shader>,
shader_handle: &Handle<Shader>, shader_handle: &Handle<Shader>,
shader_defs: &HashSet<String>, shader_specialization: &ShaderSpecialization,
) -> Handle<Shader> { ) -> Handle<Shader> {
let compiled_shaders = self let compiled_shaders = self
.shader_source_to_compiled .shader_source_to_compiled
@ -100,18 +115,26 @@ impl PipelineCompiler {
return *shader_handle; return *shader_handle;
} }
if let Some((_compiled_shader_defs, compiled_shader)) = compiled_shaders if let Some((_shader_specialization, compiled_shader)) =
compiled_shaders
.iter() .iter()
.find(|(compiled_shader_defs, _compiled_shader)| *compiled_shader_defs == *shader_defs) .find(|(current_shader_specialization, _compiled_shader)| {
*current_shader_specialization == *shader_specialization
})
{ {
// if shader has already been compiled with current configuration, use existing shader // if shader has already been compiled with current configuration, use existing shader
*compiled_shader *compiled_shader
} else { } else {
// if no shader exists with the current configuration, create new shader and compile // if no shader exists with the current configuration, create new shader and compile
let shader_def_vec = shader_defs.iter().cloned().collect::<Vec<String>>(); let shader_def_vec = shader_specialization
.shader_defs
.iter()
.cloned()
.collect::<Vec<String>>();
let compiled_shader = shader.get_spirv_shader(Some(&shader_def_vec)); let compiled_shader = shader.get_spirv_shader(Some(&shader_def_vec));
compiled_shaders.push((shader_defs.clone(), *shader_handle)); let compiled_handle = shader_storage.add(compiled_shader);
shader_storage.add(compiled_shader) compiled_shaders.push((shader_specialization.clone(), compiled_handle));
compiled_handle
} }
} }
@ -128,7 +151,9 @@ impl PipelineCompiler {
compiled_pipeline_descriptor.shader_stages.vertex = self.compile_shader( compiled_pipeline_descriptor.shader_stages.vertex = self.compile_shader(
shader_storage, shader_storage,
&pipeline_descriptor.shader_stages.vertex, &pipeline_descriptor.shader_stages.vertex,
&render_resource_assignments.shader_defs, &render_resource_assignments
.pipeline_specialization
.shader_specialization,
); );
compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor
.shader_stages .shader_stages
@ -138,7 +163,9 @@ impl PipelineCompiler {
self.compile_shader( self.compile_shader(
shader_storage, shader_storage,
fragment, fragment,
&render_resource_assignments.shader_defs, &render_resource_assignments
.pipeline_specialization
.shader_specialization,
) )
}); });
@ -150,6 +177,9 @@ impl PipelineCompiler {
render_resource_assignments, render_resource_assignments,
); );
compiled_pipeline_descriptor.primitive_topology = render_resource_assignments
.pipeline_specialization
.primitive_topology;
compiled_pipeline_descriptor compiled_pipeline_descriptor
} }
@ -174,8 +204,8 @@ impl PipelineCompiler {
.get_mut(pipeline_handle) .get_mut(pipeline_handle)
.unwrap() .unwrap()
.iter() .iter()
.find(|(shader_defs, _macroed_pipeline_handle)| { .find(|(pipeline_specialization, _macroed_pipeline_handle)| {
*shader_defs == render_resource_assignments.shader_defs *pipeline_specialization == render_resource_assignments.pipeline_specialization
}) { }) {
*macroed_pipeline_handle *macroed_pipeline_handle
} else { } else {
@ -194,7 +224,7 @@ impl PipelineCompiler {
.get_mut(pipeline_handle) .get_mut(pipeline_handle)
.unwrap(); .unwrap();
macro_pipelines.push(( macro_pipelines.push((
render_resource_assignments.shader_defs.clone(), render_resource_assignments.pipeline_specialization.clone(),
compiled_pipeline_handle, compiled_pipeline_handle,
)); ));
compiled_pipeline_handle compiled_pipeline_handle
@ -277,7 +307,12 @@ pub fn update_shader_assignments(
); );
// reset shader_defs so they can be changed next frame // reset shader_defs so they can be changed next frame
renderable.render_resource_assignments.shader_defs.clear(); renderable
.render_resource_assignments
.pipeline_specialization
.shader_specialization
.shader_defs
.clear();
} }
} }
} }

View File

@ -55,7 +55,7 @@ impl<'a, 'b, 'c> ForwardPipelineBuilder for RenderGraphBuilder<'a, 'b, 'c> {
}, },
write_mask: ColorWrite::ALL, write_mask: ColorWrite::ALL,
}) })
.add_draw_target(resource_name::draw_target::ASSIGNED_BATCHES); .add_draw_target(resource_name::draw_target::ASSIGNED_MESHES);
}) })
} }
} }

View File

@ -60,6 +60,12 @@ pub enum PrimitiveTopology {
TriangleStrip = 4, TriangleStrip = 4,
} }
impl Default for PrimitiveTopology {
fn default() -> Self {
PrimitiveTopology::TriangleList
}
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum FrontFace { pub enum FrontFace {
Ccw = 0, Ccw = 0,
@ -172,3 +178,9 @@ pub enum IndexFormat {
Uint16 = 0, Uint16 = 0,
Uint32 = 1, Uint32 = 1,
} }
impl Default for IndexFormat {
fn default() -> Self {
IndexFormat::Uint16
}
}

View File

@ -19,7 +19,7 @@ impl EntityRenderResourceAssignments {
} }
// TODO: make sure this runs right before rendering // TODO: make sure this runs right before rendering
pub fn build_entity_render_resource_assignments_system() -> Box<dyn Schedulable> { pub fn entity_render_resource_assignments_system() -> Box<dyn Schedulable> {
SystemBuilder::new("entity_render_resource_assignments") SystemBuilder::new("entity_render_resource_assignments")
.write_resource::<EntityRenderResourceAssignments>() .write_resource::<EntityRenderResourceAssignments>()
.with_query(<Write<Renderable>>::query().filter(changed::<Renderable>())) .with_query(<Write<Renderable>>::query().filter(changed::<Renderable>()))

View File

@ -1,5 +1,5 @@
use super::RenderResource; use super::RenderResource;
use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId}; use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization};
use std::{ use std::{
collections::{hash_map::DefaultHasher, HashMap, HashSet}, collections::{hash_map::DefaultHasher, HashMap, HashSet},
hash::{Hash, Hasher}, hash::{Hash, Hasher},
@ -15,7 +15,7 @@ pub struct RenderResourceAssignments {
bind_group_resource_sets: bind_group_resource_sets:
HashMap<BindGroupDescriptorId, (RenderResourceSetId, Option<Vec<u32>>)>, HashMap<BindGroupDescriptorId, (RenderResourceSetId, Option<Vec<u32>>)>,
dirty_bind_groups: HashSet<BindGroupDescriptorId>, dirty_bind_groups: HashSet<BindGroupDescriptorId>,
pub(crate) shader_defs: HashSet<String>, pub pipeline_specialization: PipelineSpecialization,
} }
impl RenderResourceAssignments { impl RenderResourceAssignments {

View File

@ -1,43 +1,35 @@
use crate::{ use crate::{
mesh::{self, Mesh}, mesh::{self, Mesh},
pipeline::{state_descriptors::IndexFormat, VertexBufferDescriptors}, pipeline::{state_descriptors::IndexFormat, VertexBufferDescriptor, VertexBufferDescriptors},
render_resource::{AssetBatchers, BufferInfo, BufferUsage}, render_resource::{AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments},
renderer_2::GlobalRenderResourceContext, renderer_2::{GlobalRenderResourceContext, RenderResourceContext},
shader::AsUniforms, shader::AsUniforms,
Vertex, Renderable, Vertex,
}; };
use bevy_asset::AssetStorage; use bevy_asset::{AssetStorage, Handle};
use legion::prelude::*; use legion::prelude::*;
pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Schedulable> { fn setup_mesh_resource(
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap(); render_resources: &dyn RenderResourceContext,
// TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format render_resource_assignments: &mut RenderResourceAssignments,
let vertex_buffer_descriptor = Vertex::get_vertex_buffer_descriptor().unwrap(); vertex_buffer_descriptor: &VertexBufferDescriptor,
handle: Handle<Mesh>,
meshes: &AssetStorage<Mesh>,
) {
log::trace!("setup mesh for {:?}", render_resource_assignments.id);
let index_format = IndexFormat::Uint16; let index_format = IndexFormat::Uint16;
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
SystemBuilder::new("mesh_resource_provider")
.read_resource::<GlobalRenderResourceContext>()
.read_resource::<AssetStorage<Mesh>>()
.write_resource::<AssetBatchers>()
.build(
move |_, _, (render_resource_context, meshes, asset_batchers), _| {
let render_resources = &render_resource_context.context;
if let Some(batches) = asset_batchers.get_handle_batches_mut::<Mesh>() {
for batch in batches {
let handle = batch.get_handle::<Mesh>().unwrap();
log::trace!("setup mesh for {:?}", batch.render_resource_assignments.id);
let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) = let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) =
render_resources render_resources.get_asset_resource(handle, mesh::VERTEX_BUFFER_ASSET_INDEX)
.get_asset_resource(handle, mesh::VERTEX_BUFFER_ASSET_INDEX)
{ {
( (
vertex_buffer, vertex_buffer,
render_resources render_resources.get_asset_resource(handle, mesh::INDEX_BUFFER_ASSET_INDEX),
.get_asset_resource(handle, mesh::INDEX_BUFFER_ASSET_INDEX),
) )
} else { } else {
let mesh_asset = meshes.get(&handle).unwrap(); let mesh_asset = meshes.get(&handle).unwrap();
let vertex_bytes = mesh_asset.get_vertex_buffer_bytes(&vertex_buffer_descriptor).unwrap(); let vertex_bytes = mesh_asset
.get_vertex_buffer_bytes(&vertex_buffer_descriptor)
.unwrap();
// TODO: use a staging buffer here // TODO: use a staging buffer here
let vertex_buffer = render_resources.create_buffer_with_data( let vertex_buffer = render_resources.create_buffer_with_data(
BufferInfo { BufferInfo {
@ -55,26 +47,50 @@ pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Sched
&index_bytes, &index_bytes,
); );
render_resources.set_asset_resource( render_resources.set_asset_resource(handle, vertex_buffer, mesh::VERTEX_BUFFER_ASSET_INDEX);
handle, render_resources.set_asset_resource(handle, index_buffer, mesh::INDEX_BUFFER_ASSET_INDEX);
vertex_buffer,
mesh::VERTEX_BUFFER_ASSET_INDEX,
);
render_resources.set_asset_resource(
handle,
index_buffer,
mesh::INDEX_BUFFER_ASSET_INDEX,
);
(vertex_buffer, Some(index_buffer)) (vertex_buffer, Some(index_buffer))
}; };
batch.render_resource_assignments.set_vertex_buffer( render_resource_assignments.set_vertex_buffer("Vertex", vertex_buffer, index_buffer);
"Vertex", }
vertex_buffer,
index_buffer, pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Schedulable> {
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
// TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format
let vertex_buffer_descriptor = Vertex::get_vertex_buffer_descriptor().unwrap();
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
SystemBuilder::new("mesh_resource_provider")
.read_resource::<GlobalRenderResourceContext>()
.read_resource::<AssetStorage<Mesh>>()
.write_resource::<AssetBatchers>()
.with_query(<(Read<Handle<Mesh>>, Write<Renderable>)>::query())
.build(
move |_, world, (render_resource_context, meshes, asset_batchers), query| {
let render_resources = &*render_resource_context.context;
if let Some(batches) = asset_batchers.get_handle_batches_mut::<Mesh>() {
for batch in batches {
let handle = batch.get_handle::<Mesh>().unwrap();
setup_mesh_resource(
render_resources,
&mut batch.render_resource_assignments,
&vertex_buffer_descriptor,
handle,
&meshes,
); );
} }
} }
// TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target
for (handle, mut renderable) in query.iter_mut(world) {
setup_mesh_resource(
render_resources,
&mut renderable.render_resource_assignments,
&vertex_buffer_descriptor,
*handle,
&meshes,
);
}
}, },
) )
} }

View File

@ -31,6 +31,8 @@ where
if let Some(shader_defs) = uniforms.get_shader_defs() { if let Some(shader_defs) = uniforms.get_shader_defs() {
renderable renderable
.render_resource_assignments .render_resource_assignments
.pipeline_specialization
.shader_specialization
.shader_defs .shader_defs
.extend(shader_defs) .extend(shader_defs)
} }
@ -58,6 +60,8 @@ where
if let Some(shader_defs) = uniforms.get_shader_defs() { if let Some(shader_defs) = uniforms.get_shader_defs() {
renderable renderable
.render_resource_assignments .render_resource_assignments
.pipeline_specialization
.shader_specialization
.shader_defs .shader_defs
.extend(shader_defs) .extend(shader_defs)
} }

View File

@ -10,7 +10,6 @@ fn main() {
/// set up a simple scene /// set up a simple scene
fn setup(world: &mut World, resources: &mut Resources) { fn setup(world: &mut World, resources: &mut Resources) {
env_logger::init();
// create a cube and a plane mesh // create a cube and a plane mesh
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap(); let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let cube_handle = mesh_storage.add(Mesh::from(shape::Cube)); let cube_handle = mesh_storage.add(Mesh::from(shape::Cube));
@ -45,13 +44,6 @@ fn setup(world: &mut World, resources: &mut Resources) {
translation: Translation::new(0.0, 0.0, 1.0), translation: Translation::new(0.0, 0.0, 1.0),
..Default::default() ..Default::default()
}) })
// cube
.add_entity(MeshEntity {
mesh: cube_handle,
material: cube_material_handle,
translation: Translation::new(2.0, 0.0, 1.0),
..Default::default()
})
// light // light
.add_entity(LightEntity { .add_entity(LightEntity {
translation: Translation::new(4.0, -4.0, 5.0), translation: Translation::new(4.0, -4.0, 5.0),

View File

@ -1,13 +1,9 @@
use bevy::{prelude::*, render::shader}; use bevy::prelude::*;
fn main() { fn main() {
App::build() App::build()
.add_default_plugins() .add_default_plugins()
.add_startup_system(setup) .add_startup_system(setup)
.add_system_to_stage(
stage::POST_UPDATE,
shader::asset_handle_batcher_system::<MyMaterial>(),
)
.run(); .run();
} }
@ -32,8 +28,7 @@ fn add_shader_to_render_graph(resources: &mut Resources) {
ShaderStage::Vertex, ShaderStage::Vertex,
r#" r#"
#version 450 #version 450
layout(location = 0) in vec4 Vertex_Position; layout(location = 0) in vec3 Vertex_Position;
layout(location = 0) out vec4 v_Position;
layout(set = 0, binding = 0) uniform Camera { layout(set = 0, binding = 0) uniform Camera {
mat4 ViewProj; mat4 ViewProj;
}; };
@ -41,8 +36,7 @@ fn add_shader_to_render_graph(resources: &mut Resources) {
mat4 Model; mat4 Model;
}; };
void main() { void main() {
v_Position = Model * Vertex_Position; gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0);
gl_Position = ViewProj * v_Position;
} }
"#, "#,
)) ))
@ -50,7 +44,6 @@ fn add_shader_to_render_graph(resources: &mut Resources) {
ShaderStage::Fragment, ShaderStage::Fragment,
r#" r#"
#version 450 #version 450
layout(location = 0) in vec4 v_Position;
layout(location = 0) out vec4 o_Target; layout(location = 0) out vec4 o_Target;
layout(set = 1, binding = 1) uniform MyMaterial_color { layout(set = 1, binding = 1) uniform MyMaterial_color {
vec4 color; vec4 color;
@ -73,13 +66,8 @@ fn setup(world: &mut World, resources: &mut Resources) {
let material = material_storage.add(MyMaterial { let material = material_storage.add(MyMaterial {
color: Color::rgb(0.0, 0.8, 0.0), color: Color::rgb(0.0, 0.8, 0.0),
}); });
resources.insert(material_storage); resources.insert(material_storage);
// batch materials to improve performance
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
asset_batchers.batch_types2::<Mesh, MyMaterial>();
// get a handle to our newly created shader pipeline // get a handle to our newly created shader pipeline
let mut pipeline_storage = resources let mut pipeline_storage = resources
.get_mut::<AssetStorage<PipelineDescriptor>>() .get_mut::<AssetStorage<PipelineDescriptor>>()

View File

@ -4,10 +4,6 @@ fn main() {
App::build() App::build()
.add_default_plugins() .add_default_plugins()
.add_startup_system(setup) .add_startup_system(setup)
.add_system_to_stage(
stage::POST_UPDATE,
shader::asset_handle_batcher_system::<MyMaterial>(),
)
.add_system_to_stage( .add_system_to_stage(
stage::POST_UPDATE, stage::POST_UPDATE,
shader::asset_handle_shader_def_system::<MyMaterial>(), shader::asset_handle_shader_def_system::<MyMaterial>(),
@ -38,8 +34,7 @@ fn add_shader_to_render_graph(resources: &mut Resources) {
ShaderStage::Vertex, ShaderStage::Vertex,
r#" r#"
#version 450 #version 450
layout(location = 0) in vec4 Vertex_Position; layout(location = 0) in vec3 Vertex_Position;
layout(location = 0) out vec4 v_Position;
layout(set = 0, binding = 0) uniform Camera { layout(set = 0, binding = 0) uniform Camera {
mat4 ViewProj; mat4 ViewProj;
}; };
@ -47,8 +42,7 @@ fn add_shader_to_render_graph(resources: &mut Resources) {
mat4 Model; mat4 Model;
}; };
void main() { void main() {
v_Position = Model * Vertex_Position; gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0);
gl_Position = ViewProj * v_Position;
} }
"#, "#,
)) ))
@ -56,7 +50,6 @@ fn add_shader_to_render_graph(resources: &mut Resources) {
ShaderStage::Fragment, ShaderStage::Fragment,
r#" r#"
#version 450 #version 450
layout(location = 0) in vec4 v_Position;
layout(location = 0) out vec4 o_Target; layout(location = 0) out vec4 o_Target;
layout(set = 1, binding = 1) uniform MyMaterial_color { layout(set = 1, binding = 1) uniform MyMaterial_color {
vec4 color; vec4 color;
@ -92,10 +85,6 @@ fn setup(world: &mut World, resources: &mut Resources) {
resources.insert(material_storage); resources.insert(material_storage);
// batch materials to improve performance
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
asset_batchers.batch_types2::<Mesh, MyMaterial>();
// get a handle to our newly created shader pipeline // get a handle to our newly created shader pipeline
let mut pipeline_storage = resources let mut pipeline_storage = resources
.get_mut::<AssetStorage<PipelineDescriptor>>() .get_mut::<AssetStorage<PipelineDescriptor>>()