pipeline specialization (support different primitive topologies within the same pipeline)
This commit is contained in:
parent
86d0ae6470
commit
7fe2288814
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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};
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -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>()))
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
@ -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>>()
|
||||||
|
|||||||
@ -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>>()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user