diff --git a/.vscode/settings.json b/.vscode/settings.json index 3e6ecf557d..03050dc9b8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,6 +11,7 @@ "hashset", "multizip", "passthrough", + "precompile", "rspirv", "rustc", "spirv" diff --git a/ROADMAP.md b/ROADMAP.md index e828506f8f..bc8fc193aa 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -19,6 +19,9 @@ Here is the current list of planned features. All items are sorted in approximat * Add feature docs * Add "template" projects * Add ```#![deny(warnings, missing_docs)]``` to ensure future contributions meet style/doc standards +* ECS + * Remove as many references to Resources as possible in favor of resolved resource types + * Consider adding Renderer and World to Resources * Error Handling * Custom error type? * Remove as many panics / unwraps as possible diff --git a/examples/entity_builder_comparison.rs b/examples/entity_builder_comparison.rs index 799f483838..3f23b81bd0 100644 --- a/examples/entity_builder_comparison.rs +++ b/examples/entity_builder_comparison.rs @@ -184,7 +184,7 @@ fn setup(world: &mut World, resources: &mut Resources) { // create_entities_insert_vec(world, plane_handle, cube_handle); // no-archetype precompile: .93 - // noarchetype precompile: .93 + // no-archetype precompile: .93 // create_entities_builder_add_component(world, plane_handle, cube_handle); // archetype precompile: 0.65 diff --git a/examples/simple.rs b/examples/simple.rs index a0f9ec4d2a..21a8cabcd8 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -26,13 +26,23 @@ fn setup(world: &mut World, resources: &mut Resources) { .add_entity(MeshEntity { mesh: plane_handle, material: plane_material_handle, + // renderable: Renderable::instanced(), ..Default::default() }) // cube .add_entity(MeshEntity { mesh: cube_handle, material: cube_material_handle, - translation: Translation::new(0.0, 0.0, 1.0), + // renderable: Renderable::instanced(), + translation: Translation::new(-1.5, 0.0, 1.0), + ..Default::default() + }) + // cube + .add_entity(MeshEntity { + mesh: cube_handle, + material: cube_material_handle, + // renderable: Renderable::instanced(), + translation: Translation::new(1.5, 0.0, 1.0), ..Default::default() }) // light 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 cd0480a539..7b066b32af 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 @@ -23,6 +23,7 @@ impl DrawTarget for AssignedMeshesDrawTarget { pipeline_handle: Handle, ) { let shader_pipeline_assignments = resources.get::().unwrap(); + let entity_render_resource_assignments = resources.get::().unwrap(); let mut current_mesh_handle = None; let mut current_mesh_index_len = 0; @@ -61,7 +62,8 @@ impl DrawTarget for AssignedMeshesDrawTarget { } // TODO: validate bind group properties against shader uniform properties at least once - render_pass.set_bind_groups(Some(&entity)); + let render_resource_assignments = entity_render_resource_assignments.get(*entity); + render_pass.set_bind_groups(render_resource_assignments); render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1); } } @@ -90,7 +92,7 @@ impl DrawTarget for AssignedMeshesDrawTarget { } if let Some(render_resource_assignments) = entity_render_resource_assignments.get(*entity) { - renderer.setup_entity_bind_groups(*entity, render_resource_assignments, pipeline_descriptor); + renderer.setup_bind_groups(render_resource_assignments, pipeline_descriptor); } } } 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 245ca8d3f2..6373018b1e 100644 --- a/src/render/draw_target/draw_targets/meshes_draw_target.rs +++ b/src/render/draw_target/draw_targets/meshes_draw_target.rs @@ -5,7 +5,7 @@ use crate::{ draw_target::DrawTarget, mesh::Mesh, pipeline::PipelineDescriptor, - render_resource::{resource_name, ResourceInfo}, + render_resource::{resource_name, ResourceInfo, EntityRenderResourceAssignments}, renderer::RenderPass, Renderable, }, @@ -18,13 +18,14 @@ impl DrawTarget for MeshesDrawTarget { fn draw( &self, world: &World, - _resources: &Resources, + resources: &Resources, render_pass: &mut dyn RenderPass, _pipeline_handle: Handle, ) { let mut current_mesh_handle = None; let mut current_mesh_index_len = 0; let mesh_query = <(Read>, Read)>::query(); + let entity_render_resource_assignments = resources.get::().unwrap(); for (entity, (mesh, renderable)) in mesh_query.iter_entities(world) { if !renderable.is_visible || renderable.is_instanced { @@ -53,7 +54,8 @@ impl DrawTarget for MeshesDrawTarget { } // TODO: validate bind group properties against shader uniform properties at least once - render_pass.set_bind_groups(Some(&entity)); + let render_resource_assignments = entity_render_resource_assignments.get(entity); + render_pass.set_bind_groups(render_resource_assignments); render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1); } } diff --git a/src/render/render_resource/render_resource_assignments.rs b/src/render/render_resource/render_resource_assignments.rs index 2401d1d3c9..b944719857 100644 --- a/src/render/render_resource/render_resource_assignments.rs +++ b/src/render/render_resource/render_resource_assignments.rs @@ -23,7 +23,7 @@ impl RenderResourceAssignments { } } -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)] pub struct RenderResourceAssignmentsId(usize); #[derive(Default)] 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 a9cedb9d87..66df96cfdc 100644 --- a/src/render/render_resource/resource_providers/uniform_resource_provider.rs +++ b/src/render/render_resource/resource_providers/uniform_resource_provider.rs @@ -254,6 +254,7 @@ where world: &World, resources: &Resources, ) { + let entity_render_resource_assignments = resources.get::().unwrap(); // allocate uniform buffers for (name, (resource, count, _entities)) in self.uniform_buffer_info_resources.iter_mut() { let count = *count as u64; diff --git a/src/render/renderer/renderer.rs b/src/render/renderer/renderer.rs index 9be0baadfb..a4c6c46829 100644 --- a/src/render/renderer/renderer.rs +++ b/src/render/renderer/renderer.rs @@ -89,9 +89,8 @@ pub trait Renderer { ); fn get_render_resources(&self) -> &RenderResources; fn get_render_resources_mut(&mut self) -> &mut RenderResources; - fn setup_entity_bind_groups( + fn setup_bind_groups( &mut self, - entity: Entity, render_resource_assignments: &RenderResourceAssignments, pipeline_descriptor: &PipelineDescriptor, ); @@ -106,5 +105,5 @@ pub trait RenderPass { fn set_index_buffer(&mut self, resource: RenderResource, offset: u64); fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64); fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range); - fn set_bind_groups(&mut self, entity: Option<&Entity>); + fn set_bind_groups(&mut self, render_resource_assignments: Option<&RenderResourceAssignments>); } diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs index f554943f89..955c512578 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs @@ -1,10 +1,10 @@ use super::{WgpuRenderer, WgpuResources}; use crate::render::{ pipeline::{BindType, PipelineDescriptor}, - render_resource::RenderResource, + render_resource::{RenderResource, RenderResourceAssignments}, renderer::{RenderPass, Renderer}, }; -use legion::prelude::Entity; +use std::ops::Range; pub struct WgpuRenderPass<'a, 'b, 'c, 'd> { pub render_pass: &'b mut wgpu::RenderPass<'a>, @@ -33,17 +33,12 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { self.render_pass.set_index_buffer(&buffer, offset); } - fn draw_indexed( - &mut self, - indices: core::ops::Range, - base_vertex: i32, - instances: core::ops::Range, - ) { + fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { self.render_pass .draw_indexed(indices, base_vertex, instances); } - fn set_bind_groups(&mut self, entity: Option<&Entity>) { + fn set_bind_groups(&mut self, render_resource_assignments: Option<&RenderResourceAssignments>) { let pipeline_layout = self.pipeline_descriptor.get_layout().unwrap(); for bind_group in pipeline_layout.bind_groups.iter() { let bind_group_id = bind_group.get_hash().unwrap(); @@ -52,9 +47,9 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { Some(bind_group_info) => bind_group_info, // otherwise try to get an entity-specific bind group None => { - if let Some(entity) = entity { + if let Some(assignments) = render_resource_assignments { self.wgpu_resources - .get_entity_bind_group(*entity, bind_group_id) + .get_assignments_bind_group(assignments.get_id(), bind_group_id) .unwrap() } else { panic!("No bind group exists that matches: {:?}"); @@ -81,12 +76,12 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { .dynamic_uniform_buffer_info .get(&resource) { - let index = dynamic_uniform_buffer_info - .offsets - .get(entity.unwrap()) - .unwrap(); + // let index = dynamic_uniform_buffer_info + // .offsets + // .get(entity.unwrap()) + // .unwrap(); - dynamic_uniform_indices.push(*index); + // dynamic_uniform_indices.push(*index); } } } diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs index 11f0d2b7ba..d1dbcb5d71 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs @@ -677,9 +677,8 @@ impl Renderer for WgpuRenderer { &mut self.wgpu_resources.render_resources } - fn setup_entity_bind_groups( + fn setup_bind_groups( &mut self, - entity: Entity, render_resource_assignments: &RenderResourceAssignments, pipeline_descriptor: &PipelineDescriptor, ) { @@ -690,10 +689,10 @@ impl Renderer for WgpuRenderer { if let None = self.wgpu_resources.bind_groups.get(&bind_group_id) { if let None = self .wgpu_resources - .get_entity_bind_group(entity, bind_group_id) + .get_assignments_bind_group(render_resource_assignments.get_id(), bind_group_id) { self.wgpu_resources - .create_entity_bind_group(&self.device, bind_group, entity, render_resource_assignments); + .create_assignments_bind_group(&self.device, bind_group, render_resource_assignments); } } } diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_resources.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_resources.rs index 125dd1bf22..0d2f2e7aad 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_resources.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_resources.rs @@ -1,9 +1,8 @@ use crate::{ - legion::prelude::*, render::{ pipeline::{BindGroup, BindType}, render_resource::{ - BufferUsage, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, + BufferUsage, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, RenderResourceAssignmentsId, }, shader::DynamicUniformBufferInfo, texture::{SamplerDescriptor, TextureDescriptor}, @@ -23,7 +22,7 @@ pub struct WgpuResources { pub resource_info: HashMap, pub bind_groups: HashMap, pub bind_group_layouts: HashMap, - pub entity_bind_groups: HashMap<(Entity, u64), BindGroupInfo>, + pub assignment_bind_groups: HashMap<(RenderResourceAssignmentsId, u64), BindGroupInfo>, pub dynamic_uniform_buffer_info: HashMap, } @@ -37,7 +36,7 @@ impl WgpuResources { bind_groups: HashMap::new(), bind_group_layouts: HashMap::new(), dynamic_uniform_buffer_info: HashMap::new(), - entity_bind_groups: HashMap::new(), + assignment_bind_groups: HashMap::new(), render_resources: RenderResources::default(), } } @@ -109,19 +108,18 @@ impl WgpuResources { .insert(bind_group_id, BindGroupInfo { bind_group }); } } - pub fn get_entity_bind_group( + pub fn get_assignments_bind_group( &self, - entity: Entity, + render_resource_assignment_id: RenderResourceAssignmentsId, bind_group_id: u64, ) -> Option<&BindGroupInfo> { - self.entity_bind_groups.get(&(entity, bind_group_id)) + self.assignment_bind_groups.get(&(render_resource_assignment_id, bind_group_id)) } - pub fn create_entity_bind_group( + pub fn create_assignments_bind_group( &mut self, device: &wgpu::Device, bind_group: &BindGroup, - entity: Entity, render_resource_assignments: &RenderResourceAssignments, ) { // TODO: don't make this per-entity. bind groups should be re-used across the same resource when possible @@ -167,8 +165,8 @@ impl WgpuResources { } } else { panic!( - "No resource assigned to uniform \"{}\" for entity {}", - binding.name, entity + "No resource assigned to uniform \"{}\" for RenderResourceAssignments {:?}", + binding.name, render_resource_assignments.get_id() ); } }) @@ -181,8 +179,8 @@ impl WgpuResources { let bind_group = device.create_bind_group(&bind_group_descriptor); // TODO: storing a large number entity bind groups might actually be really bad. make sure this is ok - self.entity_bind_groups - .insert((entity, bind_group_id), BindGroupInfo { bind_group }); + self.assignment_bind_groups + .insert((render_resource_assignments.get_id(), bind_group_id), BindGroupInfo { bind_group }); } pub fn create_buffer(