render graph 2: schedulers + window nodes

This commit is contained in:
Carter Anderson 2020-04-21 10:30:01 -07:00
parent 210a50e781
commit 5fec31b63c
12 changed files with 473 additions and 175 deletions

View file

@ -41,7 +41,7 @@ use self::{
render_resource::{
entity_render_resource_assignments_system,
resource_providers::{
Camera2dResourceProvider, CameraResourceProvider, LightResourceProvider,
LightResourceProvider,
UniformResourceProvider,
},
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
@ -50,12 +50,11 @@ use self::{
texture::Texture,
};
use bevy_app::{stage, AppBuilder, AppPlugin, GetEventReader};
use bevy_app::{stage, AppBuilder, AppPlugin};
use bevy_asset::AssetStorage;
use bevy_transform::prelude::LocalToWorld;
use bevy_window::WindowResized;
use render_resource::resource_providers::{CameraNode, mesh_resource_provider_system};
use render_graph_2::RenderGraph2;
use render_resource::resource_providers::{mesh_resource_provider_system};
use render_graph_2::{nodes::{Camera2dNode, CameraNode}, RenderGraph2};
pub static RENDER_RESOURCE_STAGE: &str = "render_resource";
pub static RENDER_STAGE: &str = "render";
@ -78,9 +77,6 @@ impl RenderPlugin {
.add_draw_target(AssignedBatchesDrawTarget::default())
.add_draw_target(AssignedMeshesDrawTarget::default())
.add_draw_target(UiDrawTarget::default())
.add_resource_provider(Camera2dResourceProvider::new(
resources.get_event_reader::<WindowResized>(),
))
.add_resource_provider(LightResourceProvider::new(10))
.add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true))
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true))
@ -93,6 +89,7 @@ impl AppPlugin for RenderPlugin {
fn build(&self, app: &mut AppBuilder) {
let mut render_graph = RenderGraph2::default();
render_graph.add_system_node(CameraNode::default(), app.resources_mut());
render_graph.add_system_node(Camera2dNode::default(), app.resources_mut());
let mut asset_batchers = AssetBatchers::default();
asset_batchers.batch_types2::<Mesh, StandardMaterial>();
app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE)

View file

@ -1,3 +1,5 @@
pub mod nodes;
use crate::{
render_resource::{RenderResource, ResourceInfo},
renderer_2::RenderContext,
@ -76,37 +78,124 @@ impl NodeId {
}
}
pub struct ResourceBinding {
pub resource: Option<RenderResource>,
pub slot: ResourceSlot,
}
#[derive(Default)]
pub struct ResourceBindings {
bindings: Vec<ResourceBinding>,
}
impl ResourceBindings {
pub fn set(&mut self, index: usize, resource: RenderResource) {
self.bindings[index].resource = Some(resource);
}
pub fn set_named(&mut self, name: &str, resource: RenderResource) {
let binding = self
.bindings
.iter_mut()
.find(|b| b.slot.name == name)
.expect("Name not found");
binding.resource = Some(resource);
}
pub fn get(&self, index: usize) -> Option<RenderResource> {
self.bindings
.get(index)
.and_then(|binding| binding.resource)
}
pub fn get_named(&self, name: &str) -> Option<RenderResource> {
self.bindings
.iter()
.find(|b| b.slot.name == name)
.and_then(|binding| binding.resource)
}
}
impl From<&ResourceSlot> for ResourceBinding {
fn from(slot: &ResourceSlot) -> Self {
ResourceBinding {
resource: None,
slot: slot.clone(),
}
}
}
impl From<&[ResourceSlot]> for ResourceBindings {
fn from(slots: &[ResourceSlot]) -> Self {
ResourceBindings {
bindings: slots
.iter()
.map(|s| s.into())
.collect::<Vec<ResourceBinding>>(),
}
}
}
#[derive(Clone)]
pub struct ResourceSlot {
name: Option<String>,
name: &'static str,
resource_type: ResourceInfo,
}
pub struct ResourceSlotBinding {
resource: RenderResource,
}
pub struct NodeDescriptor {
pub inputs: Vec<ResourceSlot>,
pub outputs: Vec<ResourceSlot>,
impl ResourceSlot {
pub const fn new(name: &'static str, resource_type: ResourceInfo) -> Self {
ResourceSlot {
name,
resource_type,
}
}
}
pub trait Node: Send + Sync + 'static {
fn descriptor(&self) -> &NodeDescriptor;
fn input(&self) -> &[ResourceSlot] {
&[]
}
fn output(&self) -> &[ResourceSlot] {
&[]
}
fn update(
&mut self,
world: &World,
resources: &Resources,
render_context: &mut dyn RenderContext,
input: &ResourceBindings,
output: &mut ResourceBindings,
);
}
pub struct NodeState {
pub node: Box<dyn Node>,
pub input: ResourceBindings,
pub output: ResourceBindings,
}
impl NodeState {
pub fn new<T>(node: T) -> Self
where
T: Node,
{
NodeState {
input: ResourceBindings::from(node.input()),
output: ResourceBindings::from(node.output()),
node: Box::new(node),
}
}
}
pub trait SystemNode: Node {
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable>;
}
#[derive(Default)]
pub struct RenderGraph2 {
nodes: HashMap<NodeId, Box<dyn Node>>,
nodes: HashMap<NodeId, NodeState>,
new_systems: Vec<Box<dyn Schedulable>>,
system_executor: Option<Executor>,
}
@ -117,7 +206,7 @@ impl RenderGraph2 {
T: Node + 'static,
{
let id = NodeId::new();
self.nodes.insert(id, Box::new(node));
self.nodes.insert(id, NodeState::new(node));
id
}
@ -127,14 +216,10 @@ impl RenderGraph2 {
{
let id = NodeId::new();
self.new_systems.push(node.get_system(resources));
self.nodes.insert(id, Box::new(node));
self.nodes.insert(id, NodeState::new(node));
id
}
pub fn get_schedule(&mut self) -> impl Iterator<Item = &mut Box<dyn Node>> {
self.nodes.values_mut()
}
pub fn take_executor(&mut self) -> Option<Executor> {
// rebuild executor if there are new systems
if self.new_systems.len() > 0 {
@ -157,3 +242,54 @@ impl RenderGraph2 {
self.system_executor = Some(executor);
}
}
#[derive(Default)]
pub struct Stage<'a> {
ordered_jobs: Vec<OrderedJob<'a>>,
}
impl<'a> Stage<'a> {
pub fn add(&mut self, job: OrderedJob<'a>) {
self.ordered_jobs.push(job);
}
pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut OrderedJob<'a>> {
self.ordered_jobs.iter_mut()
}
}
#[derive(Default)]
pub struct OrderedJob<'a> {
node_states: Vec<&'a mut NodeState>,
}
impl<'a> OrderedJob<'a> {
pub fn add(&mut self, node_state: &'a mut NodeState) {
self.node_states.push(node_state);
}
pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut &'a mut NodeState> {
self.node_states.iter_mut()
}
}
pub trait RenderGraphScheduler {
fn get_stages<'a>(&mut self, render_graph: &'a mut RenderGraph2) -> Vec<Stage<'a>>;
}
#[derive(Default)]
pub struct LinearScheduler;
impl RenderGraphScheduler for LinearScheduler {
fn get_stages<'a>(&mut self, render_graph: &'a mut RenderGraph2) -> Vec<Stage<'a>> {
let mut stage = Stage::default();
let mut job = OrderedJob::default();
for node_state in render_graph.nodes.values_mut() {
job.add(node_state);
}
stage.ordered_jobs.push(job);
vec![stage]
}
}

