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

View file

@ -1,3 +1,5 @@
pub mod nodes;
use crate::{ use crate::{
render_resource::{RenderResource, ResourceInfo}, render_resource::{RenderResource, ResourceInfo},
renderer_2::RenderContext, 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 { pub struct ResourceSlot {
name: Option<String>, name: &'static str,
resource_type: ResourceInfo, resource_type: ResourceInfo,
} }
pub struct ResourceSlotBinding { impl ResourceSlot {
resource: RenderResource, pub const fn new(name: &'static str, resource_type: ResourceInfo) -> Self {
ResourceSlot {
name,
resource_type,
}
} }
pub struct NodeDescriptor {
pub inputs: Vec<ResourceSlot>,
pub outputs: Vec<ResourceSlot>,
} }
pub trait Node: Send + Sync + 'static { pub trait Node: Send + Sync + 'static {
fn descriptor(&self) -> &NodeDescriptor; fn input(&self) -> &[ResourceSlot] {
&[]
}
fn output(&self) -> &[ResourceSlot] {
&[]
}
fn update( fn update(
&mut self, &mut self,
world: &World, world: &World,
resources: &Resources, resources: &Resources,
render_context: &mut dyn RenderContext, 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 { pub trait SystemNode: Node {
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable>; fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable>;
} }
#[derive(Default)] #[derive(Default)]
pub struct RenderGraph2 { pub struct RenderGraph2 {
nodes: HashMap<NodeId, Box<dyn Node>>, nodes: HashMap<NodeId, NodeState>,
new_systems: Vec<Box<dyn Schedulable>>, new_systems: Vec<Box<dyn Schedulable>>,
system_executor: Option<Executor>, system_executor: Option<Executor>,
} }
@ -117,7 +206,7 @@ impl RenderGraph2 {
T: Node + 'static, T: Node + 'static,
{ {
let id = NodeId::new(); let id = NodeId::new();
self.nodes.insert(id, Box::new(node)); self.nodes.insert(id, NodeState::new(node));
id id
} }
@ -127,14 +216,10 @@ impl RenderGraph2 {
{ {
let id = NodeId::new(); let id = NodeId::new();
self.new_systems.push(node.get_system(resources)); self.new_systems.push(node.get_system(resources));
self.nodes.insert(id, Box::new(node)); self.nodes.insert(id, NodeState::new(node));
id 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> { pub fn take_executor(&mut self) -> Option<Executor> {
// rebuild executor if there are new systems // rebuild executor if there are new systems
if self.new_systems.len() > 0 { if self.new_systems.len() > 0 {
@ -157,3 +242,54 @@ impl RenderGraph2 {
self.system_executor = Some(executor); 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::{ use crate::{
render_graph_2::{CommandQueue, Node, NodeDescriptor, SystemNode}, render_graph_2::{CommandQueue, Node, SystemNode, ResourceBindings},
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
renderer_2::{GlobalRenderResourceContext, RenderContext}, renderer_2::{GlobalRenderResourceContext, RenderContext},
ActiveCamera, Camera, ActiveCamera, Camera,
@ -10,8 +8,8 @@ use crate::{
use bevy_app::{Events, GetEventReader}; use bevy_app::{Events, GetEventReader};
use bevy_transform::prelude::*; use bevy_transform::prelude::*;
use legion::prelude::*; use legion::prelude::*;
use once_cell::sync::Lazy;
use zerocopy::AsBytes; use zerocopy::AsBytes;
use bevy_window::WindowResized;
#[derive(Default)] #[derive(Default)]
pub struct CameraNode { pub struct CameraNode {
@ -19,19 +17,13 @@ pub struct CameraNode {
} }
impl Node for 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( fn update(
&mut self, &mut self,
_world: &World, _world: &World,
_resources: &Resources, _resources: &Resources,
render_context: &mut dyn RenderContext, render_context: &mut dyn RenderContext,
_input: &ResourceBindings,
_output: &mut ResourceBindings,
) { ) {
self.command_queue.execute(render_context); self.command_queue.execute(render_context);
} }

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::{ use crate::{
render_resource::{RenderResourceAssignments, ResourceProvider}, render_graph_2::{Node, ResourceBindings, ResourceSlot},
render_resource::{RenderResourceAssignments, ResourceInfo, ResourceProvider},
renderer_2::RenderContext, renderer_2::RenderContext,
texture::TextureDescriptor, texture::TextureDescriptor,
}; };
use bevy_window::Windows; use bevy_app::{EventReader, Events};
use bevy_window::{WindowResized, Windows};
use legion::prelude::*; 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 struct FrameTextureResourceProvider {
pub name: String, pub name: String,
pub descriptor: TextureDescriptor, pub descriptor: TextureDescriptor,

View file

@ -1,12 +1,8 @@
mod camera2d_resource_provider;
mod camera_resource_provider;
mod frame_texture_resource_provider; mod frame_texture_resource_provider;
mod light_resource_provider; mod light_resource_provider;
mod mesh_resource_provider; mod mesh_resource_provider;
mod uniform_resource_provider; mod uniform_resource_provider;
pub use camera2d_resource_provider::*;
pub use camera_resource_provider::*;
pub use frame_texture_resource_provider::*; pub use frame_texture_resource_provider::*;
pub use light_resource_provider::*; pub use light_resource_provider::*;
pub use mesh_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::prelude::*;
use legion_transform::{local_to_world_system, prelude::*}; // use bevy_transform::{local_to_world_system, prelude::*};
use test::Bencher; // use test::Bencher;
#[bench] // #[bench]
fn local_to_world_update_without_change(b: &mut Bencher) { // fn local_to_world_update_without_change(b: &mut Bencher) {
let _ = env_logger::builder().is_test(true).try_init(); // let _ = env_logger::builder().is_test(true).try_init();
let mut world = Universe::new().create_world(); // let mut world = Universe::new().create_world();
let system = local_to_world_system::build(&mut world); // let system = local_to_world_system::build(&mut world);
let ltw = LocalToWorld::identity(); // let ltw = LocalToWorld::identity();
let t = Translation::new(1.0, 2.0, 3.0); // let t = Translation::new(1.0, 2.0, 3.0);
let r = Rotation::from_euler_angles(1.0, 2.0, 3.0); // let r = Rotation::from_euler_angles(1.0, 2.0, 3.0);
let s = Scale(2.0); // let s = Scale(2.0);
let nus = NonUniformScale::new(1.0, 2.0, 3.0); // let nus = NonUniformScale::new(1.0, 2.0, 3.0);
// Add N of every combination of transform types. // // Add N of every combination of transform types.
let n = 1000; // let n = 1000;
let _translation = *world.insert((), vec![(ltw, t); n]).first().unwrap(); // let _translation = *world.insert((), vec![(ltw, t); n]).first().unwrap();
let _rotation = *world.insert((), vec![(ltw, r); n]).first().unwrap(); // let _rotation = *world.insert((), vec![(ltw, r); n]).first().unwrap();
let _scale = *world.insert((), vec![(ltw, s); 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 _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_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_scale = *world.insert((), vec![(ltw, t, s); n]).first().unwrap();
let _translation_and_nus = *world.insert((), vec![(ltw, t, nus); 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_scale = *world.insert((), vec![(ltw, r, s); n]).first().unwrap();
let _rotation_nus = *world.insert((), vec![(ltw, r, nus); 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_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(); // 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 // // Run the system once outside the test (which should compute everything and it shouldn't be
// touched again). // // touched again).
system.run(&mut world); // system.run(&mut world);
system.command_buffer_mut().write(&mut world); // system.command_buffer_mut().write(&mut world);
// Then time the already-computed updates. // // Then time the already-computed updates.
b.iter(|| { // b.iter(|| {
system.run(&mut world); // system.run(&mut world);
system.command_buffer_mut().write(&mut world); // system.command_buffer_mut().write(&mut world);
}); // });
} // }

View file

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