use RenderResourceAssignments in place of Entity

This commit is contained in:
Carter Anderson 2020-03-20 17:49:29 -07:00
parent f90205a40d
commit ae0d5abf45
12 changed files with 54 additions and 44 deletions

View File

@ -11,6 +11,7 @@
"hashset", "hashset",
"multizip", "multizip",
"passthrough", "passthrough",
"precompile",
"rspirv", "rspirv",
"rustc", "rustc",
"spirv" "spirv"

View File

@ -19,6 +19,9 @@ Here is the current list of planned features. All items are sorted in approximat
* Add feature docs * Add feature docs
* Add "template" projects * Add "template" projects
* Add ```#![deny(warnings, missing_docs)]``` to ensure future contributions meet style/doc standards * 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 * Error Handling
* Custom error type? * Custom error type?
* Remove as many panics / unwraps as possible * Remove as many panics / unwraps as possible

View File

@ -184,7 +184,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
// create_entities_insert_vec(world, plane_handle, cube_handle); // create_entities_insert_vec(world, plane_handle, cube_handle);
// no-archetype precompile: .93 // no-archetype precompile: .93
// noarchetype precompile: .93 // no-archetype precompile: .93
// create_entities_builder_add_component(world, plane_handle, cube_handle); // create_entities_builder_add_component(world, plane_handle, cube_handle);
// archetype precompile: 0.65 // archetype precompile: 0.65

View File

@ -26,13 +26,23 @@ fn setup(world: &mut World, resources: &mut Resources) {
.add_entity(MeshEntity { .add_entity(MeshEntity {
mesh: plane_handle, mesh: plane_handle,
material: plane_material_handle, material: plane_material_handle,
// renderable: Renderable::instanced(),
..Default::default() ..Default::default()
}) })
// cube // cube
.add_entity(MeshEntity { .add_entity(MeshEntity {
mesh: cube_handle, mesh: cube_handle,
material: cube_material_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() ..Default::default()
}) })
// light // light

View File

@ -23,6 +23,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
pipeline_handle: Handle<PipelineDescriptor>, pipeline_handle: Handle<PipelineDescriptor>,
) { ) {
let shader_pipeline_assignments = resources.get::<ShaderPipelineAssignments>().unwrap(); let shader_pipeline_assignments = resources.get::<ShaderPipelineAssignments>().unwrap();
let entity_render_resource_assignments = resources.get::<EntityRenderResourceAssignments>().unwrap();
let mut current_mesh_handle = None; let mut current_mesh_handle = None;
let mut current_mesh_index_len = 0; 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 // 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); 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) { 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);
} }
} }
} }

View File

@ -5,7 +5,7 @@ use crate::{
draw_target::DrawTarget, draw_target::DrawTarget,
mesh::Mesh, mesh::Mesh,
pipeline::PipelineDescriptor, pipeline::PipelineDescriptor,
render_resource::{resource_name, ResourceInfo}, render_resource::{resource_name, ResourceInfo, EntityRenderResourceAssignments},
renderer::RenderPass, renderer::RenderPass,
Renderable, Renderable,
}, },
@ -18,13 +18,14 @@ impl DrawTarget for MeshesDrawTarget {
fn draw( fn draw(
&self, &self,
world: &World, world: &World,
_resources: &Resources, resources: &Resources,
render_pass: &mut dyn RenderPass, render_pass: &mut dyn RenderPass,
_pipeline_handle: Handle<PipelineDescriptor>, _pipeline_handle: Handle<PipelineDescriptor>,
) { ) {
let mut current_mesh_handle = None; let mut current_mesh_handle = None;
let mut current_mesh_index_len = 0; let mut current_mesh_index_len = 0;
let mesh_query = <(Read<Handle<Mesh>>, Read<Renderable>)>::query(); let mesh_query = <(Read<Handle<Mesh>>, Read<Renderable>)>::query();
let entity_render_resource_assignments = resources.get::<EntityRenderResourceAssignments>().unwrap();
for (entity, (mesh, renderable)) in mesh_query.iter_entities(world) { for (entity, (mesh, renderable)) in mesh_query.iter_entities(world) {
if !renderable.is_visible || renderable.is_instanced { 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 // 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); render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
} }
} }

View File

@ -23,7 +23,7 @@ impl RenderResourceAssignments {
} }
} }
#[derive(Eq, PartialEq, Debug, Copy, Clone)] #[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
pub struct RenderResourceAssignmentsId(usize); pub struct RenderResourceAssignmentsId(usize);
#[derive(Default)] #[derive(Default)]