View file

@ -0,0 +1,100 @@
use bevy_app::{Events, GetEventReader};
use bevy_window::WindowResized;
use crate::{
camera::{ActiveCamera2d, Camera},
render_graph_2::{CommandQueue, Node, SystemNode, ResourceBindings},
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
renderer_2::{GlobalRenderResourceContext, RenderContext},
};
use bevy_transform::components::LocalToWorld;
use legion::prelude::*;
use zerocopy::AsBytes;
#[derive(Default)]
pub struct Camera2dNode {
command_queue: CommandQueue,
}
impl Node for Camera2dNode {
fn update(
&mut self,
_world: &World,
_resources: &Resources,
render_context: &mut dyn RenderContext,
_input: &ResourceBindings,
_output: &mut ResourceBindings,
) {
self.command_queue.execute(render_context);
}
}
impl SystemNode for Camera2dNode {
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> {
let mut camera_buffer = None;
let mut tmp_buffer = None;
let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>();
let mut command_queue = self.command_queue.clone();
SystemBuilder::new("camera_resource_provider")
.read_resource::<GlobalRenderResourceContext>()
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
.write_resource::<RenderResourceAssignments>()
.read_resource::<Events<WindowResized>>()
.with_query(<(Read<Camera>, Read<LocalToWorld>, Read<ActiveCamera2d>)>::query())
.build(
move |_,
world,
(
render_resource_context,
ref mut render_resource_assignments,
window_resized_events,
),
query| {
let render_resources = &render_resource_context.context;
if camera_buffer.is_none() {
let buffer = render_resources.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>(),
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer);
camera_buffer = Some(buffer);
}
let primary_window_resized_event = window_resized_events
.find_latest(&mut window_resized_event_reader, |event| event.is_primary);
if let Some(_) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (camera, local_to_world, _) in query.iter(world) {
let camera_matrix: [[f32; 4]; 4] =
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
if let Some(old_tmp_buffer) = tmp_buffer {
render_resources.remove_buffer(old_tmp_buffer);
}
tmp_buffer = Some(render_resources.create_buffer_mapped(
BufferInfo {
size: matrix_size,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data, _renderer| {
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
},
));
command_queue.copy_buffer_to_buffer(
tmp_buffer.unwrap(),
0,
camera_buffer.unwrap(),
0,
matrix_size as u64,
);
}
}
},
)
}
}

