make DrawTarget setup world read only. add render_resource_sets_system

This commit is contained in:
Carter Anderson 2020-04-12 11:45:44 -07:00
parent 1d44b4034f
commit a8f5402ff1
13 changed files with 101 additions and 33 deletions

View file

@ -163,6 +163,10 @@ impl<T> AssetStorage<T> {
pub fn get_mut(&mut self, handle: &Handle<T>) -> Option<&mut T> {
self.assets.get_mut(&handle.id)
}
pub fn iter(&self) -> impl Iterator<Item=(Handle<T>, &T)> {
self.assets.iter().map(|(k,v)| (Handle::new(*k), v))
}
}
impl<T> GetBytes for Handle<T> {

View file

@ -16,7 +16,7 @@ pub trait DrawTarget {
);
fn setup(
&mut self,
_world: &mut World,
_world: &World,
_resources: &Resources,
_renderer: &mut dyn Renderer,
_pipeline_handle: Handle<PipelineDescriptor>,

View file

@ -62,7 +62,7 @@ impl DrawTarget for AssignedBatchesDrawTarget {
fn setup(
&mut self,
world: &mut World,
world: &World,
resources: &Resources,
renderer: &mut dyn Renderer,
pipeline_handle: Handle<PipelineDescriptor>,
@ -89,8 +89,8 @@ impl DrawTarget for AssignedBatchesDrawTarget {
log::trace!("{:#?}", batch);
renderer.setup_bind_groups(&mut batch.render_resource_assignments, pipeline_descriptor);
for batched_entity in batch.entities.iter() {
let mut renderable = world
.get_component_mut::<Renderable>(*batched_entity)
let renderable = world
.get_component::<Renderable>(*batched_entity)
.unwrap();
if !renderable.is_visible || renderable.is_instanced {
continue;
@ -102,7 +102,7 @@ impl DrawTarget for AssignedBatchesDrawTarget {
batch.render_resource_assignments.id
);
renderer.setup_bind_groups(
&mut renderable.render_resource_assignments,
&renderable.render_resource_assignments,
pipeline_descriptor,
);
}

View file

@ -4,7 +4,7 @@ use legion::prelude::*;
use crate::{
draw_target::DrawTarget,
mesh::Mesh,
pipeline::{PipelineDescriptor, ShaderPipelineAssignments},
pipeline::{PipelineDescriptor, PipelineAssignments},
render_resource::{
resource_name, EntityRenderResourceAssignments, RenderResourceAssignments, ResourceInfo,
},
@ -23,7 +23,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
render_pass: &mut dyn RenderPass,
pipeline_handle: Handle<PipelineDescriptor>,
) {
let shader_pipeline_assignments = resources.get::<ShaderPipelineAssignments>().unwrap();
let shader_pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
let entity_render_resource_assignments =
resources.get::<EntityRenderResourceAssignments>().unwrap();
let mut current_mesh_handle = None;
@ -78,16 +78,16 @@ impl DrawTarget for AssignedMeshesDrawTarget {
fn setup(
&mut self,
world: &mut World,
world: &World,
resources: &Resources,
renderer: &mut dyn Renderer,
pipeline_handle: Handle<PipelineDescriptor>,
pipeline_descriptor: &PipelineDescriptor,
) {
let shader_pipeline_assignments = resources.get::<ShaderPipelineAssignments>().unwrap();
let pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
let entity_render_resource_assignments =
resources.get::<EntityRenderResourceAssignments>().unwrap();
let assigned_render_resource_assignments = shader_pipeline_assignments
let assigned_render_resource_assignments = pipeline_assignments
.assignments
.get(&pipeline_handle);
let mut global_render_resource_assignments =
@ -98,13 +98,13 @@ impl DrawTarget for AssignedMeshesDrawTarget {
let entity = entity_render_resource_assignments
.get(*assignment_id)
.unwrap();
let mut renderable = world.get_component_mut::<Renderable>(*entity).unwrap();
let renderable = world.get_component::<Renderable>(*entity).unwrap();
if !renderable.is_visible || renderable.is_instanced {
continue;
}
renderer.setup_bind_groups(
&mut renderable.render_resource_assignments,
&renderable.render_resource_assignments,
pipeline_descriptor,
);
}

View file

@ -65,7 +65,7 @@ impl DrawTarget for UiDrawTarget {
fn setup(
&mut self,
_world: &mut World,
_world: &World,
resources: &Resources,
renderer: &mut dyn Renderer,
_pipeline_handle: Handle<PipelineDescriptor>,

View file

@ -36,7 +36,7 @@ use self::{
pass::passes::ForwardPassBuilder,
pipeline::{
pipelines::ForwardPipelineBuilder, PipelineCompiler, PipelineDescriptor,
ShaderPipelineAssignments, VertexBufferDescriptors,
PipelineAssignments, VertexBufferDescriptors,
},
render_graph::RenderGraph,
render_resource::{
@ -107,7 +107,7 @@ impl AppPlugin for RenderPlugin {
.add_resource(AssetStorage::<Shader>::new())
.add_resource(AssetStorage::<StandardMaterial>::new())
.add_resource(AssetStorage::<PipelineDescriptor>::new())
.add_resource(ShaderPipelineAssignments::new())
.add_resource(PipelineAssignments::new())
.add_resource(VertexBufferDescriptors::default())
.add_resource(PipelineCompiler::new())
.add_resource(RenderResourceAssignments::default())

View file

@ -151,7 +151,7 @@ impl PipelineCompiler {
fn update_shader_assignments(
&mut self,
vertex_buffer_descriptors: &VertexBufferDescriptors,
shader_pipeline_assignments: &mut ShaderPipelineAssignments,
shader_pipeline_assignments: &mut PipelineAssignments,
renderer: &dyn Renderer,
pipeline_storage: &mut AssetStorage<PipelineDescriptor>,
shader_storage: &mut AssetStorage<Shader>,
@ -222,13 +222,13 @@ impl PipelineCompiler {
}
}
pub struct ShaderPipelineAssignments {
pub struct PipelineAssignments {
pub assignments: HashMap<Handle<PipelineDescriptor>, Vec<RenderResourceAssignmentsId>>,
}
impl ShaderPipelineAssignments {
impl PipelineAssignments {
pub fn new() -> Self {
ShaderPipelineAssignments {
PipelineAssignments {
assignments: HashMap::new(),
}
}
@ -244,7 +244,7 @@ pub fn update_shader_assignments(
// lots of string + hashset allocations. sees uniform_resource_provider for more context
{
let mut shader_pipeline_assignments =
resources.get_mut::<ShaderPipelineAssignments>().unwrap();
resources.get_mut::<PipelineAssignments>().unwrap();
let mut pipeline_compiler = resources.get_mut::<PipelineCompiler>().unwrap();
let mut shader_storage = resources.get_mut::<AssetStorage<Shader>>().unwrap();
let vertex_buffer_descriptors = resources.get::<VertexBufferDescriptors>().unwrap();

View file

@ -15,7 +15,6 @@ use std::collections::{HashMap, HashSet};
#[derive(Default)]
pub struct RenderGraph {
pub pipeline_descriptors: HashSet<Handle<PipelineDescriptor>>,
// TODO: make this ordered
pub pass_descriptors: HashMap<String, PassDescriptor>,
pub pass_pipelines: HashMap<String, Vec<Handle<PipelineDescriptor>>>,
pub resource_providers: Vec<Box<dyn ResourceProvider + Send + Sync>>,

View file

@ -68,7 +68,7 @@ impl RenderResourceAssignments {
.insert(name.to_string(), (vertices_resource, indices_resource));
}
pub fn get_or_update_render_resource_set_id(
pub fn update_render_resource_set_id(
&mut self,
bind_group_descriptor: &BindGroupDescriptor,
) -> Option<RenderResourceSetId> {
@ -191,23 +191,23 @@ mod tests {
equal_assignments.set("a", RenderResource(1));
equal_assignments.set("b", RenderResource(2));
let set_id = assignments.get_or_update_render_resource_set_id(&bind_group_descriptor);
let set_id = assignments.update_render_resource_set_id(&bind_group_descriptor);
assert_ne!(set_id, None);
let different_set_id =
different_assignments.get_or_update_render_resource_set_id(&bind_group_descriptor);
different_assignments.update_render_resource_set_id(&bind_group_descriptor);
assert_ne!(different_set_id, None);
assert_ne!(different_set_id, set_id);
let equal_set_id =
equal_assignments.get_or_update_render_resource_set_id(&bind_group_descriptor);
equal_assignments.update_render_resource_set_id(&bind_group_descriptor);
assert_ne!(equal_set_id, None);
assert_eq!(equal_set_id, set_id);
let mut unmatched_assignments = RenderResourceAssignments::default();
unmatched_assignments.set("a", RenderResource(1));
let unmatched_set_id =
unmatched_assignments.get_or_update_render_resource_set_id(&bind_group_descriptor);
unmatched_assignments.update_render_resource_set_id(&bind_group_descriptor);
assert_eq!(unmatched_set_id, None);
}
}

View file

@ -48,7 +48,7 @@ pub trait Renderer {
);
fn setup_bind_groups(
&mut self,
render_resource_assignments: &mut RenderResourceAssignments,
render_resource_assignments: &RenderResourceAssignments,
pipeline_descriptor: &PipelineDescriptor,
);
}

View file

@ -1,7 +1,9 @@
mod wgpu_render_context;
mod wgpu_render_resource_context;
mod wgpu_transactional_render_resource_context;
mod systems;
pub use wgpu_render_context::*;
pub use wgpu_render_resource_context::*;
pub use wgpu_transactional_render_resource_context::*;
pub use systems::*;

View file

@ -0,0 +1,62 @@
use bevy_asset::AssetStorage;
use bevy_render::{
pipeline::{PipelineCompiler, PipelineDescriptor, PipelineAssignments},
render_graph::RenderGraph,
render_resource::{EntityRenderResourceAssignments, RenderResourceAssignments}, Renderable,
};
use legion::prelude::*;
pub fn render_resource_sets_system() -> Box<dyn Schedulable> {
SystemBuilder::new("update_render_resource_sets")
.read_resource::<RenderGraph>()
.read_resource::<AssetStorage<PipelineDescriptor>>()
.read_resource::<PipelineCompiler>()
.read_resource::<PipelineAssignments>()
.read_resource::<EntityRenderResourceAssignments>()
.write_resource::<RenderResourceAssignments>()
.write_component::<Renderable>()
.build(
|_,
world,
(
render_graph,
pipelines,
pipeline_compiler,
pipeline_assignments,
entity_render_resource_assignments,
global_render_resource_assignments,
),
_| {
// PERF: consider doing a par-iter over all renderable components so this can be parallelized
for handle in render_graph.pipeline_descriptors.iter() {
for compiled_pipeline_handle in pipeline_compiler.iter_compiled_pipelines(*handle).unwrap() {
if let Some(compiled_pipeline_assignments) =
pipeline_assignments.assignments.get(compiled_pipeline_handle)
{
let compiled_pipeline = pipelines.get(compiled_pipeline_handle).unwrap();
let pipeline_layout = compiled_pipeline.get_layout().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() {
global_render_resource_assignments.update_render_resource_set_id(bind_group);
}
for assignment_id in compiled_pipeline_assignments.iter() {
let entity = entity_render_resource_assignments
.get(*assignment_id)
.unwrap();
let mut renderable = world.get_component_mut::<Renderable>(*entity).unwrap();
if !renderable.is_visible || renderable.is_instanced {
continue;
}
for bind_group in pipeline_layout.bind_groups.iter() {
renderable.render_resource_assignments.update_render_resource_set_id(bind_group);
// TODO: also setup bind groups here if possible
}
}
}
}
}
},
)
}

View file

@ -3,7 +3,7 @@ use super::{
WgpuRenderPass, WgpuResources,
};
use crate::renderer_2::{
WgpuRenderContext, WgpuRenderResourceContext, WgpuTransactionalRenderResourceContext,
WgpuRenderContext, WgpuRenderResourceContext, WgpuTransactionalRenderResourceContext, render_resource_sets_system,
};
use bevy_app::{EventReader, Events};
use bevy_asset::{AssetStorage, Handle};
@ -467,6 +467,7 @@ impl Renderer for WgpuRenderer {
self.create_queued_textures(resources);
let mut encoder = self.encoder.take().unwrap();
render_resource_sets_system().run(world, resources);
// setup draw targets
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
render_graph.setup_pipeline_draw_targets(world, resources, self);
@ -665,19 +666,19 @@ impl Renderer for WgpuRenderer {
fn setup_bind_groups(
&mut self,
render_resource_assignments: &mut RenderResourceAssignments,
render_resource_assignments: &RenderResourceAssignments,
pipeline_descriptor: &PipelineDescriptor,
) {
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() {
if let Some(render_resource_set_id) =
render_resource_assignments.get_or_update_render_resource_set_id(bind_group)
if let Some((render_resource_set_id, _indices)) =
render_resource_assignments.get_render_resource_set_id(bind_group.id)
{
if let None = self
.global_context
.render_resources
.wgpu_resources
.get_bind_group(bind_group.id, render_resource_set_id)
.get_bind_group(bind_group.id, *render_resource_set_id)
{
self.global_context
.render_resources