View File

@ -254,6 +254,7 @@ where
world: &World, world: &World,
resources: &Resources, resources: &Resources,
) { ) {
let entity_render_resource_assignments = resources.get::<EntityRenderResourceAssignments>().unwrap();
// allocate uniform buffers // allocate uniform buffers
for (name, (resource, count, _entities)) in self.uniform_buffer_info_resources.iter_mut() { for (name, (resource, count, _entities)) in self.uniform_buffer_info_resources.iter_mut() {
let count = *count as u64; let count = *count as u64;

View File

@ -89,9 +89,8 @@ pub trait Renderer {
); );
fn get_render_resources(&self) -> &RenderResources; fn get_render_resources(&self) -> &RenderResources;
fn get_render_resources_mut(&mut self) -> &mut RenderResources; fn get_render_resources_mut(&mut self) -> &mut RenderResources;
fn setup_entity_bind_groups( fn setup_bind_groups(
&mut self, &mut self,
entity: Entity,
render_resource_assignments: &RenderResourceAssignments, render_resource_assignments: &RenderResourceAssignments,
pipeline_descriptor: &PipelineDescriptor, pipeline_descriptor: &PipelineDescriptor,
); );
@ -106,5 +105,5 @@ pub trait RenderPass {
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64); fn set_index_buffer(&mut self, resource: RenderResource, offset: u64);
fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64); fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64);
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>); fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
fn set_bind_groups(&mut self, entity: Option<&Entity>); fn set_bind_groups(&mut self, render_resource_assignments: Option<&RenderResourceAssignments>);
} }

View File

@ -1,10 +1,10 @@
use super::{WgpuRenderer, WgpuResources}; use super::{WgpuRenderer, WgpuResources};
use crate::render::{ use crate::render::{
pipeline::{BindType, PipelineDescriptor}, pipeline::{BindType, PipelineDescriptor},
render_resource::RenderResource, render_resource::{RenderResource, RenderResourceAssignments},
renderer::{RenderPass, Renderer}, renderer::{RenderPass, Renderer},
}; };
use legion::prelude::Entity; use std::ops::Range;
pub struct WgpuRenderPass<'a, 'b, 'c, 'd> { pub struct WgpuRenderPass<'a, 'b, 'c, 'd> {
pub render_pass: &'b mut wgpu::RenderPass<'a>, 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); self.render_pass.set_index_buffer(&buffer, offset);
} }
fn draw_indexed( fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
&mut self,
indices: core::ops::Range<u32>,
base_vertex: i32,
instances: core::ops::Range<u32>,
) {
self.render_pass self.render_pass
.draw_indexed(indices, base_vertex, instances); .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(); let pipeline_layout = self.pipeline_descriptor.get_layout().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() { for bind_group in pipeline_layout.bind_groups.iter() {
let bind_group_id = bind_group.get_hash().unwrap(); 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, Some(bind_group_info) => bind_group_info,
// otherwise try to get an entity-specific bind group // otherwise try to get an entity-specific bind group
None => { None => {
if let Some(entity) = entity { if let Some(assignments) = render_resource_assignments {
self.wgpu_resources self.wgpu_resources
.get_entity_bind_group(*entity, bind_group_id) .get_assignments_bind_group(assignments.get_id(), bind_group_id)
.unwrap() .unwrap()
} else { } else {
panic!("No bind group exists that matches: {:?}"); 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 .dynamic_uniform_buffer_info
.get(&resource) .get(&resource)
{ {
let index = dynamic_uniform_buffer_info // let index = dynamic_uniform_buffer_info
.offsets // .offsets
.get(entity.unwrap()) // .get(entity.unwrap())
.unwrap(); // .unwrap();
dynamic_uniform_indices.push(*index); // dynamic_uniform_indices.push(*index);
} }
} }
} }

View File

@ -677,9 +677,8 @@ impl Renderer for WgpuRenderer {
&mut self.wgpu_resources.render_resources &mut self.wgpu_resources.render_resources
} }
fn setup_entity_bind_groups( fn setup_bind_groups(
&mut self, &mut self,
entity: Entity,
render_resource_assignments: &RenderResourceAssignments, render_resource_assignments: &RenderResourceAssignments,
pipeline_descriptor: &PipelineDescriptor, 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.bind_groups.get(&bind_group_id) {
if let None = self if let None = self
.wgpu_resources .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 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);
} }
} }
} }