View file

@ -1,7 +1,5 @@
use bevy_window::WindowResized;
use crate::{
render_graph_2::{CommandQueue, Node, NodeDescriptor, SystemNode},
render_graph_2::{CommandQueue, Node, SystemNode, ResourceBindings},
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
renderer_2::{GlobalRenderResourceContext, RenderContext},
ActiveCamera, Camera,
@ -10,8 +8,8 @@ use crate::{
use bevy_app::{Events, GetEventReader};
use bevy_transform::prelude::*;
use legion::prelude::*;
use once_cell::sync::Lazy;
use zerocopy::AsBytes;
use bevy_window::WindowResized;
#[derive(Default)]
pub struct CameraNode {
@ -19,19 +17,13 @@ pub struct CameraNode {
}
impl Node for CameraNode {
fn descriptor(&self) -> &NodeDescriptor {
static DESCRIPTOR: Lazy<NodeDescriptor> = Lazy::new(|| NodeDescriptor {
inputs: Vec::new(),
outputs: Vec::new(),
});
&DESCRIPTOR
}
fn update(
&mut self,
_world: &World,
_resources: &Resources,
render_context: &mut dyn RenderContext,
_input: &ResourceBindings,
_output: &mut ResourceBindings,
) {
self.command_queue.execute(render_context);
}
@ -104,4 +96,4 @@ impl SystemNode for CameraNode {
},
)
}
}
}

View file

@ -0,0 +1,9 @@
mod camera_node;
mod camera2d_node;
mod window_texture_node;
mod window_swapchain_node;
pub use camera_node::*;
pub use camera2d_node::*;
pub use window_texture_node::*;
pub use window_swapchain_node::*;

View file

