asset handle batcher system

This commit is contained in:
Carter Anderson 2020-04-12 00:54:51 -07:00
parent 32bce28b00
commit 1d44b4034f
7 changed files with 74 additions and 64 deletions

View File

@ -83,7 +83,7 @@ impl RenderPlugin {
resources.get_event_reader::<WindowResized>(), resources.get_event_reader::<WindowResized>(),
)) ))
.add_resource_provider(LightResourceProvider::new(10)) .add_resource_provider(LightResourceProvider::new(10))
.add_resource_provider(MeshResourceProvider::new()) .add_resource_provider(MeshResourceProvider::default())
.add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true)) .add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true))
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)) .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true))
.add_forward_pass() .add_forward_pass()
@ -99,6 +99,7 @@ impl AppPlugin for RenderPlugin {
.build_system_on_stage(stage::POST_UPDATE, camera::camera_update_system) .build_system_on_stage(stage::POST_UPDATE, camera::camera_update_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(stage::POST_UPDATE, shader::asset_handle_shader_def_system::<StandardMaterial>()) .add_system_to_stage(stage::POST_UPDATE, shader::asset_handle_shader_def_system::<StandardMaterial>())
.add_system_to_stage(stage::POST_UPDATE, shader::asset_handle_batcher_system::<StandardMaterial>())
.add_stage_after(stage::POST_UPDATE, RENDER_STAGE) .add_stage_after(stage::POST_UPDATE, RENDER_STAGE)
.add_resource(RenderGraph::default()) .add_resource(RenderGraph::default())
.add_resource(AssetStorage::<Mesh>::new()) .add_resource(AssetStorage::<Mesh>::new())

View File

@ -4,40 +4,18 @@ use crate::{
render_resource::{ render_resource::{
AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments, ResourceProvider, AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments, ResourceProvider,
}, },
renderer_2::RenderContext,
shader::AsUniforms, shader::AsUniforms,
Renderable, Vertex, renderer_2::RenderContext, Vertex,
}; };
use bevy_asset::{AssetStorage, Handle}; use bevy_asset::{AssetStorage, Handle};
use legion::{filter::*, prelude::*}; use legion::prelude::*;
use zerocopy::AsBytes; use zerocopy::AsBytes;
pub struct MeshResourceProvider { #[derive(Default)]
pub mesh_query: Query< pub struct MeshResourceProvider;
(Read<Handle<Mesh>>, Read<Renderable>),
EntityFilterTuple<
And<(
ComponentFilter<Handle<Mesh>>,
ComponentFilter<Renderable>,
ComponentFilter<Handle<Mesh>>,
)>,
And<(Passthrough, Passthrough)>,
And<(
Passthrough,
Passthrough,
ComponentChangedFilter<Handle<Mesh>>,
)>,
>,
>,
}
impl MeshResourceProvider { impl MeshResourceProvider {
pub fn new() -> Self {
MeshResourceProvider {
mesh_query: <(Read<Handle<Mesh>>, Read<Renderable>)>::query()
.filter(changed::<Handle<Mesh>>()),
}
}
fn setup_mesh_resources( fn setup_mesh_resources(
render_context: &mut dyn RenderContext, render_context: &mut dyn RenderContext,
mesh_storage: &AssetStorage<Mesh>, mesh_storage: &AssetStorage<Mesh>,
@ -45,13 +23,11 @@ impl MeshResourceProvider {
render_resource_assignments: &mut RenderResourceAssignments, render_resource_assignments: &mut RenderResourceAssignments,
) { ) {
let render_resources = render_context.resources_mut(); let render_resources = render_context.resources_mut();
let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) = render_resources let (vertex_buffer, index_buffer) =
.get_mesh_vertices_resource(handle) if let Some(vertex_buffer) = render_resources.get_mesh_vertices_resource(handle) {
{
( (
vertex_buffer, vertex_buffer,
render_resources render_resources.get_mesh_indices_resource(handle),
.get_mesh_indices_resource(handle),
) )
} else { } else {
let mesh_asset = mesh_storage.get(&handle).unwrap(); let mesh_asset = mesh_storage.get(&handle).unwrap();
@ -91,7 +67,12 @@ impl ResourceProvider for MeshResourceProvider {
vertex_buffer_descriptors.set(Vertex::get_vertex_buffer_descriptor().cloned().unwrap()); vertex_buffer_descriptors.set(Vertex::get_vertex_buffer_descriptor().cloned().unwrap());
} }
fn update(&mut self, _render_context: &mut dyn RenderContext, _world: &World, _resources: &Resources) { fn update(
&mut self,
_render_context: &mut dyn RenderContext,
_world: &World,
_resources: &Resources,
) {
} }
fn finish_update( fn finish_update(

View File

@ -167,9 +167,8 @@ where
fn update_uniform_handles_info(&mut self, world: &World, resources: &Resources) { fn update_uniform_handles_info(&mut self, world: &World, resources: &Resources) {
let handle_query = self.handle_query.take().unwrap(); let handle_query = self.handle_query.take().unwrap();
let assets = resources.get::<AssetStorage<T>>(); let assets = resources.get::<AssetStorage<T>>();
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
if let Some(assets) = assets { if let Some(assets) = assets {
for (entity, (handle, renderable)) in handle_query.iter_entities(world) { for (handle, renderable) in handle_query.iter(world) {
if !renderable.is_visible { if !renderable.is_visible {
return; return;
} }
@ -187,7 +186,6 @@ where
); );
} }
} else { } else {
asset_batchers.set_entity_handle(entity, *handle);
let uniforms = assets let uniforms = assets
.get(&handle) .get(&handle)
.expect("Handle points to a non-existent resource"); .expect("Handle points to a non-existent resource");

View File

@ -2,7 +2,7 @@ use crate::{
color::ColorSource, color::ColorSource,
pipeline::{BindType, VertexBufferDescriptor}, pipeline::{BindType, VertexBufferDescriptor},
texture::Texture, texture::Texture,
Renderable, Renderable, render_resource::AssetBatchers,
}; };
use bevy_asset::{AssetStorage, Handle}; use bevy_asset::{AssetStorage, Handle};
@ -49,6 +49,10 @@ where
.with_query(<(Read<Handle<T>>, Write<Renderable>)>::query()) .with_query(<(Read<Handle<T>>, Write<Renderable>)>::query())
.build(|_, world, asset_storage, query| { .build(|_, world, asset_storage, query| {
for (uniform_handle, mut renderable) in query.iter_mut(world) { for (uniform_handle, mut renderable) in query.iter_mut(world) {
if !renderable.is_visible || renderable.is_instanced {
continue;
}
let uniforms = asset_storage.get(&uniform_handle).unwrap(); let uniforms = asset_storage.get(&uniform_handle).unwrap();
if let Some(shader_defs) = uniforms.get_shader_defs() { if let Some(shader_defs) = uniforms.get_shader_defs() {
renderable.render_resource_assignments.shader_defs.extend(shader_defs) renderable.render_resource_assignments.shader_defs.extend(shader_defs)
@ -57,6 +61,27 @@ where
}) })
} }
pub fn asset_handle_batcher_system<T>() -> Box<dyn Schedulable>
where
T: AsUniforms + Send + Sync + 'static,
{
SystemBuilder::new(format!(
"asset_handle_batcher::{}",
std::any::type_name::<T>()
))
.write_resource::<AssetBatchers>()
.with_query(<(Read<Handle<T>>, Read<Renderable>)>::query())
.build(|_, world, asset_batchers, query| {
for (entity, (uniform_handle, renderable)) in query.iter_entities(world) {
if !renderable.is_visible || renderable.is_instanced {
continue;
}
asset_batchers.set_entity_handle(entity, *uniform_handle);
}
})
}
pub trait ShaderDefSuffixProvider { pub trait ShaderDefSuffixProvider {
fn get_shader_def(&self) -> Option<&'static str>; fn get_shader_def(&self) -> Option<&'static str>;
} }

View File

@ -231,7 +231,7 @@ impl WgpuRenderer {
device: Arc<wgpu::Device>, device: Arc<wgpu::Device>,
global_wgpu_resources: &WgpuResources, global_wgpu_resources: &WgpuResources,
) -> (Vec::<wgpu::CommandBuffer>, Vec::<WgpuResources>) { ) -> (Vec::<wgpu::CommandBuffer>, Vec::<WgpuResources>) {
let max_thread_count = 4; let max_thread_count = 8;
let (sender, receiver) = crossbeam_channel::bounded(max_thread_count); let (sender, receiver) = crossbeam_channel::bounded(max_thread_count);
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
let chunk_size = (render_graph.resource_providers.len() + max_thread_count - 1) / max_thread_count; // divide ints rounding remainder up let chunk_size = (render_graph.resource_providers.len() + max_thread_count - 1) / max_thread_count; // divide ints rounding remainder up

View File

@ -1,8 +1,9 @@
use bevy::{prelude::*}; use bevy::{prelude::*, render::shader};
fn main() { fn main() {
App::build() App::build()
.add_default_plugins() .add_default_plugins()
.add_system_to_stage(stage::POST_UPDATE, shader::asset_handle_batcher_system::<MyMaterial>())
.setup(setup) .setup(setup)
.run(); .run();
} }

View File

@ -4,6 +4,10 @@ fn main() {
App::build() App::build()
.add_default_plugins() .add_default_plugins()
.setup(setup) .setup(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>(),