diff --git a/Cargo.lock b/Cargo.lock index e42ddf0c..ad567ad4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,7 +128,7 @@ dependencies = [ "serde_bytes", "serde_json", "time", - "uuid", + "uuid 1.5.0", ] [[package]] @@ -145,10 +145,12 @@ dependencies = [ "bitflags 2.4.1", "colored", "component_derive", + "downcast-rs", "dual_quaternion", "futures", "gltf", "intel_tex_2", + "intertrait", "json", "libdeflater", "log", @@ -270,6 +272,12 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + [[package]] name = "dual_quaternion" version = "0.2.0" @@ -660,6 +668,29 @@ dependencies = [ "ispc_rt", ] +[[package]] +name = "intertrait" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00fc6ef7d878dfcf59d9e556ef1b368d7f55b9da5813ed481a3573eef485a01" +dependencies = [ + "intertrait-macros", + "linkme", + "once_cell", +] + +[[package]] +name = "intertrait-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d56984da2d4c9d6d7de8463892e65a9354f4238f641c246fe99176150e97bb8" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "uuid 0.8.2", +] + [[package]] name = "is-terminal" version = "0.4.9" @@ -768,6 +799,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "linkme" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd4ad156b9934dc21cad96fd17278a7cb6f30a5657a9d976cd7b71d6d49c02c" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fd9dc7072de7168cbdaba9125e8f742cd3a965aa12bde994b4611a174488d8" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "linux-raw-sys" version = "0.4.10" @@ -1052,7 +1103,7 @@ dependencies = [ "serde-wasm-bindgen", "smallvec", "thiserror", - "uuid", + "uuid 1.5.0", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1633,6 +1684,15 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", +] + [[package]] name = "uuid" version = "1.5.0" diff --git a/Cargo.toml b/Cargo.toml index b9db6bed..9f4b3446 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,9 @@ edition = "2021" license = "MIT" rust-version = "1.73.0" +[features] +multithreading = [] + [dependencies] component_derive = { path = "component_derive" } @@ -31,6 +34,8 @@ log = "0.4.20" simple_logger = "4.2.0" meshopt = "0.1.9" colored = "2.0.4" +downcast-rs = "1.2.0" +intertrait = "0.2.2" [profile.dev] incremental = true diff --git a/src/application.rs b/src/application.rs index bd2f6a77..83454d29 100644 --- a/src/application.rs +++ b/src/application.rs @@ -60,7 +60,7 @@ impl Application for BaseApplication { use log::{info, trace}; use maths_rs::prelude::Base; -use crate::{orchestrator, rendering::render_system, window_system, input_manager, Vector2, rendering::{self}, resource_manager, file_tracker}; +use crate::{orchestrator::{self, EntityHandle}, rendering::render_system, window_system, input_manager, Vector2, rendering::{self}, resource_manager, file_tracker}; /// An orchestrated application is an application that uses the orchestrator to manage systems. /// It is the recommended way to create a simple application. @@ -128,7 +128,7 @@ pub struct GraphicsApplication { mouse_device_handle: input_manager::DeviceHandle, input_system_handle: orchestrator::EntityHandle, renderer_handle: orchestrator::EntityHandle, - render_system_handle: orchestrator::EntityHandle, + render_system_handle: orchestrator::EntityHandle, } impl Application for GraphicsApplication { @@ -139,7 +139,7 @@ impl Application for GraphicsApplication { let orchestrator = application.get_mut_orchestrator(); - orchestrator.spawn_entity(resource_manager::resource_manager::ResourceManager::new_as_system()); + let resource_manager_handle = orchestrator.spawn_entity(resource_manager::resource_manager::ResourceManager::new_as_system()).unwrap(); let window_system_handle = orchestrator.spawn_entity(window_system::WindowSystem::new_as_system()).unwrap(); let input_system_handle = orchestrator.spawn_entity(input_manager::InputManager::new_as_system()).unwrap(); @@ -165,7 +165,7 @@ impl Application for GraphicsApplication { let render_system_handle = rendering::create_render_system(&orchestrator); - let renderer_handle = orchestrator.spawn_entity(rendering::renderer::Renderer::new_as_system()).unwrap(); + let renderer_handle = EntityHandle::spawn(orchestrator, rendering::renderer::Renderer::new_as_system(render_system_handle.clone(), window_system_handle.clone(), resource_manager_handle)).unwrap(); orchestrator.spawn_entity(rendering::render_orchestrator::RenderOrchestrator::new()); @@ -205,7 +205,7 @@ impl Application for GraphicsApplication { true }); - self.application.get_orchestrator().invoke_mut(self.input_system_handle.copy(), input_manager::InputManager::update); + self.application.get_orchestrator().invoke_mut(&self.input_system_handle, input_manager::InputManager::update); // self.application.get_orchestrator().get_2_mut_and(&self.render_system_handle, &self.visibility_render_domain_handle, |render_system, visibility_render_domain| { // // let files = changed_files.iter().filter(|event| { @@ -224,7 +224,7 @@ impl Application for GraphicsApplication { // visibility_render_domain.render(self.get_orchestrator(), render_system, self.tick_count as u32); // }); - self.application.get_orchestrator().invoke_mut(self.renderer_handle.copy(), rendering::renderer::Renderer::render); + self.application.get_orchestrator().invoke_mut(&self.renderer_handle, rendering::renderer::Renderer::render); if !window_res { self.application.close(); @@ -244,8 +244,8 @@ impl GraphicsApplication { pub fn get_orchestrator(&self) -> &orchestrator::Orchestrator { self.application.get_orchestrator() } pub fn get_mut_orchestrator(&mut self) -> &mut orchestrator::Orchestrator { self.application.get_mut_orchestrator() } - pub fn get_input_system_handle(&self) -> orchestrator::EntityHandle { - self.input_system_handle.copy() + pub fn get_input_system_handle_ref(&self) -> &orchestrator::EntityHandle { + &self.input_system_handle } pub fn do_loop(&mut self) { diff --git a/src/camera.rs b/src/camera.rs index 3c254daf..c9d40801 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -35,11 +35,11 @@ impl Camera { fn get_orientation(&self) -> Vec3f { self.direction } fn set_orientation(&mut self, _orchestrator: orchestrator::OrchestratorReference, orientation: Vec3f) { self.direction = orientation; } - pub const fn orientation() -> Property<(), Camera, Vec3f> { Property::Component { getter: Self::get_orientation, setter: Self::set_orientation } } + pub const fn orientation() -> Property { Property { getter: Self::get_orientation, setter: Self::set_orientation } } fn get_position(&self) -> Vec3f { self.position } fn set_position(&mut self, _orchestrator: orchestrator::OrchestratorReference, position: Vec3f) { self.position = position; } - pub const fn position() -> Property<(), Camera, Vec3f> { Property::Component { getter: Self::get_position, setter: Self::set_position } } + pub const fn position() -> Property { Property { getter: Self::get_position, setter: Self::set_position } } } impl Entity for Camera {} diff --git a/src/input_manager.rs b/src/input_manager.rs index 92604c80..459c7174 100644 --- a/src/input_manager.rs +++ b/src/input_manager.rs @@ -588,10 +588,10 @@ impl InputManager { match value { Value::Vector2(v) => { - orchestrator.set_owned_property(orchestrator::InternalId(i as u32), Action::::value, v); + // orchestrator.set_owned_property(orchestrator::InternalId(i as u32), Action::::value, v); } Value::Vector3(v) => { - orchestrator.set_owned_property(orchestrator::InternalId(i as u32), Action::::value, v); + // orchestrator.set_owned_property(orchestrator::InternalId(i as u32), Action::::value, v); } _ => {} } @@ -1309,12 +1309,12 @@ impl InputManager { orchestrator::InternalId(handle.0) } - pub fn get_action_value(&self, action_handle: &EntityHandle>) -> T where Value: Extract { + pub fn get_action_value(&self, action_handle: &EntityHandle>) -> T where Value: Extract { let state = self.get_action_state(ActionHandle(action_handle.get_external_key()), &DeviceHandle(0)); state.value.extract() } - pub fn set_action_value(&mut self, _action_handle: &EntityHandle>, _value: T) { + pub fn set_action_value(&mut self, _action_handle: &EntityHandle>, _value: T) { } } @@ -1329,7 +1329,7 @@ pub struct Action { pub phantom: std::marker::PhantomData, } -impl orchestrator::Entity for Action {} +impl orchestrator::Entity for Action {} pub trait GetType { fn get_type() -> Types; @@ -1347,10 +1347,6 @@ impl GetType for Vector3 { fn get_type() -> Types { Types::Vector3 } } -impl orchestrator::Component for Action { +impl orchestrator::Component for Action { // type Parameters<'a> = ActionParameters<'a>; -} - -impl Action { - pub const fn value() -> Property where T: GetType, Value: Extract { Property::System { getter: InputManager::get_action_value, setter: InputManager::set_action_value } } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 88a134e6..a19e98d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ #![feature(is_sorted)] #![feature(iter_map_windows)] #![feature(pointer_is_aligned)] +#![feature(coerce_unsized, unsize)] // #![warn(missing_docs)] # Disable now because we are writing a lot of code // #![warn(missing_doc_code_examples)] # Disable now because we are writing a lot of code diff --git a/src/orchestrator.rs b/src/orchestrator.rs index 8423256e..508f9442 100644 --- a/src/orchestrator.rs +++ b/src/orchestrator.rs @@ -2,60 +2,109 @@ //! It contains systems and task to accomplish that feat. use std::{collections::HashMap, any::Any}; - +use downcast_rs::{impl_downcast, Downcast}; +use intertrait::*; +use intertrait::cast::*; use log::{trace, warn}; /// System handle is a handle to a system in an [`Orchestrator`] pub struct SystemHandle(u32); -pub trait Entity: Any + Send + 'static { +pub trait Entity: CastFrom + Downcast + Any + 'static { fn to_subclass(&self) -> &dyn Any where Self: Sized { self } } +impl_downcast!(Entity); + /// A system is a collection of components and logic to operate on them. pub trait System: Entity + Any {} -pub struct EntityHandle { +#[cfg(feature="multithreading")] +#[derive(Clone, Debug, Hash, PartialEq)] +pub struct EntityHandle(std::sync::Arc>); + +#[cfg(not(feature="multithreading"))] +#[derive(Debug,)] +pub struct EntityHandle { + container: std::rc::Rc>, internal_id: u32, external_id: u32, - phantom: std::marker::PhantomData, } -impl std::hash::Hash for EntityHandle { - fn hash(&self, state: &mut H) { - self.internal_id.hash(state); - self.external_id.hash(state); +impl EntityHandle { + pub fn new(object: std::rc::Rc>, internal_id: u32, external_id: u32) -> Self { + Self { + container: object, + internal_id: internal_id, + external_id: external_id, + } + } + + pub fn get_external_key(&self) -> u32 { + self.external_id } } -impl PartialEq for EntityHandle { - fn eq(&self, other: &Self) -> bool { - self.internal_id == other.internal_id && self.external_id == other.external_id +fn downcast_inner(decoder: &std::rc::Rc>) -> Option>> { + if (*decoder.read().unwrap()).type_id() == std::any::TypeId::of::() { + let raw: *const std::sync::RwLock = std::rc::Rc::into_raw(decoder.clone()); + let raw: *const std::sync::RwLock = raw.cast(); + + // SAFETY: This is safe because the pointer orignally came from an Arc + // with the same size and alignment since we've checked (via Any) that + // the object within is the type being casted to. + Some(unsafe { std::rc::Rc::from_raw(raw) }) + } else { + None } } -impl Eq for EntityHandle {} +impl EntityHandle { + fn downcast(&self) -> Option> { + let down = downcast_inner::(&self.container); + Some(EntityHandle { + container: down?, + internal_id: self.internal_id, + external_id: self.external_id, + }) + } +} -impl EntityHandle { - pub fn get_external_key(&self) -> u32 { self.external_id } - pub fn copy(&self) -> Self { +impl Clone for EntityHandle { + fn clone(&self) -> Self { Self { + container: self.container.clone(), internal_id: self.internal_id, external_id: self.external_id, - phantom: std::marker::PhantomData, } } - pub fn get_contents(&self) -> (u32, u32) { - (self.internal_id, self.external_id) - } - pub fn from_contents(contents: (u32, u32)) -> Self { - Self { - internal_id: contents.0, - external_id: contents.1, - phantom: std::marker::PhantomData, +} + +use std::marker::Unsize; +use std::ops::CoerceUnsized; +impl CoerceUnsized> for EntityHandle +where + T: Unsize + ?Sized, + U: ?Sized {} + +impl EntityHandle { + pub fn spawn(orchestrator: &Orchestrator, function: F) -> Option> where T: Entity + 'static, F: IntoHandler { + let handle = function.call(orchestrator)?; + + trace!("{}", std::any::type_name::()); + + { + let systems_data = orchestrator.listeners_by_class.lock().unwrap(); + if let Some(listeners) = systems_data.get(std::any::type_name::()) { + for listener in listeners { + (listener.1)(orchestrator, listener.0, handle.clone()); + } + } } + + Some(handle) } } @@ -67,13 +116,8 @@ pub trait Component : Entity { pub trait OwnedComponent : Entity { } -enum UpdateFunctionTypes { - Component(std::boxed::Box), - System(std::boxed::Box), -} - struct Tie { - update_function: UpdateFunctionTypes, + update_function: std::boxed::Box, destination_system_handle: u32, } @@ -81,7 +125,7 @@ struct Tie { pub struct Orchestrator { sep: std::sync::Mutex<(crate::executor::Executor, crate::executor::Spawner)>, systems_data: std::sync::RwLock, - listeners_by_class: std::sync::Mutex)>>>, + listeners_by_class: std::sync::Mutex)>)>>>, tasks: Vec, ties: std::sync::RwLock>>, // parameters: std::sync::RwLock>>, @@ -89,9 +133,12 @@ pub struct Orchestrator { unsafe impl Send for Orchestrator {} -// type EntityStorage = std::sync::Arc>; +#[cfg(feature="multithreading")] type EntityStorage = std::sync::Arc>; +#[cfg(not(feature="multithreading"))] +type EntityStorage = std::rc::Rc>; + struct SystemsData { counter: u32, systems: HashMap, @@ -113,14 +160,15 @@ pub enum PPP { } /// Entity creation functions must return this type. -pub struct EntityReturn<'c, T> { +pub struct EntityReturn<'c, T: Entity> { // entity: T, create: std::boxed::Box T + 'c>, post_creation_functions: Vec>, - listens_to: Vec<(&'static str, Box)>, + // listens_to: Vec<(&'static str, Box)>)>, + listens_to: Vec<(&'static str, Box)>)>, } -impl <'c, T: 'static> EntityReturn<'c, T> { +impl <'c, T: Entity + 'static> EntityReturn<'c, T> { // pub fn new(entity: T) -> Self { // Self { // entity, @@ -162,17 +210,21 @@ impl <'c, T: 'static> EntityReturn<'c, T> { // TODO: Notify listener of the entities that existed before they started to listen. // Maybe add a parameter to choose whether to listen retroactively or not. With a default value of true. - let b = Box::new(move |orchestrator: &Orchestrator, entity_to_notify: u32, ha: (u32, u32)| { + let b = Box::new(move |orchestrator: &Orchestrator, system_to_notify: u32, component_handle: EntityHandle| { let systems_data = orchestrator.systems_data.read().unwrap(); - let mut lock_guard = systems_data.systems[&entity_to_notify].write().unwrap(); + let mut lock_guard = systems_data.systems[&system_to_notify].write().unwrap(); let system: &mut T = lock_guard.downcast_mut().unwrap(); - let orchestrator_reference = OrchestratorReference { orchestrator, internal_id: entity_to_notify }; + let orchestrator_reference = OrchestratorReference { orchestrator, internal_id: system_to_notify }; - let component = systems_data.systems[&ha.0].read().unwrap(); + let component = systems_data.systems[&component_handle.internal_id].read().unwrap(); let component: &C = component.downcast_ref().unwrap(); - T::on_create(system, orchestrator_reference, EntityHandle:: { internal_id: ha.0, external_id: ha.1, phantom: std::marker::PhantomData }, component); + if let Some(x) = component_handle.downcast() { + system.on_create(orchestrator_reference, x, component); + } else { + panic!("Failed to downcast component"); + } }); self.listens_to.push((std::any::type_name::(), b)); @@ -181,15 +233,9 @@ impl <'c, T: 'static> EntityReturn<'c, T> { } } -pub enum Property { - System { - getter: fn(&S, &EntityHandle) -> V, - setter: fn(&mut S, &EntityHandle, V), - }, - Component { - getter: fn(&E) -> V, - setter: fn(&mut E, OrchestratorReference, V), - }, +pub struct Property { + pub getter: fn(&E) -> V, + pub setter: fn(&mut E, OrchestratorReference, V), } impl Orchestrator { @@ -216,7 +262,7 @@ impl Orchestrator { } /// Spawn entity is a function that spawns an entity and returns a handle to it. - pub fn spawn_entity<'c, T, P, F: 'c>(&self, function: F) -> Option> where T: Entity + Send + 'static, F: IntoHandler { + pub fn spawn_entity<'c, T, P, F: 'c>(&self, function: F) -> Option> where T: Entity + 'static, F: IntoHandler { let handle = function.call(self)?; trace!("{}", std::any::type_name::()); @@ -225,7 +271,7 @@ impl Orchestrator { let systems_data = self.listeners_by_class.lock().unwrap(); if let Some(listeners) = systems_data.get(std::any::type_name::()) { for listener in listeners { - (listener.1)(self, listener.0, (handle.internal_id, handle.external_id)); + (listener.1)(self, listener.0, handle.clone()); } } } @@ -244,23 +290,30 @@ impl Orchestrator { // let obj = std::sync::Arc::new(std::sync::RwLock::new(C::new(OrchestratorReference { orchestrator: self, internal_id }, parameters))); - { + let object = { + #[cfg(not(feature="multithreading"))] + let object = std::rc::Rc::new(std::sync::RwLock::new(component)); + let mut systems_data = self.systems_data.write().unwrap(); - systems_data.systems.insert(internal_id, std::sync::Arc::new(std::sync::RwLock::new(component))); + + systems_data.systems.insert(internal_id, object.clone()); + systems_data.systems_by_name.insert(std::any::type_name::(), internal_id); // self.parameters.write().unwrap().insert(internal_id, std::sync::Arc::new(component)); - } + + object + }; let external_id = 0; - let handle = EntityHandle:: { internal_id, external_id, phantom: std::marker::PhantomData }; + let handle = EntityHandle::new(object, internal_id, external_id); { let systems_data = self.listeners_by_class.lock().unwrap(); if let Some(listeners) = systems_data.get(std::any::type_name::()) { for listener in listeners { - (listener.1)(self, listener.0, (handle.internal_id, handle.external_id)); + (listener.1)(self, listener.0, handle.clone()); } } else { warn!("No listeners for {}", std::any::type_name::()); @@ -271,18 +324,15 @@ impl Orchestrator { } /// Ties a property of a component to a property of another component. - pub fn tie(&self, receiver_component_handle: &EntityHandle, i: fn() -> Property, _sender_component_handle: &EntityHandle, j: fn() -> Property) { + pub fn tie(&self, receiver_component_handle: &EntityHandle, i: fn() -> Property, _sender_component_handle: &EntityHandle, j: fn() -> Property) { let property_function_pointer = j as *const (); // Use the property function pointer as a key to the ties hashmap. let property = i(); - let update_function = match property { - Property::Component { getter: _, setter } => UpdateFunctionTypes::Component(std::boxed::Box::new(setter)), - Property::System { getter: _, setter } => UpdateFunctionTypes::System(std::boxed::Box::new(setter)), - }; - let mut ties = self.ties.write().unwrap(); + let update_function = Box::new(property.setter); + if let std::collections::hash_map::Entry::Vacant(e) = ties.entry(property_function_pointer as usize) { let mut ties_new = Vec::new(); ties_new.push(Tie { update_function, destination_system_handle: receiver_component_handle.internal_id }); @@ -296,7 +346,7 @@ impl Orchestrator { } } - pub fn set_property(&self, component_handle: &EntityHandle, function: fn() -> Property, value: V) { + pub fn set_property(&self, component_handle: &EntityHandle, function: fn() -> Property, value: V) { let po = function as *const (); let ties = self.ties.read().unwrap(); @@ -305,18 +355,9 @@ impl Orchestrator { for tie in ties { unsafe { - match tie.update_function { - UpdateFunctionTypes::Component(ref setter) => { - let mut component = systems_data.systems[&tie.destination_system_handle].write().unwrap(); - let setter = setter.downcast_ref_unchecked::(); - (setter)(component.downcast_mut_unchecked::(), OrchestratorReference { orchestrator: self, internal_id: tie.destination_system_handle }, value); - }, - UpdateFunctionTypes::System(ref setter) => { - let mut component = systems_data.systems[&tie.destination_system_handle].write().unwrap(); - let setter = setter.downcast_ref_unchecked::, V)>(); - (setter)(component.downcast_mut_unchecked::(), component_handle, value); - }, - } + let mut component = systems_data.systems[&tie.destination_system_handle].write().unwrap(); + let setter = tie.update_function.downcast_ref_unchecked::(); + (setter)(component.downcast_mut::().unwrap(), OrchestratorReference { orchestrator: self, internal_id: tie.destination_system_handle }, value); } } } @@ -335,19 +376,19 @@ impl Orchestrator { self.tasks.push(Task { function: std::boxed::Box::new(task) }); } - pub fn get_and(&self, component_handle: &EntityHandle, function: F) -> R where F: FnOnce(&C) -> R { + pub fn get_and(&self, component_handle: &EntityHandle, function: F) -> R where F: FnOnce(&C) -> R { let systems_data = self.systems_data.read().unwrap(); let component = systems_data.systems[&component_handle.internal_id].read().unwrap(); function(component.downcast_ref::().unwrap()) } - pub fn get_mut_and(&self, component_handle: &EntityHandle, function: F) -> R where F: FnOnce(&mut C) -> R { + pub fn get_mut_and(&self, component_handle: &EntityHandle, function: F) -> R where F: FnOnce(&mut C) -> R { let systems_data = self.systems_data.read().unwrap(); let mut component = systems_data.systems[&component_handle.internal_id].write().unwrap(); function(component.downcast_mut::().unwrap()) } - pub fn get_2_mut_and(&self, component_handle_0: &EntityHandle, component_handle_1: &EntityHandle, function: F) -> R where F: FnOnce(&mut C0, &mut C1) -> R { + pub fn get_2_mut_and(&self, component_handle_0: &EntityHandle, component_handle_1: &EntityHandle, function: F) -> R where F: FnOnce(&mut C0, &mut C1) -> R { let systems_data = self.systems_data.read().unwrap(); let mut component_0 = systems_data.systems[&component_handle_0.internal_id].write().unwrap(); let mut component_1 = systems_data.systems[&component_handle_1.internal_id].write().unwrap(); @@ -361,53 +402,43 @@ impl Orchestrator { // function(component.downcast_mut::().unwrap()) // } - pub fn get_property(&self, component_handle: &EntityHandle, function: fn() -> Property) -> V { + pub fn get_property(&self, component_handle: &EntityHandle, function: fn() -> Property) -> V { let systems_data = self.systems_data.read().unwrap(); let property = function(); - match property { - Property::Component { getter, setter: _ } => { - let component = systems_data.systems[&component_handle.internal_id].read().unwrap(); - let getter = getter as *const (); - let getter = unsafe { std::mem::transmute::<*const (), fn(&C) -> V>(getter) }; - (getter)(component.downcast_ref::().unwrap()) - }, - Property::System { getter, setter: _ } => { - let component = systems_data.systems[&component_handle.internal_id].read().unwrap(); - let getter = getter as *const (); - let getter = unsafe { std::mem::transmute::<*const (), fn(&S, &EntityHandle) -> V>(getter) }; - (getter)(component.downcast_ref::().unwrap(), component_handle) - }, - } + let component = systems_data.systems[&component_handle.internal_id].read().unwrap(); + let getter = property.getter as *const (); + let getter = unsafe { std::mem::transmute::<*const (), fn(&C) -> V>(getter) }; + (getter)(component.downcast_ref::().unwrap()) } - pub fn set_owned_property(&self, internal_id: u32, component_handle: InternalId, function: fn() -> Property, value: V) { - let systems_data = self.systems_data.read().unwrap(); - - let _property = function(); - - let ties = self.ties.read().unwrap(); + // pub fn set_owned_property(&self, internal_id: u32, component_handle: InternalId, function: fn() -> Property, value: V) { + // let systems_data = self.systems_data.read().unwrap(); - if let Some(ties) = ties.get(&(function as *const () as usize)) { - for tie in ties { - unsafe { - match tie.update_function { - UpdateFunctionTypes::Component(ref setter) => { - let mut component = systems_data.systems[&tie.destination_system_handle].write().unwrap(); - let setter = setter.downcast_ref_unchecked::(); - (setter)(component.downcast_mut_unchecked::(), OrchestratorReference { orchestrator: self, internal_id: tie.destination_system_handle }, value); - }, - UpdateFunctionTypes::System(ref setter) => { - let mut component = systems_data.systems[&tie.destination_system_handle].write().unwrap(); - let setter = setter.downcast_ref_unchecked::, V)>(); - (setter)(component.downcast_mut_unchecked::(), &EntityHandle::{ internal_id, external_id: component_handle.0, phantom: std::marker::PhantomData }, value); - }, - } - } - } - } - } + // let _property = function(); + + // let ties = self.ties.read().unwrap(); + + // if let Some(ties) = ties.get(&(function as *const () as usize)) { + // for tie in ties { + // unsafe { + // match tie.update_function { + // UpdateFunctionTypes::Component(ref setter) => { + // let mut component = systems_data.systems[&tie.destination_system_handle].write().unwrap(); + // let setter = setter.downcast_ref_unchecked::(); + // (setter)(component.downcast_mut_unchecked::(), OrchestratorReference { orchestrator: self, internal_id: tie.destination_system_handle }, value); + // }, + // UpdateFunctionTypes::System(ref setter) => { + // let mut component = systems_data.systems[&tie.destination_system_handle].write().unwrap(); + // let setter = setter.downcast_ref_unchecked::, V)>(); + // (setter)(component.downcast_mut_unchecked::(), &EntityHandle::::new(, internal_id, component_handle.0), value); + // }, + // } + // } + // } + // } + // } pub fn invoke(&self, handle: EntityHandle, function: fn(&E, &Orchestrator)) { let systems_data = self.systems_data.read().unwrap(); @@ -416,37 +447,43 @@ impl Orchestrator { function(component, self); } - pub fn invoke_mut(&self, handle: EntityHandle, function: fn(&mut E, OrchestratorReference)) { + pub fn invoke_mut(&self, handle: &EntityHandle, function: fn(&mut E, OrchestratorReference)) { let systems_data = self.systems_data.read().unwrap(); let mut component = systems_data.systems[&handle.internal_id].write().unwrap(); let component = component.downcast_mut::().unwrap(); function(component, OrchestratorReference { orchestrator: self, internal_id: handle.external_id }); } - pub fn get_by_class(&self) -> EntityReference { + pub fn get_entity(&self, entity_handle: &EntityHandle) -> EntityReference { let systems_data = self.systems_data.read().unwrap(); - EntityReference { lock: systems_data.systems[&systems_data.systems_by_name[std::any::type_name::()]].clone(), phantom: std::marker::PhantomData } - } - - pub fn get_entity(&self, entity_handle: &EntityHandle) -> EntityReference { - let systems_data = self.systems_data.read().unwrap(); - EntityReference { lock: systems_data.systems[&entity_handle.internal_id].clone(), phantom: std::marker::PhantomData } + EntityReference { lock: std::rc::Rc::clone(&entity_handle.container) } } } pub struct EntityReference where T: ?Sized { - lock: std::sync::Arc>, - phantom: std::marker::PhantomData, + lock: std::rc::Rc>, } impl EntityReference { + #[cfg(feature="multithreading")] pub fn get(&self) -> std::sync::RwLockReadGuard { self.lock.read().unwrap() } + #[cfg(not(feature="multithreading"))] + pub fn get(&self) -> std::sync::RwLockReadGuard { + self.lock.read().unwrap() + } + + #[cfg(feature="multithreading")] pub fn get_mut(&self) -> std::sync::RwLockWriteGuard { self.lock.write().unwrap() } + + #[cfg(not(feature="multithreading"))] + pub fn get_mut(&self) -> std::sync::RwLockWriteGuard { + self.lock.write().unwrap() + } } trait Parameter where Self: Sized { @@ -579,7 +616,7 @@ mod tests { } } - orchestrator.spawn_entity(System::new()); + let _: Option> = orchestrator.spawn_entity(System::new()); assert_eq!(unsafe { COUNTER }, 0); @@ -779,15 +816,15 @@ pub struct OrchestratorReference<'a> { } impl <'a> OrchestratorReference<'a> { - pub fn tie<'b, T: 'static, U: 'b, V: 'static, S0: 'static, S1: 'static>(&self, receiver_component_handle: &EntityHandle, i: fn() -> Property, sender_component_handle: &EntityHandle, j: fn() -> Property) { + pub fn tie<'b, T: Entity + 'static, U: Entity + 'b, V: 'static>(&self, receiver_component_handle: &EntityHandle, i: fn() -> Property, sender_component_handle: &EntityHandle, j: fn() -> Property) { self.orchestrator.tie(receiver_component_handle, i, sender_component_handle, j); } - pub fn tie_self(&self, consuming_property: fn() -> Property, sender_component_handle: &EntityHandle, j: fn() -> Property) { - self.orchestrator.tie(&EntityHandle::{ internal_id: self.internal_id, external_id: 0, phantom: std::marker::PhantomData }, consuming_property, sender_component_handle, j); - } + // pub fn tie_self(&self, consuming_property: fn() -> Property, sender_component_handle: &EntityHandle, j: fn() -> Property) { + // self.orchestrator.tie(&EntityHandle::::new(object, internal_id, external_id){ internal_id: self.internal_id, external_id: 0, phantom: std::marker::PhantomData }, consuming_property, sender_component_handle, j); + // } - pub fn spawn_entity<'c, T, P, F: 'c>(&self, function: F) -> Option> where T: Entity + Send + 'static, F: IntoHandler { + pub fn spawn_entity<'c, T, P, F: 'c>(&self, function: F) -> Option> where T: Entity + 'static, F: IntoHandler { self.orchestrator.spawn_entity::<'c, T, P, F>(function) } @@ -795,35 +832,31 @@ impl <'a> OrchestratorReference<'a> { self.orchestrator.spawn::(component) } - pub fn set_property(&self, component_handle: &EntityHandle, property: fn() -> Property, value: V) { - self.orchestrator.set_property::(component_handle, property, value); + pub fn set_property(&self, component_handle: &EntityHandle, property: fn() -> Property, value: V) { + self.orchestrator.set_property::(component_handle, property, value); } - pub fn set_owned_property(&self, internal_id: InternalId, property: fn() -> Property, value: T) { - self.orchestrator.set_owned_property::(self.internal_id, internal_id, property, value); - } + // pub fn set_owned_property(&self, internal_id: InternalId, property: fn() -> Property, value: T) { + // self.orchestrator.set_owned_property::(self.internal_id, internal_id, property, value); + // } - pub fn get_entity(&self, entity_handle: &EntityHandle) -> EntityReference { + pub fn get_entity(&self, entity_handle: &EntityHandle) -> EntityReference { self.orchestrator.get_entity::(entity_handle) } - pub fn get_by_class(&self) -> EntityReference { - self.orchestrator.get_by_class::() - } - - pub fn get_property(&self, component_handle: &EntityHandle, property: fn() -> Property) -> V { - self.orchestrator.get_property::(component_handle, property) + pub fn get_property(&self, component_handle: &EntityHandle, property: fn() -> Property) -> V { + self.orchestrator.get_property::(component_handle, property) } } pub struct InternalId(pub u32); /// Handles extractor pattern for most functions passed to the orchestrator. -pub trait IntoHandler { +pub trait IntoHandler { fn call(self, orchestrator: &Orchestrator,) -> Option>; } -impl IntoHandler<(), R> for EntityReturn<'_, R> { +impl IntoHandler<(), R> for EntityReturn<'_, R> { fn call(self, orchestrator: &Orchestrator,) -> Option> { let internal_id = { let mut systems_data = orchestrator.systems_data.write().unwrap(); @@ -833,8 +866,13 @@ impl IntoHandler<(), R> for EntityReturn<'_, R> { }; let entity = (self.create)(OrchestratorReference { orchestrator, internal_id }); + + #[cfg(feature="multithreading")] let obj = std::sync::Arc::new(std::sync::RwLock::new(entity)); + #[cfg(not(feature="multithreading"))] + let obj = std::rc::Rc::new(std::sync::RwLock::new(entity)); + { let mut systems_data = orchestrator.systems_data.write().unwrap(); systems_data.systems.insert(internal_id, obj.clone()); @@ -850,8 +888,6 @@ impl IntoHandler<(), R> for EntityReturn<'_, R> { } { - // let mut obj = obj.write().unwrap(); - for (type_id, f) in self.listens_to { let mut listeners = orchestrator.listeners_by_class.lock().unwrap(); @@ -861,6 +897,6 @@ impl IntoHandler<(), R> for EntityReturn<'_, R> { } } - Some(EntityHandle:: { internal_id, external_id: 0, phantom: std::marker::PhantomData }) + Some(EntityHandle::::new(obj, internal_id, 0)) } } \ No newline at end of file diff --git a/src/rendering/aces_tonemap_render_pass.rs b/src/rendering/aces_tonemap_render_pass.rs index d726f217..93a6ce70 100644 --- a/src/rendering/aces_tonemap_render_pass.rs +++ b/src/rendering/aces_tonemap_render_pass.rs @@ -41,7 +41,12 @@ impl AcesToneMapPass { }, ]); - let tone_mapping_shader = render_system.create_shader(render_system::ShaderSource::GLSL(TONE_MAPPING_SHADER), render_system::ShaderTypes::Compute,); + let tone_mapping_shader = render_system.create_shader(render_system::ShaderSource::GLSL(TONE_MAPPING_SHADER), render_system::ShaderTypes::Compute, + &[ + render_system::ShaderBindingDescriptor::new(0, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 1, render_system::AccessPolicies::WRITE), + ]); + let tone_mapping_pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&tone_mapping_shader, render_system::ShaderTypes::Compute, vec![])); AcesToneMapPass { @@ -64,20 +69,20 @@ impl AcesToneMapPass { impl tonemap_render_pass::ToneMapRenderPass for AcesToneMapPass { fn render(&self, command_buffer_recording: &mut dyn render_system::CommandBufferRecording,) { - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.source_image_handle), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.result_image_handle), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); + // command_buffer_recording.consume_resources(&[ + // render_system::Consumption{ + // handle: render_system::Handle::Image(self.source_image_handle), + // stages: render_system::Stages::COMPUTE, + // access: render_system::AccessPolicies::READ, + // layout: render_system::Layouts::General, + // }, + // render_system::Consumption{ + // handle: render_system::Handle::Image(self.result_image_handle), + // stages: render_system::Stages::COMPUTE, + // access: render_system::AccessPolicies::WRITE, + // layout: render_system::Layouts::General, + // }, + // ]); command_buffer_recording.bind_compute_pipeline(&self.pipeline); command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout, &[self.descriptor_set]); diff --git a/src/rendering/mesh.rs b/src/rendering/mesh.rs index 206667ae..98ebeb9c 100644 --- a/src/rendering/mesh.rs +++ b/src/rendering/mesh.rs @@ -20,5 +20,5 @@ impl Mesh { fn get_transform(&self) -> maths_rs::Mat4f { self.transform } - pub const fn transform() -> orchestrator::Property<(), Self, maths_rs::Mat4f> { orchestrator::Property::Component { getter: Mesh::get_transform, setter: Mesh::set_transform } } + pub const fn transform() -> orchestrator::Property { orchestrator::Property { getter: Mesh::get_transform, setter: Mesh::set_transform } } } \ No newline at end of file diff --git a/src/rendering/mod.rs b/src/rendering/mod.rs index 039a242a..00da4ecd 100644 --- a/src/rendering/mod.rs +++ b/src/rendering/mod.rs @@ -1,4 +1,4 @@ -use crate::orchestrator; +use crate::orchestrator::{self, EntityHandle}; pub mod render_orchestrator; pub mod shader_generator; @@ -26,6 +26,6 @@ pub mod aces_tonemap_render_pass; pub(crate) mod shader_compilation; -pub fn create_render_system(orchestrator: &orchestrator::Orchestrator) -> orchestrator::EntityHandle { - orchestrator.spawn_entity(vulkan_render_system::VulkanRenderSystem::new_as_system()).unwrap() +pub fn create_render_system(orchestrator: &orchestrator::Orchestrator) -> EntityHandle { + EntityHandle::spawn(orchestrator, vulkan_render_system::VulkanRenderSystem::new_as_system()).unwrap() } \ No newline at end of file diff --git a/src/rendering/render_system.rs b/src/rendering/render_system.rs index e14ecc58..d103afc2 100644 --- a/src/rendering/render_system.rs +++ b/src/rendering/render_system.rs @@ -251,7 +251,7 @@ pub trait CommandBufferRecording { fn draw_indexed(&mut self, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32); - fn consume_resources(&mut self, handles: &[Consumption]); + unsafe fn consume_resources(&mut self, handles: &[Consumption]); fn dispatch_meshes(&mut self, x: u32, y: u32, z: u32); @@ -272,7 +272,7 @@ pub trait CommandBufferRecording { fn end(&mut self); /// Binds a decriptor set on the GPU. - fn bind_descriptor_sets(&self, pipeline_layout: &PipelineLayoutHandle, sets: &[DescriptorSetHandle]); + fn bind_descriptor_sets(&mut self, pipeline_layout: &PipelineLayoutHandle, sets: &[DescriptorSetHandle]); fn copy_to_swapchain(&mut self, source_texture_handle: ImageHandle, present_image_index: u32 ,swapchain_handle: SwapchainHandle); @@ -317,6 +317,23 @@ pub enum UseCases { DYNAMIC } +#[derive(Clone,)] +pub struct ShaderBindingDescriptor { + pub(crate) set: u32, + pub(crate) binding: u32, + pub(crate) access: AccessPolicies, +} + +impl ShaderBindingDescriptor { + pub fn new(set: u32, binding: u32, access: AccessPolicies) -> Self { + Self { + set, + binding, + access, + } + } +} + pub trait RenderSystem: orchestrator::System { /// Returns whether the underlying API has encountered any errors. Used during tests to assert whether the validation layers have caught any errors. fn has_errors(&self) -> bool; @@ -327,7 +344,7 @@ pub trait RenderSystem: orchestrator::System { fn add_mesh_from_vertices_and_indices(&mut self, vertex_count: u32, index_count: u32, vertices: &[u8], indices: &[u8], vertex_layout: &[VertexElement]) -> MeshHandle; /// Creates a shader. - fn create_shader(&mut self, shader_source_type: ShaderSource, stage: ShaderTypes) -> ShaderHandle; + fn create_shader(&mut self, shader_source_type: ShaderSource, stage: ShaderTypes, shader_binding_descriptors: &[ShaderBindingDescriptor],) -> ShaderHandle; fn create_descriptor_set_template(&mut self, name: Option<&str>, binding_templates: &[DescriptorSetBindingTemplate]) -> DescriptorSetTemplateHandle; @@ -335,7 +352,7 @@ pub trait RenderSystem: orchestrator::System { fn create_descriptor_binding(&mut self, descriptor_set: DescriptorSetHandle, binding_template: &DescriptorSetBindingTemplate) -> DescriptorSetBindingHandle; - fn write(&self, descriptor_set_writes: &[DescriptorWrite]); + fn write(&mut self, descriptor_set_writes: &[DescriptorWrite]); fn create_pipeline_layout(&mut self, descriptor_set_template_handles: &[DescriptorSetTemplateHandle], push_constant_ranges: &[PushConstantRange]) -> PipelineLayoutHandle; @@ -459,7 +476,7 @@ pub enum ShaderTypes { Compute, Task, Mesh, - Raygen, + RayGen, ClosestHit, AnyHit, Intersection, @@ -619,8 +636,6 @@ bitflags::bitflags! { const HOST = 0b10000000; /// The shader write stage. const SHADER_WRITE = 0b1000000000; - /// The indirect commands evaluation stage. - const INDIRECT = 0b10000000000; /// The task stage. const TASK = 0b100000000000; /// The ray generation stage. @@ -713,6 +728,8 @@ pub enum Layouts { General, /// The resource will be used as a shader binding table. ShaderBindingTable, + /// Indirect. + Indirect, } #[derive(Clone, Copy)] @@ -933,159 +950,6 @@ pub enum AccelerationStructureTypes { }, } -pub struct RenderSystemImplementation { - pointer: Box, -} - -impl RenderSystemImplementation { - pub fn new(pointer: Box) -> Self { - Self { - pointer, - } - } -} - -impl orchestrator::Entity for RenderSystemImplementation {} -impl orchestrator::System for RenderSystemImplementation {} - -impl RenderSystem for RenderSystemImplementation { - fn has_errors(&self) -> bool { - self.pointer.has_errors() - } - - fn add_mesh_from_vertices_and_indices(&mut self, vertex_count: u32, index_count: u32, vertices: &[u8], indices: &[u8], vertex_layout: &[VertexElement]) -> MeshHandle { - self.pointer.add_mesh_from_vertices_and_indices(vertex_count, index_count, vertices, indices, vertex_layout) - } - - fn create_shader(&mut self, shader_source_type: ShaderSource, stage: ShaderTypes) -> ShaderHandle { - self.pointer.create_shader(shader_source_type, stage) - } - - fn get_buffer_address(&self, buffer_handle: BaseBufferHandle) -> u64 { - self.pointer.get_buffer_address(buffer_handle) - } - - fn write(&self, descriptor_set_writes: &[DescriptorWrite]) { - self.pointer.write(descriptor_set_writes) - } - - fn get_buffer_slice(&mut self, buffer_handle: BaseBufferHandle) -> &[u8] { - self.pointer.get_buffer_slice(buffer_handle) - } - - fn get_mut_buffer_slice(&self, buffer_handle: BaseBufferHandle) -> &mut [u8] { - self.pointer.get_mut_buffer_slice(buffer_handle) - } - - fn get_texture_slice_mut(&self, texture_handle: ImageHandle) -> &mut [u8] { - self.pointer.get_texture_slice_mut(texture_handle) - } - - fn get_image_data(&self, texture_copy_handle: TextureCopyHandle) -> &[u8] { - self.pointer.get_image_data(texture_copy_handle) - } - - fn bind_to_window(&mut self, window_os_handles: &window_system::WindowOsHandles) -> SwapchainHandle { - self.pointer.bind_to_window(window_os_handles) - } - - fn present(&self, image_index: u32, swapchains: &[SwapchainHandle], synchronizer_handle: SynchronizerHandle) { - self.pointer.present(image_index, swapchains, synchronizer_handle) - } - - fn wait(&self, synchronizer_handle: SynchronizerHandle) { - self.pointer.wait(synchronizer_handle) - } - - fn start_frame_capture(&self) { - self.pointer.start_frame_capture() - } - - fn end_frame_capture(&self) { - self.pointer.end_frame_capture() - } - - fn acquire_swapchain_image(&self, swapchain_handle: SwapchainHandle, synchronizer_handle: SynchronizerHandle) -> u32 { - self.pointer.acquire_swapchain_image(swapchain_handle, synchronizer_handle) - } - - fn create_buffer(&mut self, name: Option<&str>, size: usize, uses: Uses, accesses: DeviceAccesses, use_case: UseCases) -> BaseBufferHandle { - self.pointer.create_buffer(name, size, uses, accesses, use_case) - } - - fn create_allocation(&mut self, size: usize, _resource_uses: Uses, resource_device_accesses: DeviceAccesses) -> AllocationHandle { - self.pointer.create_allocation(size, _resource_uses, resource_device_accesses) - } - - fn create_command_buffer(&mut self, name: Option<&str>) -> CommandBufferHandle { - self.pointer.create_command_buffer(name) - } - - fn create_command_buffer_recording<'a>(&'a self, command_buffer_handle: CommandBufferHandle, frame: Option) -> Box { - self.pointer.create_command_buffer_recording(command_buffer_handle, frame) - } - - fn create_descriptor_binding(&mut self, descriptor_set: DescriptorSetHandle, binding: &DescriptorSetBindingTemplate) -> DescriptorSetBindingHandle { - self.pointer.create_descriptor_binding(descriptor_set, binding) - } - - fn create_descriptor_set(&mut self, name: Option<&str>, descriptor_set_layout_handle: &DescriptorSetTemplateHandle) -> DescriptorSetHandle { - self.pointer.create_descriptor_set(name, descriptor_set_layout_handle) - } - - fn create_descriptor_set_template(&mut self, name: Option<&str>, bindings: &[DescriptorSetBindingTemplate]) -> DescriptorSetTemplateHandle { - self.pointer.create_descriptor_set_template(name, bindings) - } - - fn create_raster_pipeline(&mut self, pipeline_blocks: &[PipelineConfigurationBlocks]) -> PipelineHandle { - self.pointer.create_raster_pipeline(pipeline_blocks) - } - - fn create_compute_pipeline(&mut self, pipeline_layout_handle: &PipelineLayoutHandle, shader_parameter: ShaderParameter) -> PipelineHandle { - self.pointer.create_compute_pipeline(pipeline_layout_handle, shader_parameter) - } - - fn create_ray_tracing_pipeline(&mut self, pipeline_layout_handle: &PipelineLayoutHandle, shaders: &[ShaderParameter]) -> PipelineHandle { - self.pointer.create_ray_tracing_pipeline(pipeline_layout_handle, shaders) - } - - fn create_pipeline_layout(&mut self, descriptor_set_layout_handles: &[DescriptorSetTemplateHandle], push_constant_ranges: &[PushConstantRange]) -> PipelineLayoutHandle { - self.pointer.create_pipeline_layout(descriptor_set_layout_handles, push_constant_ranges) - } - - fn create_sampler(&mut self, filtering_mode: FilteringModes, mip_map_mode: FilteringModes, addressing_mode: SamplerAddressingModes, anisotropy: Option, min_lod: f32, max_lod: f32,) -> SamplerHandle { - self.pointer.create_sampler(filtering_mode, mip_map_mode, addressing_mode, anisotropy, min_lod, max_lod) - } - - fn create_acceleration_structure_instance_buffer(&mut self, name: Option<&str>, max_instance_count: u32) -> BaseBufferHandle { - self.pointer.create_acceleration_structure_instance_buffer(name, max_instance_count) - } - - fn create_bottom_level_acceleration_structure(&mut self, description: &BottomLevelAccelerationStructure,) -> BottomLevelAccelerationStructureHandle { - self.pointer.create_bottom_level_acceleration_structure(description,) - } - - fn create_top_level_acceleration_structure(&mut self, name: Option<&str>,) -> TopLevelAccelerationStructureHandle { - self.pointer.create_top_level_acceleration_structure(name,) - } - - fn write_instance(&mut self, instances_buffer_handle: BaseBufferHandle, instance_index: usize, transform: [[f32; 4]; 3], custom_index: u16, mask: u8, sbt_record_offset: usize, acceleration_structure: BottomLevelAccelerationStructureHandle) { - self.pointer.write_instance(instances_buffer_handle, instance_index, transform, custom_index, mask, sbt_record_offset, acceleration_structure) - } - - fn write_sbt_entry(&mut self, sbt_buffer_handle: BaseBufferHandle, sbt_record_offset: usize, pipeline_handle: PipelineHandle, shader_handle: ShaderHandle) { - self.pointer.write_sbt_entry(sbt_buffer_handle, sbt_record_offset, pipeline_handle, shader_handle) - } - - fn create_synchronizer(&mut self, name: Option<&str>, signaled: bool) -> SynchronizerHandle { - self.pointer.create_synchronizer(name, signaled) - } - - fn create_image(&mut self, name: Option<&str>, extent: crate::Extent, format: Formats, compression: Option, resource_uses: Uses, device_accesses: DeviceAccesses, use_case: UseCases) -> ImageHandle { - self.pointer.create_image(name, extent, format, compression, resource_uses, device_accesses, use_case) - } -} - #[cfg(test)] pub(super) mod tests { use super::*; @@ -1162,8 +1026,8 @@ pub(super) mod tests { } "; - let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex); - let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment); + let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex, &[]); + let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment, &[]); let pipeline_layout = renderer.create_pipeline_layout(&[], &[]); @@ -1296,8 +1160,8 @@ pub(super) mod tests { } "; - let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex,); - let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment,); + let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex, &[]); + let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment, &[]); let pipeline_layout = renderer.create_pipeline_layout(&[], &[]); @@ -1421,8 +1285,8 @@ pub(super) mod tests { } "; - let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex,); - let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment,); + let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex, &[]); + let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment, &[]); let pipeline_layout = renderer.create_pipeline_layout(&[], &[]); @@ -1547,8 +1411,8 @@ pub(super) mod tests { } "; - let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex,); - let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment,); + let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex, &[]); + let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment, &[]); let pipeline_layout = renderer.create_pipeline_layout(&[], &[]); @@ -1683,8 +1547,8 @@ pub(super) mod tests { } "; - let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex,); - let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment,); + let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex, &[]); + let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment, &[]); let pipeline_layout = renderer.create_pipeline_layout(&[], &[PushConstantRange{ offset: 0, size: 16 * 4 }]); @@ -1848,8 +1712,8 @@ pub(super) mod tests { } "; - let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex,); - let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment,); + let vertex_shader = renderer.create_shader(ShaderSource::GLSL(vertex_shader_code), ShaderTypes::Vertex, &[ShaderBindingDescriptor::new(0, 1, AccessPolicies::READ)]); + let fragment_shader = renderer.create_shader(ShaderSource::GLSL(fragment_shader_code), ShaderTypes::Fragment, &[ShaderBindingDescriptor::new(0, 0, AccessPolicies::READ), ShaderBindingDescriptor::new(0, 2, AccessPolicies::READ)]); let buffer = renderer.create_buffer(None, 64, Uses::Uniform | Uses::Storage, DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead, UseCases::DYNAMIC); @@ -1917,14 +1781,14 @@ pub(super) mod tests { command_buffer_recording.write_image_data(sampled_texture, &pixels); - command_buffer_recording.consume_resources(&[ - Consumption{ - handle: Handle::Image(sampled_texture), - stages: Stages::FRAGMENT, - access: AccessPolicies::READ, - layout: Layouts::Read, - } - ]); + // command_buffer_recording.consume_resources(&[ + // Consumption{ + // handle: Handle::Image(sampled_texture), + // stages: Stages::FRAGMENT, + // access: AccessPolicies::READ, + // layout: Layouts::Read, + // } + // ]); let attachments = [ AttachmentInformation { @@ -2080,9 +1944,9 @@ void main() { } "; - let raygen_shader = renderer.create_shader(ShaderSource::GLSL(raygen_shader_code), ShaderTypes::Raygen,); - let closest_hit_shader = renderer.create_shader(ShaderSource::GLSL(closest_hit_shader_code), ShaderTypes::ClosestHit,); - let miss_shader = renderer.create_shader(ShaderSource::GLSL(miss_shader_code), ShaderTypes::Miss,); + let raygen_shader = renderer.create_shader(ShaderSource::GLSL(raygen_shader_code), ShaderTypes::RayGen, &[ShaderBindingDescriptor::new(0, 0, AccessPolicies::READ), ShaderBindingDescriptor::new(0, 1, AccessPolicies::WRITE)]); + let closest_hit_shader = renderer.create_shader(ShaderSource::GLSL(closest_hit_shader_code), ShaderTypes::ClosestHit, &[ShaderBindingDescriptor::new(0, 2, AccessPolicies::READ), ShaderBindingDescriptor::new(0, 3, AccessPolicies::READ), ShaderBindingDescriptor::new(0, 4, AccessPolicies::READ)]); + let miss_shader = renderer.create_shader(ShaderSource::GLSL(miss_shader_code), ShaderTypes::Miss, &[]); let top_level_acceleration_structure = renderer.create_top_level_acceleration_structure(Some("Top Level")); let bottom_level_acceleration_structure = renderer.create_bottom_level_acceleration_structure(&BottomLevelAccelerationStructure{ @@ -2126,7 +1990,7 @@ void main() { let pipeline = renderer.create_ray_tracing_pipeline( &pipeline_layout, - &[(&raygen_shader, ShaderTypes::Raygen, vec![]), (&closest_hit_shader, ShaderTypes::ClosestHit, vec![]), (&miss_shader, ShaderTypes::Miss, vec![])], + &[(&raygen_shader, ShaderTypes::RayGen, vec![]), (&closest_hit_shader, ShaderTypes::ClosestHit, vec![]), (&miss_shader, ShaderTypes::Miss, vec![])], ); let building_command_buffer_handle = renderer.create_command_buffer(None); @@ -2208,14 +2072,14 @@ void main() { scratch_buffer: BufferDescriptor { buffer: scratch_buffer, offset: 0, range: 1024 * 512, slot: 0 }, }]); - command_buffer_recording.consume_resources(&[ + unsafe { command_buffer_recording.consume_resources(&[ Consumption { handle: Handle::BottomLevelAccelerationStructure(bottom_level_acceleration_structure), stages: Stages::ACCELERATION_STRUCTURE_BUILD, access: AccessPolicies::READ, layout: Layouts::General, } - ]); + ]) }; command_buffer_recording.build_top_level_acceleration_structure(&TopLevelAccelerationStructureBuild { acceleration_structure: top_level_acceleration_structure, @@ -2233,44 +2097,44 @@ void main() { command_buffer_recording.bind_descriptor_sets(&pipeline_layout, &[descriptor_set]); - command_buffer_recording.consume_resources(&[ - Consumption { - handle: Handle::Image(render_target), - stages: Stages::RAYGEN, - access: AccessPolicies::WRITE, - layout: Layouts::General, - }, - Consumption { - handle: Handle::TopLevelAccelerationStructure(top_level_acceleration_structure), - stages: Stages::RAYGEN, - access: AccessPolicies::READ, - layout: Layouts::General, - }, - Consumption { - handle: Handle::BottomLevelAccelerationStructure(bottom_level_acceleration_structure), - stages: Stages::RAYGEN, - access: AccessPolicies::READ, - layout: Layouts::General, - }, - Consumption { - handle: Handle::Buffer(raygen_sbt_buffer), - stages: Stages::RAYGEN, - access: AccessPolicies::READ, - layout: Layouts::General, - }, - Consumption { - handle: Handle::Buffer(miss_sbt_buffer), - stages: Stages::RAYGEN, - access: AccessPolicies::READ, - layout: Layouts::General, - }, - Consumption { - handle: Handle::Buffer(hit_sbt_buffer), - stages: Stages::RAYGEN, - access: AccessPolicies::READ, - layout: Layouts::General, - }, - ]); + // unsafe { command_buffer_recording.consume_resources(&[ + // Consumption { + // handle: Handle::Image(render_target), + // stages: Stages::RAYGEN, + // access: AccessPolicies::WRITE, + // layout: Layouts::General, + // }, + // Consumption { + // handle: Handle::TopLevelAccelerationStructure(top_level_acceleration_structure), + // stages: Stages::RAYGEN, + // access: AccessPolicies::READ, + // layout: Layouts::General, + // }, + // Consumption { + // handle: Handle::BottomLevelAccelerationStructure(bottom_level_acceleration_structure), + // stages: Stages::RAYGEN, + // access: AccessPolicies::READ, + // layout: Layouts::General, + // }, + // Consumption { + // handle: Handle::Buffer(raygen_sbt_buffer), + // stages: Stages::RAYGEN, + // access: AccessPolicies::READ, + // layout: Layouts::General, + // }, + // Consumption { + // handle: Handle::Buffer(miss_sbt_buffer), + // stages: Stages::RAYGEN, + // access: AccessPolicies::READ, + // layout: Layouts::General, + // }, + // Consumption { + // handle: Handle::Buffer(hit_sbt_buffer), + // stages: Stages::RAYGEN, + // access: AccessPolicies::READ, + // layout: Layouts::General, + // }, + // ]) }; command_buffer_recording.trace_rays(BindingTables { raygen: BufferStridedRange { buffer: raygen_sbt_buffer, offset: 0, stride: 64, size: 64 }, diff --git a/src/rendering/renderer.rs b/src/rendering/renderer.rs index 5cfd38d4..78193dfd 100644 --- a/src/rendering/renderer.rs +++ b/src/rendering/renderer.rs @@ -1,4 +1,6 @@ -use crate::{orchestrator, window_system, Extent}; +use std::ops::{DerefMut, Deref}; + +use crate::{orchestrator::{self, EntityHandle}, window_system::{self, WindowSystem}, Extent, resource_manager::resource_manager::ResourceManager}; use super::{visibility_model::render_domain::VisibilityWorldRenderDomain, render_system::{self, RenderSystem}, aces_tonemap_render_pass::AcesToneMapPass, tonemap_render_pass::ToneMapRenderPass, world_render_domain::WorldRenderDomain}; @@ -13,26 +15,32 @@ pub struct Renderer { result: render_system::ImageHandle, + render_system: EntityHandle, + window_system: EntityHandle, + visibility_render_model: orchestrator::EntityHandle, tonemap_render_model: orchestrator::EntityHandle, } impl Renderer { - pub fn new_as_system() -> orchestrator::EntityReturn<'static, Self> { + pub fn new_as_system(render_system_handle: EntityHandle, window_system_handle: EntityHandle, resource_manager_handle: EntityHandle) -> orchestrator::EntityReturn<'static, Self> { orchestrator::EntityReturn::new_from_function(move |orchestrator| { - let render_system = orchestrator.get_by_class::(); - let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); + let result = { + let render_system = orchestrator.get_entity(&render_system_handle); + let mut render_system = render_system.get_mut(); - let result = render_system.create_image(Some("result"), Extent::plane(1920, 1080), render_system::Formats::RGBAu8, None, render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); + render_system.create_image(Some("result"), Extent::plane(1920, 1080), render_system::Formats::RGBAu8, None, render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC) + }; + + let visibility_render_model = orchestrator.spawn_entity(VisibilityWorldRenderDomain::new(render_system_handle.clone(), resource_manager_handle)).unwrap(); - let visibility_render_model = orchestrator.spawn_entity(VisibilityWorldRenderDomain::new(render_system)).unwrap(); + let render_system = orchestrator.get_entity(&render_system_handle); + let mut render_system = render_system.get_mut(); let tonemap_render_model = { let visibility_render_model = orchestrator.get_entity(&visibility_render_model); - let mut visibility_render_model = visibility_render_model.get_mut(); - let visibility_render_model = visibility_render_model.downcast_mut::().unwrap(); - orchestrator.spawn_entity(AcesToneMapPass::new_as_system(render_system, visibility_render_model.get_result_image(), result)).unwrap() + let visibility_render_model = visibility_render_model.get(); + orchestrator.spawn_entity(AcesToneMapPass::new_as_system(render_system.deref_mut(), visibility_render_model.get_result_image(), result)).unwrap() }; let render_command_buffer = render_system.create_command_buffer(Some("Render")); @@ -50,6 +58,9 @@ impl Renderer { result, + render_system: render_system_handle, + window_system: window_system_handle, + visibility_render_model, tonemap_render_model, } @@ -59,11 +70,10 @@ impl Renderer { pub fn render(&mut self, orchestrator: orchestrator::OrchestratorReference) { if self.swapchain_handles.is_empty() { return; } - let swapchain_handle = self.swapchain_handles[0]; - - let render_system = orchestrator.get_by_class::(); + let render_system = orchestrator.get_entity(&self.render_system); let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); + + let swapchain_handle = self.swapchain_handles[0]; render_system.wait(self.render_finished_synchronizer); @@ -75,13 +85,11 @@ impl Renderer { let visibility_render_model = orchestrator.get_entity(&self.visibility_render_model); let mut visibility_render_model = visibility_render_model.get_mut(); - let visibility_render_model = visibility_render_model.downcast_mut::().unwrap(); - visibility_render_model.render(&orchestrator, render_system, command_buffer_recording.as_mut()); + visibility_render_model.render(&orchestrator, render_system.deref(), command_buffer_recording.as_mut()); let tonemap_render_model = orchestrator.get_entity(&self.tonemap_render_model); let mut tonemap_render_model = tonemap_render_model.get_mut(); - let tonemap_render_model = tonemap_render_model.downcast_mut::().unwrap(); tonemap_render_model.render(command_buffer_recording.as_mut()); @@ -101,13 +109,11 @@ impl Renderer { impl orchestrator::EntitySubscriber for Renderer { fn on_create(&mut self, orchestrator: orchestrator::OrchestratorReference, handle: orchestrator::EntityHandle, window: &window_system::Window) { - let render_system = orchestrator.get_by_class::(); + let render_system = orchestrator.get_entity(&self.render_system); let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); - let window_system = orchestrator.get_by_class::(); + let window_system = orchestrator.get_entity(&self.window_system); let mut window_system = window_system.get_mut(); - let window_system = window_system.downcast_mut::().unwrap(); let swapchain_handle = render_system.bind_to_window(&window_system.get_os_handles(&handle)); diff --git a/src/rendering/shadow_render_pass.rs b/src/rendering/shadow_render_pass.rs index 94d75112..33653b3a 100644 --- a/src/rendering/shadow_render_pass.rs +++ b/src/rendering/shadow_render_pass.rs @@ -1,359 +1,359 @@ -use crate::Extent; +// use crate::Extent; -use super::{render_system, world_render_domain::WorldRenderDomain}; +// use super::{render_system, world_render_domain::WorldRenderDomain}; -struct ShadowRenderingPass { - pipeline: render_system::PipelineHandle, - pipeline_layout: render_system::PipelineLayoutHandle, - descriptor_set: render_system::DescriptorSetHandle, - shadow_map: render_system::ImageHandle, -} +// struct ShadowRenderingPass { +// pipeline: render_system::PipelineHandle, +// pipeline_layout: render_system::PipelineLayoutHandle, +// descriptor_set: render_system::DescriptorSetHandle, +// shadow_map: render_system::ImageHandle, +// } -impl ShadowRenderingPass { - fn new(render_system: &mut dyn render_system::RenderSystem, render_domain: &impl WorldRenderDomain) -> ShadowRenderingPass { - let shadow_map_binding_template = render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::StorageImage, render_system::Stages::MESH); - let depth_binding_template = render_system::DescriptorSetBindingTemplate::new(1, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::MESH); - - let bindings = [shadow_map_binding_template.clone(), depth_binding_template.clone()]; +// impl ShadowRenderingPass { +// fn new(render_system: &mut dyn render_system::RenderSystem, render_domain: &impl WorldRenderDomain) -> ShadowRenderingPass { +// let shadow_map_binding_template = render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::StorageImage, render_system::Stages::MESH); +// let depth_binding_template = render_system::DescriptorSetBindingTemplate::new(1, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::MESH); + +// let bindings = [shadow_map_binding_template.clone(), depth_binding_template.clone()]; - let descriptor_set_template = render_system.create_descriptor_set_template(Some("Shadow Rendering Set Layout"), &bindings); - - let pipeline_layout = render_system.create_pipeline_layout(&[render_domain.get_descriptor_set_template(), descriptor_set_template], &[]); - - let descriptor_set = render_system.create_descriptor_set(Some("Shadow Rendering Descriptor Set"), &descriptor_set_template); - - let shadow_map_binding = render_system.create_descriptor_binding(descriptor_set, &shadow_map_binding_template); - let depth_binding = render_system.create_descriptor_binding(descriptor_set, &depth_binding_template); - - let colored_shadow: bool = false; - - let shadow_map_resolution = Extent::square(4096); - - let shadow_map = render_system.create_image(Some("Shadow Map"), shadow_map_resolution, render_system::Formats::Depth32, None, render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - - render_system.write(&[ - render_system::DescriptorWrite { - binding_handle: shadow_map_binding, - array_element: 0, - descriptor: render_system::Descriptor::Image{ handle: shadow_map, layout: render_system::Layouts::General }, - }, - ]); - - let ray_gen_shader = render_system.create_shader(render_system::ShaderSource::GLSL(SHADOW_RAY_GEN_SHADER), render_system::ShaderTypes::Raygen); - let hit_shader = render_system.create_shader(render_system::ShaderSource::GLSL(SHADOW_HIT_SHADER), render_system::ShaderTypes::ClosestHit); - let miss_shader = render_system.create_shader(render_system::ShaderSource::GLSL(SHADOW_MISS_SHADER), render_system::ShaderTypes::Miss); - - let pipeline = render_system.create_ray_tracing_pipeline(&pipeline_layout, &[ - (&ray_gen_shader, render_system::ShaderTypes::Raygen, vec![]), - (&hit_shader, render_system::ShaderTypes::ClosestHit, vec![]), - (&miss_shader, render_system::ShaderTypes::Miss, vec![]), - ]); - - ShadowRenderingPass { pipeline, pipeline_layout, descriptor_set, shadow_map } - } - - fn render(&self, command_buffer_recording: &mut dyn render_system::CommandBufferRecording) { - command_buffer_recording.start_region("Shadow Rendering"); - - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.shadow_map), - stages: render_system::Stages::MESH, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); - - command_buffer_recording.bind_raster_pipeline(&self.pipeline); - command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout, &[self.descriptor_set]); - command_buffer_recording.dispatch_meshes(1, 1, 1); - - command_buffer_recording.end_region(); - } -} - -const SHADOW_RAY_GEN_SHADER: &'static str = " -#version 460 core -#pragma shader_stage(raygen) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_buffer_reference: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_shader_16bit_storage: require -#extension GL_EXT_ray_tracing: require - -layout(row_major) uniform; layout(row_major) buffer; - -struct Camera { - mat4 view_matrix; - mat4 projection_matrix; - mat4 view_projection; -}; - -layout(set=0,binding=0,scalar) buffer readonly CameraBuffer { - Camera camera; -}; - -layout(set=1,binding=0) uniform accelerationStructureEXT top_level_acceleration_structure; -layout(set=1,binding=1, r32ui) coherent uniform uimage2D shadow_map; -layout(set=1,binding=2) uniform sampler2D depth; - -layout(location = 0) rayPayloadEXT float hit_distance; - -mat3 matrix_from_direction_vector(vec3 d) { - // TODO: check for colinearity - vec3 u = cross(vec3(0.0, 1.0, 0.0), d); - vec3 v = cross(d, u); - return mat3(u, v, d); -} - -vec3 get_view_position(uvec2 coords) { - float depth_value = texelFetch(depth, ivec2(coords), 0).r; - vec2 uv = (vec2(coords) + vec2(0.5)) / vec2(textureSize(depth, 0).xy); - vec4 clip_space = vec4(uv * 2.0 - 1.0, depth_value, 1.0); - vec4 view_space = inverse(camera.projection_matrix) * clip_space; - view_space /= view_space.w; - return view_space.xyz; -} +// let descriptor_set_template = render_system.create_descriptor_set_template(Some("Shadow Rendering Set Layout"), &bindings); + +// let pipeline_layout = render_system.create_pipeline_layout(&[render_domain.get_descriptor_set_template(), descriptor_set_template], &[]); + +// let descriptor_set = render_system.create_descriptor_set(Some("Shadow Rendering Descriptor Set"), &descriptor_set_template); + +// let shadow_map_binding = render_system.create_descriptor_binding(descriptor_set, &shadow_map_binding_template); +// let depth_binding = render_system.create_descriptor_binding(descriptor_set, &depth_binding_template); + +// let colored_shadow: bool = false; + +// let shadow_map_resolution = Extent::square(4096); + +// let shadow_map = render_system.create_image(Some("Shadow Map"), shadow_map_resolution, render_system::Formats::Depth32, None, render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + +// render_system.write(&[ +// render_system::DescriptorWrite { +// binding_handle: shadow_map_binding, +// array_element: 0, +// descriptor: render_system::Descriptor::Image{ handle: shadow_map, layout: render_system::Layouts::General }, +// }, +// ]); + +// let ray_gen_shader = render_system.create_shader(render_system::ShaderSource::GLSL(SHADOW_RAY_GEN_SHADER), render_system::ShaderTypes::Raygen); +// let hit_shader = render_system.create_shader(render_system::ShaderSource::GLSL(SHADOW_HIT_SHADER), render_system::ShaderTypes::ClosestHit); +// let miss_shader = render_system.create_shader(render_system::ShaderSource::GLSL(SHADOW_MISS_SHADER), render_system::ShaderTypes::Miss); + +// let pipeline = render_system.create_ray_tracing_pipeline(&pipeline_layout, &[ +// (&ray_gen_shader, render_system::ShaderTypes::Raygen, vec![]), +// (&hit_shader, render_system::ShaderTypes::ClosestHit, vec![]), +// (&miss_shader, render_system::ShaderTypes::Miss, vec![]), +// ]); + +// ShadowRenderingPass { pipeline, pipeline_layout, descriptor_set, shadow_map } +// } + +// fn render(&self, command_buffer_recording: &mut dyn render_system::CommandBufferRecording) { +// command_buffer_recording.start_region("Shadow Rendering"); + +// command_buffer_recording.consume_resources(&[ +// render_system::Consumption{ +// handle: render_system::Handle::Image(self.shadow_map), +// stages: render_system::Stages::MESH, +// access: render_system::AccessPolicies::WRITE, +// layout: render_system::Layouts::General, +// }, +// ]); + +// command_buffer_recording.bind_raster_pipeline(&self.pipeline); +// command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout, &[self.descriptor_set]); +// command_buffer_recording.dispatch_meshes(1, 1, 1); + +// command_buffer_recording.end_region(); +// } +// } + +// const SHADOW_RAY_GEN_SHADER: &'static str = " +// #version 460 core +// #pragma shader_stage(raygen) + +// #extension GL_EXT_scalar_block_layout: enable +// #extension GL_EXT_buffer_reference: enable +// #extension GL_EXT_buffer_reference2: enable +// #extension GL_EXT_shader_16bit_storage: require +// #extension GL_EXT_ray_tracing: require + +// layout(row_major) uniform; layout(row_major) buffer; + +// struct Camera { +// mat4 view_matrix; +// mat4 projection_matrix; +// mat4 view_projection; +// }; + +// layout(set=0,binding=0,scalar) buffer readonly CameraBuffer { +// Camera camera; +// }; + +// layout(set=1,binding=0) uniform accelerationStructureEXT top_level_acceleration_structure; +// layout(set=1,binding=1, r32ui) coherent uniform uimage2D shadow_map; +// layout(set=1,binding=2) uniform sampler2D depth; + +// layout(location = 0) rayPayloadEXT float hit_distance; + +// mat3 matrix_from_direction_vector(vec3 d) { +// // TODO: check for colinearity +// vec3 u = cross(vec3(0.0, 1.0, 0.0), d); +// vec3 v = cross(d, u); +// return mat3(u, v, d); +// } + +// vec3 get_view_position(uvec2 coords) { +// float depth_value = texelFetch(depth, ivec2(coords), 0).r; +// vec2 uv = (vec2(coords) + vec2(0.5)) / vec2(textureSize(depth, 0).xy); +// vec4 clip_space = vec4(uv * 2.0 - 1.0, depth_value, 1.0); +// vec4 view_space = inverse(camera.projection_matrix) * clip_space; +// view_space /= view_space.w; +// return view_space.xyz; +// } -vec3 get_view_position(vec2 uv) { - // snap to center of pixel - uv *= textureSize(depth, 0).xy; - uv = floor(uv) + vec2(0.5); - uv /= textureSize(depth, 0).xy; - float depth_value = texture(depth, uv).r; - vec4 clip_space = vec4(uv * 2.0 - 1.0, depth_value, 1.0); - vec4 view_space = inverse(camera.projection_matrix) * clip_space; - view_space /= view_space.w; - return view_space.xyz; -} - -float length_squared(float v) { return v * v; } -float length_squared(vec2 v) { return dot(v, v); } -float length_squared(vec3 v) { return dot(v, v); } - -vec3 min_diff(vec3 p, vec3 a, vec3 b) { - vec3 ap = a - p; - vec3 bp = p - b; - return (length_squared(ap) < length_squared(bp)) ? ap : bp; -} - -void main() { - const vec2 pixel_center = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 uv = pixel_center / vec2(gl_LaunchSizeEXT.xy); - vec2 d = uv * 2.0 - 1.0; - - uvec2 coords = uvec2(gl_LaunchIDEXT.xy); - - vec3 p = get_view_position(coords + uvec2(0, 0)); - vec3 pt = get_view_position(coords + uvec2(0, 1)); - vec3 pl = get_view_position(coords + uvec2(-1, 0)); - vec3 pr = get_view_position(coords + uvec2(1, 0)); - vec3 pb = get_view_position(coords + uvec2(0, -1)); - - vec3 n = normalize(cross(min_diff(p, pr, pl), min_diff(p, pt, pb))); - - vec3 direction = vec3(0, 1, 0); // Overhead light - vec3 position = get_view_position(uv); - - vec2 shadow_d = position.xz / vec2(4.0); // Assuming overhead light, map 8 x 8 area to shadow map - vec2 shadow_uv = shadow_d * 0.5 + 0.5; - ivec2 shadow_texel_coord = ivec2(shadow_uv * imageSize(shadow_map)); - - if (dot(n, direction) <= 0.0) { - imageAtomicMin(shadow_map, shadow_texel_coord, 0); - return; - } - - vec3 origin = position + n * 0.001; // Offset origin slightly to avoid self-intersection - - const float ray_distance = 10.0; // Maximum distance to check for intersection - - uint ray_flags = 0; - uint cull_mask = 0xff; - float t_min = 0.0f; - float t_max = ray_distance; - - traceRayEXT(top_level_acceleration_structure, ray_flags, cull_mask, 0, 0, 0, origin, t_min, direction, t_max, 0); - - imageAtomicMin(shadow_map, shadow_texel_coord, (1 << 32) - 1); -}"; - -const SHADOW_HIT_SHADER: &'static str = " -#version 460 core -#pragma shader_stage(closest) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_buffer_reference: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_shader_16bit_storage: require -#extension GL_EXT_ray_tracing: require - -layout(row_major) uniform; layout(row_major) buffer; - -layout(location = 0) rayPayloadInEXT float hit_distance; - -void main() { - hit_distance = gl_HitTEXT / gl_RayTmaxEXT; -}"; - -const SHADOW_MISS_SHADER: &'static str = " -#version 460 core -#pragma shader_stage(miss) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_buffer_reference: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_shader_16bit_storage: require -#extension GL_EXT_ray_tracing: require - -layout(row_major) uniform; layout(row_major) buffer; - -layout(location = 0) rayPayloadInEXT float hit_distance; - -void main() { - hit_distance = 1.0f; -}"; - -struct ShadowMappingPass { - pipeline_layout: render_system::PipelineLayoutHandle, - pipeline: render_system::PipelineHandle, - descriptor_set_template: render_system::DescriptorSetTemplateHandle, - descriptor_set: render_system::DescriptorSetHandle, - - depth_target: render_system::ImageHandle, - shadow_map: render_system::ImageHandle, - occlusion_map: render_system::ImageHandle, -} - -impl ShadowMappingPass { - fn new(render_system: &mut dyn render_system::RenderSystem, shadow_rendering_pass: &ShadowRenderingPass, occlusion_map: render_system::ImageHandle, parent_descriptor_set_template: render_system::DescriptorSetTemplateHandle, depth_target: render_system::ImageHandle) -> ShadowMappingPass { - let shadow_map_binding_template = render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::COMPUTE); - let depth_binding_template = render_system::DescriptorSetBindingTemplate::new(1, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::COMPUTE); - let result_binding_template = render_system::DescriptorSetBindingTemplate::new(2, render_system::DescriptorType::StorageImage, render_system::Stages::COMPUTE); - - let descriptor_set_template = render_system.create_descriptor_set_template(Some("Shadow Mapping Pass Set Layout"), &[shadow_map_binding_template.clone(), depth_binding_template.clone(), result_binding_template.clone()]); - let pipeline_layout = render_system.create_pipeline_layout(&[parent_descriptor_set_template, descriptor_set_template], &[]); - let descriptor_set = render_system.create_descriptor_set(Some("Shadow Mapping Pass Descriptor Set"), &descriptor_set_template); - - let shader = render_system.create_shader(render_system::ShaderSource::GLSL(BUILD_SHADOW_MAP_SHADER), render_system::ShaderTypes::Compute,); - let pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&shader, render_system::ShaderTypes::Compute, vec![])); - - let shadow_map_binding = render_system.create_descriptor_binding(descriptor_set, &shadow_map_binding_template); - let depth_binding = render_system.create_descriptor_binding(descriptor_set, &depth_binding_template); - let result_binding = render_system.create_descriptor_binding(descriptor_set, &result_binding_template); - - let sampler = render_system.create_sampler(render_system::FilteringModes::Linear, render_system::FilteringModes::Linear, render_system::SamplerAddressingModes::Clamp, None, 0f32, 0f32); - - render_system.write(&[ - render_system::DescriptorWrite { - binding_handle: shadow_map_binding, - array_element: 0, - descriptor: render_system::Descriptor::CombinedImageSampler { image_handle: shadow_rendering_pass.shadow_map, sampler_handle: sampler, layout: render_system::Layouts::Read }, - }, - render_system::DescriptorWrite { - binding_handle: depth_binding, - array_element: 0, - descriptor: render_system::Descriptor::CombinedImageSampler { image_handle: depth_target, sampler_handle: sampler, layout: render_system::Layouts::Read }, - }, - render_system::DescriptorWrite { - binding_handle: result_binding, - array_element: 0, - descriptor: render_system::Descriptor::Image{ handle: occlusion_map, layout: render_system::Layouts::General }, - }, - ]); - - ShadowMappingPass { - pipeline_layout, - pipeline, - descriptor_set_template, - descriptor_set, - - depth_target, - shadow_map: shadow_rendering_pass.shadow_map, - occlusion_map, - } - } - - fn render(&self, command_buffer_recording: &mut dyn render_system::CommandBufferRecording) { - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.shadow_map), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::Read, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.depth_target), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::Read, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.occlusion_map), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); - - command_buffer_recording.bind_compute_pipeline(&self.pipeline); - command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout, &[self.descriptor_set]); - command_buffer_recording.dispatch(render_system::DispatchExtent::new(Extent::plane(1920, 1080), Extent::square(32))); - } -} - -const BUILD_SHADOW_MAP_SHADER: &'static str = " -#version 460 core -#pragma shader_stage(compute) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_buffer_reference: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_shader_16bit_storage: require -#extension GL_EXT_ray_tracing: require - -layout(row_major) uniform; layout(row_major) buffer; - -struct Camera { - mat4 view_matrix; - mat4 projection_matrix; - mat4 view_projection; -}; - -layout(set=0,binding=0,scalar) buffer readonly CameraBuffer { - Camera camera; -}; - -layout(set=1,binding=0) uniform sampler2D shadow_map; -layout(set=1,binding=1) uniform sampler2D depth; -layout(set=1,binding=2, r8) uniform image2D occlusion_map; - -vec3 get_view_position(vec2 uv) { - // snap to center of pixel - uv *= textureSize(depth, 0).xy; - uv = floor(uv) + vec2(0.5); - uv /= textureSize(depth, 0).xy; - float depth_value = texture(depth, uv).r; - vec4 clip_space = vec4(uv * 2.0 - 1.0, depth_value, 1.0); - vec4 view_space = inverse(camera.projection_matrix) * clip_space; - view_space /= view_space.w; - return view_space.xyz; -} - -layout(local_size_x=32, local_size_y=32) in; -void main() { - const vec2 pixel_center = vec2(gl_GlobalInvocationID.xy) + vec2(0.5); - const vec2 uv = pixel_center / vec2(gl_WorkGroupSize.xy * gl_NumWorkGroups.xy); - vec2 d = uv * 2.0 - 1.0; - - vec3 position = get_view_position(uv); - - vec2 shadow_d = position.xz / vec2(4.0); // Assuming overhead light, map 8 x 8 area to shadow map - vec2 shadow_uv = shadow_d * 0.5 + 0.5; - ivec2 shadow_texel_coord = ivec2(shadow_uv * textureSize(shadow_map, 0)); +// vec3 get_view_position(vec2 uv) { +// // snap to center of pixel +// uv *= textureSize(depth, 0).xy; +// uv = floor(uv) + vec2(0.5); +// uv /= textureSize(depth, 0).xy; +// float depth_value = texture(depth, uv).r; +// vec4 clip_space = vec4(uv * 2.0 - 1.0, depth_value, 1.0); +// vec4 view_space = inverse(camera.projection_matrix) * clip_space; +// view_space /= view_space.w; +// return view_space.xyz; +// } + +// float length_squared(float v) { return v * v; } +// float length_squared(vec2 v) { return dot(v, v); } +// float length_squared(vec3 v) { return dot(v, v); } + +// vec3 min_diff(vec3 p, vec3 a, vec3 b) { +// vec3 ap = a - p; +// vec3 bp = p - b; +// return (length_squared(ap) < length_squared(bp)) ? ap : bp; +// } + +// void main() { +// const vec2 pixel_center = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); +// const vec2 uv = pixel_center / vec2(gl_LaunchSizeEXT.xy); +// vec2 d = uv * 2.0 - 1.0; + +// uvec2 coords = uvec2(gl_LaunchIDEXT.xy); + +// vec3 p = get_view_position(coords + uvec2(0, 0)); +// vec3 pt = get_view_position(coords + uvec2(0, 1)); +// vec3 pl = get_view_position(coords + uvec2(-1, 0)); +// vec3 pr = get_view_position(coords + uvec2(1, 0)); +// vec3 pb = get_view_position(coords + uvec2(0, -1)); + +// vec3 n = normalize(cross(min_diff(p, pr, pl), min_diff(p, pt, pb))); + +// vec3 direction = vec3(0, 1, 0); // Overhead light +// vec3 position = get_view_position(uv); + +// vec2 shadow_d = position.xz / vec2(4.0); // Assuming overhead light, map 8 x 8 area to shadow map +// vec2 shadow_uv = shadow_d * 0.5 + 0.5; +// ivec2 shadow_texel_coord = ivec2(shadow_uv * imageSize(shadow_map)); + +// if (dot(n, direction) <= 0.0) { +// imageAtomicMin(shadow_map, shadow_texel_coord, 0); +// return; +// } + +// vec3 origin = position + n * 0.001; // Offset origin slightly to avoid self-intersection + +// const float ray_distance = 10.0; // Maximum distance to check for intersection + +// uint ray_flags = 0; +// uint cull_mask = 0xff; +// float t_min = 0.0f; +// float t_max = ray_distance; + +// traceRayEXT(top_level_acceleration_structure, ray_flags, cull_mask, 0, 0, 0, origin, t_min, direction, t_max, 0); + +// imageAtomicMin(shadow_map, shadow_texel_coord, (1 << 32) - 1); +// }"; + +// const SHADOW_HIT_SHADER: &'static str = " +// #version 460 core +// #pragma shader_stage(closest) + +// #extension GL_EXT_scalar_block_layout: enable +// #extension GL_EXT_buffer_reference: enable +// #extension GL_EXT_buffer_reference2: enable +// #extension GL_EXT_shader_16bit_storage: require +// #extension GL_EXT_ray_tracing: require + +// layout(row_major) uniform; layout(row_major) buffer; + +// layout(location = 0) rayPayloadInEXT float hit_distance; + +// void main() { +// hit_distance = gl_HitTEXT / gl_RayTmaxEXT; +// }"; + +// const SHADOW_MISS_SHADER: &'static str = " +// #version 460 core +// #pragma shader_stage(miss) + +// #extension GL_EXT_scalar_block_layout: enable +// #extension GL_EXT_buffer_reference: enable +// #extension GL_EXT_buffer_reference2: enable +// #extension GL_EXT_shader_16bit_storage: require +// #extension GL_EXT_ray_tracing: require + +// layout(row_major) uniform; layout(row_major) buffer; + +// layout(location = 0) rayPayloadInEXT float hit_distance; + +// void main() { +// hit_distance = 1.0f; +// }"; + +// struct ShadowMappingPass { +// pipeline_layout: render_system::PipelineLayoutHandle, +// pipeline: render_system::PipelineHandle, +// descriptor_set_template: render_system::DescriptorSetTemplateHandle, +// descriptor_set: render_system::DescriptorSetHandle, + +// depth_target: render_system::ImageHandle, +// shadow_map: render_system::ImageHandle, +// occlusion_map: render_system::ImageHandle, +// } + +// impl ShadowMappingPass { +// fn new(render_system: &mut dyn render_system::RenderSystem, shadow_rendering_pass: &ShadowRenderingPass, occlusion_map: render_system::ImageHandle, parent_descriptor_set_template: render_system::DescriptorSetTemplateHandle, depth_target: render_system::ImageHandle) -> ShadowMappingPass { +// let shadow_map_binding_template = render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::COMPUTE); +// let depth_binding_template = render_system::DescriptorSetBindingTemplate::new(1, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::COMPUTE); +// let result_binding_template = render_system::DescriptorSetBindingTemplate::new(2, render_system::DescriptorType::StorageImage, render_system::Stages::COMPUTE); + +// let descriptor_set_template = render_system.create_descriptor_set_template(Some("Shadow Mapping Pass Set Layout"), &[shadow_map_binding_template.clone(), depth_binding_template.clone(), result_binding_template.clone()]); +// let pipeline_layout = render_system.create_pipeline_layout(&[parent_descriptor_set_template, descriptor_set_template], &[]); +// let descriptor_set = render_system.create_descriptor_set(Some("Shadow Mapping Pass Descriptor Set"), &descriptor_set_template); + +// let shader = render_system.create_shader(render_system::ShaderSource::GLSL(BUILD_SHADOW_MAP_SHADER), render_system::ShaderTypes::Compute,); +// let pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&shader, render_system::ShaderTypes::Compute, vec![])); + +// let shadow_map_binding = render_system.create_descriptor_binding(descriptor_set, &shadow_map_binding_template); +// let depth_binding = render_system.create_descriptor_binding(descriptor_set, &depth_binding_template); +// let result_binding = render_system.create_descriptor_binding(descriptor_set, &result_binding_template); + +// let sampler = render_system.create_sampler(render_system::FilteringModes::Linear, render_system::FilteringModes::Linear, render_system::SamplerAddressingModes::Clamp, None, 0f32, 0f32); + +// render_system.write(&[ +// render_system::DescriptorWrite { +// binding_handle: shadow_map_binding, +// array_element: 0, +// descriptor: render_system::Descriptor::CombinedImageSampler { image_handle: shadow_rendering_pass.shadow_map, sampler_handle: sampler, layout: render_system::Layouts::Read }, +// }, +// render_system::DescriptorWrite { +// binding_handle: depth_binding, +// array_element: 0, +// descriptor: render_system::Descriptor::CombinedImageSampler { image_handle: depth_target, sampler_handle: sampler, layout: render_system::Layouts::Read }, +// }, +// render_system::DescriptorWrite { +// binding_handle: result_binding, +// array_element: 0, +// descriptor: render_system::Descriptor::Image{ handle: occlusion_map, layout: render_system::Layouts::General }, +// }, +// ]); + +// ShadowMappingPass { +// pipeline_layout, +// pipeline, +// descriptor_set_template, +// descriptor_set, + +// depth_target, +// shadow_map: shadow_rendering_pass.shadow_map, +// occlusion_map, +// } +// } + +// fn render(&self, command_buffer_recording: &mut dyn render_system::CommandBufferRecording) { +// command_buffer_recording.consume_resources(&[ +// render_system::Consumption{ +// handle: render_system::Handle::Image(self.shadow_map), +// stages: render_system::Stages::COMPUTE, +// access: render_system::AccessPolicies::READ, +// layout: render_system::Layouts::Read, +// }, +// render_system::Consumption{ +// handle: render_system::Handle::Image(self.depth_target), +// stages: render_system::Stages::COMPUTE, +// access: render_system::AccessPolicies::READ, +// layout: render_system::Layouts::Read, +// }, +// render_system::Consumption{ +// handle: render_system::Handle::Image(self.occlusion_map), +// stages: render_system::Stages::COMPUTE, +// access: render_system::AccessPolicies::WRITE, +// layout: render_system::Layouts::General, +// }, +// ]); + +// command_buffer_recording.bind_compute_pipeline(&self.pipeline); +// command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout, &[self.descriptor_set]); +// command_buffer_recording.dispatch(render_system::DispatchExtent::new(Extent::plane(1920, 1080), Extent::square(32))); +// } +// } + +// const BUILD_SHADOW_MAP_SHADER: &'static str = " +// #version 460 core +// #pragma shader_stage(compute) + +// #extension GL_EXT_scalar_block_layout: enable +// #extension GL_EXT_buffer_reference: enable +// #extension GL_EXT_buffer_reference2: enable +// #extension GL_EXT_shader_16bit_storage: require +// #extension GL_EXT_ray_tracing: require + +// layout(row_major) uniform; layout(row_major) buffer; + +// struct Camera { +// mat4 view_matrix; +// mat4 projection_matrix; +// mat4 view_projection; +// }; + +// layout(set=0,binding=0,scalar) buffer readonly CameraBuffer { +// Camera camera; +// }; + +// layout(set=1,binding=0) uniform sampler2D shadow_map; +// layout(set=1,binding=1) uniform sampler2D depth; +// layout(set=1,binding=2, r8) uniform image2D occlusion_map; + +// vec3 get_view_position(vec2 uv) { +// // snap to center of pixel +// uv *= textureSize(depth, 0).xy; +// uv = floor(uv) + vec2(0.5); +// uv /= textureSize(depth, 0).xy; +// float depth_value = texture(depth, uv).r; +// vec4 clip_space = vec4(uv * 2.0 - 1.0, depth_value, 1.0); +// vec4 view_space = inverse(camera.projection_matrix) * clip_space; +// view_space /= view_space.w; +// return view_space.xyz; +// } + +// layout(local_size_x=32, local_size_y=32) in; +// void main() { +// const vec2 pixel_center = vec2(gl_GlobalInvocationID.xy) + vec2(0.5); +// const vec2 uv = pixel_center / vec2(gl_WorkGroupSize.xy * gl_NumWorkGroups.xy); +// vec2 d = uv * 2.0 - 1.0; + +// vec3 position = get_view_position(uv); + +// vec2 shadow_d = position.xz / vec2(4.0); // Assuming overhead light, map 8 x 8 area to shadow map +// vec2 shadow_uv = shadow_d * 0.5 + 0.5; +// ivec2 shadow_texel_coord = ivec2(shadow_uv * textureSize(shadow_map, 0)); - float shadow = texelFetch(shadow_map, shadow_texel_coord, 0).r; +// float shadow = texelFetch(shadow_map, shadow_texel_coord, 0).r; - imageStore(occlusion_map, ivec2(gl_GlobalInvocationID.xy), vec4(shadow, shadow, shadow, 1.0)); -}"; \ No newline at end of file +// imageStore(occlusion_map, ivec2(gl_GlobalInvocationID.xy), vec4(shadow, shadow, shadow, 1.0)); +// }"; \ No newline at end of file diff --git a/src/rendering/ssao_render_pass.rs b/src/rendering/ssao_render_pass.rs index cc69133c..6041426d 100644 --- a/src/rendering/ssao_render_pass.rs +++ b/src/rendering/ssao_render_pass.rs @@ -43,7 +43,11 @@ impl ScreenSpaceAmbientOcclusionPass { let blur_y_source_binding = render_system.create_descriptor_binding(blur_y_descriptor_set, &source_binding_template); let blur_y_result_binding = render_system.create_descriptor_binding(blur_y_descriptor_set, &result_binding_template); - let shader = render_system.create_shader(render_system::ShaderSource::GLSL(HBAO_SHADER), render_system::ShaderTypes::Compute,); + let shader = render_system.create_shader(render_system::ShaderSource::GLSL(HBAO_SHADER), render_system::ShaderTypes::Compute, &[ + render_system::ShaderBindingDescriptor::new(0, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 2, render_system::AccessPolicies::WRITE), + ]); let pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&shader, render_system::ShaderTypes::Compute, vec![])); @@ -97,7 +101,12 @@ impl ScreenSpaceAmbientOcclusionPass { // }, ]); - let blur_shader = render_system.create_shader(render_system::ShaderSource::GLSL(BLUR_SHADER), render_system::ShaderTypes::Compute,); + let blur_shader = render_system.create_shader(render_system::ShaderSource::GLSL(BLUR_SHADER), render_system::ShaderTypes::Compute, &[ + render_system::ShaderBindingDescriptor::new(0, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 1, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 2, render_system::AccessPolicies::WRITE), + ]); let blur_x_pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&blur_shader, render_system::ShaderTypes::Compute, vec![Box::new(render_system::GenericSpecializationMapEntry{ constant_id: 0 as u32, r#type: "vec2f".to_string(), value: [1f32, 0f32,] })])); let blur_y_pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&blur_shader, render_system::ShaderTypes::Compute, vec![Box::new(render_system::GenericSpecializationMapEntry{ constant_id: 0 as u32, r#type: "vec2f".to_string(), value: [0f32, 1f32,] })])); @@ -121,57 +130,57 @@ impl ScreenSpaceAmbientOcclusionPass { } fn render(&self, command_buffer_recording: &mut dyn render_system::CommandBufferRecording) { - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.depth_target), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::Read, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.result), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); + // command_buffer_recording.consume_resources(&[ + // render_system::Consumption{ + // handle: render_system::Handle::Image(self.depth_target), + // stages: render_system::Stages::COMPUTE, + // access: render_system::AccessPolicies::READ, + // layout: render_system::Layouts::Read, + // }, + // render_system::Consumption{ + // handle: render_system::Handle::Image(self.result), + // stages: render_system::Stages::COMPUTE, + // access: render_system::AccessPolicies::WRITE, + // layout: render_system::Layouts::General, + // }, + // ]); command_buffer_recording.bind_compute_pipeline(&self.pipeline); command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout, &[self.descriptor_set]); command_buffer_recording.dispatch(render_system::DispatchExtent { workgroup_extent: Extent { width: 32, height: 32, depth: 1 }, dispatch_extent: Extent { width: 1920, height: 1080, depth: 1 } }); - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.result), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::Read, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.x_blur_target), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); + // command_buffer_recording.consume_resources(&[ + // render_system::Consumption{ + // handle: render_system::Handle::Image(self.result), + // stages: render_system::Stages::COMPUTE, + // access: render_system::AccessPolicies::READ, + // layout: render_system::Layouts::Read, + // }, + // render_system::Consumption{ + // handle: render_system::Handle::Image(self.x_blur_target), + // stages: render_system::Stages::COMPUTE, + // access: render_system::AccessPolicies::WRITE, + // layout: render_system::Layouts::General, + // }, + // ]); command_buffer_recording.bind_compute_pipeline(&self.blur_x_pipeline); command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout, &[self.blur_x_descriptor_set]); command_buffer_recording.dispatch(render_system::DispatchExtent { workgroup_extent: Extent { width: 128, height: 1, depth: 1 }, dispatch_extent: Extent { width: 1920, height: 1080, depth: 1 } }); - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.x_blur_target), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::Read, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.y_blur_target), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); + // command_buffer_recording.consume_resources(&[ + // render_system::Consumption{ + // handle: render_system::Handle::Image(self.x_blur_target), + // stages: render_system::Stages::COMPUTE, + // access: render_system::AccessPolicies::READ, + // layout: render_system::Layouts::Read, + // }, + // render_system::Consumption{ + // handle: render_system::Handle::Image(self.y_blur_target), + // stages: render_system::Stages::COMPUTE, + // access: render_system::AccessPolicies::WRITE, + // layout: render_system::Layouts::General, + // }, + // ]); command_buffer_recording.bind_compute_pipeline(&self.blur_y_pipeline); command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout, &[self.blur_y_descriptor_set]); command_buffer_recording.dispatch(render_system::DispatchExtent { workgroup_extent: Extent { width: 128, height: 1, depth: 1 }, dispatch_extent: Extent { width: 1920, height: 1080, depth: 1 } }); diff --git a/src/rendering/visibility_model/render_domain.rs b/src/rendering/visibility_model/render_domain.rs index 4b8efc1f..f8de0352 100644 --- a/src/rendering/visibility_model/render_domain.rs +++ b/src/rendering/visibility_model/render_domain.rs @@ -1,5 +1,5 @@ -use std::cmp::min; use std::collections::HashMap; +use std::ops::DerefMut; use log::error; use maths_rs::{prelude::MatTranslate, Mat4f}; @@ -7,8 +7,9 @@ use maths_rs::{prelude::MatTranslate, Mat4f}; use crate::orchestrator::EntityHandle; use crate::rendering::mesh; use crate::rendering::world_render_domain::WorldRenderDomain; +use crate::resource_manager::resource_manager::ResourceManager; use crate::{resource_manager::{self, mesh_resource_handler, material_resource_handler::{Shader, Material, Variant}, texture_resource_handler}, rendering::{render_system::{RenderSystem, self}, directional_light::DirectionalLight, point_light::PointLight}, Extent, orchestrator::{Entity, System, self, OrchestratorReference}, Vector3, camera::{self}, math, window_system}; -use crate::rendering::render_system::{BindingTables, BottomLevelAccelerationStructure, BottomLevelAccelerationStructureBuild, BottomLevelAccelerationStructureBuildDescriptions, BottomLevelAccelerationStructureDescriptions, BufferDescriptor, BufferStridedRange, DataTypes, DeviceAccesses, Encodings, ShaderTypes, TopLevelAccelerationStructureBuild, TopLevelAccelerationStructureBuildDescriptions, UseCases, Uses, CommandBufferRecording}; +use crate::rendering::render_system::{BottomLevelAccelerationStructure, BottomLevelAccelerationStructureDescriptions, DataTypes, Encodings, Uses, CommandBufferRecording}; struct VisibilityInfo { instance_count: u32, @@ -57,6 +58,9 @@ struct RayTracing { /// This the visibility buffer implementation of the world render domain. pub struct VisibilityWorldRenderDomain { + render_system: EntityHandle, + resource_manager: EntityHandle, + visibility_info: VisibilityInfo, camera: Option>, @@ -135,8 +139,11 @@ pub struct VisibilityWorldRenderDomain { } impl VisibilityWorldRenderDomain { - pub fn new<'a>(render_system: &'a mut dyn render_system::RenderSystem) -> orchestrator::EntityReturn<'a, Self> { + pub fn new<'a>(render_system_handle: EntityHandle, resource_manager_handle: EntityHandle) -> orchestrator::EntityReturn<'a, Self> { orchestrator::EntityReturn::new_from_function(move |orchestrator| { + let render_system = orchestrator.get_entity(&render_system_handle); + let mut render_system = render_system.get_mut(); + let bindings = [ render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::FRAGMENT | render_system::Stages::RAYGEN | render_system::Stages::COMPUTE), render_system::DescriptorSetBindingTemplate::new(1, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::FRAGMENT | render_system::Stages::COMPUTE), @@ -218,8 +225,19 @@ impl VisibilityWorldRenderDomain { }, ]); - let visibility_pass_mesh_shader = render_system.create_shader(render_system::ShaderSource::GLSL(VISIBILITY_PASS_MESH_SOURCE), render_system::ShaderTypes::Mesh,); - let visibility_pass_fragment_shader = render_system.create_shader(render_system::ShaderSource::GLSL(VISIBILITY_PASS_FRAGMENT_SOURCE), render_system::ShaderTypes::Fragment,); + let visibility_pass_mesh_shader = render_system.create_shader(render_system::ShaderSource::GLSL(VISIBILITY_PASS_MESH_SOURCE), render_system::ShaderTypes::Mesh, + &[ + render_system::ShaderBindingDescriptor::new(0, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 1, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 2, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 3, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 4, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 5, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 6, render_system::AccessPolicies::READ), + ] + ); + + let visibility_pass_fragment_shader = render_system.create_shader(render_system::ShaderSource::GLSL(VISIBILITY_PASS_FRAGMENT_SOURCE), render_system::ShaderTypes::Fragment, &[]); let visibility_pass_shaders = [ (&visibility_pass_mesh_shader, render_system::ShaderTypes::Mesh, vec![]), @@ -336,13 +354,34 @@ impl VisibilityWorldRenderDomain { }, ]); - let material_count_shader = render_system.create_shader(render_system::ShaderSource::GLSL(MATERIAL_COUNT_SOURCE), render_system::ShaderTypes::Compute,); + let material_count_shader = render_system.create_shader(render_system::ShaderSource::GLSL(MATERIAL_COUNT_SOURCE), render_system::ShaderTypes::Compute, + &[ + render_system::ShaderBindingDescriptor::new(0, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 0, render_system::AccessPolicies::READ | render_system::AccessPolicies::WRITE), + render_system::ShaderBindingDescriptor::new(1, 7, render_system::AccessPolicies::READ), + ] + ); let material_count_pipeline = render_system.create_compute_pipeline(&visibility_pass_pipeline_layout, (&material_count_shader, render_system::ShaderTypes::Compute, vec![])); - let material_offset_shader = render_system.create_shader(render_system::ShaderSource::GLSL(MATERIAL_OFFSET_SOURCE), render_system::ShaderTypes::Compute,); + let material_offset_shader = render_system.create_shader(render_system::ShaderSource::GLSL(MATERIAL_OFFSET_SOURCE), render_system::ShaderTypes::Compute, + &[ + render_system::ShaderBindingDescriptor::new(1, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 1, render_system::AccessPolicies::WRITE), + render_system::ShaderBindingDescriptor::new(1, 2, render_system::AccessPolicies::WRITE), + render_system::ShaderBindingDescriptor::new(1, 3, render_system::AccessPolicies::WRITE), + ] + ); let material_offset_pipeline = render_system.create_compute_pipeline(&visibility_pass_pipeline_layout, (&material_offset_shader, render_system::ShaderTypes::Compute, vec![])); - let pixel_mapping_shader = render_system.create_shader(render_system::ShaderSource::GLSL(PIXEL_MAPPING_SOURCE), render_system::ShaderTypes::Compute,); + let pixel_mapping_shader = render_system.create_shader(render_system::ShaderSource::GLSL(PIXEL_MAPPING_SOURCE), render_system::ShaderTypes::Compute, + &[ + render_system::ShaderBindingDescriptor::new(0, 1, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 1, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 2, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 4, render_system::AccessPolicies::WRITE), + render_system::ShaderBindingDescriptor::new(1, 7, render_system::AccessPolicies::READ), + ] + ); let pixel_mapping_pipeline = render_system.create_compute_pipeline(&visibility_pass_pipeline_layout, (&pixel_mapping_shader, render_system::ShaderTypes::Compute, vec![])); let light_data_buffer = render_system.create_buffer(Some("Light Data"), std::mem::size_of::(), render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); @@ -421,6 +460,9 @@ impl VisibilityWorldRenderDomain { let transfer_command_buffer = render_system.create_command_buffer(Some("Transfer")); Self { + render_system: render_system_handle, + resource_manager: resource_manager_handle, + visibility_info: VisibilityInfo{ triangle_count: 0, instance_count: 0, meshlet_count:0, vertex_count:0, }, shaders: HashMap::new(), @@ -499,7 +541,7 @@ impl VisibilityWorldRenderDomain { .add_listener::() } - fn load_material(&mut self, resource_manager: &mut resource_manager::resource_manager::ResourceManager, render_system: &mut render_system::RenderSystemImplementation, asset_url: &str) { + fn load_material(&mut self, resource_manager: &mut resource_manager::resource_manager::ResourceManager, render_system: &mut dyn render_system::RenderSystem, asset_url: &str) { let (response, buffer) = resource_manager.get(asset_url).unwrap(); for resource_document in &response.resources { @@ -543,7 +585,26 @@ impl VisibilityWorldRenderDomain { let offset = resource_document.offset as usize; let size = resource_document.size as usize; - let new_shader = render_system.create_shader(render_system::ShaderSource::SPIRV(&buffer[offset..(offset + size)]), shader.stage,); + let new_shader = render_system.create_shader(render_system::ShaderSource::SPIRV(&buffer[offset..(offset + size)]), shader.stage, &[ + render_system::ShaderBindingDescriptor::new(0, 1, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 2, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 3, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 4, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 5, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 6, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(0, 7, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 0, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 1, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 4, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(1, 6, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(2, 0, render_system::AccessPolicies::WRITE), + render_system::ShaderBindingDescriptor::new(2, 1, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(2, 2, render_system::AccessPolicies::WRITE), + render_system::ShaderBindingDescriptor::new(2, 3, render_system::AccessPolicies::WRITE), + render_system::ShaderBindingDescriptor::new(2, 4, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(2, 5, render_system::AccessPolicies::READ), + render_system::ShaderBindingDescriptor::new(2, 10, render_system::AccessPolicies::READ), + ]); self.shaders.insert(resource_id, (hash, new_shader, shader.stage)); } @@ -661,9 +722,8 @@ impl VisibilityWorldRenderDomain { fn get_transform(&self) -> Mat4f { return Mat4f::identity(); } fn set_transform(&mut self, orchestrator: OrchestratorReference, value: Mat4f) { - let render_system = orchestrator.get_by_class::(); + let render_system = orchestrator.get_entity(&self.render_system); let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::<&mut render_system::RenderSystemImplementation>().unwrap(); // let closed_frame_index = self.current_frame % 2; @@ -680,9 +740,6 @@ impl VisibilityWorldRenderDomain { } } - /// Return the property for the transform of a mesh - pub const fn transform() -> orchestrator::Property<(), Self, Mat4f> { orchestrator::Property::Component { getter: Self::get_transform, setter: Self::set_transform } } - pub fn render(&mut self, orchestrator: &OrchestratorReference, render_system: &dyn render_system::RenderSystem, command_buffer_recording: &mut dyn render_system::CommandBufferRecording) { let camera_handle = if let Some(camera_handle) = &self.camera { camera_handle } else { return; }; @@ -691,17 +748,6 @@ impl VisibilityWorldRenderDomain { command_buffer_recording.transfer_textures(&self.pending_texture_loads); - let consumption = self.pending_texture_loads.iter().map(|handle|{ - render_system::Consumption{ - handle: render_system::Handle::Image(*handle), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::Read, - } - }).collect::>(); - - command_buffer_recording.consume_resources(&consumption); - self.pending_texture_loads.clear(); command_buffer_recording.execute(&[], &[], self.transfer_synchronizer); @@ -734,26 +780,6 @@ impl VisibilityWorldRenderDomain { command_buffer_recording.start_region("Visibility Model"); - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.vertex_positions_buffer), - stages: render_system::Stages::MESH, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.vertex_normals_buffer), - stages: render_system::Stages::MESH, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - },render_system::Consumption{ - handle: render_system::Handle::Buffer(self.primitive_indices_buffer), - stages: render_system::Stages::MESH, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - ]); - let attachments = [ render_system::AttachmentInformation { image: self.primitive_index, @@ -784,206 +810,44 @@ impl VisibilityWorldRenderDomain { command_buffer_recording.start_region("Visibility Render Model"); command_buffer_recording.start_region("Visibility Buffer"); - - command_buffer_recording.consume_resources(&[ - render_system::Consumption { - handle: render_system::Handle::Buffer(self.camera_data_buffer_handle), - stages: render_system::Stages::MESH | render_system::Stages::FRAGMENT, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption { - handle: render_system::Handle::Buffer(self.vertex_positions_buffer), - stages: render_system::Stages::MESH, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption { - handle: render_system::Handle::Buffer(self.vertex_normals_buffer), - stages: render_system::Stages::MESH, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption { - handle: render_system::Handle::Buffer(self.primitive_indices_buffer), - stages: render_system::Stages::MESH, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption { - handle: render_system::Handle::Buffer(self.meshes_data_buffer), - stages: render_system::Stages::MESH | render_system::Stages::FRAGMENT, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption { - handle: render_system::Handle::Buffer(self.meshlets_data_buffer), - stages: render_system::Stages::MESH | render_system::Stages::FRAGMENT, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - ]); - - command_buffer_recording.start_render_pass(Extent::plane(1920, 1080), &attachments); - command_buffer_recording.bind_raster_pipeline(&self.visibility_pass_pipeline); - command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout_handle, &[self.descriptor_set]); - + command_buffer_recording.start_render_pass(Extent::plane(1920, 1080), &attachments); command_buffer_recording.dispatch_meshes(self.visibility_info.meshlet_count, 1, 1); - command_buffer_recording.end_render_pass(); + command_buffer_recording.end_region(); command_buffer_recording.clear_buffers(&[self.material_count, self.material_offset, self.material_offset_scratch, self.material_evaluation_dispatches, self.material_xy]); - command_buffer_recording.end_region(); - command_buffer_recording.start_region("Material Count"); - - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_count), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ | render_system::AccessPolicies::WRITE, // Atomic operations are read/write - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.instance_id), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - ]); - command_buffer_recording.bind_compute_pipeline(&self.material_count_pipeline); command_buffer_recording.bind_descriptor_sets(&self.visibility_pass_pipeline_layout, &[self.descriptor_set, self.visibility_passes_descriptor_set]); command_buffer_recording.dispatch(render_system::DispatchExtent { workgroup_extent: Extent::square(32), dispatch_extent: Extent::plane(1920, 1080) }); - command_buffer_recording.end_region(); command_buffer_recording.start_region("Material Offset"); - - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_count), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_offset), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_offset_scratch), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); command_buffer_recording.bind_compute_pipeline(&self.material_offset_pipeline); command_buffer_recording.bind_descriptor_sets(&self.visibility_pass_pipeline_layout, &[self.descriptor_set, self.visibility_passes_descriptor_set]); command_buffer_recording.dispatch(render_system::DispatchExtent { workgroup_extent: Extent { width: 1, height: 1, depth: 1 }, dispatch_extent: Extent { width: 1, height: 1, depth: 1 } }); - command_buffer_recording.end_region(); command_buffer_recording.start_region("Pixel Mapping"); - - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_offset), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_offset_scratch), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ | render_system::AccessPolicies::WRITE, // Atomic operations are read/write - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_xy), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); - command_buffer_recording.bind_compute_pipeline(&self.pixel_mapping_pipeline); command_buffer_recording.bind_descriptor_sets(&self.visibility_pass_pipeline_layout, &[self.descriptor_set, self.visibility_passes_descriptor_set]); command_buffer_recording.dispatch(render_system::DispatchExtent { workgroup_extent: Extent::square(32), dispatch_extent: Extent { width: 1920, height: 1080, depth: 1 } }); - command_buffer_recording.end_region(); command_buffer_recording.start_region("Material Evaluation"); - command_buffer_recording.clear_images(&[(self.albedo, render_system::ClearValue::Color(crate::RGBA::black())),(self.occlusion_map, render_system::ClearValue::Color(crate::RGBA::white()))]); - - command_buffer_recording.consume_resources(&[ - render_system::Consumption { - handle: render_system::Handle::Image(self.albedo), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - render_system::Consumption { - handle: render_system::Handle::Image(self.primitive_index), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption { - handle: render_system::Handle::Image(self.instance_id), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_evaluation_dispatches), - stages: render_system::Stages::INDIRECT, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Buffer(self.material_xy), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.debug_position), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.debug_normal), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - render_system::Consumption{ - handle: render_system::Handle::Image(self.occlusion_map), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::Read, - }, - ]); - - command_buffer_recording.bind_descriptor_sets(&self.material_evaluation_pipeline_layout, &[self.descriptor_set, self.visibility_passes_descriptor_set, self.material_evaluation_descriptor_set]); - for (_, (i, pipeline)) in self.material_evaluation_materials.iter() { // No need for sync here, as each thread across all invocations will write to a different pixel command_buffer_recording.bind_compute_pipeline(pipeline); + command_buffer_recording.bind_descriptor_sets(&self.material_evaluation_pipeline_layout, &[self.descriptor_set, self.visibility_passes_descriptor_set, self.material_evaluation_descriptor_set]); command_buffer_recording.write_to_push_constant(&self.material_evaluation_pipeline_layout, 0, unsafe { std::slice::from_raw_parts(&(*i as u32) as *const u32 as *const u8, std::mem::size_of::()) }); command_buffer_recording.indirect_dispatch(&render_system::BufferDescriptor { buffer: self.material_evaluation_dispatches, offset: (*i as u64 * 12), range: 12, slot: 0 }); } - command_buffer_recording.end_region(); // render_system.wait(self.transfer_synchronizer); // Wait for buffers to be copied over to the GPU, or else we might overwrite them on the CPU before they are copied over @@ -1034,24 +898,21 @@ struct MaterialData { impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain { fn on_create(&mut self, orchestrator: OrchestratorReference, handle: EntityHandle, mesh: &mesh::Mesh) { - let render_system = orchestrator.get_by_class::(); + let render_system = orchestrator.get_entity(&self.render_system); let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); - orchestrator.tie_self(Self::transform, &handle, mesh::Mesh::transform); + // orchestrator.tie_self(Self::transform, &handle, mesh::Mesh::transform); { - let resource_manager = orchestrator.get_by_class::(); + let resource_manager = orchestrator.get_entity(&self.resource_manager); let mut resource_manager = resource_manager.get_mut(); - let resource_manager: &mut resource_manager::resource_manager::ResourceManager = resource_manager.downcast_mut().unwrap(); - self.load_material(resource_manager, render_system, mesh.material_id); + self.load_material(resource_manager.deref_mut(), render_system.deref_mut(), mesh.material_id); } if !self.mesh_resources.contains_key(mesh.resource_id) { // Load only if not already loaded - let resource_manager = orchestrator.get_by_class::(); + let resource_manager = orchestrator.get_entity(&self.resource_manager); let mut resource_manager = resource_manager.get_mut(); - let resource_manager: &mut resource_manager::resource_manager::ResourceManager = resource_manager.downcast_mut().unwrap(); let resource_request = resource_manager.request_resource(mesh.resource_id); @@ -1227,9 +1088,8 @@ impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain { fn on_create(&mut self, orchestrator: OrchestratorReference, handle: EntityHandle, light: &DirectionalLight) { - let render_system = orchestrator.get_by_class::(); + let render_system = orchestrator.get_entity(&self.render_system); let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); let lighting_data = unsafe { (render_system.get_mut_buffer_slice(self.light_data_buffer).as_mut_ptr() as *mut LightingData).as_mut().unwrap() }; @@ -1246,9 +1106,8 @@ impl orchestrator::EntitySubscriber for VisibilityWorldRenderD impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain { fn on_create(&mut self, orchestrator: OrchestratorReference, handle: EntityHandle, light: &PointLight) { - let render_system = orchestrator.get_by_class::(); + let render_system = orchestrator.get_entity(&self.render_system); let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); let lighting_data = unsafe { (render_system.get_mut_buffer_slice(self.light_data_buffer).as_mut_ptr() as *mut LightingData).as_mut().unwrap() }; diff --git a/src/rendering/vulkan_render_system.rs b/src/rendering/vulkan_render_system.rs index ffc5604a..db2cc233 100644 --- a/src/rendering/vulkan_render_system.rs +++ b/src/rendering/vulkan_render_system.rs @@ -46,6 +46,7 @@ pub struct VulkanRenderSystem { descriptor_sets: Vec, meshes: Vec, acceleration_structures: Vec, + shaders: Vec, pipelines: Vec, command_buffers: Vec, synchronizers: Vec, @@ -114,7 +115,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { } /// Creates a shader. - fn create_shader(&mut self, shader_source_type: render_system::ShaderSource, stage: render_system::ShaderTypes,) -> render_system::ShaderHandle { + fn create_shader(&mut self, shader_source_type: render_system::ShaderSource, stage: render_system::ShaderTypes, shader_binding_descriptors: &[ShaderBindingDescriptor],) -> render_system::ShaderHandle { match shader_source_type { render_system::ShaderSource::GLSL(source_code) => { let compiler = shaderc::Compiler::new().unwrap(); @@ -130,7 +131,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { match binary { Ok(binary) => { - self.create_vulkan_shader(stage, binary.as_binary_u8()) + self.create_vulkan_shader(stage, binary.as_binary_u8(), shader_binding_descriptors) }, Err(err) => { let error_string = err.to_string(); @@ -141,7 +142,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { } } render_system::ShaderSource::SPIRV(spirv) => { - self.create_vulkan_shader(stage, spirv) + self.create_vulkan_shader(stage, spirv, shader_binding_descriptors) } } } @@ -227,8 +228,11 @@ impl render_system::RenderSystem for VulkanRenderSystem { let created_binding = Binding { descriptor_set_handle: descriptor_set, descriptor_type, + type_: binding.descriptor_type, count: binding.descriptor_count, index: binding.binding, + stages: binding.stages, + pipeline_stages: to_pipeline_stage_flags(binding.stages), }; let binding_handle = render_system::DescriptorSetBindingHandle(self.bindings.len() as u64); @@ -275,6 +279,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { self.descriptor_sets.push( DescriptorSet { next: None, + resources: Vec::with_capacity(16), descriptor_set, descriptor_set_layout: *descriptor_set_layout_handle, } @@ -304,7 +309,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { handle } - fn write(&self, descriptor_set_writes: &[render_system::DescriptorWrite]) { + fn write(&mut self, descriptor_set_writes: &[render_system::DescriptorWrite]) { for descriptor_set_write in descriptor_set_writes { let binding = &self.bindings[descriptor_set_write.binding_handle.0 as usize]; let descriptor_set = &self.descriptor_sets[binding.descriptor_set_handle.0 as usize]; @@ -460,6 +465,32 @@ impl render_system::RenderSystem for VulkanRenderSystem { } } } + + for dsw in descriptor_set_writes { + let binding = &self.bindings[dsw.binding_handle.0 as usize]; + + let mut descriptor_set_handle_option = Some(binding.descriptor_set_handle); + + while let Some(descriptor_set_handle) = descriptor_set_handle_option { + let descriptor_set = &mut self.descriptor_sets[descriptor_set_handle.0 as usize]; + + match dsw.descriptor { + Descriptor::Buffer { handle, .. } => { + descriptor_set.resources.push((dsw.binding_handle, render_system::Handle::Buffer(handle))); + } + Descriptor::Image { handle, .. } => { + descriptor_set.resources.push((dsw.binding_handle, render_system::Handle::Image(handle))); + } + Descriptor::CombinedImageSampler { image_handle, .. } => { + descriptor_set.resources.push((dsw.binding_handle, render_system::Handle::Image(image_handle))); + } + _ => {} + } + + descriptor_set_handle_option = descriptor_set.next; + } + + } } fn create_pipeline_layout(&mut self, descriptor_set_layout_handles: &[render_system::DescriptorSetTemplateHandle], push_constant_ranges: &[render_system::PushConstantRange]) -> render_system::PipelineLayoutHandle { @@ -532,11 +563,13 @@ impl render_system::RenderSystem for VulkanRenderSystem { let pipeline_layout = &self.pipeline_layouts[pipeline_layout_handle.0 as usize]; + let shader = &self.shaders[shader_parameter.0.0 as usize]; + let create_infos = [ vk::ComputePipelineCreateInfo::default() .stage(vk::PipelineShaderStageCreateInfo::default() .stage(vk::ShaderStageFlags::COMPUTE) - .module(vk::ShaderModule::from_raw(shader_parameter.0.0)) + .module(shader.shader) .name(std::ffi::CStr::from_bytes_with_nul(b"main\0").unwrap()) .specialization_info(&specialization_info) /* .build() */ @@ -550,9 +583,15 @@ impl render_system::RenderSystem for VulkanRenderSystem { let handle = render_system::PipelineHandle(self.pipelines.len() as u64); + let resource_access = shader.shader_binding_descriptors.iter().map(|descriptor| { + ((descriptor.set, descriptor.binding), (render_system::Stages::COMPUTE, descriptor.access)) + }).collect::>(); + self.pipelines.push(Pipeline { pipeline: pipeline_handle, shader_handles: HashMap::new(), + shaders: vec![*shader_parameter.0], + resource_access, }); handle @@ -561,10 +600,12 @@ impl render_system::RenderSystem for VulkanRenderSystem { fn create_ray_tracing_pipeline(&mut self, pipeline_layout_handle: &render_system::PipelineLayoutHandle, shaders: &[render_system::ShaderParameter]) -> render_system::PipelineHandle { let mut groups = Vec::with_capacity(1024); - let stages = shaders.iter().map(|shader| { + let stages = shaders.iter().map(|stage| { + let shader = &self.shaders[stage.0.0 as usize]; + vk::PipelineShaderStageCreateInfo::default() - .stage(to_shader_stage_flags(shader.1)) - .module(vk::ShaderModule::from_raw(shader.0.0)) + .stage(to_shader_stage_flags(stage.1)) + .module(shader.shader) .name(std::ffi::CStr::from_bytes_with_nul(b"main\0").unwrap()) // .specialization_info(&specilization_infos[specilization_info_count - 1]) /* .build() */ @@ -572,7 +613,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { for (i, shader) in shaders.iter().enumerate() { match shader.1 { - render_system::ShaderTypes::Raygen | render_system::ShaderTypes::Miss | render_system::ShaderTypes::Callable => { + render_system::ShaderTypes::RayGen | render_system::ShaderTypes::Miss | render_system::ShaderTypes::Callable => { groups.push(vk::RayTracingShaderGroupCreateInfoKHR::default() .ty(vk::RayTracingShaderGroupTypeKHR::GENERAL) .general_shader(i as u32) @@ -636,9 +677,19 @@ impl render_system::RenderSystem for VulkanRenderSystem { let handle = render_system::PipelineHandle(self.pipelines.len() as u64); + let resource_access = shaders.iter().map(|shader| { + let shader = &self.shaders[shader.0.0 as usize]; + + shader.shader_binding_descriptors.iter().map(|descriptor| { + ((descriptor.set, descriptor.binding), (shader.stage, descriptor.access)) + }).collect::>() + }).flatten().collect::>(); + self.pipelines.push(Pipeline { pipeline: pipeline_handle, shader_handles: handles, + shaders: shaders.iter().map(|shader| *shader.0).collect(), + resource_access, }); handle @@ -1284,17 +1335,28 @@ pub(crate) struct PipelineLayout { descriptor_set_template_indices: HashMap, } -#[derive(Clone, Copy)] +#[derive(Clone)] pub(crate) struct DescriptorSet { next: Option, descriptor_set: vk::DescriptorSet, descriptor_set_layout: render_system::DescriptorSetTemplateHandle, + + resources: Vec<(render_system::DescriptorSetBindingHandle, render_system::Handle)>, +} + +#[derive(Clone)] +pub(crate) struct Shader { + shader: vk::ShaderModule, + stage: render_system::Stages, + shader_binding_descriptors: Vec, } #[derive(Clone)] pub(crate) struct Pipeline { pipeline: vk::Pipeline, shader_handles: HashMap, + shaders: Vec, + resource_access: Vec<((u32, u32), (render_system::Stages, render_system::AccessPolicies))>, } #[derive(Clone, Copy)] @@ -1306,7 +1368,10 @@ pub(crate) struct CommandBufferInternal { #[derive(Clone)] pub(crate) struct Binding { descriptor_set_handle: render_system::DescriptorSetHandle, + type_: render_system::DescriptorType, descriptor_type: vk::DescriptorType, + stages: render_system::Stages, + pipeline_stages: vk::PipelineStageFlags2, index: u32, count: u32, } @@ -1426,6 +1491,7 @@ fn texture_format_and_resource_use_to_image_layout(_texture_format: render_syste render_system::Layouts::Read => vk::ImageLayout::READ_ONLY_OPTIMAL, render_system::Layouts::General => vk::ImageLayout::GENERAL, render_system::Layouts::ShaderBindingTable => vk::ImageLayout::UNDEFINED, + render_system::Layouts::Indirect => vk::ImageLayout::UNDEFINED, } } @@ -1546,7 +1612,7 @@ fn to_shader_stage_flags(shader_type: render_system::ShaderTypes) -> vk::ShaderS render_system::ShaderTypes::Compute => vk::ShaderStageFlags::COMPUTE, render_system::ShaderTypes::Task => vk::ShaderStageFlags::TASK_EXT, render_system::ShaderTypes::Mesh => vk::ShaderStageFlags::MESH_EXT, - render_system::ShaderTypes::Raygen => vk::ShaderStageFlags::RAYGEN_KHR, + render_system::ShaderTypes::RayGen => vk::ShaderStageFlags::RAYGEN_KHR, render_system::ShaderTypes::ClosestHit => vk::ShaderStageFlags::CLOSEST_HIT_KHR, render_system::ShaderTypes::AnyHit => vk::ShaderStageFlags::ANY_HIT_KHR, render_system::ShaderTypes::Intersection => vk::ShaderStageFlags::INTERSECTION_KHR, @@ -1582,8 +1648,46 @@ fn to_pipeline_stage_flags(stages: render_system::Stages) -> vk::PipelineStageFl pipeline_stage_flags |= vk::PipelineStageFlags2::BOTTOM_OF_PIPE } - if stages.contains(render_system::Stages::INDIRECT) { - pipeline_stage_flags |= vk::PipelineStageFlags2::DRAW_INDIRECT; + if stages.contains(render_system::Stages::RAYGEN) { + pipeline_stage_flags |= vk::PipelineStageFlags2::RAY_TRACING_SHADER_KHR; + } + + if stages.contains(render_system::Stages::ACCELERATION_STRUCTURE_BUILD) { + pipeline_stage_flags |= vk::PipelineStageFlags2::ACCELERATION_STRUCTURE_BUILD_KHR; + } + + pipeline_stage_flags +} + +fn to_pipeline_stage_flags_with_layout(stages: render_system::Stages, layout: render_system::Layouts) -> vk::PipelineStageFlags2 { + let mut pipeline_stage_flags = vk::PipelineStageFlags2::NONE; + + if stages.contains(render_system::Stages::VERTEX) { + pipeline_stage_flags |= vk::PipelineStageFlags2::VERTEX_SHADER + } + + if stages.contains(render_system::Stages::MESH) { + pipeline_stage_flags |= vk::PipelineStageFlags2::MESH_SHADER_EXT; + } + + if stages.contains(render_system::Stages::FRAGMENT) { + pipeline_stage_flags |= vk::PipelineStageFlags2::FRAGMENT_SHADER + } + + if stages.contains(render_system::Stages::COMPUTE) { + if layout == render_system::Layouts::Indirect { + pipeline_stage_flags |= vk::PipelineStageFlags2::DRAW_INDIRECT + } else { + pipeline_stage_flags |= vk::PipelineStageFlags2::COMPUTE_SHADER + } + } + + if stages.contains(render_system::Stages::TRANSFER) { + pipeline_stage_flags |= vk::PipelineStageFlags2::TRANSFER + } + + if stages.contains(render_system::Stages::PRESENTATION) { + pipeline_stage_flags |= vk::PipelineStageFlags2::BOTTOM_OF_PIPE } if stages.contains(render_system::Stages::RAYGEN) { @@ -1630,10 +1734,6 @@ fn to_pipeline_stage_flags_with_format(stages: render_system::Stages, format: re pipeline_stage_flags |= vk::PipelineStageFlags2::BOTTOM_OF_PIPE } - if stages.contains(render_system::Stages::INDIRECT) { - pipeline_stage_flags |= vk::PipelineStageFlags2::DRAW_INDIRECT; - } - if stages.contains(render_system::Stages::RAYGEN) { pipeline_stage_flags |= vk::PipelineStageFlags2::RAY_TRACING_SHADER_KHR; } @@ -1655,10 +1755,11 @@ fn to_access_flags(accesses: render_system::AccessPolicies, stages: render_syste access_flags |= vk::AccessFlags2::SHADER_SAMPLED_READ; } if stages.intersects(render_system::Stages::COMPUTE) { - access_flags |= vk::AccessFlags2::SHADER_READ - } - if stages.intersects(render_system::Stages::INDIRECT) { - access_flags |= vk::AccessFlags2::INDIRECT_COMMAND_READ + if layout == render_system::Layouts::Indirect { + access_flags |= vk::AccessFlags2::INDIRECT_COMMAND_READ + } else { + access_flags |= vk::AccessFlags2::SHADER_READ + } } if stages.intersects(render_system::Stages::RAYGEN) { if layout == render_system::Layouts::ShaderBindingTable { @@ -1713,9 +1814,6 @@ fn to_access_flags_with_format(accesses: render_system::AccessPolicies, stages: access_flags |= vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_READ } } - if stages.intersects(render_system::Stages::INDIRECT) { - access_flags |= vk::AccessFlags2::INDIRECT_COMMAND_READ - } if stages.intersects(render_system::Stages::RAYGEN) { access_flags |= vk::AccessFlags2::SHADER_READ } @@ -1823,6 +1921,24 @@ impl Size for &[render_system::VertexElement] { } } +impl Into for render_system::ShaderTypes { + fn into(self) -> render_system::Stages { + match self { + ShaderTypes::Vertex => render_system::Stages::VERTEX, + ShaderTypes::Fragment => render_system::Stages::FRAGMENT, + ShaderTypes::Compute => render_system::Stages::COMPUTE, + ShaderTypes::Task => render_system::Stages::TASK, + ShaderTypes::Mesh => render_system::Stages::MESH, + ShaderTypes::RayGen => render_system::Stages::RAYGEN, + ShaderTypes::ClosestHit => render_system::Stages::CLOSEST_HIT, + ShaderTypes::AnyHit => render_system::Stages::ANY_HIT, + ShaderTypes::Intersection => render_system::Stages::INTERSECTION, + ShaderTypes::Miss => render_system::Stages::MISS, + ShaderTypes::Callable => render_system::Stages::CALLABLE, + } + } +} + pub struct Settings { validation: bool, ray_tracing: bool, @@ -2091,6 +2207,7 @@ impl VulkanRenderSystem { bindings: Vec::with_capacity(1024), descriptor_sets: Vec::with_capacity(512), acceleration_structures: Vec::new(), + shaders: Vec::with_capacity(1024), pipelines: Vec::with_capacity(1024), meshes: Vec::new(), command_buffers: Vec::with_capacity(32), @@ -2099,24 +2216,32 @@ impl VulkanRenderSystem { } } - pub fn new_as_system() -> orchestrator::EntityReturn<'static, render_system::RenderSystemImplementation> { + pub fn new_as_system() -> orchestrator::EntityReturn<'static, VulkanRenderSystem> { let settings = Settings { validation: true, ray_tracing: true, }; - orchestrator::EntityReturn::new(render_system::RenderSystemImplementation::new(Box::new(VulkanRenderSystem::new(&settings)))) + orchestrator::EntityReturn::new(VulkanRenderSystem::new(&settings)) } fn get_log_count(&self) -> u64 { self.debug_data.error_count } - fn create_vulkan_shader(&self, stage: render_system::ShaderTypes, shader: &[u8]) -> render_system::ShaderHandle { + fn create_vulkan_shader(&mut self, stage: render_system::ShaderTypes, shader: &[u8], shader_binding_descriptors: &[ShaderBindingDescriptor]) -> render_system::ShaderHandle { let shader_module_create_info = vk::ShaderModuleCreateInfo::default() .code(unsafe { shader.align_to::().1 }) /* .build() */; let shader_module = unsafe { self.device.create_shader_module(&shader_module_create_info, None).expect("No shader module") }; - render_system::ShaderHandle(shader_module.as_raw()) + let handle = render_system::ShaderHandle(self.shaders.len() as u64); + + self.shaders.push(Shader { + shader: shader_module, + stage: stage.into(), + shader_binding_descriptors: shader_binding_descriptors.to_vec(), + }); + + handle } fn create_vulkan_pipeline(&mut self, blocks: &[render_system::PipelineConfigurationBlocks]) -> render_system::PipelineHandle { @@ -2231,10 +2356,10 @@ impl VulkanRenderSystem { let stages = shaders .iter() - .map(move |shader| { + .map(move |stage| { let entries_offset = entry_count; - for entry in &shader.2 { + for entry in &stage.2 { specialization_entries_buffer.extend_from_slice(entry.get_data()); entries[entry_count] = vk::SpecializationMapEntry::default() @@ -2249,9 +2374,11 @@ impl VulkanRenderSystem { // .data(&specialization_entries_buffer) // .map_entries(&entries[entries_offset..entry_count]); + let shader = &vulkan_render_system.shaders[stage.0.0 as usize]; + vk::PipelineShaderStageCreateInfo::default() - .stage(to_shader_stage_flags(shader.1)) - .module(vk::ShaderModule::from_raw(shader.0.0)) + .stage(to_shader_stage_flags(stage.1)) + .module(shader.shader) .name(std::ffi::CStr::from_bytes_with_nul(b"main\0").unwrap()) // .specialization_info(&specilization_infos[specilization_info_count - 1]) /* .build() */ @@ -2337,7 +2464,26 @@ impl VulkanRenderSystem { let handle = render_system::PipelineHandle(self.pipelines.len() as u64); - self.pipelines.push(Pipeline { pipeline, shader_handles: HashMap::new() }); + let resource_access: Vec<((u32, u32), (render_system::Stages, render_system::AccessPolicies))> = blocks.iter().find_map(|b| { + match b { + render_system::PipelineConfigurationBlocks::Shaders { shaders } => { + Some(shaders.iter().map(|s| { + let shader = &self.shaders[s.0.0 as usize]; + shader.shader_binding_descriptors.iter().map(|sbd| { + ((sbd.set, sbd.binding), (Into::::into(s.1), sbd.access)) + }).collect::>() + })) + }, + _ => None, + } + }).unwrap().flatten().collect::>(); + + self.pipelines.push(Pipeline { + pipeline, + shader_handles: HashMap::new(), + shaders: Vec::new(), + resource_access, + }); handle } @@ -2794,6 +2940,10 @@ pub struct VulkanCommandBufferRecording<'a> { modulo_frame_index: u32, states: HashMap, pipeline_bind_point: vk::PipelineBindPoint, + + stages: vk::PipelineStageFlags2, + + bound_pipeline: Option, } impl VulkanCommandBufferRecording<'_> { @@ -2805,6 +2955,10 @@ impl VulkanCommandBufferRecording<'_> { modulo_frame_index: frame_index.map(|frame_index| frame_index % render_system.frames as u32).unwrap_or(0), in_render_pass: false, states: HashMap::new(), + + stages: vk::PipelineStageFlags2::empty(), + + bound_pipeline: None, } } @@ -2853,9 +3007,9 @@ impl VulkanCommandBufferRecording<'_> { &self.render_system.command_buffers[self.command_buffer.0 as usize].frames[self.modulo_frame_index as usize] } - fn get_descriptor_set(&self, desciptor_set_handle: &render_system::DescriptorSetHandle) -> (render_system::DescriptorSetHandle, &DescriptorSet) { + fn get_descriptor_set(&self, descriptor_set_handle: &render_system::DescriptorSetHandle) -> (render_system::DescriptorSetHandle, &DescriptorSet) { let mut i = 0; - let mut handle = desciptor_set_handle.clone(); + let mut handle = descriptor_set_handle.clone(); loop { let descriptor_set = &self.render_system.descriptor_sets[handle.0 as usize]; if i == self.modulo_frame_index { @@ -2884,15 +3038,17 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> /// Starts a render pass on the GPU. /// A render pass is a particular configuration of render targets which will be used simultaneously to render certain imagery. fn start_render_pass(&mut self, extent: crate::Extent, attachments: &[render_system::AttachmentInformation]) { - self.consume_resources(&attachments.iter().map(|attachment| - render_system::Consumption{ - handle: render_system::Handle::Image(attachment.image), - stages: render_system::Stages::FRAGMENT, - access: render_system::AccessPolicies::WRITE, - layout: attachment.layout, - } - // r(false, (texture_format_and_resource_use_to_image_layout(attachment.format, attachment.layout, None), if attachment.format == TextureFormats::Depth32 { vk::PipelineStageFlags2::LATE_FRAGMENT_TESTS } else { vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT }, if attachment.format == TextureFormats::Depth32 { vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_WRITE } else { vk::AccessFlags2::COLOR_ATTACHMENT_WRITE }))) - ).collect::>()); + unsafe { + self.consume_resources(&attachments.iter().map(|attachment| + render_system::Consumption{ + handle: render_system::Handle::Image(attachment.image), + stages: render_system::Stages::FRAGMENT, + access: render_system::AccessPolicies::WRITE, + layout: attachment.layout, + } + // r(false, (texture_format_and_resource_use_to_image_layout(attachment.format, attachment.layout, None), if attachment.format == TextureFormats::Depth32 { vk::PipelineStageFlags2::LATE_FRAGMENT_TESTS } else { vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT }, if attachment.format == TextureFormats::Depth32 { vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_WRITE } else { vk::AccessFlags2::COLOR_ATTACHMENT_WRITE }))) + ).collect::>()); + } let render_area = vk::Rect2D::default() .offset(vk::Offset2D::default().x(0).y(0)/* .build() */) @@ -3146,21 +3302,27 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> let command_buffer = self.get_command_buffer(); let pipeline = self.render_system.pipelines[pipeline_handle.0 as usize].pipeline; unsafe { self.render_system.device.cmd_bind_pipeline(command_buffer.command_buffer, vk::PipelineBindPoint::GRAPHICS, pipeline); } + self.pipeline_bind_point = vk::PipelineBindPoint::GRAPHICS; + self.bound_pipeline = Some(*pipeline_handle); } fn bind_compute_pipeline(&mut self, pipeline_handle: &render_system::PipelineHandle) { let command_buffer = self.get_command_buffer(); let pipeline = self.render_system.pipelines[pipeline_handle.0 as usize].pipeline; unsafe { self.render_system.device.cmd_bind_pipeline(command_buffer.command_buffer, vk::PipelineBindPoint::COMPUTE, pipeline); } + self.pipeline_bind_point = vk::PipelineBindPoint::COMPUTE; + self.bound_pipeline = Some(*pipeline_handle); } fn bind_ray_tracing_pipeline(&mut self, pipeline_handle: &render_system::PipelineHandle) { let command_buffer = self.get_command_buffer(); let pipeline = self.render_system.pipelines[pipeline_handle.0 as usize].pipeline; unsafe { self.render_system.device.cmd_bind_pipeline(command_buffer.command_buffer, vk::PipelineBindPoint::RAY_TRACING_KHR, pipeline); } + self.pipeline_bind_point = vk::PipelineBindPoint::RAY_TRACING_KHR; + self.bound_pipeline = Some(*pipeline_handle); } /// Writes to the push constant register. @@ -3213,12 +3375,12 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } fn clear_images(&mut self, textures: &[(render_system::ImageHandle, render_system::ClearValue)]) { - self.consume_resources(textures.iter().map(|(texture_handle, _)| render_system::Consumption { + unsafe { self.consume_resources(textures.iter().map(|(texture_handle, _)| render_system::Consumption { handle: render_system::Handle::Image(*texture_handle), stages: render_system::Stages::TRANSFER, access: render_system::AccessPolicies::WRITE, layout: render_system::Layouts::Transfer, - }).collect::>().as_slice()); + }).collect::>().as_slice()) }; for (texture_handle, clear_value) in textures { let (_, texture) = self.get_texture(*texture_handle); @@ -3242,13 +3404,13 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } } - fn consume_resources(&mut self, consumptions: &[render_system::Consumption]) { + unsafe fn consume_resources(&mut self, consumptions: &[render_system::Consumption]) { let mut image_memory_barriers = Vec::new(); let mut buffer_memory_barriers = Vec::new(); let mut memory_barriers = Vec::new(); for consumption in consumptions { - let mut new_stage_mask = to_pipeline_stage_flags(consumption.stages); + let mut new_stage_mask = to_pipeline_stage_flags_with_layout(consumption.stages, consumption.layout); let mut new_access_mask = to_access_flags(consumption.access, consumption.stages, consumption.layout); match consumption.handle { @@ -3358,22 +3520,6 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> ); } - // let memory_barrier = if let Some(source) = barrier.source { - // vk::MemoryBarrier2::default() - // .src_stage_mask(to_pipeline_stage_flags(source.stage)) - // .src_access_mask(to_access_flags(source.access, source.stage)) - - // } else { - // vk::MemoryBarrier2::default() - // .src_stage_mask(vk::PipelineStageFlags2::empty()) - // .src_access_mask(vk::AccessFlags2KHR::empty()) - // } - // .dst_stage_mask(to_pipeline_stage_flags(barrier.destination.stage)) - // .dst_access_mask(to_access_flags(barrier.destination.access, barrier.destination.stage)) - // /* .build() */; - - // memory_barriers.push(memory_barrier); - let dependency_info = vk::DependencyInfo::default() .image_memory_barriers(&image_memory_barriers) .buffer_memory_barriers(&buffer_memory_barriers) @@ -3381,20 +3527,22 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> .dependency_flags(vk::DependencyFlags::BY_REGION) /* .build() */; + dbg!(dependency_info); + let command_buffer = self.get_command_buffer(); unsafe { self.render_system.device.cmd_pipeline_barrier2(command_buffer.command_buffer, &dependency_info) }; } fn clear_buffers(&mut self, buffer_handles: &[render_system::BaseBufferHandle]) { - self.consume_resources(&buffer_handles.iter().map(|buffer_handle| + unsafe { self.consume_resources(&buffer_handles.iter().map(|buffer_handle| render_system::Consumption{ handle: render_system::Handle::Buffer(*buffer_handle), stages: render_system::Stages::TRANSFER, access: render_system::AccessPolicies::WRITE, layout: render_system::Layouts::Transfer, } - ).collect::>()); + ).collect::>()) }; for buffer_handle in buffer_handles { unsafe { @@ -3430,8 +3578,21 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } fn indirect_dispatch(&mut self, buffer_descriptor: &render_system::BufferDescriptor) { - let command_buffer = self.get_command_buffer(); let buffer = self.render_system.buffers[buffer_descriptor.buffer.0 as usize]; + + unsafe { + self.consume_resources(&[ + render_system::Consumption{ + handle: render_system::Handle::Buffer(buffer_descriptor.buffer), + stages: render_system::Stages::COMPUTE, + access: render_system::AccessPolicies::READ, + layout: render_system::Layouts::Indirect, + } + ]) + } + + let command_buffer = self.get_command_buffer(); + unsafe { self.render_system.device.cmd_dispatch_indirect(command_buffer.command_buffer, buffer.buffer, buffer_descriptor.offset); } @@ -3458,7 +3619,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } fn transfer_textures(&mut self, texture_handles: &[render_system::ImageHandle]) { - self.consume_resources(&texture_handles.iter().map(|texture_handle| + unsafe { self.consume_resources(&texture_handles.iter().map(|texture_handle| render_system::Consumption{ handle: render_system::Handle::Image(*texture_handle), stages: render_system::Stages::TRANSFER, @@ -3466,7 +3627,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> layout: render_system::Layouts::Transfer, } // r(false, (texture_format_and_resource_use_to_image_layout(attachment.format, attachment.layout, None), if attachment.format == TextureFormats::Depth32 { vk::PipelineStageFlags2::LATE_FRAGMENT_TESTS } else { vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT }, if attachment.format == TextureFormats::Depth32 { vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_WRITE } else { vk::AccessFlags2::COLOR_ATTACHMENT_WRITE }))) - ).collect::>()); + ).collect::>()) }; let command_buffer = self.get_command_buffer(); @@ -3503,14 +3664,14 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } fn write_image_data(&mut self, texture_handle: render_system::ImageHandle, data: &[render_system::RGBAu8]) { - self.consume_resources( + unsafe { self.consume_resources( &[render_system::Consumption{ handle: render_system::Handle::Image(texture_handle), stages: render_system::Stages::TRANSFER, access: render_system::AccessPolicies::WRITE, layout: render_system::Layouts::Transfer, }] - ); + ) }; let (texture_handle, texture) = self.get_texture(texture_handle); @@ -3569,14 +3730,14 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } fn copy_to_swapchain(&mut self, source_texture_handle: render_system::ImageHandle, present_image_index: u32, swapchain_handle: render_system::SwapchainHandle) { - self.consume_resources(&[ + unsafe { self.consume_resources(&[ render_system::Consumption { handle: render_system::Handle::Image(source_texture_handle), stages: render_system::Stages::TRANSFER, access: render_system::AccessPolicies::READ, layout: render_system::Layouts::Transfer, }, - ]); + ]) }; let (_, source_texture) = self.get_texture(source_texture_handle); let swapchain = &self.render_system.swapchains[swapchain_handle.0 as usize]; @@ -3707,7 +3868,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } /// Binds a decriptor set on the GPU. - fn bind_descriptor_sets(&self, pipeline_layout_handle: &render_system::PipelineLayoutHandle, sets: &[render_system::DescriptorSetHandle]) { + fn bind_descriptor_sets(&mut self, pipeline_layout_handle: &render_system::PipelineLayoutHandle, sets: &[render_system::DescriptorSetHandle]) { let command_buffer = self.get_command_buffer(); let pipeline_layout = &self.render_system.pipeline_layouts[pipeline_layout_handle.0 as usize]; @@ -3729,15 +3890,50 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> self.render_system.device.cmd_bind_descriptor_sets(command_buffer.command_buffer, self.pipeline_bind_point, vulkan_pipeline_layout_handle, i, &descriptor_sets, &[]); } } + + let mut consumptions = Vec::with_capacity(32); + + let bound_pipeline_handle = self.bound_pipeline.expect("No bound pipeline"); + + let pipeline = &self.render_system.pipelines[bound_pipeline_handle.0 as usize]; + + for ((set_index, binding_index), (stages, accesses)) in &pipeline.resource_access { + let set_handle = if let Some(h) = sets.get(*set_index as usize) { h } else { continue; }; // TODO: log error + + let (_, descriptor_set) = self.get_descriptor_set(set_handle); + + for (binding_handle, resource_handle) in descriptor_set.resources.iter().filter(|(binding_handle, _)| self.render_system.bindings[binding_handle.0 as usize].index == *binding_index) { + let binding = self.render_system.bindings.get(binding_handle.0 as usize).expect("No binding found"); + + consumptions.push( + render_system::Consumption { + handle: resource_handle.clone(), + stages: *stages, + access: *accesses, + layout: match binding.type_ { + render_system::DescriptorType::UniformBuffer => render_system::Layouts::General, + render_system::DescriptorType::StorageBuffer => render_system::Layouts::General, + render_system::DescriptorType::StorageImage => render_system::Layouts::General, + render_system::DescriptorType::Sampler => render_system::Layouts::General, + render_system::DescriptorType::CombinedImageSampler => render_system::Layouts::Read, + render_system::DescriptorType::AccelerationStructure => render_system::Layouts::General, + render_system::DescriptorType::SampledImage => render_system::Layouts::Read, + }, + } + ); + } + } + + unsafe { self.consume_resources(&consumptions) }; } fn sync_textures(&mut self, texture_handles: &[render_system::ImageHandle]) -> Vec { - self.consume_resources(&texture_handles.iter().map(|texture_handle| render_system::Consumption { + unsafe { self.consume_resources(&texture_handles.iter().map(|texture_handle| render_system::Consumption { handle: render_system::Handle::Image(*texture_handle), stages: render_system::Stages::TRANSFER, access: render_system::AccessPolicies::READ, layout: render_system::Layouts::Transfer, - }).collect::>()); + }).collect::>()) }; let command_buffer = self.get_command_buffer(); diff --git a/src/window_system.rs b/src/window_system.rs index dc5853ba..219c375a 100644 --- a/src/window_system.rs +++ b/src/window_system.rs @@ -637,6 +637,7 @@ impl WindowSystem { } pub fn update_window(&self, window_handle: u32) -> Option { + if window_handle as usize >= self.windows.len() { return None; } self.windows[window_handle as usize].update() } diff --git a/tests/gallery_shooter.rs b/tests/gallery_shooter.rs index 9b3b8806..b0dad55a 100644 --- a/tests/gallery_shooter.rs +++ b/tests/gallery_shooter.rs @@ -69,7 +69,7 @@ impl Player { focus_distance: 0.0, }); - orchestrator.tie(&camera_handle, byte_engine::camera::Camera::orientation, &lookaround, input_manager::Action::value); + // orchestrator.tie(&camera_handle, byte_engine::camera::Camera::orientation, &lookaround, input_manager::Action::value); // orchestrator.tie_self(Player::lookaround, &handle, input_manager::Action::value); @@ -82,7 +82,7 @@ impl Player { } impl Player { - pub const fn lookaround() -> orchestrator::Property<(), Player, Vec3f> { orchestrator::Property::Component { getter: Self::get_lookaround, setter: Self::set_lookaround } } + pub const fn lookaround() -> orchestrator::Property { orchestrator::Property { getter: Self::get_lookaround, setter: Self::set_lookaround } } fn get_lookaround(&self) -> Vec3f { Vec3f::new(0.0, 0.0, 0.0)