From 7e4c2a613b782caf92d4664d5dae8d5e51474f61 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Wed, 10 Mar 2021 22:41:33 +0100 Subject: [PATCH] Finish splitting camera bindings --- .../src/render_graph/nodes/camera_node.rs | 131 ++++++++++-------- .../src/render_graph/nodes/pass_node.rs | 9 +- 2 files changed, 77 insertions(+), 63 deletions(-) diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index 9a4061ec2ab14..19ca6fb936978 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -6,13 +6,14 @@ use crate::{ RenderResourceBindings, RenderResourceContext, }, }; -use bevy_core::{AsBytes, Bytes}; +use bevy_core::{AsBytes, Byteable, Bytes}; use bevy_ecs::{ system::{BoxedSystem, IntoSystem, Local, Query, Res, ResMut}, world::World, }; use bevy_transform::prelude::*; +use bevy_utils::HashMap; use std::borrow::Cow; #[derive(Debug)] @@ -51,9 +52,9 @@ impl SystemNode for CameraNode { config.0 = Some(CameraNodeState { camera_name: self.camera_name.clone(), command_queue: self.command_queue.clone(), - camera_buffer: None, - staging_buffer: None, - }) + buffers: HashMap::default(), + // staging_buffer: None, + }); }); Box::new(system) } @@ -63,8 +64,8 @@ impl SystemNode for CameraNode { pub struct CameraNodeState { command_queue: CommandQueue, camera_name: Cow<'static, str>, - camera_buffer: Option, - staging_buffer: Option, + buffers: HashMap, + // staging_buffer: Option, } pub fn camera_node_system( @@ -76,73 +77,85 @@ pub fn camera_node_system( mut render_resource_bindings: ResMut, query: Query<(&Camera, &GlobalTransform)>, ) { - let render_resource_context = &**render_resource_context; + let camera_name = state.camera_name.clone(); - let (camera, global_transform) = if let Some(entity) = active_cameras.get(&state.camera_name) { + let (camera, global_transform) = if let Some(entity) = active_cameras.get(&camera_name) { query.get(entity).unwrap() } else { return; }; let view_matrix = global_transform.compute_matrix().inverse(); - let camera_matrix = [ - (camera.projection_matrix * view_matrix).to_cols_array(), + let view_proj_matrix = camera.projection_matrix * view_matrix; + + make_binding( + &mut *state, + &**render_resource_context, + &mut *render_resource_bindings, + &format!("{}ViewProj", camera_name), + view_proj_matrix.to_cols_array(), + ); + + make_binding( + &mut *state, + &**render_resource_context, + &mut *render_resource_bindings, + &format!("{}View", camera_name), view_matrix.to_cols_array(), - ]; - let buffer_size = camera_matrix.byte_len(); + ); +} - let staging_buffer = if let Some(staging_buffer) = state.staging_buffer { - render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write); - staging_buffer - } else { - let buffer = render_resource_context.create_buffer(BufferInfo { - size: buffer_size, - buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, - ..Default::default() - }); - render_resource_bindings.set( - &format!("{}ViewProj", &state.camera_name), - RenderResourceBinding::Buffer { - buffer, - range: 0..view_matrix.byte_len() as u64, - dynamic_index: None, - }, - ); - render_resource_bindings.set( - &format!("{}View", &state.camera_name), - RenderResourceBinding::Buffer { - buffer, - range: view_matrix.byte_len() as u64..buffer_size as u64, - dynamic_index: None, - }, - ); - state.camera_buffer = Some(buffer); - - let staging_buffer = render_resource_context.create_buffer(BufferInfo { - size: buffer_size, - buffer_usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE, - mapped_at_creation: true, - }); +fn make_binding( + state: &mut CameraNodeState, + render_resource_context: &dyn RenderResourceContext, + render_resource_bindings: &mut RenderResourceBindings, + binding_name: &str, + bytes: B, +) where + B: Bytes + Byteable, +{ + let buffer_size = bytes.byte_len(); - state.staging_buffer = Some(staging_buffer); - staging_buffer - }; + let buffers_entry = state.buffers.entry(binding_name.to_owned()); + + let (staging_buffer, buffer) = buffers_entry + .and_modify(|(staging_buffer, _)| { + render_resource_context.map_buffer(*staging_buffer, BufferMapMode::Write); + }) + .or_insert_with(|| { + let buffer = render_resource_context.create_buffer(BufferInfo { + size: buffer_size, + buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, + ..Default::default() + }); + + render_resource_bindings.set( + &binding_name, + RenderResourceBinding::Buffer { + buffer, + range: 0..buffer_size as u64, + dynamic_index: None, + }, + ); + + let staging_buffer = render_resource_context.create_buffer(BufferInfo { + size: buffer_size, + buffer_usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE, + mapped_at_creation: true, + }); + (staging_buffer, buffer) + }); render_resource_context.write_mapped_buffer( - staging_buffer, + *staging_buffer, 0..buffer_size as u64, &mut |data, _renderer| { - data[0..buffer_size].copy_from_slice(camera_matrix.as_bytes()); + data[0..buffer_size].copy_from_slice(bytes.as_bytes()); }, ); - render_resource_context.unmap_buffer(staging_buffer); - - let camera_buffer = state.camera_buffer.unwrap(); - state.command_queue.copy_buffer_to_buffer( - staging_buffer, - 0, - camera_buffer, - 0, - buffer_size as u64, - ); + render_resource_context.unmap_buffer(*staging_buffer); + + state + .command_queue + .copy_buffer_to_buffer(*staging_buffer, 0, *buffer, 0, buffer_size as u64); } diff --git a/crates/bevy_render/src/render_graph/nodes/pass_node.rs b/crates/bevy_render/src/render_graph/nodes/pass_node.rs index b308b0c8e2a01..b5cf71cb6ce71 100644 --- a/crates/bevy_render/src/render_graph/nodes/pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/pass_node.rs @@ -208,7 +208,7 @@ where TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap()); } - for camera_info in self.cameras.iter_mut() { + 'outer: for camera_info in self.cameras.iter_mut() { let camera_name = &camera_info.name; if render_context @@ -217,22 +217,23 @@ where { let mut camera_bind_group_builder = BindGroup::build(); - for binding_name in self + for (index, binding_name) in self .camera_bind_group_descriptor .bindings .iter() .map(|binding| &binding.name) + .enumerate() { let camera_binding = if let Some(camera_binding) = render_resource_bindings.get( &format!("{}{}", &camera_name, binding_name.replace("Camera", "")), ) { camera_binding.clone() } else { - continue; + continue 'outer; }; camera_bind_group_builder = - camera_bind_group_builder.add_binding(0, camera_binding); + camera_bind_group_builder.add_binding(index as u32, camera_binding); } let camera_bind_group = camera_bind_group_builder.finish();