View File

@ -1,9 +1,8 @@
use crate::{ use crate::{
legion::prelude::*,
render::{ render::{
pipeline::{BindGroup, BindType}, pipeline::{BindGroup, BindType},
render_resource::{ render_resource::{
BufferUsage, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, BufferUsage, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, RenderResourceAssignmentsId,
}, },
shader::DynamicUniformBufferInfo, shader::DynamicUniformBufferInfo,
texture::{SamplerDescriptor, TextureDescriptor}, texture::{SamplerDescriptor, TextureDescriptor},
@ -23,7 +22,7 @@ pub struct WgpuResources {
pub resource_info: HashMap<RenderResource, ResourceInfo>, pub resource_info: HashMap<RenderResource, ResourceInfo>,
pub bind_groups: HashMap<u64, BindGroupInfo>, pub bind_groups: HashMap<u64, BindGroupInfo>,
pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>, pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>,
pub entity_bind_groups: HashMap<(Entity, u64), BindGroupInfo>, pub assignment_bind_groups: HashMap<(RenderResourceAssignmentsId, u64), BindGroupInfo>,
pub dynamic_uniform_buffer_info: HashMap<RenderResource, DynamicUniformBufferInfo>, pub dynamic_uniform_buffer_info: HashMap<RenderResource, DynamicUniformBufferInfo>,
} }
@ -37,7 +36,7 @@ impl WgpuResources {
bind_groups: HashMap::new(), bind_groups: HashMap::new(),
bind_group_layouts: HashMap::new(), bind_group_layouts: HashMap::new(),
dynamic_uniform_buffer_info: HashMap::new(), dynamic_uniform_buffer_info: HashMap::new(),
entity_bind_groups: HashMap::new(), assignment_bind_groups: HashMap::new(),
render_resources: RenderResources::default(), render_resources: RenderResources::default(),
} }
} }
@ -109,19 +108,18 @@ impl WgpuResources {
.insert(bind_group_id, BindGroupInfo { bind_group }); .insert(bind_group_id, BindGroupInfo { bind_group });
} }
} }
pub fn get_entity_bind_group( pub fn get_assignments_bind_group(
&self, &self,
entity: Entity, render_resource_assignment_id: RenderResourceAssignmentsId,
bind_group_id: u64, bind_group_id: u64,
) -> Option<&BindGroupInfo> { ) -> 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, &mut self,
device: &wgpu::Device, device: &wgpu::Device,
bind_group: &BindGroup, bind_group: &BindGroup,
entity: Entity,
render_resource_assignments: &RenderResourceAssignments, render_resource_assignments: &RenderResourceAssignments,
) { ) {
// TODO: don't make this per-entity. bind groups should be re-used across the same resource when possible // 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 { } else {
panic!( panic!(
"No resource assigned to uniform \"{}\" for entity {}", "No resource assigned to uniform \"{}\" for RenderResourceAssignments {:?}",
binding.name, entity binding.name, render_resource_assignments.get_id()
); );
} }
}) })
@ -181,8 +179,8 @@ impl WgpuResources {
let bind_group = device.create_bind_group(&bind_group_descriptor); 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 // TODO: storing a large number entity bind groups might actually be really bad. make sure this is ok
self.entity_bind_groups self.assignment_bind_groups
.insert((entity, bind_group_id), BindGroupInfo { bind_group }); .insert((render_resource_assignments.get_id(), bind_group_id), BindGroupInfo { bind_group });
} }
pub fn create_buffer( pub fn create_buffer(