@ -0,0 +1,70 @@
use crate::{
render_graph_2::{Node, ResourceBindings, ResourceSlot},
render_resource::{RenderResource, ResourceInfo},
renderer_2::RenderContext,
texture::TextureDescriptor,
};
use bevy_app::{EventReader, Events};
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
use legion::prelude::*;
pub struct WindowSwapChainNode {
window_id: WindowId,
use_primary_window: bool,
window_resized_event_reader: EventReader<WindowResized>,
window_created_event_reader: EventReader<WindowCreated>,
swap_chain_resource: Option<RenderResource>,
}
impl Node for WindowSwapChainNode {
fn output(&self) -> &[ResourceSlot] {
static OUTPUT: &[ResourceSlot] = &[ResourceSlot::new(
"swapchain_texture",
ResourceInfo::Texture,
)];
OUTPUT
}
fn update(
&mut self,
_world: &World,
resources: &Resources,
render_context: &mut dyn RenderContext,
_input: &ResourceBindings,
output: &mut ResourceBindings,
) {
const WINDOW_TEXTURE: usize = 0;
let window_created_events = resources.get::<Events<WindowCreated>>().unwrap();
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
let windows = resources.get::<Windows>().unwrap();
let render_resources = render_context.resources_mut();
let window = if self.use_primary_window {
windows.get_primary().expect("No primary window exists")
} else {
windows
.get(self.window_id)
.expect("Received window resized event for non-existent window")
};
// create window swapchain
if let Some(_) = window_created_events
.find_latest(&mut self.window_created_event_reader, |e| {
e.id == window.id
})
{
render_resources.create_swap_chain(window);
}
// resize window swapchain
if let Some(_) = window_resized_events
.find_latest(&mut self.window_resized_event_reader, |e| {
e.id == window.id
})
{
render_resources.create_swap_chain(window);
}
output.set(WINDOW_TEXTURE, self.swap_chain_resource.unwrap());
}
}

View file

@ -0,0 +1,45 @@
use crate::{
render_graph_2::{Node, ResourceBindings, ResourceSlot},
render_resource::ResourceInfo,
renderer_2::RenderContext,
texture::TextureDescriptor,
};
use bevy_app::{EventReader, Events};
use bevy_window::WindowResized;
use legion::prelude::*;
pub struct WindowTextureNode {
pub descriptor: TextureDescriptor,
window_resized_event_reader: EventReader<WindowResized>,
}
impl Node for WindowTextureNode {
fn output(&self) -> &[ResourceSlot] {
static OUTPUT: &[ResourceSlot] =
&[ResourceSlot::new("window_texture", ResourceInfo::Texture)];
OUTPUT
}
fn update(
&mut self,
_world: &World,
resources: &Resources,
render_context: &mut dyn RenderContext,
_input: &ResourceBindings,
output: &mut ResourceBindings,
) {
const WINDOW_TEXTURE: usize = 0;
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
if let Some(event) = window_resized_events.latest(&mut self.window_resized_event_reader) {
let render_resources = render_context.resources_mut();
if let Some(old_texture) = output.get(WINDOW_TEXTURE) {
render_resources.remove_texture(old_texture);
}
self.descriptor.size.width = event.width;
self.descriptor.size.height = event.height;
let texture_resource = render_resources.create_texture(&self.descriptor);
output.set(WINDOW_TEXTURE, texture_resource);
}
}
}

View file

@ -1,91 +0,0 @@
use bevy_app::{EventReader, Events};
use bevy_window::WindowResized;
use crate::{
camera::{ActiveCamera2d, Camera},
render_resource::{
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
ResourceProvider,
},
renderer_2::RenderContext,
};
use legion::prelude::*;
use zerocopy::AsBytes;
pub struct Camera2dResourceProvider {
pub camera_buffer: Option<RenderResource>,
pub tmp_buffer: Option<RenderResource>,
pub window_resized_event_reader: EventReader<WindowResized>,
}
impl Camera2dResourceProvider {
pub fn new(window_resized_event_reader: EventReader<WindowResized>) -> Self {
Camera2dResourceProvider {
camera_buffer: None,
tmp_buffer: None,
window_resized_event_reader,
}
}
}
impl ResourceProvider for Camera2dResourceProvider {
fn initialize(
&mut self,
render_context: &mut dyn RenderContext,
_world: &mut World,
resources: &Resources,
) {
let buffer = render_context.resources_mut().create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>(),
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer);
self.camera_buffer = Some(buffer);
}
fn update(
&mut self,
render_context: &mut dyn RenderContext,
world: &World,
resources: &Resources,
) {
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
let primary_window_resized_event = window_resized_events
.find_latest(&mut self.window_resized_event_reader, |event| event.is_primary);
if let Some(_) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (camera, _) in <(Read<Camera>, Read<ActiveCamera2d>)>::query().iter(world) {
let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d();
if let Some(old_tmp_buffer) = self.tmp_buffer {
render_context.resources_mut().remove_buffer(old_tmp_buffer);
}
self.tmp_buffer = Some(render_context.resources_mut().create_buffer_mapped(
BufferInfo {
size: matrix_size,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data, _renderer| {
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
},
));
render_context.copy_buffer_to_buffer(
self.tmp_buffer.unwrap(),
0,
self.camera_buffer.unwrap(),
0,
matrix_size as u64,
);
}
}
}
}

