RenderGraph2: rendering works again!

This commit is contained in:
Carter Anderson 2020-04-23 21:41:13 -07:00
parent b7d2f068ec
commit 209b4b48d9
4 changed files with 63 additions and 81 deletions

View File

@ -255,6 +255,19 @@ impl PipelineCompiler {
None None
} }
} }
pub fn iter_all_compiled_pipelines(
&self,
) -> impl Iterator<Item = &Handle<PipelineDescriptor>> {
self.pipeline_source_to_compiled
.values()
.map(|compiled_pipelines| {
compiled_pipelines
.iter()
.map(|(_, pipeline_handle)| pipeline_handle)
})
.flatten()
}
} }
pub struct PipelineAssignments { pub struct PipelineAssignments {

View File

@ -76,7 +76,6 @@ impl Node for PassNode {
input: &ResourceSlots, input: &ResourceSlots,
_output: &mut ResourceSlots, _output: &mut ResourceSlots,
) { ) {
let render_resource_assignments = resources.get::<RenderResourceAssignments>().unwrap();
let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap(); let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap();
let pipeline_storage = resources.get::<AssetStorage<PipelineDescriptor>>().unwrap(); let pipeline_storage = resources.get::<AssetStorage<PipelineDescriptor>>().unwrap();
@ -103,6 +102,18 @@ impl Node for PassNode {
for compiled_pipeline_handle in compiled_pipelines_iter { for compiled_pipeline_handle in compiled_pipelines_iter {
let compiled_pipeline_descriptor = let compiled_pipeline_descriptor =
pipeline_storage.get(compiled_pipeline_handle).unwrap(); pipeline_storage.get(compiled_pipeline_handle).unwrap();
let pipeline_layout = compiled_pipeline_descriptor.get_layout().unwrap();
{
// TODO: this breaks down in a parallel setting. it needs to change. ideally in a way that
// doesn't require modifying RenderResourceAssignments
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() {
render_resource_assignments.update_render_resource_set_id(bind_group);
}
}
render_context.create_render_pipeline( render_context.create_render_pipeline(
*compiled_pipeline_handle, *compiled_pipeline_handle,
&compiled_pipeline_descriptor, &compiled_pipeline_descriptor,
@ -121,6 +132,7 @@ impl Node for PassNode {
} }
} }
let render_resource_assignments = resources.get::<RenderResourceAssignments>().unwrap();
render_context.begin_pass( render_context.begin_pass(
&self.descriptor, &self.descriptor,
&render_resource_assignments, &render_resource_assignments,

View File

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

@ -1,11 +1,12 @@
use crate::renderer_2::{ use crate::renderer_2::{
render_resource_sets_system, WgpuRenderContext, WgpuRenderResourceContext, WgpuRenderGraphExecutor, render_resource_sets_system, WgpuRenderContext, WgpuRenderGraphExecutor,
WgpuRenderResourceContext,
}; };
use bevy_app::{EventReader, Events}; use bevy_app::{EventReader, Events};
use bevy_render::{ use bevy_render::{
pipeline::{update_shader_assignments}, pipeline::update_shader_assignments,
render_graph::RenderGraph, render_graph::RenderGraph,
render_graph_2::{RenderGraph2, RenderGraphStager, DependentNodeStager}, render_graph_2::{DependentNodeStager, RenderGraph2, RenderGraphStager},
render_resource::RenderResourceAssignments, render_resource::RenderResourceAssignments,
renderer_2::{GlobalRenderResourceContext, RenderResourceContext}, renderer_2::{GlobalRenderResourceContext, RenderResourceContext},
}; };
@ -127,30 +128,19 @@ impl WgpuRenderer {
let chunk_size = (render_graph.resource_providers.len() + thread_count - 1) / thread_count; // divide ints rounding remainder up let chunk_size = (render_graph.resource_providers.len() + thread_count - 1) / thread_count; // divide ints rounding remainder up
// crossbeam_utils::thread::scope(|s| { // crossbeam_utils::thread::scope(|s| {
for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) { for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) {
// TODO: try to unify this Device usage
let device = self.device.clone(); let device = self.device.clone();
// let sender = sender.clone();
// s.spawn(|_| {
// TODO: replace WgpuResources with Global+Local resources
let mut render_context = let mut render_context =
WgpuRenderContext::new(device, render_resource_context.clone()); WgpuRenderContext::new(device, render_resource_context.clone());
for resource_provider in resource_provider_chunk.iter_mut() { for resource_provider in resource_provider_chunk.iter_mut() {
resource_provider.finish_update(&mut render_context, world, resources); resource_provider.finish_update(&mut render_context, world, resources);
} }
results.push(render_context.finish()); results.push(render_context.finish());
// sender.send(render_context.finish()).unwrap();
// });
} }
// });
for command_buffer in results { for command_buffer in results {
// for i in 0..thread_count {
// let (command_buffer, wgpu_resources) = receiver.recv().unwrap();
if let Some(command_buffer) = command_buffer { if let Some(command_buffer) = command_buffer {
command_buffers.push(command_buffer); command_buffers.push(command_buffer);
} }
// println!("got {}", i);
} }
self.queue.submit(&command_buffers); self.queue.submit(&command_buffers);
@ -206,6 +196,8 @@ impl WgpuRenderer {
executor.execute(world, resources); executor.execute(world, resources);
} }
render_resource_sets_system().run(world, resources);
let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap(); let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap();
if let Some(executor) = executor.take() { if let Some(executor) = executor.take() {
render_graph.set_executor(executor); render_graph.set_executor(executor);
@ -220,11 +212,17 @@ impl WgpuRenderer {
let executor = WgpuRenderGraphExecutor { let executor = WgpuRenderGraphExecutor {
max_thread_count: 2, max_thread_count: 2,
}; };
executor.execute(world, resources, self.device.clone(), &mut self.queue, &mut borrowed); executor.execute(
world,
resources,
self.device.clone(),
&mut self.queue,
&mut borrowed,
);
} }
pub fn update(&mut self, world: &mut World, resources: &mut Resources) { pub fn update(&mut self, world: &mut World, resources: &mut Resources) {
let mut encoder = { {
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
let render_resource_context = global_context let render_resource_context = global_context
.context .context
@ -248,36 +246,13 @@ impl WgpuRenderer {
update_shader_assignments(world, resources, &render_context); update_shader_assignments(world, resources, &render_context);
self.create_queued_textures(resources, &mut render_context.render_resources); self.create_queued_textures(resources, &mut render_context.render_resources);
render_context.command_encoder.take()
}; };
self.run_graph(world, resources); self.run_graph(world, resources);
render_resource_sets_system().run(world, resources);
// TODO: add to POST_UPDATE and remove redundant global_context let render_resource_context = resources.get::<GlobalRenderResourceContext>().unwrap();
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); render_resource_context
let render_resource_context = global_context
.context .context
.downcast_mut::<WgpuRenderResourceContext>()
.unwrap();
let mut render_context =
WgpuRenderContext::new(self.device.clone(), render_resource_context.clone());
if let Some(command_encoder) = encoder.take() {
render_context.command_encoder.set(command_encoder);
}
// setup draw targets
// let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
// render_graph.setup_pipeline_draw_targets(world, resources, &mut render_context);
let command_buffer = render_context.finish();
if let Some(command_buffer) = command_buffer {
self.queue.submit(&[command_buffer]);
}
// clear swap chain textures
render_context
.render_resources
.drop_all_swap_chain_textures(); .drop_all_swap_chain_textures();
} }
} }