diff --git a/examples/instancing.rs b/examples/instancing.rs index c19f3f905d..3fec9e3cfc 100644 --- a/examples/instancing.rs +++ b/examples/instancing.rs @@ -96,7 +96,7 @@ fn setup(world: &mut World, resources: &mut Resources) { 0.0, ), renderable: Renderable { - instanced: true, + is_instanced: true, ..Default::default() }, ..Default::default() diff --git a/examples/instancing_old.rs b/examples/instancing_old.rs index a0e5ff64f2..8f2eabe960 100644 --- a/examples/instancing_old.rs +++ b/examples/instancing_old.rs @@ -162,7 +162,7 @@ fn create_person(world: &mut World, mesh_handle: Handle, translation: Tran ..Default::default() }, Renderable { - instanced: true, + is_instanced: true, ..Default::default() }, mesh_handle, diff --git a/src/render/draw_target/draw_targets/assigned_meshes_draw_target.rs b/src/render/draw_target/draw_targets/assigned_meshes_draw_target.rs index 6db8494f14..cd0480a539 100644 --- a/src/render/draw_target/draw_targets/assigned_meshes_draw_target.rs +++ b/src/render/draw_target/draw_targets/assigned_meshes_draw_target.rs @@ -34,11 +34,11 @@ impl DrawTarget for AssignedMeshesDrawTarget { for entity in assigned_entities.iter() { // TODO: hopefully legion has better random access apis that are more like queries? let renderable = world.get_component::(*entity).unwrap(); - let mesh = *world.get_component::>(*entity).unwrap(); - if !renderable.is_visible { + if !renderable.is_visible || renderable.is_instanced { continue; } + let mesh = *world.get_component::>(*entity).unwrap(); let renderer = render_pass.get_renderer(); let render_resources = renderer.get_render_resources(); if current_mesh_handle != Some(mesh) { @@ -85,7 +85,7 @@ impl DrawTarget for AssignedMeshesDrawTarget { for entity in assigned_entities.iter() { // TODO: hopefully legion has better random access apis that are more like queries? let renderable = world.get_component::(*entity).unwrap(); - if !renderable.is_visible { + if !renderable.is_visible || renderable.is_instanced { continue; } diff --git a/src/render/draw_target/draw_targets/meshes_draw_target.rs b/src/render/draw_target/draw_targets/meshes_draw_target.rs index 4601e93ec0..245ca8d3f2 100644 --- a/src/render/draw_target/draw_targets/meshes_draw_target.rs +++ b/src/render/draw_target/draw_targets/meshes_draw_target.rs @@ -27,7 +27,7 @@ impl DrawTarget for MeshesDrawTarget { let mesh_query = <(Read>, Read)>::query(); for (entity, (mesh, renderable)) in mesh_query.iter_entities(world) { - if !renderable.is_visible { + if !renderable.is_visible || renderable.is_instanced { continue; } diff --git a/src/render/render_resource/resource_providers/uniform_resource_provider.rs b/src/render/render_resource/resource_providers/uniform_resource_provider.rs index f3ec644a94..26ac66f754 100644 --- a/src/render/render_resource/resource_providers/uniform_resource_provider.rs +++ b/src/render/render_resource/resource_providers/uniform_resource_provider.rs @@ -71,19 +71,22 @@ where let mut entity_render_resource_assignments = resources.get_mut::().unwrap(); // TODO: only update handle values when Asset value has changed if let Some(asset_storage) = resources.get::>() { - for (entity, (handle, _renderable)) in handle_query.iter_entities(world) { - asset_batchers.set_entity_handle(entity, *handle); - let render_resource_assignments = entity_render_resource_assignments.get_mut_or_create(entity); - if let Some(uniforms) = asset_storage.get(&handle) { - self.setup_entity_uniform_resources( - entity, - uniforms, - renderer, - resources, - render_resource_assignments, - true, - Some(*handle), - ) + for (entity, (handle, renderable)) in handle_query.iter_entities(world) { + if renderable.is_instanced { + asset_batchers.set_entity_handle(entity, *handle); + } else { + let render_resource_assignments = entity_render_resource_assignments.get_mut_or_create(entity); + if let Some(uniforms) = asset_storage.get(&handle) { + self.setup_entity_uniform_resources( + entity, + uniforms, + renderer, + resources, + render_resource_assignments, + true, + Some(*handle), + ) + } } } } @@ -273,6 +276,7 @@ where } // copy entity uniform data to buffers + // PERF: consider iter_chunks here and calling get_bytes() on each chunk? for (name, (resource, _count, entities)) in self.uniform_buffer_info_resources.iter() { let resource = resource.unwrap(); let size = { @@ -290,15 +294,20 @@ where // TODO: check if index has changed. if it has, then entity should be updated // TODO: only mem-map entities if their data has changed // PERF: These hashmap inserts are pretty expensive (10 fps for 10000 entities) - for (entity, _) in self.resource_query.iter_entities(world) { - if !entities.contains(&entity) { + for (entity, (_, renderable)) in self.resource_query.iter_entities(world) { + if renderable.is_instanced || !entities.contains(&entity) { continue; } + info.offsets.insert(entity, offset as u32); offset += alignment; } - for (entity, _) in self.handle_query.as_ref().unwrap().iter_entities(world) { + for (entity, (_, renderable)) in self.handle_query.as_ref().unwrap().iter_entities(world) { + if renderable.is_instanced { + continue; + } + info.offsets.insert(entity, offset as u32); offset += alignment; } @@ -311,10 +320,10 @@ where &mut |mapped| { let alignment = BIND_BUFFER_ALIGNMENT as usize; let mut offset = 0usize; - for (entity, (uniforms, _renderable)) in + for (entity, (uniforms, renderable)) in self.resource_query.iter_entities(world) { - if !entities.contains(&entity) { + if renderable.is_instanced || !entities.contains(&entity) { continue; } if let Some(uniform_bytes) = uniforms.get_uniform_bytes_ref(&name) { @@ -329,13 +338,14 @@ where } if let Some(asset_storage) = resources.get::>() { - for (entity, (handle, _renderable)) in + for (entity, (handle, renderable)) in self.handle_query.as_ref().unwrap().iter_entities(world) { - let uniforms = asset_storage.get(&handle).unwrap(); - if !entities.contains(&entity) { + if renderable.is_instanced ||!entities.contains(&entity) { continue; } + + let uniforms = asset_storage.get(&handle).unwrap(); if let Some(uniform_bytes) = uniforms.get_uniform_bytes_ref(&name) { mapped[offset..(offset + uniform_bytes.len())] .copy_from_slice(uniform_bytes); @@ -398,7 +408,11 @@ where self.update_asset_uniforms(renderer, world, resources); let mut entity_render_resource_assignments = resources.get_mut::().unwrap(); - for (entity, (uniforms, _renderable)) in query.iter_entities(world) { + for (entity, (uniforms, renderable)) in query.iter_entities(world) { + if renderable.is_instanced { + continue; + } + let render_resource_assignments = entity_render_resource_assignments.get_mut_or_create(entity); self.setup_entity_uniform_resources(entity, &uniforms, renderer, resources, render_resource_assignments, true, None); } diff --git a/src/render/renderable.rs b/src/render/renderable.rs index 62b116e766..0e85750df5 100644 --- a/src/render/renderable.rs +++ b/src/render/renderable.rs @@ -11,15 +11,15 @@ use std::collections::{HashMap, HashSet}; pub struct Renderable { pub is_visible: bool, + pub is_instanced: bool, pub pipelines: Vec>, pub shader_defs: HashSet, - pub instanced: bool, } impl Renderable { pub fn instanced() -> Self { Renderable { - instanced: false, + is_instanced: true, ..Default::default() } } @@ -33,7 +33,7 @@ impl Default for Renderable { Handle::new(0), // TODO: this could be better ], shader_defs: HashSet::new(), - instanced: false, + is_instanced: false, } } } @@ -127,7 +127,7 @@ pub fn update_shader_assignments( for (entity, mut renderable) in >::query().iter_entities_mut(world) { // if instancing is enabled, set the def here - if renderable.instanced { + if renderable.is_instanced { renderable.shader_defs.insert("INSTANCING".to_string()); }