View file

@ -1,11 +1,50 @@
use crate::{
render_resource::{RenderResourceAssignments, ResourceProvider},
render_graph_2::{Node, ResourceBindings, ResourceSlot},
render_resource::{RenderResourceAssignments, ResourceInfo, ResourceProvider},
renderer_2::RenderContext,
texture::TextureDescriptor,
};
use bevy_window::Windows;
use bevy_app::{EventReader, Events};
use bevy_window::{WindowResized, Windows};
use legion::prelude::*;
pub struct WindowTextureNode {
pub name: String,
pub descriptor: TextureDescriptor,
pub window_resized_event_reader: EventReader<WindowResized>,
}
impl Node for WindowTextureNode {
fn output(&self) -> &[ResourceSlot] {
static OUTPUT: &[ResourceSlot] =
&[ResourceSlot::new("window_texture", ResourceInfo::Texture)];
OUTPUT
}
fn update(
&mut self,
_world: &World,
resources: &Resources,
render_context: &mut dyn RenderContext,
_input: &ResourceBindings,
output: &mut ResourceBindings,
) {
const WINDOW_TEXTURE: usize = 0;
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
if let Some(event) = window_resized_events.latest(&mut self.window_resized_event_reader) {
let render_resources = render_context.resources_mut();
if let Some(old_texture) = output.get(WINDOW_TEXTURE) {
render_resources.remove_texture(old_texture);
}
self.descriptor.size.width = event.width;
self.descriptor.size.height = event.height;
let texture_resource = render_resources.create_texture(&self.descriptor);
output.set(WINDOW_TEXTURE, texture_resource);
}
}
}
pub struct FrameTextureResourceProvider {
pub name: String,
pub descriptor: TextureDescriptor,

View file

@ -1,12 +1,8 @@
mod camera2d_resource_provider;
mod camera_resource_provider;
mod frame_texture_resource_provider;
mod light_resource_provider;
mod mesh_resource_provider;
mod uniform_resource_provider;
pub use camera2d_resource_provider::*;
pub use camera_resource_provider::*;
pub use frame_texture_resource_provider::*;
pub use light_resource_provider::*;
pub use mesh_resource_provider::*;

View file

@ -1,46 +1,46 @@
#![feature(test)]
// #![feature(test)]
extern crate test;
// extern crate test;
use legion::prelude::*;
use legion_transform::{local_to_world_system, prelude::*};
use test::Bencher;
// use legion::prelude::*;
// use bevy_transform::{local_to_world_system, prelude::*};
// use test::Bencher;
#[bench]
fn local_to_world_update_without_change(b: &mut Bencher) {
let _ = env_logger::builder().is_test(true).try_init();
// #[bench]
// fn local_to_world_update_without_change(b: &mut Bencher) {
// let _ = env_logger::builder().is_test(true).try_init();
let mut world = Universe::new().create_world();
let system = local_to_world_system::build(&mut world);
// let mut world = Universe::new().create_world();
// let system = local_to_world_system::build(&mut world);
let ltw = LocalToWorld::identity();
let t = Translation::new(1.0, 2.0, 3.0);
let r = Rotation::from_euler_angles(1.0, 2.0, 3.0);
let s = Scale(2.0);
let nus = NonUniformScale::new(1.0, 2.0, 3.0);
// let ltw = LocalToWorld::identity();
// let t = Translation::new(1.0, 2.0, 3.0);
// let r = Rotation::from_euler_angles(1.0, 2.0, 3.0);
// let s = Scale(2.0);
// let nus = NonUniformScale::new(1.0, 2.0, 3.0);
// Add N of every combination of transform types.
let n = 1000;
let _translation = *world.insert((), vec![(ltw, t); n]).first().unwrap();
let _rotation = *world.insert((), vec![(ltw, r); n]).first().unwrap();
let _scale = *world.insert((), vec![(ltw, s); n]).first().unwrap();
let _non_uniform_scale = *world.insert((), vec![(ltw, nus); n]).first().unwrap();
let _translation_and_rotation = *world.insert((), vec![(ltw, t, r); n]).first().unwrap();
let _translation_and_scale = *world.insert((), vec![(ltw, t, s); n]).first().unwrap();
let _translation_and_nus = *world.insert((), vec![(ltw, t, nus); n]).first().unwrap();
let _rotation_scale = *world.insert((), vec![(ltw, r, s); n]).first().unwrap();
let _rotation_nus = *world.insert((), vec![(ltw, r, nus); n]).first().unwrap();
let _translation_rotation_scale = *world.insert((), vec![(ltw, t, r, s); n]).first().unwrap();
let _translation_rotation_nus = *world.insert((), vec![(ltw, t, r, nus); n]).first().unwrap();
// // Add N of every combination of transform types.
// let n = 1000;
// let _translation = *world.insert((), vec![(ltw, t); n]).first().unwrap();
// let _rotation = *world.insert((), vec![(ltw, r); n]).first().unwrap();
// let _scale = *world.insert((), vec![(ltw, s); n]).first().unwrap();
// let _non_uniform_scale = *world.insert((), vec![(ltw, nus); n]).first().unwrap();
// let _translation_and_rotation = *world.insert((), vec![(ltw, t, r); n]).first().unwrap();
// let _translation_and_scale = *world.insert((), vec![(ltw, t, s); n]).first().unwrap();
// let _translation_and_nus = *world.insert((), vec![(ltw, t, nus); n]).first().unwrap();
// let _rotation_scale = *world.insert((), vec![(ltw, r, s); n]).first().unwrap();
// let _rotation_nus = *world.insert((), vec![(ltw, r, nus); n]).first().unwrap();
// let _translation_rotation_scale = *world.insert((), vec![(ltw, t, r, s); n]).first().unwrap();
// let _translation_rotation_nus = *world.insert((), vec![(ltw, t, r, nus); n]).first().unwrap();
// Run the system once outside the test (which should compute everything and it shouldn't be
// touched again).
system.run(&mut world);
system.command_buffer_mut().write(&mut world);
// // Run the system once outside the test (which should compute everything and it shouldn't be
// // touched again).
// system.run(&mut world);
// system.command_buffer_mut().write(&mut world);
// Then time the already-computed updates.
b.iter(|| {
system.run(&mut world);
system.command_buffer_mut().write(&mut world);
});
}
// // Then time the already-computed updates.
// b.iter(|| {
// system.run(&mut world);
// system.command_buffer_mut().write(&mut world);
// });
// }

View file

@ -6,7 +6,7 @@ use bevy_asset::AssetStorage;
use bevy_render::{
pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor},
render_graph::RenderGraph,
render_graph_2::RenderGraph2,
render_graph_2::{LinearScheduler, RenderGraph2, RenderGraphScheduler},
render_resource::RenderResourceAssignments,
renderer_2::{GlobalRenderResourceContext, RenderContext, RenderResourceContext},
};
@ -245,10 +245,15 @@ impl WgpuRenderer {
.context
.downcast_mut::<WgpuRenderResourceContext>()
.unwrap();
let mut linear_scheduler = LinearScheduler::default();
let mut render_context =
WgpuRenderContext::new(self.device.clone(), render_resource_context.clone());
for node in render_graph.get_schedule() {
node.update(world, resources, &mut render_context);
for mut stage in linear_scheduler.get_stages(&mut render_graph) {
for job in stage.iter_mut() {
for node_state in job.iter_mut() {
node_state.node.update(world, resources, &mut render_context, &node_state.input, &mut node_state.output);
}
}
}
let command_buffer = render_context.finish();