mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 06:30:19 +00:00
render graph 2: schedulers + window nodes
This commit is contained in:
parent
210a50e781
commit
5fec31b63c
12 changed files with 473 additions and 175 deletions
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
}
|
100
bevy_render/src/render_graph_2/nodes/camera2d_node.rs
Normal file
100
bevy_render/src/render_graph_2/nodes/camera2d_node.rs
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
|
@ -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 {
|
|||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
9
bevy_render/src/render_graph_2/nodes/mod.rs
Normal file
9
bevy_render/src/render_graph_2/nodes/mod.rs
Normal 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::*;
|
|
@ -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());
|
||||
}
|
||||
}
|
45
bevy_render/src/render_graph_2/nodes/window_texture_node.rs
Normal file
45
bevy_render/src/render_graph_2/nodes/window_texture_node.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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);
|
||||
// });
|
||||
// }
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue