diff --git a/.devcontainer/devcontainer.json b/.devcontainer/documentation/devcontainer.json similarity index 81% rename from .devcontainer/devcontainer.json rename to .devcontainer/documentation/devcontainer.json index f84552ef..b18c193e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/documentation/devcontainer.json @@ -1,5 +1,5 @@ { - "name": "Docs DevContainer", + "name": "📖 Docs", "image": "mcr.microsoft.com/devcontainers/javascript-node:1-20-bullseye", "postCreateCommand": "npm install retypeapp --global" } \ No newline at end of file diff --git a/.devcontainer/rust/devcontainer.json b/.devcontainer/rust/devcontainer.json new file mode 100644 index 00000000..ef38436b --- /dev/null +++ b/.devcontainer/rust/devcontainer.json @@ -0,0 +1,13 @@ +{ + "name": "🦀 Rust", + "image": "mcr.microsoft.com/devcontainers/rust:1-1-bullseye", + "onCreateCommand": "apt update && apt install -y cmake && git clone https://github.com/rui314/mold.git && mkdir mold/build && cd mold/build && git checkout v2.4.0 && ../install-build-deps.sh && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=c++ .. && cmake --build . -j $(nproc) && sudo cmake --build . --target install" + // Use 'mounts' to make the cargo cache persistent in a Docker Volume. + // "mounts": [ + // { + // "source": "devcontainer-cargo-cache-${devcontainerId}", + // "target": "/usr/local/cargo", + // "type": "volume" + // } + // ] +} diff --git a/docs/Design/Rendering/Render Models/Ray Traced Shadow Maps/index.yml b/docs/Design/Rendering/Render Models/Ray Traced Shadow Maps/index.yml new file mode 100644 index 00000000..b9de87f9 --- /dev/null +++ b/docs/Design/Rendering/Render Models/Ray Traced Shadow Maps/index.yml @@ -0,0 +1 @@ +icon: sun \ No newline at end of file diff --git a/src/application.rs b/src/application.rs index c7f43e66..bd2f6a77 100644 --- a/src/application.rs +++ b/src/application.rs @@ -127,7 +127,7 @@ pub struct GraphicsApplication { window_system_handle: orchestrator::EntityHandle, mouse_device_handle: input_manager::DeviceHandle, input_system_handle: orchestrator::EntityHandle, - visibility_render_domain_handle: orchestrator::EntityHandle, + renderer_handle: orchestrator::EntityHandle, render_system_handle: orchestrator::EntityHandle, } @@ -165,13 +165,13 @@ impl Application for GraphicsApplication { let render_system_handle = rendering::create_render_system(&orchestrator); - let visibility_render_domain_handle = orchestrator.spawn_entity(rendering::visibility_model::render_domain::VisibilityWorldRenderDomain::new()).unwrap(); + let renderer_handle = orchestrator.spawn_entity(rendering::renderer::Renderer::new_as_system()).unwrap(); orchestrator.spawn_entity(rendering::render_orchestrator::RenderOrchestrator::new()); let _: orchestrator::EntityHandle = orchestrator.spawn(window_system::Window{ name: "Main Window".to_string(), extent: crate::Extent { width: 1920, height: 1080, depth: 1 }, id_name: "main_window".to_string() }); - GraphicsApplication { application, file_tracker_handle, window_system_handle, input_system_handle, mouse_device_handle, visibility_render_domain_handle, tick_count: 0, render_system_handle } + GraphicsApplication { application, file_tracker_handle, window_system_handle, input_system_handle, mouse_device_handle, renderer_handle, tick_count: 0, render_system_handle } } fn initialize(&mut self, _arguments: std::env::Args) { @@ -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.visibility_render_domain_handle.copy(), rendering::visibility_model::render_domain::VisibilityWorldRenderDomain::render); + self.application.get_orchestrator().invoke_mut(self.renderer_handle.copy(), rendering::renderer::Renderer::render); if !window_res { self.application.close(); diff --git a/src/file_tracker.rs b/src/file_tracker.rs index f4af16ae..65ddc4b8 100644 --- a/src/file_tracker.rs +++ b/src/file_tracker.rs @@ -16,7 +16,7 @@ pub struct FileTracker { } impl FileTracker { - pub fn new() -> orchestrator::EntityReturn { + pub fn new() -> orchestrator::EntityReturn<'static, FileTracker> { std::fs::create_dir_all(".byte-editor").unwrap(); let db = polodb_core::Database::open_file(".byte-editor/files.db").unwrap(); diff --git a/src/input_manager.rs b/src/input_manager.rs index fcd2ec02..92604c80 100644 --- a/src/input_manager.rs +++ b/src/input_manager.rs @@ -271,7 +271,7 @@ impl InputManager { } } - pub fn new_as_system() -> orchestrator::EntityReturn { + pub fn new_as_system() -> orchestrator::EntityReturn<'static, InputManager> { orchestrator::EntityReturn::new(Self::new()) .add_listener::>() .add_listener::>() diff --git a/src/lib.rs b/src/lib.rs index 12008530..88a134e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,38 @@ impl Extent { depth, } } + + pub fn line(width: u32) -> Self { + Self { + width, + height: 1, + depth: 1, + } + } + + pub fn square(size: u32) -> Self { + Self { + width: size, + height: size, + depth: 1, + } + } + + pub fn plane(width: u32, height: u32) -> Self { + Self { + width, + height, + depth: 1, + } + } + + pub fn volume(width: u32, height: u32, depth: u32) -> Self { + Self { + width, + height, + depth, + } + } } #[derive(Debug, Clone, Copy, PartialEq)] @@ -57,6 +89,11 @@ pub struct RGBA { pub a: f32, } +impl RGBA { + pub fn black() -> Self { Self { r: 0.0, g: 0.0, b: 0.0, a: 1.0, } } + pub fn white() -> Self { Self { r: 1.0, g: 1.0, b: 1.0, a: 1.0, } } +} + fn insert_return_length(collection: &mut Vec, value: T) -> usize { let length = collection.len(); collection.push(value); diff --git a/src/orchestrator.rs b/src/orchestrator.rs index ab20bed4..8423256e 100644 --- a/src/orchestrator.rs +++ b/src/orchestrator.rs @@ -113,14 +113,14 @@ pub enum PPP { } /// Entity creation functions must return this type. -pub struct EntityReturn { +pub struct EntityReturn<'c, T> { // entity: T, - create: std::boxed::Box T>, + create: std::boxed::Box T + 'c>, post_creation_functions: Vec>, listens_to: Vec<(&'static str, Box)>, } -impl EntityReturn { +impl <'c, T: 'static> EntityReturn<'c, T> { // pub fn new(entity: T) -> Self { // Self { // entity, @@ -137,7 +137,7 @@ impl EntityReturn { } } - pub fn new_from_function(function: fn(OrchestratorReference) -> T) -> Self { + pub fn new_from_function(function: impl FnOnce(OrchestratorReference) -> T + 'c) -> Self { Self { create: std::boxed::Box::new(function), post_creation_functions: Vec::new(), @@ -216,7 +216,7 @@ impl Orchestrator { } /// Spawn entity is a function that spawns an entity and returns a handle to it. - pub fn spawn_entity(&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 + Send + 'static, F: IntoHandler { let handle = function.call(self)?; trace!("{}", std::any::type_name::()); @@ -427,6 +427,11 @@ impl Orchestrator { 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 } + } } pub struct EntityReference where T: ?Sized { @@ -559,7 +564,7 @@ mod tests { impl super::System for System {} impl System { - fn new() -> EntityReturn { + fn new<'c>() -> EntityReturn<'c, System> { EntityReturn::new(System {}).add_listener::() } } @@ -782,8 +787,8 @@ impl <'a> OrchestratorReference<'a> { self.orchestrator.tie(&EntityHandle::{ internal_id: self.internal_id, external_id: 0, phantom: std::marker::PhantomData }, consuming_property, sender_component_handle, j); } - pub fn spawn_entity(&self, function: F) -> Option> where T: Entity + Send + 'static, F: IntoHandler { - self.orchestrator.spawn_entity::(function) + pub fn spawn_entity<'c, T, P, F: 'c>(&self, function: F) -> Option> where T: Entity + Send + 'static, F: IntoHandler { + self.orchestrator.spawn_entity::<'c, T, P, F>(function) } pub fn spawn(&self, component: C) -> EntityHandle { @@ -798,6 +803,10 @@ impl <'a> OrchestratorReference<'a> { self.orchestrator.set_owned_property::(self.internal_id, internal_id, property, value); } + 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::() } @@ -814,7 +823,7 @@ pub trait IntoHandler { fn call(self, orchestrator: &Orchestrator,) -> Option>; } -impl IntoHandler<(), R> for EntityReturn { +impl IntoHandler<(), R> for EntityReturn<'_, R> { fn call(self, orchestrator: &Orchestrator,) -> Option> { let internal_id = { let mut systems_data = orchestrator.systems_data.write().unwrap(); diff --git a/src/rendering/aces_tonemap_render_pass.rs b/src/rendering/aces_tonemap_render_pass.rs new file mode 100644 index 00000000..d726f217 --- /dev/null +++ b/src/rendering/aces_tonemap_render_pass.rs @@ -0,0 +1,145 @@ +use crate::{Extent, orchestrator::{self, Entity, System}}; + +use super::{render_system, tonemap_render_pass}; + +pub struct AcesToneMapPass { + pipeline_layout: render_system::PipelineLayoutHandle, + pipeline: render_system::PipelineHandle, + descriptor_set_layout: render_system::DescriptorSetTemplateHandle, + descriptor_set: render_system::DescriptorSetHandle, + + source_image_handle: render_system::ImageHandle, + result_image_handle: render_system::ImageHandle, +} + +impl AcesToneMapPass { + fn new(render_system: &mut dyn render_system::RenderSystem, source_image: render_system::ImageHandle, result_image: render_system::ImageHandle) -> AcesToneMapPass { + let bindings = [ + render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::StorageImage, render_system::Stages::COMPUTE), + render_system::DescriptorSetBindingTemplate::new(1, render_system::DescriptorType::StorageImage, render_system::Stages::COMPUTE), + ]; + + let descriptor_set_layout = render_system.create_descriptor_set_template(Some("Tonemap Pass Set Layout"), &bindings); + + let pipeline_layout = render_system.create_pipeline_layout(&[descriptor_set_layout], &[]); + + let descriptor_set = render_system.create_descriptor_set(Some("Tonemap Pass Descriptor Set"), &descriptor_set_layout); + + let albedo_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[0]); + let result_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[1]); + + render_system.write(&[ + render_system::DescriptorWrite { + binding_handle: albedo_binding, + array_element: 0, + descriptor: render_system::Descriptor::Image{ handle: source_image, layout: render_system::Layouts::General }, + }, + render_system::DescriptorWrite { + binding_handle: result_binding, + array_element: 0, + descriptor: render_system::Descriptor::Image{ handle: result_image, layout: render_system::Layouts::General }, + }, + ]); + + let tone_mapping_shader = render_system.create_shader(render_system::ShaderSource::GLSL(TONE_MAPPING_SHADER), render_system::ShaderTypes::Compute,); + let tone_mapping_pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&tone_mapping_shader, render_system::ShaderTypes::Compute, vec![])); + + AcesToneMapPass { + descriptor_set_layout, + pipeline_layout, + descriptor_set, + pipeline: tone_mapping_pipeline, + + source_image_handle: source_image, + result_image_handle: result_image, + } + } + + pub fn new_as_system(render_system: &mut dyn render_system::RenderSystem, source_image: render_system::ImageHandle, result_image: render_system::ImageHandle) -> orchestrator::EntityReturn { + orchestrator::EntityReturn::new_from_function(move |orchestrator| { + AcesToneMapPass::new(render_system, source_image, result_image) + }) + } +} + +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.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::square(32), dispatch_extent: Extent { width: 1920, height: 1080, depth: 1 } }); + } +} + +impl Entity for AcesToneMapPass {} +impl System for AcesToneMapPass {} + +const TONE_MAPPING_SHADER: &'static str = r#" +#version 450 +#pragma shader_stage(compute) + +#extension GL_EXT_scalar_block_layout: enable +#extension GL_EXT_buffer_reference2: enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable + +layout(set=0, binding=0, rgba16) uniform readonly image2D source; +layout(set=0, binding=1, rgba8) uniform image2D result; + +vec3 ACESNarkowicz(vec3 x) { + const float a = 2.51; + const float b = 0.03; + const float c = 2.43; + const float d = 0.59; + const float e = 0.14; + return clamp((x*(a*x+b))/(x*(c*x+d)+e), 0.0, 1.0); +} + +const mat3 ACES_INPUT_MAT = mat3( + vec3( 0.59719, 0.35458, 0.04823), + vec3( 0.07600, 0.90834, 0.01566), + vec3( 0.02840, 0.13383, 0.83777) +); + +const mat3 ACES_OUTPUT_MAT = mat3( + vec3( 1.60475, -0.53108, -0.07367), + vec3(-0.10208, 1.10813, -0.00605), + vec3(-0.00327, -0.07276, 1.07602) +); + +vec3 RRTAndODTFit(vec3 v) { + vec3 a = v * (v + 0.0245786) - 0.000090537; + vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081; + return a / b; +} + +vec3 ACESFitted(vec3 x) { + return clamp(ACES_OUTPUT_MAT * RRTAndODTFit(ACES_INPUT_MAT * x), 0.0, 1.0); +} + +layout(local_size_x=32, local_size_y=32) in; +void main() { + if (gl_GlobalInvocationID.x >= imageSize(source).x || gl_GlobalInvocationID.y >= imageSize(source).y) { return; } + + vec4 source_color = imageLoad(source, ivec2(gl_GlobalInvocationID.xy)); + + vec3 result_color = ACESNarkowicz(source_color.rgb); + + result_color = pow(result_color, vec3(1.0 / 2.2)); + + imageStore(result, ivec2(gl_GlobalInvocationID.xy), vec4(result_color, 1.0)); +} +"#; \ No newline at end of file diff --git a/src/rendering/mod.rs b/src/rendering/mod.rs index 29d72fcf..039a242a 100644 --- a/src/rendering/mod.rs +++ b/src/rendering/mod.rs @@ -13,8 +13,17 @@ pub mod mesh; pub mod cct; mod vulkan_render_system; +pub mod world_render_domain; pub mod visibility_model; +pub mod renderer; + +pub mod tonemap_render_pass; + +pub mod shadow_render_pass; +pub mod ssao_render_pass; +pub mod aces_tonemap_render_pass; + pub(crate) mod shader_compilation; pub fn create_render_system(orchestrator: &orchestrator::Orchestrator) -> orchestrator::EntityHandle { diff --git a/src/rendering/render_orchestrator.rs b/src/rendering/render_orchestrator.rs index d8f16984..8e592f77 100644 --- a/src/rendering/render_orchestrator.rs +++ b/src/rendering/render_orchestrator.rs @@ -13,7 +13,7 @@ pub struct RenderOrchestrator { } impl RenderOrchestrator { - pub fn new() -> orchestrator::EntityReturn { + pub fn new() -> orchestrator::EntityReturn<'static, RenderOrchestrator> { orchestrator::EntityReturn::new(Self { render_passes: Vec::new(), }) } diff --git a/src/rendering/render_system.rs b/src/rendering/render_system.rs index e775ddcc..e14ecc58 100644 --- a/src/rendering/render_system.rs +++ b/src/rendering/render_system.rs @@ -175,9 +175,9 @@ pub struct TopLevelAccelerationStructureBuild { pub struct BufferStridedRange { pub buffer: BaseBufferHandle, - pub offset: u64, - pub stride: u64, - pub size: u64, + pub offset: usize, + pub stride: usize, + pub size: usize, } pub struct BindingTables { @@ -192,6 +192,15 @@ pub struct DispatchExtent { pub dispatch_extent: Extent, } +impl DispatchExtent { + pub fn new(dispatch_extent: Extent, workgroup_extent: Extent) -> Self { + Self { + workgroup_extent, + dispatch_extent, + } + } +} + pub enum BottomLevelAccelerationStructureDescriptions { Mesh { vertex_count: u32, @@ -251,7 +260,7 @@ pub trait CommandBufferRecording { fn trace_rays(&mut self, binding_tables: BindingTables, x: u32, y: u32, z: u32); - fn clear_textures(&mut self, textures: &[(ImageHandle, ClearValue)]); + fn clear_images(&mut self, textures: &[(ImageHandle, ClearValue)]); fn clear_buffers(&mut self, buffer_handles: &[BaseBufferHandle]); fn transfer_textures(&mut self, texture_handles: &[ImageHandle]); @@ -263,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, u32)]); + fn bind_descriptor_sets(&self, pipeline_layout: &PipelineLayoutHandle, sets: &[DescriptorSetHandle]); fn copy_to_swapchain(&mut self, source_texture_handle: ImageHandle, present_image_index: u32 ,swapchain_handle: SwapchainHandle); @@ -336,7 +345,7 @@ pub trait RenderSystem: orchestrator::System { fn create_ray_tracing_pipeline(&mut self, pipeline_layout_handle: &PipelineLayoutHandle, shaders: &[ShaderParameter]) -> PipelineHandle; - fn create_command_buffer(&mut self) -> CommandBufferHandle; + fn create_command_buffer(&mut self, name: Option<&str>) -> CommandBufferHandle; fn create_command_buffer_recording(&self, command_buffer_handle: CommandBufferHandle, frame_index: Option) -> Box; @@ -374,7 +383,8 @@ pub trait RenderSystem: orchestrator::System { fn create_top_level_acceleration_structure(&mut self, name: Option<&str>,) -> TopLevelAccelerationStructureHandle; fn create_bottom_level_acceleration_structure(&mut self, description: &BottomLevelAccelerationStructure) -> BottomLevelAccelerationStructureHandle; - fn write_instance(&mut self, instances_buffer_handle: BaseBufferHandle, transform: [[f32; 4]; 3], custom_index: u16, mask: u8, sbt_record_offset: usize, acceleration_structure: BottomLevelAccelerationStructureHandle); + 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); + fn write_sbt_entry(&mut self, sbt_buffer_handle: BaseBufferHandle, sbt_record_offset: usize, pipeline_handle: PipelineHandle, shader_handle: ShaderHandle); fn bind_to_window(&mut self, window_os_handles: &window_system::WindowOsHandles) -> SwapchainHandle; @@ -383,7 +393,7 @@ pub trait RenderSystem: orchestrator::System { /// Creates a synchronization primitive (implemented as a semaphore/fence/event).\ /// Multiple underlying synchronization primitives are created, one for each frame - fn create_synchronizer(&mut self, signaled: bool) -> SynchronizerHandle; + fn create_synchronizer(&mut self, name: Option<&str>, signaled: bool) -> SynchronizerHandle; /// Acquires an image from the swapchain as to have it ready for presentation. /// @@ -477,7 +487,6 @@ pub enum Formats { RGBAf16, /// 32 bit float per component RGBA. RGBAf32, - R32(Encodings), /// 10 bit unsigned for R, G and 11 bit unsigned for B normalized RGB. RGBu10u10u11, /// 8 bit unsigned per component normalized BGRA. @@ -485,7 +494,9 @@ pub enum Formats { /// 32 bit float depth. Depth32, U32, + R8(Encodings), R16(Encodings), + R32(Encodings), RG16(Encodings), RGB16(Encodings), RGBA16(Encodings), @@ -624,6 +635,8 @@ bitflags::bitflags! { const MISS = 0b1000000000000000; /// The callable stage. const CALLABLE = 0b10000000000000000; + /// The acceleration structure build stage. + const ACCELERATION_STRUCTURE_BUILD = 0b100000000000000000; } } @@ -698,6 +711,8 @@ pub enum Layouts { Read, /// The resource will be used as a read/write storage. General, + /// The resource will be used as a shader binding table. + ShaderBindingTable, } #[derive(Clone, Copy)] @@ -1002,8 +1017,8 @@ impl RenderSystem for RenderSystemImplementation { self.pointer.create_allocation(size, _resource_uses, resource_device_accesses) } - fn create_command_buffer(&mut self) -> CommandBufferHandle { - self.pointer.create_command_buffer() + 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 { @@ -1054,16 +1069,16 @@ impl RenderSystem for RenderSystemImplementation { self.pointer.create_top_level_acceleration_structure(name,) } - fn write_instance(&mut self, instances_buffer_handle: BaseBufferHandle, transform: [[f32; 4]; 3], custom_index: u16, mask: u8, sbt_record_offset: usize, acceleration_structure: BottomLevelAccelerationStructureHandle) { - self.pointer.write_instance(instances_buffer_handle, transform, custom_index, mask, sbt_record_offset, acceleration_structure) + 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, signaled: bool) -> SynchronizerHandle { - self.pointer.create_synchronizer(signaled) + 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 { @@ -1100,7 +1115,7 @@ pub(super) mod tests { } pub(crate) fn render_triangle(renderer: &mut dyn RenderSystem) { - let signal = renderer.create_synchronizer(false); + let signal = renderer.create_synchronizer(None, false); let floats: [f32;21] = [ 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, @@ -1175,7 +1190,7 @@ pub(super) mod tests { PipelineConfigurationBlocks::RenderTargets { targets: &attachments }, ]); - let command_buffer_handle = renderer.create_command_buffer(); + let command_buffer_handle = renderer.create_command_buffer(None); renderer.start_frame_capture(); @@ -1306,10 +1321,10 @@ pub(super) mod tests { PipelineConfigurationBlocks::RenderTargets { targets: &attachments }, ]); - let command_buffer_handle = renderer.create_command_buffer(); + let command_buffer_handle = renderer.create_command_buffer(None); - let render_finished_synchronizer = renderer.create_synchronizer(false); - let image_ready = renderer.create_synchronizer(false); + let render_finished_synchronizer = renderer.create_synchronizer(None, false); + let image_ready = renderer.create_synchronizer(None, false); let image_index = renderer.acquire_swapchain_image(swapchain, image_ready); @@ -1431,10 +1446,10 @@ pub(super) mod tests { PipelineConfigurationBlocks::RenderTargets { targets: &attachments }, ]); - let command_buffer_handle = renderer.create_command_buffer(); + let command_buffer_handle = renderer.create_command_buffer(None); - let render_finished_synchronizer = renderer.create_synchronizer(true); - let image_ready = renderer.create_synchronizer(true); + let render_finished_synchronizer = renderer.create_synchronizer(None, true); + let image_ready = renderer.create_synchronizer(None, true); for i in 0..2*64 { renderer.wait(render_finished_synchronizer); @@ -1560,9 +1575,9 @@ pub(super) mod tests { PipelineConfigurationBlocks::RenderTargets { targets: &attachments }, ]); - let command_buffer_handle = renderer.create_command_buffer(); + let command_buffer_handle = renderer.create_command_buffer(None); - let render_finished_synchronizer = renderer.create_synchronizer(false); + let render_finished_synchronizer = renderer.create_synchronizer(None, false); for i in 0..FRAMES_IN_FLIGHT * 10 { // renderer.wait(render_finished_synchronizer); @@ -1698,9 +1713,9 @@ pub(super) mod tests { let _buffer = renderer.create_buffer(None, 64, Uses::Storage, DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead, UseCases::DYNAMIC); - let command_buffer_handle = renderer.create_command_buffer(); + let command_buffer_handle = renderer.create_command_buffer(None); - let render_finished_synchronizer = renderer.create_synchronizer(false); + let render_finished_synchronizer = renderer.create_synchronizer(None, false); for i in 0..FRAMES_IN_FLIGHT * 10 { // renderer.wait(render_finished_synchronizer); @@ -1779,7 +1794,7 @@ pub(super) mod tests { } pub(crate) fn descriptor_sets(renderer: &mut dyn RenderSystem) { - let signal = renderer.create_synchronizer(false); + let signal = renderer.create_synchronizer(None, false); let floats: [f32;21] = [ 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, @@ -1894,7 +1909,7 @@ pub(super) mod tests { PipelineConfigurationBlocks::RenderTargets { targets: &attachments }, ]); - let command_buffer_handle = renderer.create_command_buffer(); + let command_buffer_handle = renderer.create_command_buffer(None); renderer.start_frame_capture(); @@ -1926,7 +1941,7 @@ pub(super) mod tests { command_buffer_recording.bind_raster_pipeline(&pipeline); - command_buffer_recording.bind_descriptor_sets(&pipeline_layout, &[(descriptor_set, 0)]); + command_buffer_recording.bind_descriptor_sets(&pipeline_layout, &[descriptor_set]); command_buffer_recording.draw_mesh(&mesh); @@ -2114,19 +2129,19 @@ void main() { &[(&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(); - let rendering_command_buffer_handle = renderer.create_command_buffer(); + let building_command_buffer_handle = renderer.create_command_buffer(None); + let rendering_command_buffer_handle = renderer.create_command_buffer(None); - let render_finished_synchronizer = renderer.create_synchronizer(false); + let render_finished_synchronizer = renderer.create_synchronizer(None, false); // let image_ready = renderer.create_synchronizer(true); let instances_buffer = renderer.create_acceleration_structure_instance_buffer(None, 1); - renderer.write_instance(instances_buffer, [[1f32, 0f32, 0f32, 0f32], [0f32, 1f32, 0f32, 0f32], [0f32, 0f32, 1f32, 0f32]], 0, 0xFF, 0, bottom_level_acceleration_structure); + renderer.write_instance(instances_buffer, 0, [[1f32, 0f32, 0f32, 0f32], [0f32, 1f32, 0f32, 0f32], [0f32, 0f32, 1f32, 0f32]], 0, 0xFF, 0, bottom_level_acceleration_structure); - let build_sync = renderer.create_synchronizer(true); + let build_sync = renderer.create_synchronizer(None, true); - let scratch_buffer = renderer.create_buffer(None, 1024 * 1024, Uses::AccelerationStructureBuildScratch, DeviceAccesses::GpuWrite, UseCases::DYNAMIC); + let scratch_buffer = renderer.create_buffer(None, 1024 * 1024, Uses::AccelerationStructureBuildScratch, DeviceAccesses::GpuWrite, UseCases::STATIC); let raygen_sbt_buffer = renderer.create_buffer(None, 64, Uses::ShaderBindingTable, DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead, UseCases::STATIC); let miss_sbt_buffer = renderer.create_buffer(None, 64, Uses::ShaderBindingTable, DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead, UseCases::STATIC); @@ -2196,7 +2211,7 @@ void main() { command_buffer_recording.consume_resources(&[ Consumption { handle: Handle::BottomLevelAccelerationStructure(bottom_level_acceleration_structure), - stages: Stages::RAYGEN, + stages: Stages::ACCELERATION_STRUCTURE_BUILD, access: AccessPolicies::READ, layout: Layouts::General, } @@ -2216,7 +2231,7 @@ void main() { command_buffer_recording.bind_ray_tracing_pipeline(&pipeline); - command_buffer_recording.bind_descriptor_sets(&pipeline_layout, &[(descriptor_set, 0)]); + command_buffer_recording.bind_descriptor_sets(&pipeline_layout, &[descriptor_set]); command_buffer_recording.consume_resources(&[ Consumption { diff --git a/src/rendering/renderer.rs b/src/rendering/renderer.rs new file mode 100644 index 00000000..5cfd38d4 --- /dev/null +++ b/src/rendering/renderer.rs @@ -0,0 +1,118 @@ +use crate::{orchestrator, window_system, Extent}; + +use super::{visibility_model::render_domain::VisibilityWorldRenderDomain, render_system::{self, RenderSystem}, aces_tonemap_render_pass::AcesToneMapPass, tonemap_render_pass::ToneMapRenderPass, world_render_domain::WorldRenderDomain}; + +pub struct Renderer { + rendered_frame_count: usize, + + swapchain_handles: Vec, + + render_command_buffer: render_system::CommandBufferHandle, + render_finished_synchronizer: render_system::SynchronizerHandle, + image_ready: render_system::SynchronizerHandle, + + result: render_system::ImageHandle, + + visibility_render_model: orchestrator::EntityHandle, + tonemap_render_model: orchestrator::EntityHandle, +} + +impl Renderer { + pub fn new_as_system() -> 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 = 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)).unwrap(); + + 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 render_command_buffer = render_system.create_command_buffer(Some("Render")); + let render_finished_synchronizer = render_system.create_synchronizer(Some("Render Finisished"), true); + let image_ready = render_system.create_synchronizer(Some("Swapchain Available"), false); + + Renderer { + rendered_frame_count: 0, + + swapchain_handles: vec![], + + render_command_buffer, + render_finished_synchronizer, + image_ready, + + result, + + visibility_render_model, + tonemap_render_model, + } + }).add_listener::() + } + + 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 mut render_system = render_system.get_mut(); + let render_system = render_system.downcast_mut::().unwrap(); + + render_system.wait(self.render_finished_synchronizer); + + render_system.start_frame_capture(); + + let image_index = render_system.acquire_swapchain_image(swapchain_handle, self.image_ready); + + let mut command_buffer_recording = render_system.create_command_buffer_recording(self.render_command_buffer, Some(self.rendered_frame_count as u32)); + + 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()); + + 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()); + + // Copy to swapchain + + command_buffer_recording.copy_to_swapchain(self.result, image_index, swapchain_handle); + + command_buffer_recording.execute(&[self.image_ready], &[self.render_finished_synchronizer], self.render_finished_synchronizer); + + render_system.end_frame_capture(); + + render_system.present(image_index, &[swapchain_handle], self.render_finished_synchronizer); + + self.rendered_frame_count += 1; + } +} + +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 mut render_system = render_system.get_mut(); + let render_system = render_system.downcast_mut::().unwrap(); + + let window_system = orchestrator.get_by_class::(); + 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)); + + self.swapchain_handles.push(swapchain_handle); + } +} + +impl orchestrator::Entity for Renderer {} \ No newline at end of file diff --git a/src/rendering/rendering_domain.rs b/src/rendering/rendering_domain.rs new file mode 100644 index 00000000..325e1c8d --- /dev/null +++ b/src/rendering/rendering_domain.rs @@ -0,0 +1,3 @@ +trait RenderingDomain { + +} \ No newline at end of file diff --git a/src/rendering/shadow_render_pass.rs b/src/rendering/shadow_render_pass.rs new file mode 100644 index 00000000..94d75112 --- /dev/null +++ b/src/rendering/shadow_render_pass.rs @@ -0,0 +1,359 @@ +use crate::Extent; + +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, +} + +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; +} + +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; + + 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 new file mode 100644 index 00000000..cc69133c --- /dev/null +++ b/src/rendering/ssao_render_pass.rs @@ -0,0 +1,182 @@ +use crate::Extent; + +use super::render_system; + +struct ScreenSpaceAmbientOcclusionPass { + pipeline_layout: render_system::PipelineLayoutHandle, + pipeline: render_system::PipelineHandle, + blur_x_pipeline: render_system::PipelineHandle, + blur_y_pipeline: render_system::PipelineHandle, + descriptor_set_layout: render_system::DescriptorSetTemplateHandle, + descriptor_set: render_system::DescriptorSetHandle, + blur_x_descriptor_set: render_system::DescriptorSetHandle, + blur_y_descriptor_set: render_system::DescriptorSetHandle, + depth_binding: render_system::DescriptorSetBindingHandle, + result: render_system::ImageHandle, + x_blur_target: render_system::ImageHandle, + y_blur_target: render_system::ImageHandle, + + // Not owned by this render pass + depth_target: render_system::ImageHandle, +} + +impl ScreenSpaceAmbientOcclusionPass { + fn new(render_system: &mut dyn render_system::RenderSystem, parent_descriptor_set_layout: render_system::DescriptorSetTemplateHandle, depth_target: render_system::ImageHandle) -> ScreenSpaceAmbientOcclusionPass { + let depth_binding_template = render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::COMPUTE); + let source_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_layout = render_system.create_descriptor_set_template(Some("HBAO Pass Set Layout"), &[depth_binding_template.clone(), source_binding_template.clone(), result_binding_template.clone()]); + + let pipeline_layout = render_system.create_pipeline_layout(&[parent_descriptor_set_layout, descriptor_set_layout], &[]); + + let descriptor_set = render_system.create_descriptor_set(Some("HBAO Descriptor Set"), &descriptor_set_layout); + let blur_x_descriptor_set = render_system.create_descriptor_set(Some("HBAO Blur X Descriptor Set"), &descriptor_set_layout); + let blur_y_descriptor_set = render_system.create_descriptor_set(Some("HBAO Blur Y Descriptor Set"), &descriptor_set_layout); + + 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 blur_x_source_binding = render_system.create_descriptor_binding(blur_x_descriptor_set, &source_binding_template); + let blur_x_result_binding = render_system.create_descriptor_binding(blur_x_descriptor_set, &result_binding_template); + + 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 pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&shader, render_system::ShaderTypes::Compute, vec![])); + + let result = render_system.create_image(Some("HBAO Result"), Extent::new(1920, 1080, 1), render_system::Formats::RGBA16(render_system::Encodings::IEEE754), None, render_system::Uses::Storage | render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); + let x_blur_target = render_system.create_image(Some("X Blur"), Extent::new(1920, 1080, 1), render_system::Formats::RGBA16(render_system::Encodings::IEEE754), None, render_system::Uses::Storage | render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); + let y_blur_target = render_system.create_image(Some("Y Blur"), Extent::new(1920, 1080, 1), render_system::Formats::RGBA16(render_system::Encodings::IEEE754), None, render_system::Uses::Storage | render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); + + 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: 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: result, layout: render_system::Layouts::General }, + }, + ]); + + render_system.write(&[ + render_system::DescriptorWrite { + binding_handle: blur_x_source_binding, + array_element: 0, + descriptor: render_system::Descriptor::CombinedImageSampler { image_handle: result, sampler_handle: sampler, layout: render_system::Layouts::Read }, + }, + render_system::DescriptorWrite { + binding_handle: blur_x_result_binding, + array_element: 0, + descriptor: render_system::Descriptor::Image{ handle: x_blur_target, layout: render_system::Layouts::General }, + }, + ]); + + render_system.write(&[ + render_system::DescriptorWrite { + binding_handle: blur_y_source_binding, + array_element: 0, + descriptor: render_system::Descriptor::CombinedImageSampler { image_handle: x_blur_target, sampler_handle: sampler, layout: render_system::Layouts::Read }, + }, + render_system::DescriptorWrite { + binding_handle: blur_y_result_binding, + array_element: 0, + descriptor: render_system::Descriptor::Image{ handle: y_blur_target, layout: render_system::Layouts::General }, + }, + // render_system::DescriptorWrite { // AO Texture + // binding_handle: occlussion_texture_binding, + // array_element: 0, + // descriptor: render_system::Descriptor::CombinedImageSampler{ image_handle: y_blur_target, sampler_handle: sampler, layout: render_system::Layouts::Read }, + // }, + ]); + + let blur_shader = render_system.create_shader(render_system::ShaderSource::GLSL(BLUR_SHADER), render_system::ShaderTypes::Compute,); + + 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,] })])); + + ScreenSpaceAmbientOcclusionPass { + pipeline_layout, + descriptor_set_layout, + descriptor_set, + blur_x_descriptor_set, + blur_y_descriptor_set, + blur_x_pipeline, + blur_y_pipeline, + pipeline, + depth_binding, + result, + x_blur_target, + y_blur_target, + + depth_target, + } + } + + 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.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.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.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 } }); + } +} + +const HBAO_SHADER: &'static str = include_str!("../../assets/engine/shaders/ssao.comp"); +const BLUR_SHADER: &'static str = include_str!("../../assets/engine/shaders/blur.comp"); \ No newline at end of file diff --git a/src/rendering/tonemap_render_pass.rs b/src/rendering/tonemap_render_pass.rs new file mode 100644 index 00000000..32ca06fd --- /dev/null +++ b/src/rendering/tonemap_render_pass.rs @@ -0,0 +1,5 @@ +use super::render_system; + +pub trait ToneMapRenderPass { + fn render(&self, command_buffer_recording: &mut dyn render_system::CommandBufferRecording,); +} \ No newline at end of file diff --git a/src/rendering/visibility_model/render_domain.rs b/src/rendering/visibility_model/render_domain.rs index 5908d9d9..4b8efc1f 100644 --- a/src/rendering/visibility_model/render_domain.rs +++ b/src/rendering/visibility_model/render_domain.rs @@ -1,3 +1,4 @@ +use std::cmp::min; use std::collections::HashMap; use log::error; @@ -5,7 +6,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::{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}; struct VisibilityInfo { instance_count: u32, @@ -14,55 +17,84 @@ struct VisibilityInfo { vertex_count: u32, } -struct HBAOPass { - pipeline_layout: render_system::PipelineLayoutHandle, - pipeline: render_system::PipelineHandle, - blur_x_pipeline: render_system::PipelineHandle, - blur_y_pipeline: render_system::PipelineHandle, - descriptor_set_layout: render_system::DescriptorSetTemplateHandle, - descriptor_set: render_system::DescriptorSetHandle, - blur_x_descriptor_set: render_system::DescriptorSetHandle, - blur_y_descriptor_set: render_system::DescriptorSetHandle, - depth_binding: render_system::DescriptorSetBindingHandle, - result: render_system::ImageHandle, - x_blur_target: render_system::ImageHandle, - y_blur_target: render_system::ImageHandle, -} - -struct ToneMapPass { - pipeline_layout: render_system::PipelineLayoutHandle, - pipeline: render_system::PipelineHandle, - descriptor_set_layout: render_system::DescriptorSetTemplateHandle, - descriptor_set: render_system::DescriptorSetHandle, -} - struct MeshData { meshlets: Vec, vertex_count: u32, triangle_count: u32, /// The base index of the vertex buffer vertex_offset: u32, + /// The base index into the triangle indices buffer + triangle_offset: u32, + acceleration_structure: Option, +} + +enum MeshState { + Build { + mesh_handle: String, + }, + Update {}, +} + +struct RayTracing { + top_level_acceleration_structure: render_system::TopLevelAccelerationStructureHandle, + descriptor_set_template: render_system::DescriptorSetTemplateHandle, + descriptor_set: render_system::DescriptorSetHandle, + pipeline_layout: render_system::PipelineLayoutHandle, + pipeline: render_system::PipelineHandle, + + ray_gen_sbt_buffer: render_system::BaseBufferHandle, + miss_sbt_buffer: render_system::BaseBufferHandle, + hit_sbt_buffer: render_system::BaseBufferHandle, + + shadow_map_resolution: Extent, + shadow_map: render_system::ImageHandle, + + instances_buffer: render_system::BaseBufferHandle, + scratch_buffer: render_system::BaseBufferHandle, + + pending_meshes: Vec, } /// This the visibility buffer implementation of the world render domain. pub struct VisibilityWorldRenderDomain { + visibility_info: VisibilityInfo, + + camera: Option>, + + meshes: HashMap, + + mesh_resources: HashMap<&'static str, u32>, + + /// Maps resource ids to shaders + /// The hash and the shader handle are stored to determine if the shader has changed + shaders: std::collections::HashMap, + + material_evaluation_materials: HashMap, + + pending_texture_loads: Vec, + + occlusion_map: render_system::ImageHandle, + + transfer_synchronizer: render_system::SynchronizerHandle, + transfer_command_buffer: render_system::CommandBufferHandle, + + // Visibility + pipeline_layout_handle: render_system::PipelineLayoutHandle, vertex_positions_buffer: render_system::BaseBufferHandle, vertex_normals_buffer: render_system::BaseBufferHandle, + + /// Indices laid out as a triangle list + triangle_indices_buffer: render_system::BaseBufferHandle, + + /// Indices laid out as indices into the vertex buffers vertex_indices_buffer: render_system::BaseBufferHandle, + /// Indices laid out as indices into the `vertex_indices_buffer` primitive_indices_buffer: render_system::BaseBufferHandle, albedo: render_system::ImageHandle, depth_target: render_system::ImageHandle, - result: render_system::ImageHandle, - - visiblity_info: VisibilityInfo, - - render_finished_synchronizer: render_system::SynchronizerHandle, - image_ready: render_system::SynchronizerHandle, - render_command_buffer: render_system::CommandBufferHandle, - current_frame: usize, camera_data_buffer_handle: render_system::BaseBufferHandle, materials_data_buffer_handle: render_system::BaseBufferHandle, @@ -72,26 +104,10 @@ pub struct VisibilityWorldRenderDomain { textures_binding: render_system::DescriptorSetBindingHandle, - transfer_synchronizer: render_system::SynchronizerHandle, - transfer_command_buffer: render_system::CommandBufferHandle, - meshes_data_buffer: render_system::BaseBufferHandle, meshlets_data_buffer: render_system::BaseBufferHandle, + vertex_layout: [render_system::VertexElement; 2], - camera: Option>, - - meshes: HashMap, - - mesh_resources: HashMap<&'static str, u32>, - - VERTEX_LAYOUT: [render_system::VertexElement; 2], - - /// Maps resource ids to shaders - /// The hash and the shader handle are stored to determine if the shader has changed - shaders: std::collections::HashMap, - - swapchain_handles: Vec, - visibility_pass_pipeline_layout: render_system::PipelineLayoutHandle, visibility_passes_descriptor_set: render_system::DescriptorSetHandle, visibility_pass_pipeline: render_system::PipelineHandle, @@ -113,475 +129,150 @@ pub struct VisibilityWorldRenderDomain { material_evaluation_descriptor_set: render_system::DescriptorSetHandle, material_evaluation_pipeline_layout: render_system::PipelineLayoutHandle, - material_evaluation_materials: HashMap, - - tone_map_pass: ToneMapPass, debug_position: render_system::ImageHandle, debug_normal: render_system::ImageHandle, light_data_buffer: render_system::BaseBufferHandle, - - hbao_pass: HBAOPass, - - pending_texture_loads: Vec, - - top_level_acceleration_structure: render_system::TopLevelAccelerationStructureHandle, } -const VERTEX_COUNT: u32 = 64; -const TRIANGLE_COUNT: u32 = 126; - -const MAX_MESHLETS: usize = 1024; -const MAX_INSTANCES: usize = 1024; -const MAX_MATERIALS: usize = 1024; -const MAX_LIGHTS: usize = 16; -const MAX_TRIANGLES: usize = 65536; -const MAX_PRIMITIVE_TRIANGLES: usize = 65536; -const MAX_VERTICES: usize = 65536; +impl VisibilityWorldRenderDomain { + pub fn new<'a>(render_system: &'a mut dyn render_system::RenderSystem) -> orchestrator::EntityReturn<'a, Self> { + orchestrator::EntityReturn::new_from_function(move |orchestrator| { + 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), + render_system::DescriptorSetBindingTemplate::new(2, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), + render_system::DescriptorSetBindingTemplate::new(3, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), + render_system::DescriptorSetBindingTemplate::new(4, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), + render_system::DescriptorSetBindingTemplate::new(5, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), + render_system::DescriptorSetBindingTemplate::new(6, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), + render_system::DescriptorSetBindingTemplate::new(7, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::COMPUTE), + ]; -const VISIBILITY_PASS_MESH_SOURCE: &'static str = " -#version 450 -#pragma shader_stage(mesh) + let descriptor_set_layout = render_system.create_descriptor_set_template(Some("Base Set Layout"), &bindings); -#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_shader_explicit_arithmetic_types: enable -#extension GL_EXT_mesh_shader: require -#extension GL_EXT_debug_printf : enable + let descriptor_set = render_system.create_descriptor_set(Some("Base Descriptor Set"), &descriptor_set_layout); -layout(row_major) uniform; layout(row_major) buffer; + let camera_data_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[0]); + let meshes_data_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[1]); + let vertex_positions_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[2]); + let vertex_normals_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[3]); + let vertex_indices_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[4]); + let primitive_indices_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[5]); + let meshlets_data_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[6]); + let textures_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[7]); -layout(location=0) perprimitiveEXT out uint out_instance_index[126]; -layout(location=1) perprimitiveEXT out uint out_primitive_index[126]; + let pipeline_layout_handle = render_system.create_pipeline_layout(&[descriptor_set_layout], &[]); + + let vertex_positions_buffer_handle = render_system.create_buffer(Some("Visibility Vertex Positions Buffer"), std::mem::size_of::<[[f32; 3]; MAX_VERTICES]>(), render_system::Uses::Vertex | Uses::AccelerationStructureBuild | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let vertex_normals_buffer_handle = render_system.create_buffer(Some("Visibility Vertex Normals Buffer"), std::mem::size_of::<[[f32; 3]; MAX_VERTICES]>(), render_system::Uses::Vertex | Uses::AccelerationStructureBuild | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let triangle_indices_buffer_handle = render_system.create_buffer(Some("Visibility Triangle Indices Buffer"), std::mem::size_of::<[[u16; 3]; MAX_TRIANGLES]>(), render_system::Uses::Index | Uses::AccelerationStructureBuild | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let vertex_indices_buffer_handle = render_system.create_buffer(Some("Visibility Index Buffer"), std::mem::size_of::<[[u8; 3]; MAX_TRIANGLES]>(), render_system::Uses::Index | Uses::AccelerationStructureBuild | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let primitive_indices_buffer_handle = render_system.create_buffer(Some("Visibility Primitive Indices Buffer"), std::mem::size_of::<[[u16; 3]; MAX_PRIMITIVE_TRIANGLES]>(), render_system::Uses::Index | Uses::AccelerationStructureBuild | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); -struct Camera { - mat4 view_matrix; - mat4 projection_matrix; - mat4 view_projection; -}; + let debug_position = render_system.create_image(Some("debug position"), Extent::new(1920, 1080, 1), render_system::Formats::RGBAu16, None, render_system::Uses::RenderTarget | render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); + let debug_normals = render_system.create_image(Some("debug normal"), Extent::new(1920, 1080, 1), render_system::Formats::RGBAu16, None, render_system::Uses::RenderTarget | render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); -struct Mesh { - mat4 model; - uint material_id; - uint32_t base_vertex_index; -}; + let albedo = render_system.create_image(Some("albedo"), Extent::new(1920, 1080, 1), render_system::Formats::RGBAu16, None, render_system::Uses::RenderTarget | render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); + let depth_target = render_system.create_image(Some("depth_target"), Extent::new(1920, 1080, 1), render_system::Formats::Depth32, None, render_system::Uses::DepthStencil | render_system::Uses::Image, render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); -struct Meshlet { - uint32_t instance_index; - uint16_t vertex_offset; - uint16_t triangle_offset; - uint8_t vertex_count; - uint8_t triangle_count; -}; + let camera_data_buffer_handle = render_system.create_buffer(Some("Visibility Camera Data"), 16 * 4 * 4, render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); -layout(set=0,binding=0,scalar) buffer readonly CameraBuffer { - Camera camera; -}; + let meshes_data_buffer = render_system.create_buffer(Some("Visibility Meshes Data"), std::mem::size_of::<[ShaderInstanceData; MAX_INSTANCES]>(), render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let meshlets_data_buffer = render_system.create_buffer(Some("Visibility Meshlets Data"), std::mem::size_of::<[ShaderMeshletData; MAX_MESHLETS]>(), render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); -layout(set=0,binding=1,scalar) buffer readonly MeshesBuffer { - Mesh meshes[]; -}; + render_system.write(&[ + render_system::DescriptorWrite { + binding_handle: camera_data_binding, + array_element: 0, + descriptor: render_system::Descriptor::Buffer{ handle: camera_data_buffer_handle, size: render_system::Ranges::Whole }, + }, + render_system::DescriptorWrite { + binding_handle: meshes_data_binding, + array_element: 0, + descriptor: render_system::Descriptor::Buffer{ handle: meshes_data_buffer, size: render_system::Ranges::Whole }, + }, + render_system::DescriptorWrite { + binding_handle: vertex_positions_binding, + array_element: 0, + descriptor: render_system::Descriptor::Buffer{ handle: vertex_positions_buffer_handle, size: render_system::Ranges::Whole }, + }, + render_system::DescriptorWrite { + binding_handle: vertex_normals_binding, + array_element: 0, + descriptor: render_system::Descriptor::Buffer{ handle: vertex_normals_buffer_handle, size: render_system::Ranges::Whole }, + }, + render_system::DescriptorWrite { + binding_handle: vertex_indices_binding, + array_element: 0, + descriptor: render_system::Descriptor::Buffer{ handle: vertex_indices_buffer_handle, size: render_system::Ranges::Whole }, + }, + render_system::DescriptorWrite { + binding_handle: primitive_indices_binding, + array_element: 0, + descriptor: render_system::Descriptor::Buffer{ handle: primitive_indices_buffer_handle, size: render_system::Ranges::Whole }, + }, + render_system::DescriptorWrite { + binding_handle: meshlets_data_binding, + array_element: 0, + descriptor: render_system::Descriptor::Buffer { handle: meshlets_data_buffer, size: render_system::Ranges::Whole }, + }, + ]); -layout(set=0,binding=2,scalar) buffer readonly MeshVertexPositions { - vec3 vertex_positions[]; -}; + 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,); -layout(set=0,binding=4,scalar) buffer readonly VertexIndices { - uint16_t vertex_indices[]; -}; + let visibility_pass_shaders = [ + (&visibility_pass_mesh_shader, render_system::ShaderTypes::Mesh, vec![]), + (&visibility_pass_fragment_shader, render_system::ShaderTypes::Fragment, vec![]), + ]; -layout(set=0,binding=5,scalar) buffer readonly PrimitiveIndices { - uint8_t primitive_indices[]; -}; + let primitive_index = render_system.create_image(Some("primitive index"), crate::Extent::new(1920, 1080, 1), render_system::Formats::U32, None, render_system::Uses::RenderTarget | render_system::Uses::Storage, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); + let instance_id = render_system.create_image(Some("instance_id"), crate::Extent::new(1920, 1080, 1), render_system::Formats::U32, None, render_system::Uses::RenderTarget | render_system::Uses::Storage, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); -layout(set=0,binding=6,scalar) buffer readonly MeshletsBuffer { - Meshlet meshlets[]; -}; + let attachments = [ + render_system::AttachmentInformation { + image: primitive_index, + layout: render_system::Layouts::RenderTarget, + format: render_system::Formats::U32, + clear: render_system::ClearValue::Integer(!0u32, 0, 0, 0), + load: false, + store: true, + }, + render_system::AttachmentInformation { + image: instance_id, + layout: render_system::Layouts::RenderTarget, + format: render_system::Formats::U32, + clear: render_system::ClearValue::Integer(!0u32, 0, 0, 0), + load: false, + store: true, + }, + render_system::AttachmentInformation { + image: depth_target, + layout: render_system::Layouts::RenderTarget, + format: render_system::Formats::Depth32, + clear: render_system::ClearValue::Depth(0f32), + load: false, + store: true, + }, + ]; -layout(triangles, max_vertices=64, max_primitives=126) out; -layout(local_size_x=128) in; -void main() { - uint meshlet_index = gl_WorkGroupID.x; + let vertex_layout = [ + render_system::VertexElement{ name: "POSITION".to_string(), format: render_system::DataTypes::Float3, binding: 0 }, + render_system::VertexElement{ name: "NORMAL".to_string(), format: render_system::DataTypes::Float3, binding: 1 }, + ]; - Meshlet meshlet = meshlets[meshlet_index]; - Mesh mesh = meshes[meshlet.instance_index]; + let visibility_pass_pipeline = render_system.create_raster_pipeline(&[ + render_system::PipelineConfigurationBlocks::Layout { layout: &pipeline_layout_handle }, + render_system::PipelineConfigurationBlocks::Shaders { shaders: &visibility_pass_shaders }, + render_system::PipelineConfigurationBlocks::RenderTargets { targets: &attachments }, + ]); - uint instance_index = meshlet.instance_index; + let material_count = render_system.create_buffer(Some("Material Count"), std::mem::size_of::<[u32; MAX_MATERIALS]>(), render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let material_offset = render_system.create_buffer(Some("Material Offset"), std::mem::size_of::<[u32; MAX_MATERIALS]>(), render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let material_offset_scratch = render_system.create_buffer(Some("Material Offset Scratch"), std::mem::size_of::<[u32; MAX_MATERIALS]>(), render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let material_evaluation_dispatches = render_system.create_buffer(Some("Material Evaluation Dipatches"), std::mem::size_of::<[[u32; 3]; MAX_MATERIALS]>(), render_system::Uses::Storage | render_system::Uses::TransferDestination | render_system::Uses::Indirect, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - SetMeshOutputsEXT(meshlet.vertex_count, meshlet.triangle_count); - - if (gl_LocalInvocationID.x < uint(meshlet.vertex_count)) { - uint vertex_index = mesh.base_vertex_index + uint32_t(vertex_indices[uint(meshlet.vertex_offset) + gl_LocalInvocationID.x]); - gl_MeshVerticesEXT[gl_LocalInvocationID.x].gl_Position = camera.view_projection * meshes[instance_index].model * vec4(vertex_positions[vertex_index], 1.0); - // gl_MeshVerticesEXT[gl_LocalInvocationID.x].gl_Position = vec4(vertex_positions[vertex_index], 1.0); - } - - if (gl_LocalInvocationID.x < uint(meshlet.triangle_count)) { - uint triangle_index = uint(meshlet.triangle_offset) + gl_LocalInvocationID.x; - uint triangle_indices[3] = uint[](primitive_indices[triangle_index * 3 + 0], primitive_indices[triangle_index * 3 + 1], primitive_indices[triangle_index * 3 + 2]); - gl_PrimitiveTriangleIndicesEXT[gl_LocalInvocationID.x] = uvec3(triangle_indices[0], triangle_indices[1], triangle_indices[2]); - out_instance_index[gl_LocalInvocationID.x] = instance_index; - out_primitive_index[gl_LocalInvocationID.x] = (meshlet_index << 8) | (gl_LocalInvocationID.x & 0xFF); - } -}"; - -const VISIBILITY_PASS_FRAGMENT_SOURCE: &'static str = r#" -#version 450 -#pragma shader_stage(fragment) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_shader_explicit_arithmetic_types : enable -#extension GL_EXT_buffer_reference: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_mesh_shader: require - -layout(location=0) perprimitiveEXT flat in uint in_instance_index; -layout(location=1) perprimitiveEXT flat in uint in_primitive_index; - -layout(location=0) out uint out_primitive_index; -layout(location=1) out uint out_instance_id; - -void main() { - out_primitive_index = in_primitive_index; - out_instance_id = in_instance_index; -} -"#; - -const MATERIAL_COUNT_SOURCE: &'static str = r#" -#version 450 -#pragma shader_stage(compute) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_shader_explicit_arithmetic_types : enable - -struct Mesh { - mat4 model; - uint material_index; - uint32_t base_vertex_index; -}; - -layout(set=0,binding=1,scalar) buffer MeshesBuffer { - Mesh meshes[]; -}; - -layout(set=1,binding=0,scalar) buffer MaterialCount { - uint material_count[]; -}; - -layout(set=1, binding=7, r32ui) uniform readonly uimage2D instance_index; - -layout(local_size_x=32, local_size_y=32) in; -void main() { - // If thread is out of bound respect to the material_id texture, return - if (gl_GlobalInvocationID.x >= imageSize(instance_index).x || gl_GlobalInvocationID.y >= imageSize(instance_index).y) { return; } - - uint pixel_instance_index = imageLoad(instance_index, ivec2(gl_GlobalInvocationID.xy)).r; - - if (pixel_instance_index == 0xFFFFFFFF) { return; } - - uint material_index = meshes[pixel_instance_index].material_index; - - atomicAdd(material_count[material_index], 1); -} -"#; - -const MATERIAL_OFFSET_SOURCE: &'static str = r#" -#version 450 -#pragma shader_stage(compute) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_shader_explicit_arithmetic_types : enable - -layout(set=1,binding=0,scalar) buffer MaterialCount { - uint material_count[]; -}; - -layout(set=1,binding=1,scalar) buffer MaterialOffset { - uint material_offset[]; -}; - -layout(set=1,binding=2,scalar) buffer MaterialOffsetScratch { - uint material_offset_scratch[]; -}; - -layout(set=1,binding=3,scalar) buffer MaterialEvaluationDispatches { - uvec3 material_evaluation_dispatches[]; -}; - -layout(local_size_x=1) in; -void main() { - uint sum = 0; - - for (uint i = 0; i < 4; i++) { - material_offset[i] = sum; - material_offset_scratch[i] = sum; - material_evaluation_dispatches[i] = uvec3((material_count[i] + 31) / 32, 1, 1); - sum += material_count[i]; - } -} -"#; - -const PIXEL_MAPPING_SOURCE: &'static str = r#" -#version 450 -#pragma shader_stage(compute) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_shader_explicit_arithmetic_types : enable - -struct Mesh { - mat4 model; - uint material_index; - uint32_t base_vertex_index; -}; - -layout(set=0,binding=1,scalar) buffer MeshesBuffer { - Mesh meshes[]; -}; - -layout(set=1,binding=1,scalar) buffer MaterialOffset { - uint material_offset[]; -}; - -layout(set=1,binding=2,scalar) buffer MaterialOffsetScratch { - uint material_offset_scratch[]; -}; - -layout(set=1,binding=4,scalar) buffer PixelMapping { - u16vec2 pixel_mapping[]; -}; - -layout(set=1, binding=7, r32ui) uniform readonly uimage2D instance_index; - -layout(local_size_x=32, local_size_y=32) in; -void main() { - // If thread is out of bound respect to the material_id texture, return - if (gl_GlobalInvocationID.x >= imageSize(instance_index).x || gl_GlobalInvocationID.y >= imageSize(instance_index).y) { return; } - - uint pixel_instance_index = imageLoad(instance_index, ivec2(gl_GlobalInvocationID.xy)).r; - - if (pixel_instance_index == 0xFFFFFFFF) { return; } - - uint material_index = meshes[pixel_instance_index].material_index; - - uint offset = atomicAdd(material_offset_scratch[material_index], 1); - - pixel_mapping[offset] = u16vec2(gl_GlobalInvocationID.xy); -} -"#; - -const TONE_MAPPING_SHADER: &'static str = r#" -#version 450 -#pragma shader_stage(compute) - -#extension GL_EXT_scalar_block_layout: enable -#extension GL_EXT_buffer_reference2: enable -#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable - -layout(set=0, binding=0, rgba16) uniform readonly image2D source; -layout(set=0, binding=1, rgba8) uniform image2D result; - -vec3 ACESNarkowicz(vec3 x) { - const float a = 2.51; - const float b = 0.03; - const float c = 2.43; - const float d = 0.59; - const float e = 0.14; - return clamp((x*(a*x+b))/(x*(c*x+d)+e), 0.0, 1.0); -} - -const mat3 ACES_INPUT_MAT = mat3( - vec3( 0.59719, 0.35458, 0.04823), - vec3( 0.07600, 0.90834, 0.01566), - vec3( 0.02840, 0.13383, 0.83777) -); - -const mat3 ACES_OUTPUT_MAT = mat3( - vec3( 1.60475, -0.53108, -0.07367), - vec3(-0.10208, 1.10813, -0.00605), - vec3(-0.00327, -0.07276, 1.07602) -); - -vec3 RRTAndODTFit(vec3 v) { - vec3 a = v * (v + 0.0245786) - 0.000090537; - vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081; - return a / b; -} - -vec3 ACESFitted(vec3 x) { - return clamp(ACES_OUTPUT_MAT * RRTAndODTFit(ACES_INPUT_MAT * x), 0.0, 1.0); -} - -layout(local_size_x=32, local_size_y=32) in; -void main() { - if (gl_GlobalInvocationID.x >= imageSize(source).x || gl_GlobalInvocationID.y >= imageSize(source).y) { return; } - - vec4 source_color = imageLoad(source, ivec2(gl_GlobalInvocationID.xy)); - - vec3 result_color = ACESNarkowicz(source_color.rgb); - - result_color = pow(result_color, vec3(1.0 / 2.2)); - - imageStore(result, ivec2(gl_GlobalInvocationID.xy), vec4(result_color, 1.0)); -} -"#; - -const HBAO_SHADER: &'static str = include_str!("../../../assets/engine/shaders/ssao.comp"); -const BLUR_SHADER: &'static str = include_str!("../../../assets/engine/shaders/blur.comp"); - -impl VisibilityWorldRenderDomain { - pub fn new() -> orchestrator::EntityReturn { - 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: &mut render_system::RenderSystemImplementation = render_system.downcast_mut().unwrap(); - - let bindings = [ - render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::FRAGMENT | 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), - render_system::DescriptorSetBindingTemplate::new(2, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), - render_system::DescriptorSetBindingTemplate::new(3, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), - render_system::DescriptorSetBindingTemplate::new(4, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), - render_system::DescriptorSetBindingTemplate::new(5, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), - render_system::DescriptorSetBindingTemplate::new(6, render_system::DescriptorType::StorageBuffer, render_system::Stages::MESH | render_system::Stages::COMPUTE), - render_system::DescriptorSetBindingTemplate::new(7, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::COMPUTE), - ]; - - let descriptor_set_layout = render_system.create_descriptor_set_template(Some("Base Set Layout"), &bindings); - - let descriptor_set = render_system.create_descriptor_set(Some("Base Descriptor Set"), &descriptor_set_layout); - - let camera_data_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[0]); - let meshes_data_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[1]); - let vertex_positions_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[2]); - let vertex_normals_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[3]); - let vertex_indices_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[4]); - let primitive_indices_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[5]); - let meshlets_data_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[6]); - let textures_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[7]); - - let pipeline_layout_handle = render_system.create_pipeline_layout(&[descriptor_set_layout], &[]); - - let vertex_positions_buffer_handle = render_system.create_buffer(Some("Visibility Vertex Positions Buffer"), std::mem::size_of::<[[f32; 3]; MAX_VERTICES]>(), render_system::Uses::Vertex | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - let vertex_normals_buffer_handle = render_system.create_buffer(Some("Visibility Vertex Normals Buffer"), std::mem::size_of::<[[f32; 3]; MAX_VERTICES]>(), render_system::Uses::Vertex | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - let vertex_indices_buffer_handle = render_system.create_buffer(Some("Visibility Index Buffer"), std::mem::size_of::<[[u8; 3]; MAX_TRIANGLES]>(), render_system::Uses::Index | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - let primitive_indices_buffer_handle = render_system.create_buffer(Some("Visibility Primitive Indices Buffer"), std::mem::size_of::<[[u16; 3]; MAX_PRIMITIVE_TRIANGLES]>(), render_system::Uses::Index | render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - - let debug_position = render_system.create_image(Some("debug position"), Extent::new(1920, 1080, 1), render_system::Formats::RGBAu16, None, render_system::Uses::RenderTarget | render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - let debug_normals = render_system.create_image(Some("debug normal"), Extent::new(1920, 1080, 1), render_system::Formats::RGBAu16, None, render_system::Uses::RenderTarget | render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - - let albedo = render_system.create_image(Some("albedo"), Extent::new(1920, 1080, 1), render_system::Formats::RGBAu16, None, render_system::Uses::RenderTarget | render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - let depth_target = render_system.create_image(Some("depth_target"), Extent::new(1920, 1080, 1), render_system::Formats::Depth32, None, render_system::Uses::DepthStencil | render_system::Uses::Image, render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - - let render_finished_synchronizer = render_system.create_synchronizer(true); - let image_ready = render_system.create_synchronizer(false); - - let transfer_synchronizer = render_system.create_synchronizer(false); - - let render_command_buffer = render_system.create_command_buffer(); - let transfer_command_buffer = render_system.create_command_buffer(); - - let camera_data_buffer_handle = render_system.create_buffer(Some("Visibility Camera Data"), 16 * 4 * 4, render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - - let meshes_data_buffer = render_system.create_buffer(Some("Visibility Meshes Data"), std::mem::size_of::<[ShaderInstanceData; MAX_INSTANCES]>(), render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - let meshlets_data_buffer = render_system.create_buffer(Some("Visibility Meshlets Data"), std::mem::size_of::<[ShaderMeshletData; MAX_MESHLETS]>(), render_system::Uses::Storage, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - - render_system.write(&[ - render_system::DescriptorWrite { - binding_handle: camera_data_binding, - array_element: 0, - descriptor: render_system::Descriptor::Buffer{ handle: camera_data_buffer_handle, size: render_system::Ranges::Whole }, - }, - render_system::DescriptorWrite { - binding_handle: meshes_data_binding, - array_element: 0, - descriptor: render_system::Descriptor::Buffer{ handle: meshes_data_buffer, size: render_system::Ranges::Whole }, - }, - render_system::DescriptorWrite { - binding_handle: vertex_positions_binding, - array_element: 0, - descriptor: render_system::Descriptor::Buffer{ handle: vertex_positions_buffer_handle, size: render_system::Ranges::Whole }, - }, - render_system::DescriptorWrite { - binding_handle: vertex_normals_binding, - array_element: 0, - descriptor: render_system::Descriptor::Buffer{ handle: vertex_normals_buffer_handle, size: render_system::Ranges::Whole }, - }, - render_system::DescriptorWrite { - binding_handle: vertex_indices_binding, - array_element: 0, - descriptor: render_system::Descriptor::Buffer{ handle: vertex_indices_buffer_handle, size: render_system::Ranges::Whole }, - }, - render_system::DescriptorWrite { - binding_handle: primitive_indices_binding, - array_element: 0, - descriptor: render_system::Descriptor::Buffer{ handle: primitive_indices_buffer_handle, size: render_system::Ranges::Whole }, - }, - render_system::DescriptorWrite { - binding_handle: meshlets_data_binding, - array_element: 0, - descriptor: render_system::Descriptor::Buffer { handle: meshlets_data_buffer, size: render_system::Ranges::Whole }, - }, - ]); - - 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_shaders = [ - (&visibility_pass_mesh_shader, render_system::ShaderTypes::Mesh, vec![]), - (&visibility_pass_fragment_shader, render_system::ShaderTypes::Fragment, vec![]), - ]; - - let primitive_index = render_system.create_image(Some("primitive index"), crate::Extent::new(1920, 1080, 1), render_system::Formats::U32, None, render_system::Uses::RenderTarget | render_system::Uses::Storage, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - let instance_id = render_system.create_image(Some("instance_id"), crate::Extent::new(1920, 1080, 1), render_system::Formats::U32, None, render_system::Uses::RenderTarget | render_system::Uses::Storage, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - - let attachments = [ - render_system::AttachmentInformation { - image: primitive_index, - layout: render_system::Layouts::RenderTarget, - format: render_system::Formats::U32, - clear: render_system::ClearValue::Integer(!0u32, 0, 0, 0), - load: false, - store: true, - }, - render_system::AttachmentInformation { - image: instance_id, - layout: render_system::Layouts::RenderTarget, - format: render_system::Formats::U32, - clear: render_system::ClearValue::Integer(!0u32, 0, 0, 0), - load: false, - store: true, - }, - render_system::AttachmentInformation { - image: depth_target, - layout: render_system::Layouts::RenderTarget, - format: render_system::Formats::Depth32, - clear: render_system::ClearValue::Depth(0f32), - load: false, - store: true, - }, - ]; - - let VERTEX_LAYOUT = [ - render_system::VertexElement{ name: "POSITION".to_string(), format: render_system::DataTypes::Float3, binding: 0 }, - render_system::VertexElement{ name: "NORMAL".to_string(), format: render_system::DataTypes::Float3, binding: 1 }, - ]; - - let visibility_pass_pipeline = render_system.create_raster_pipeline(&[ - render_system::PipelineConfigurationBlocks::Layout { layout: &pipeline_layout_handle }, - render_system::PipelineConfigurationBlocks::Shaders { shaders: &visibility_pass_shaders }, - render_system::PipelineConfigurationBlocks::RenderTargets { targets: &attachments }, - ]); - - let material_count = render_system.create_buffer(Some("Material Count"), std::mem::size_of::<[u32; MAX_MATERIALS]>(), render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - let material_offset = render_system.create_buffer(Some("Material Offset"), std::mem::size_of::<[u32; MAX_MATERIALS]>(), render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - let material_offset_scratch = render_system.create_buffer(Some("Material Offset Scratch"), std::mem::size_of::<[u32; MAX_MATERIALS]>(), render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - let material_evaluation_dispatches = render_system.create_buffer(Some("Material Evaluation Dipatches"), std::mem::size_of::<[[u32; 3]; MAX_MATERIALS]>(), render_system::Uses::Storage | render_system::Uses::TransferDestination | render_system::Uses::Indirect, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); - - let material_xy = render_system.create_buffer(Some("Material XY"), 1920 * 1080 * 2 * 2, render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); + let material_xy = render_system.create_buffer(Some("Material XY"), 1920 * 1080 * 2 * 2, render_system::Uses::Storage | render_system::Uses::TransferDestination, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); let bindings = [ render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::StorageBuffer, render_system::Stages::COMPUTE), @@ -606,7 +297,6 @@ impl VisibilityWorldRenderDomain { let _material_id_binding = render_system.create_descriptor_binding(visibility_passes_descriptor_set, &bindings[5]); let vertex_id_binding = render_system.create_descriptor_binding(visibility_passes_descriptor_set, &bindings[6]); let instance_id_binding = render_system.create_descriptor_binding(visibility_passes_descriptor_set, &bindings[7]); - // let ao_texture_binding = render_system.create_descriptor_binding(visibility_passes_descriptor_set, &bindings[8]); render_system.write(&[ render_system::DescriptorWrite { // MaterialCount @@ -682,7 +372,10 @@ impl VisibilityWorldRenderDomain { let debug_normals_binding = render_system.create_descriptor_binding(material_evaluation_descriptor_set, &bindings[3]); let light_data_binding = render_system.create_descriptor_binding(material_evaluation_descriptor_set, &bindings[4]); let materials_data_binding = render_system.create_descriptor_binding(material_evaluation_descriptor_set, &bindings[5]); - let ao_texture_binding = render_system.create_descriptor_binding(material_evaluation_descriptor_set, &bindings[6]); + let occlussion_texture_binding = render_system.create_descriptor_binding(material_evaluation_descriptor_set, &bindings[6]); + + let sampler = render_system.create_sampler(render_system::FilteringModes::Linear, render_system::FilteringModes::Linear, render_system::SamplerAddressingModes::Clamp, None, 0f32, 0f32); + let occlusion_map = render_system.create_image(Some("Occlusion Map"), Extent::new(1920, 1080, 1), render_system::Formats::R8(render_system::Encodings::UnsignedNormalized), None, render_system::Uses::Storage | render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::STATIC); render_system.write(&[ render_system::DescriptorWrite { // albedo @@ -715,195 +408,45 @@ impl VisibilityWorldRenderDomain { array_element: 0, descriptor: render_system::Descriptor::Buffer{ handle: materials_data_buffer_handle, size: render_system::Ranges::Whole }, }, + render_system::DescriptorWrite { // OcclussionTexture + binding_handle: occlussion_texture_binding, + array_element: 0, + descriptor: render_system::Descriptor::CombinedImageSampler{ image_handle: occlusion_map, sampler_handle: sampler, layout: render_system::Layouts::Read }, + }, ]); let material_evaluation_pipeline_layout = render_system.create_pipeline_layout(&[descriptor_set_layout, visibility_descriptor_set_layout, material_evaluation_descriptor_set_layout], &[render_system::PushConstantRange{ offset: 0, size: 4 }]); - let result = render_system.create_image(Some("result"), Extent::new(1920, 1080, 1), 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 tone_map_pass = { - let bindings = [ - render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::StorageImage, render_system::Stages::COMPUTE), - render_system::DescriptorSetBindingTemplate::new(1, render_system::DescriptorType::StorageImage, render_system::Stages::COMPUTE), - ]; - - let descriptor_set_layout = render_system.create_descriptor_set_template(Some("Tonemap Pass Set Layout"), &bindings); + let transfer_synchronizer = render_system.create_synchronizer(Some("Transfer Synchronizer"), false); + let transfer_command_buffer = render_system.create_command_buffer(Some("Transfer")); - let pipeline_layout = render_system.create_pipeline_layout(&[descriptor_set_layout], &[]); - - let descriptor_set = render_system.create_descriptor_set(Some("Tonemap Pass Descriptor Set"), &descriptor_set_layout); - - let albedo_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[0]); - let result_binding = render_system.create_descriptor_binding(descriptor_set, &bindings[1]); - - render_system.write(&[ - render_system::DescriptorWrite { - binding_handle: albedo_binding, - array_element: 0, - descriptor: render_system::Descriptor::Image{ handle: albedo, layout: render_system::Layouts::General }, - }, - render_system::DescriptorWrite { - binding_handle: result_binding, - array_element: 0, - descriptor: render_system::Descriptor::Image{ handle: result, layout: render_system::Layouts::General }, - }, - ]); + Self { + visibility_info: VisibilityInfo{ triangle_count: 0, instance_count: 0, meshlet_count:0, vertex_count:0, }, - let tone_mapping_shader = render_system.create_shader(render_system::ShaderSource::GLSL(TONE_MAPPING_SHADER), render_system::ShaderTypes::Compute,); - let tone_mapping_pipeline = render_system.create_compute_pipeline(&pipeline_layout, (&tone_mapping_shader, render_system::ShaderTypes::Compute, vec![])); + shaders: HashMap::new(), - ToneMapPass { - descriptor_set_layout, - pipeline_layout, - descriptor_set, - pipeline: tone_mapping_pipeline, - } - }; + camera: None, - let _instance_buffer = render_system.create_acceleration_structure_instance_buffer(Some("Scene Instance Buffer"), MAX_INSTANCES as u32); - - let top_level_acceleration_structure = render_system.create_top_level_acceleration_structure(Some("Top Level Acceleration Structure")); + meshes: HashMap::new(), - let bindings = [ - render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::AccelerationStructure, render_system::Stages::RAYGEN), - ]; + mesh_resources: HashMap::new(), - let rt_pass_descriptor_set_layout = render_system.create_descriptor_set_template(Some("RT Pass Set Layout"), &bindings); + material_evaluation_materials: HashMap::new(), - let _rt_pass_pipeline_layout = render_system.create_pipeline_layout(&[descriptor_set_layout, rt_pass_descriptor_set_layout], &[]); + pending_texture_loads: Vec::new(), - let rt_pass_descriptor_set = render_system.create_descriptor_set(Some("RT Pass Descriptor Set"), &rt_pass_descriptor_set_layout); - - let top_level_binding = render_system.create_descriptor_binding(rt_pass_descriptor_set, &bindings[0]); - - render_system.write(&[ - render_system::DescriptorWrite { - binding_handle: top_level_binding, - array_element: 0, - descriptor: render_system::Descriptor::AccelerationStructure{ handle: top_level_acceleration_structure }, - }, - ]); - - 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; + occlusion_map, -void main() { - const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); - const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - vec2 d = inUV * 2.0 - 1.0; -}"; + transfer_synchronizer, + transfer_command_buffer, - let hbao_pass = { - let depth_binding_template = render_system::DescriptorSetBindingTemplate::new(0, render_system::DescriptorType::CombinedImageSampler, render_system::Stages::COMPUTE); - let source_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 hbao_pass_descriptor_set_layout = render_system.create_descriptor_set_template(Some("HBAO Pass Set Layout"), &[depth_binding_template.clone(), source_binding_template.clone(), result_binding_template.clone()]); - - let hbao_pass_pipeline_layout = render_system.create_pipeline_layout(&[descriptor_set_layout, hbao_pass_descriptor_set_layout], &[]); - - let hbao_pass_descriptor_set = render_system.create_descriptor_set(Some("HBAO Descriptor Set"), &hbao_pass_descriptor_set_layout); - let blur_x_descriptor_set = render_system.create_descriptor_set(Some("HBAO Blur X Descriptor Set"), &hbao_pass_descriptor_set_layout); - let blur_y_descriptor_set = render_system.create_descriptor_set(Some("HBAO Blur Y Descriptor Set"), &hbao_pass_descriptor_set_layout); - - let depth_binding = render_system.create_descriptor_binding(hbao_pass_descriptor_set, &depth_binding_template); - let result_binding = render_system.create_descriptor_binding(hbao_pass_descriptor_set, &result_binding_template); - - let blur_x_source_binding = render_system.create_descriptor_binding(blur_x_descriptor_set, &source_binding_template); - let blur_x_result_binding = render_system.create_descriptor_binding(blur_x_descriptor_set, &result_binding_template); - - 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 pipeline = render_system.create_compute_pipeline(&hbao_pass_pipeline_layout, (&shader, render_system::ShaderTypes::Compute, vec![])); - - let result = render_system.create_image(Some("HBAO Result"), Extent::new(1920, 1080, 1), render_system::Formats::RGBA16(render_system::Encodings::IEEE754), None, render_system::Uses::Storage | render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - let x_blur_target = render_system.create_image(Some("X Blur"), Extent::new(1920, 1080, 1), render_system::Formats::RGBA16(render_system::Encodings::IEEE754), None, render_system::Uses::Storage | render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - let y_blur_target = render_system.create_image(Some("Y Blur"), Extent::new(1920, 1080, 1), render_system::Formats::RGBA16(render_system::Encodings::IEEE754), None, render_system::Uses::Storage | render_system::Uses::Image, render_system::DeviceAccesses::GpuWrite | render_system::DeviceAccesses::GpuRead, render_system::UseCases::DYNAMIC); - - 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: 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: result, layout: render_system::Layouts::General }, - }, - ]); - - render_system.write(&[ - render_system::DescriptorWrite { - binding_handle: blur_x_source_binding, - array_element: 0, - descriptor: render_system::Descriptor::CombinedImageSampler { image_handle: result, sampler_handle: sampler, layout: render_system::Layouts::Read }, - }, - render_system::DescriptorWrite { - binding_handle: blur_x_result_binding, - array_element: 0, - descriptor: render_system::Descriptor::Image{ handle: x_blur_target, layout: render_system::Layouts::General }, - }, - ]); - - render_system.write(&[ - render_system::DescriptorWrite { - binding_handle: blur_y_source_binding, - array_element: 0, - descriptor: render_system::Descriptor::CombinedImageSampler { image_handle: x_blur_target, sampler_handle: sampler, layout: render_system::Layouts::Read }, - }, - render_system::DescriptorWrite { - binding_handle: blur_y_result_binding, - array_element: 0, - descriptor: render_system::Descriptor::Image{ handle: y_blur_target, layout: render_system::Layouts::General }, - }, - render_system::DescriptorWrite { // AO Texture - binding_handle: ao_texture_binding, - array_element: 0, - descriptor: render_system::Descriptor::CombinedImageSampler{ image_handle: y_blur_target, sampler_handle: sampler, layout: render_system::Layouts::Read }, - }, - ]); - - let blur_shader = render_system.create_shader(render_system::ShaderSource::GLSL(BLUR_SHADER), render_system::ShaderTypes::Compute,); - - let blur_x_pipeline = render_system.create_compute_pipeline(&hbao_pass_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(&hbao_pass_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,] })])); - - HBAOPass { - pipeline_layout: hbao_pass_pipeline_layout, - descriptor_set_layout: hbao_pass_descriptor_set_layout, - descriptor_set: hbao_pass_descriptor_set, - blur_x_descriptor_set, - blur_y_descriptor_set, - blur_x_pipeline, - blur_y_pipeline, - pipeline, - depth_binding, - result, - x_blur_target, - y_blur_target, - } - }; + // Visibility - Self { pipeline_layout_handle, vertex_positions_buffer: vertex_positions_buffer_handle, vertex_normals_buffer: vertex_normals_buffer_handle, + triangle_indices_buffer: triangle_indices_buffer_handle, vertex_indices_buffer: vertex_indices_buffer_handle, primitive_indices_buffer: primitive_indices_buffer_handle, @@ -914,39 +457,12 @@ void main() { albedo, depth_target, - result, - - visiblity_info: VisibilityInfo{ triangle_count: 0, instance_count: 0, meshlet_count:0, vertex_count:0, }, - - current_frame: 0, - - render_finished_synchronizer, - image_ready, - render_command_buffer, camera_data_buffer_handle, - transfer_synchronizer, - transfer_command_buffer, - meshes_data_buffer, meshlets_data_buffer, - shaders: HashMap::new(), - - camera: None, - - meshes: HashMap::new(), - - light_data_buffer, - materials_data_buffer_handle, - - mesh_resources: HashMap::new(), - - VERTEX_LAYOUT, - - swapchain_handles: Vec::new(), - visibility_pass_pipeline_layout, visibility_passes_descriptor_set, visibility_pass_pipeline, @@ -971,20 +487,14 @@ void main() { material_evaluation_dispatches, material_xy, - material_evaluation_materials: HashMap::new(), - - tone_map_pass, - hbao_pass, - - pending_texture_loads: Vec::new(), - - top_level_acceleration_structure, + light_data_buffer, + materials_data_buffer_handle, + vertex_layout, } }) // .add_post_creation_function(Box::new(Self::load_needed_assets)) .add_listener::() .add_listener::() - .add_listener::() .add_listener::() .add_listener::() } @@ -1173,19 +683,7 @@ void main() { /// 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 } } - fn execute_compute_render_pass(&self, name: &str, command_buffer_recording: &mut dyn render_system::CommandBufferRecording, fun: F) { - command_buffer_recording.start_region(name); - fun(command_buffer_recording); - command_buffer_recording.end_region(); - } - - pub fn render(&mut self, orchestrator: OrchestratorReference) { - if self.swapchain_handles.is_empty() { return; } - - let render_system = orchestrator.get_by_class::(); - let mut binding = render_system.get_mut(); - let render_system = binding.downcast_mut::().unwrap(); - + 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; }; { @@ -1206,12 +704,10 @@ void main() { self.pending_texture_loads.clear(); - command_buffer_recording.execute(&[], &[self.transfer_synchronizer], self.transfer_synchronizer); + command_buffer_recording.execute(&[], &[], self.transfer_synchronizer); } - render_system.wait(self.render_finished_synchronizer); - - render_system.start_frame_capture(); + render_system.wait(self.transfer_synchronizer); // Bad let camera_data_buffer = render_system.get_mut_buffer_slice(self.camera_data_buffer_handle); @@ -1236,11 +732,7 @@ void main() { camera_data_reference.projection_matrix = projection_matrix; camera_data_reference.view_projection_matrix = view_projection_matrix; - let swapchain_handle = self.swapchain_handles[0]; - - let image_index = render_system.acquire_swapchain_image(swapchain_handle, self.image_ready); - - let mut command_buffer_recording = render_system.create_command_buffer_recording(self.render_command_buffer, Some(self.current_frame as u32)); + command_buffer_recording.start_region("Visibility Model"); command_buffer_recording.consume_resources(&[ render_system::Consumption{ @@ -1291,7 +783,7 @@ void main() { command_buffer_recording.start_region("Visibility Render Model"); - command_buffer_recording.start_region("Visibility Pass"); + command_buffer_recording.start_region("Visibility Buffer"); command_buffer_recording.consume_resources(&[ render_system::Consumption { @@ -1332,13 +824,13 @@ void main() { }, ]); - command_buffer_recording.start_render_pass(Extent::new(1920, 1080, 1), &attachments); + 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, 0)]); + command_buffer_recording.bind_descriptor_sets(&self.pipeline_layout_handle, &[self.descriptor_set]); - command_buffer_recording.dispatch_meshes(self.visiblity_info.meshlet_count, 1, 1); + command_buffer_recording.dispatch_meshes(self.visibility_info.meshlet_count, 1, 1); command_buffer_recording.end_render_pass(); @@ -1346,239 +838,157 @@ void main() { command_buffer_recording.end_region(); - self.execute_compute_render_pass("Material Count", command_buffer_recording.as_mut(), |command_buffer_recording| { - 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, 0), (self.visibility_passes_descriptor_set, 1)]); - 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 } }); - }); - - self.execute_compute_render_pass("Material Offset", command_buffer_recording.as_mut(), |command_buffer_recording| { - 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, 0), (self.visibility_passes_descriptor_set, 1)]); - 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 } }); - }); - - self.execute_compute_render_pass("Pixel Mapping", command_buffer_recording.as_mut(), |command_buffer_recording| { - 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, 0), (self.visibility_passes_descriptor_set, 1)]); - 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 } }); - }); - - self.execute_compute_render_pass("HBAO Render Pass", command_buffer_recording.as_mut(), |command_buffer_recording| { - 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.hbao_pass.result), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); - - command_buffer_recording.bind_compute_pipeline(&self.hbao_pass.pipeline); - command_buffer_recording.bind_descriptor_sets(&self.hbao_pass.pipeline_layout, &[(self.descriptor_set, 0), (self.hbao_pass.descriptor_set, 1)]); - 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.start_region("Material Count"); - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.hbao_pass.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.hbao_pass.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.hbao_pass.blur_x_pipeline); - command_buffer_recording.bind_descriptor_sets(&self.hbao_pass.pipeline_layout, &[(self.descriptor_set, 0), (self.hbao_pass.blur_x_descriptor_set, 1)]); - 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::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.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.hbao_pass.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.hbao_pass.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.hbao_pass.blur_y_pipeline); - command_buffer_recording.bind_descriptor_sets(&self.hbao_pass.pipeline_layout, &[(self.descriptor_set, 0), (self.hbao_pass.blur_y_descriptor_set, 1)]); - 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.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) }); - self.execute_compute_render_pass("Material Evaluation", command_buffer_recording.as_mut(), |command_buffer_recording| { - command_buffer_recording.clear_textures(&[(self.albedo, render_system::ClearValue::Color(crate::RGBA { r: 0.0, g: 0.0, b: 0.0, a: 1.0 })), (self.result, render_system::ClearValue::Color(crate::RGBA { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }))]); + command_buffer_recording.end_region(); - 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.hbao_pass.result), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::READ, - layout: render_system::Layouts::Read, - }, - ]); + command_buffer_recording.start_region("Material Offset"); - command_buffer_recording.bind_descriptor_sets(&self.material_evaluation_pipeline_layout, &[(self.descriptor_set, 0), (self.visibility_passes_descriptor_set, 1), (self.material_evaluation_descriptor_set, 2)]); + 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 } }); - 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.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(); - command_buffer_recording.end_region(); // End "Visibility Render Model" + command_buffer_recording.start_region("Pixel Mapping"); - self.execute_compute_render_pass("Tone Mapping", command_buffer_recording.as_mut(), |command_buffer_recording| { - command_buffer_recording.consume_resources(&[ - render_system::Consumption{ - handle: render_system::Handle::Image(self.albedo), - 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), - stages: render_system::Stages::COMPUTE, - access: render_system::AccessPolicies::WRITE, - layout: render_system::Layouts::General, - }, - ]); - - command_buffer_recording.bind_compute_pipeline(&self.tone_map_pass.pipeline); - command_buffer_recording.bind_descriptor_sets(&self.tone_map_pass.pipeline_layout, &[(self.tone_map_pass.descriptor_set, 0)]); - 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::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, + }, + ]); - // Copy to swapchain + 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.copy_to_swapchain(self.result, image_index, swapchain_handle); + 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.execute(&[self.transfer_synchronizer, self.image_ready], &[self.render_finished_synchronizer], self.render_finished_synchronizer); + command_buffer_recording.bind_descriptor_sets(&self.material_evaluation_pipeline_layout, &[self.descriptor_set, self.visibility_passes_descriptor_set, self.material_evaluation_descriptor_set]); - render_system.end_frame_capture(); + 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.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 }); + } - render_system.present(image_index, &[swapchain_handle], self.render_finished_synchronizer); + 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 + // 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 - self.current_frame += 1; + command_buffer_recording.end_region(); } } @@ -1643,198 +1053,471 @@ impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain 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); + let resource_request = resource_manager.request_resource(mesh.resource_id); + + let resource_request = if let Some(resource_info) = resource_request { resource_info } else { return; }; + + let mut options = resource_manager::Options { resources: Vec::new(), }; + + let mut meshlet_stream_buffer = vec![0u8; 1024 * 8]; + + for resource in &resource_request.resources { + match resource.class.as_str() { + "Mesh" => { + let vertex_positions_buffer = render_system.get_mut_buffer_slice(self.vertex_positions_buffer); + let vertex_normals_buffer = render_system.get_mut_buffer_slice(self.vertex_normals_buffer); + let vertex_indices_buffer = render_system.get_mut_buffer_slice(self.vertex_indices_buffer); + let primitive_indices_buffer = render_system.get_mut_buffer_slice(self.primitive_indices_buffer); + let triangle_indices_buffer = render_system.get_mut_buffer_slice(self.triangle_indices_buffer); + + options.resources.push(resource_manager::OptionResource { + url: resource.url.clone(), + streams: vec![ + resource_manager::Stream{ buffer: &mut vertex_positions_buffer[(self.visibility_info.vertex_count as usize * std::mem::size_of::())..], name: "Vertex.Position".to_string() }, + resource_manager::Stream{ buffer: &mut vertex_normals_buffer[(self.visibility_info.vertex_count as usize * std::mem::size_of::())..], name: "Vertex.Normal".to_string() }, + resource_manager::Stream{ buffer: &mut triangle_indices_buffer[(self.visibility_info.triangle_count as usize * 3 * std::mem::size_of::())..], name: "TriangleIndices".to_string() }, + resource_manager::Stream{ buffer: &mut vertex_indices_buffer[(self.visibility_info.vertex_count as usize * std::mem::size_of::())..], name: "VertexIndices".to_string() }, + resource_manager::Stream{ buffer: &mut primitive_indices_buffer[(self.visibility_info.triangle_count as usize * 3 * std::mem::size_of::())..], name: "MeshletIndices".to_string() }, + resource_manager::Stream{ buffer: meshlet_stream_buffer.as_mut_slice() , name: "Meshlets".to_string() }, + ], + }); + + break; + } + _ => {} + } + } + + let resource = if let Ok(a) = resource_manager.load_resource(resource_request, Some(options), None) { a } else { return; }; + + let (response, _buffer) = (resource.0, resource.1.unwrap()); + + for resource in &response.resources { + match resource.class.as_str() { + "Mesh" => { + self.mesh_resources.insert(mesh.resource_id, self.visibility_info.triangle_count); + + let mesh_resource: &mesh_resource_handler::Mesh = resource.resource.downcast_ref().unwrap(); + + let acceleration_structure = if false { + let triangle_index_stream = mesh_resource.index_streams.iter().find(|is| is.stream_type == mesh_resource_handler::IndexStreamTypes::Triangles).unwrap(); + + assert_eq!(triangle_index_stream.data_type, mesh_resource_handler::IntegralTypes::U16, "Triangle index stream is not u16"); + + let bottom_level_acceleration_structure = render_system.create_bottom_level_acceleration_structure(&BottomLevelAccelerationStructure{ + description: BottomLevelAccelerationStructureDescriptions::Mesh { + vertex_count: mesh_resource.vertex_count, + vertex_position_encoding: Encodings::IEEE754, + triangle_count: triangle_index_stream.count / 3, + index_format: DataTypes::U16, + } + }); + + // ray_tracing.pending_meshes.push(MeshState::Build { mesh_handle: mesh.resource_id.to_string() }); + + Some(bottom_level_acceleration_structure) + } else { + None + }; + + { + let vertex_triangles_offset = self.visibility_info.vertex_count; + let primitive_triangle_offset = self.visibility_info.triangle_count; + + let meshlet_count; + + if let Some(meshlet_data) = &mesh_resource.meshlet_stream { + meshlet_count = meshlet_data.count; + } else { + meshlet_count = 0; + }; + + let mut mesh_vertex_count = 0; + let mut mesh_triangle_count = 0; + + let mut meshlets = Vec::with_capacity(meshlet_count as usize); + + let vertex_index_stream = mesh_resource.index_streams.iter().find(|is| is.stream_type == mesh_resource_handler::IndexStreamTypes::Vertices).unwrap(); + let meshlet_index_stream = mesh_resource.index_streams.iter().find(|is| is.stream_type == mesh_resource_handler::IndexStreamTypes::Meshlets).unwrap(); + + assert_eq!(meshlet_index_stream.data_type, mesh_resource_handler::IntegralTypes::U8, "Meshlet index stream is not u8"); + + struct Meshlet { + vertex_count: u8, + triangle_count: u8, + } + + let meshlet_stream = unsafe { + // assert_eq!(meshlet_count as usize, meshlet_stream_buffer.len() / std::mem::size_of::()); + std::slice::from_raw_parts(meshlet_stream_buffer.as_ptr() as *const Meshlet, meshlet_count as usize) + }; + + for i in 0..meshlet_count as usize { + let meshlet = &meshlet_stream[i]; + let meshlet_vertex_count = meshlet.vertex_count; + let meshlet_triangle_count = meshlet.triangle_count; + + let meshlet_data = ShaderMeshletData { + instance_index: self.visibility_info.instance_count, + vertex_triangles_offset: vertex_triangles_offset as u16 + mesh_vertex_count as u16, + triangle_offset:primitive_triangle_offset as u16 + mesh_triangle_count as u16, + vertex_count: meshlet_vertex_count, + triangle_count: meshlet_triangle_count, + }; + + meshlets.push(meshlet_data); + + mesh_vertex_count += meshlet_vertex_count as u32; + mesh_triangle_count += meshlet_triangle_count as u32; + } + + self.meshes.insert(resource.url.clone(), MeshData{ meshlets, vertex_count: mesh_vertex_count, triangle_count: mesh_triangle_count, vertex_offset: self.visibility_info.vertex_count, triangle_offset: self.visibility_info.triangle_count, acceleration_structure }); + } + } + _ => {} + } + } + } + + let meshes_data_slice = render_system.get_mut_buffer_slice(self.meshes_data_buffer); + + let mesh_data = self.meshes.get(mesh.resource_id).expect("Mesh not loaded"); + + let shader_mesh_data = ShaderInstanceData { + model: mesh.transform, + material_id: self.material_evaluation_materials.get(mesh.material_id).unwrap().0, + base_vertex_index: mesh_data.vertex_offset, + }; + + let meshes_data_slice = unsafe { std::slice::from_raw_parts_mut(meshes_data_slice.as_mut_ptr() as *mut ShaderInstanceData, MAX_INSTANCES) }; + + meshes_data_slice[self.visibility_info.instance_count as usize] = shader_mesh_data; + + if let (Some(ray_tracing), Some(acceleration_structure)) = (Option::::None, mesh_data.acceleration_structure) { + let transform = [ + [mesh.transform[0], mesh.transform[1], mesh.transform[2], mesh.transform[3]], + [mesh.transform[4], mesh.transform[5], mesh.transform[6], mesh.transform[7]], + [mesh.transform[8], mesh.transform[9], mesh.transform[10], mesh.transform[11]], + ]; + + render_system.write_instance(ray_tracing.instances_buffer, self.visibility_info.instance_count as usize, transform, self.visibility_info.instance_count as u16, 0xFF, 0, acceleration_structure); + } + + let meshlets_data_slice = render_system.get_mut_buffer_slice(self.meshlets_data_buffer); + + let meshlets_data_slice = unsafe { std::slice::from_raw_parts_mut(meshlets_data_slice.as_mut_ptr() as *mut ShaderMeshletData, MAX_MESHLETS) }; + + for (i, meshlet) in mesh_data.meshlets.iter().enumerate() { + let meshlet = ShaderMeshletData { instance_index: self.visibility_info.instance_count, ..(*meshlet) }; + meshlets_data_slice[self.visibility_info.meshlet_count as usize + i] = meshlet; + } + + self.visibility_info.meshlet_count += mesh_data.meshlets.len() as u32; + self.visibility_info.vertex_count += mesh_data.vertex_count; + self.visibility_info.triangle_count += mesh_data.triangle_count; + self.visibility_info.instance_count += 1; + + assert!((self.visibility_info.meshlet_count as usize) < MAX_MESHLETS, "Meshlet count exceeded"); + assert!((self.visibility_info.instance_count as usize) < MAX_INSTANCES, "Instance count exceeded"); + assert!((self.visibility_info.vertex_count as usize) < MAX_VERTICES, "Vertex count exceeded"); + assert!((self.visibility_info.vertex_count as usize) < MAX_PRIMITIVE_TRIANGLES, "Primitive triangle count exceeded"); + assert!((self.visibility_info.triangle_count as usize) < MAX_TRIANGLES, "Triangle count exceeded"); + } +} + +impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain { + fn on_create(&mut self, orchestrator: OrchestratorReference, handle: EntityHandle, light: &DirectionalLight) { + let render_system = orchestrator.get_by_class::(); + 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() }; + + let light_index = lighting_data.count as usize; + + lighting_data.lights[light_index].position = crate::Vec3f::new(0.0, 2.0, 0.0); + lighting_data.lights[light_index].color = light.color; + + lighting_data.count += 1; + + assert!(lighting_data.count < MAX_LIGHTS as u32, "Light count exceeded"); + } +} + +impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain { + fn on_create(&mut self, orchestrator: OrchestratorReference, handle: EntityHandle, light: &PointLight) { + let render_system = orchestrator.get_by_class::(); + 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() }; + + let light_index = lighting_data.count as usize; + + lighting_data.lights[light_index].position = light.position; + lighting_data.lights[light_index].color = light.color; + + lighting_data.count += 1; + + assert!(lighting_data.count < MAX_LIGHTS as u32, "Light count exceeded"); + } +} + +impl Entity for VisibilityWorldRenderDomain {} +impl System for VisibilityWorldRenderDomain {} + +impl WorldRenderDomain for VisibilityWorldRenderDomain { + fn get_descriptor_set_template(&self) -> render_system::DescriptorSetTemplateHandle { + self.descriptor_set_layout + } + + fn get_result_image(&self) -> render_system::ImageHandle { + self.albedo + } +} + +const VERTEX_COUNT: u32 = 64; +const TRIANGLE_COUNT: u32 = 126; + +const MAX_MESHLETS: usize = 1024; +const MAX_INSTANCES: usize = 1024; +const MAX_MATERIALS: usize = 1024; +const MAX_LIGHTS: usize = 16; +const MAX_TRIANGLES: usize = 65536; +const MAX_PRIMITIVE_TRIANGLES: usize = 65536; +const MAX_VERTICES: usize = 65536; + +const VISIBILITY_PASS_MESH_SOURCE: &'static str = " +#version 450 +#pragma shader_stage(mesh) + +#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_shader_explicit_arithmetic_types: enable +#extension GL_EXT_mesh_shader: require +#extension GL_EXT_debug_printf : enable + +layout(row_major) uniform; layout(row_major) buffer; + +layout(location=0) perprimitiveEXT out uint out_instance_index[126]; +layout(location=1) perprimitiveEXT out uint out_primitive_index[126]; + +struct Camera { + mat4 view_matrix; + mat4 projection_matrix; + mat4 view_projection; +}; + +struct Mesh { + mat4 model; + uint material_id; + uint32_t base_vertex_index; +}; + +struct Meshlet { + uint32_t instance_index; + uint16_t vertex_offset; + uint16_t triangle_offset; + uint8_t vertex_count; + uint8_t triangle_count; +}; + +layout(set=0,binding=0,scalar) buffer readonly CameraBuffer { + Camera camera; +}; + +layout(set=0,binding=1,scalar) buffer readonly MeshesBuffer { + Mesh meshes[]; +}; - let resource_request = if let Some(resource_info) = resource_request { resource_info } else { return; }; +layout(set=0,binding=2,scalar) buffer readonly MeshVertexPositions { + vec3 vertex_positions[]; +}; - let mut options = resource_manager::Options { resources: Vec::new(), }; +layout(set=0,binding=4,scalar) buffer readonly VertexIndices { + uint16_t vertex_indices[]; +}; - let mut meshlet_stream_buffer = vec![0u8; 1024 * 8]; +layout(set=0,binding=5,scalar) buffer readonly PrimitiveIndices { + uint8_t primitive_indices[]; +}; - for resource in &resource_request.resources { - match resource.class.as_str() { - "Mesh" => { - let vertex_positions_buffer = render_system.get_mut_buffer_slice(self.vertex_positions_buffer); - let vertex_normals_buffer = render_system.get_mut_buffer_slice(self.vertex_normals_buffer); - let vertex_indices_buffer = render_system.get_mut_buffer_slice(self.vertex_indices_buffer); - let primitive_indices_buffer = render_system.get_mut_buffer_slice(self.primitive_indices_buffer); +layout(set=0,binding=6,scalar) buffer readonly MeshletsBuffer { + Meshlet meshlets[]; +}; - options.resources.push(resource_manager::OptionResource { - url: resource.url.clone(), - streams: vec![ - resource_manager::Stream{ buffer: &mut vertex_positions_buffer[(self.visiblity_info.vertex_count as usize * std::mem::size_of::())..], name: "Vertex.Position".to_string() }, - resource_manager::Stream{ buffer: &mut vertex_normals_buffer[(self.visiblity_info.vertex_count as usize * std::mem::size_of::())..], name: "Vertex.Normal".to_string() }, - resource_manager::Stream{ buffer: &mut vertex_indices_buffer[(self.visiblity_info.vertex_count as usize * std::mem::size_of::())..], name: "Indices".to_string() }, - resource_manager::Stream{ buffer: &mut primitive_indices_buffer[(self.visiblity_info.triangle_count as usize * 3 * std::mem::size_of::())..], name: "MeshletIndices".to_string() }, - resource_manager::Stream{ buffer: meshlet_stream_buffer.as_mut_slice() , name: "Meshlets".to_string() }, - ], - }); +layout(triangles, max_vertices=64, max_primitives=126) out; +layout(local_size_x=128) in; +void main() { + uint meshlet_index = gl_WorkGroupID.x; - break; - } - _ => {} - } - } + Meshlet meshlet = meshlets[meshlet_index]; + Mesh mesh = meshes[meshlet.instance_index]; - let resource = if let Ok(a) = resource_manager.load_resource(resource_request, Some(options), None) { a } else { return; }; + uint instance_index = meshlet.instance_index; - let (response, _buffer) = (resource.0, resource.1.unwrap()); + SetMeshOutputsEXT(meshlet.vertex_count, meshlet.triangle_count); - for resource in &response.resources { - match resource.class.as_str() { - "Mesh" => { - self.mesh_resources.insert(mesh.resource_id, self.visiblity_info.triangle_count); + if (gl_LocalInvocationID.x < uint(meshlet.vertex_count)) { + uint vertex_index = mesh.base_vertex_index + uint32_t(vertex_indices[uint(meshlet.vertex_offset) + gl_LocalInvocationID.x]); + gl_MeshVerticesEXT[gl_LocalInvocationID.x].gl_Position = camera.view_projection * meshes[instance_index].model * vec4(vertex_positions[vertex_index], 1.0); + // gl_MeshVerticesEXT[gl_LocalInvocationID.x].gl_Position = vec4(vertex_positions[vertex_index], 1.0); + } + + if (gl_LocalInvocationID.x < uint(meshlet.triangle_count)) { + uint triangle_index = uint(meshlet.triangle_offset) + gl_LocalInvocationID.x; + uint triangle_indices[3] = uint[](primitive_indices[triangle_index * 3 + 0], primitive_indices[triangle_index * 3 + 1], primitive_indices[triangle_index * 3 + 2]); + gl_PrimitiveTriangleIndicesEXT[gl_LocalInvocationID.x] = uvec3(triangle_indices[0], triangle_indices[1], triangle_indices[2]); + out_instance_index[gl_LocalInvocationID.x] = instance_index; + out_primitive_index[gl_LocalInvocationID.x] = (meshlet_index << 8) | (gl_LocalInvocationID.x & 0xFF); + } +}"; - let mesh: &mesh_resource_handler::Mesh = resource.resource.downcast_ref().unwrap(); +const VISIBILITY_PASS_FRAGMENT_SOURCE: &'static str = r#" +#version 450 +#pragma shader_stage(fragment) - { - let vertex_triangles_offset = self.visiblity_info.vertex_count; - let primitive_triangle_offset = self.visiblity_info.triangle_count; +#extension GL_EXT_scalar_block_layout: enable +#extension GL_EXT_shader_explicit_arithmetic_types : enable +#extension GL_EXT_buffer_reference: enable +#extension GL_EXT_buffer_reference2: enable +#extension GL_EXT_mesh_shader: require - let meshlet_count; +layout(location=0) perprimitiveEXT flat in uint in_instance_index; +layout(location=1) perprimitiveEXT flat in uint in_primitive_index; - if let Some(meshlet_data) = &mesh.meshlet_stream { - meshlet_count = meshlet_data.count; - } else { - meshlet_count = 0; - }; +layout(location=0) out uint out_primitive_index; +layout(location=1) out uint out_instance_id; - let mut mesh_vertex_count = 0; - let mut mesh_triangle_count = 0; +void main() { + out_primitive_index = in_primitive_index; + out_instance_id = in_instance_index; +} +"#; - let mut meshlets = Vec::with_capacity(meshlet_count as usize); +const MATERIAL_COUNT_SOURCE: &'static str = r#" +#version 450 +#pragma shader_stage(compute) - let raw_mesh_stream = mesh.index_streams.iter().find(|is| is.stream_type == mesh_resource_handler::IndexStreamTypes::Raw).unwrap(); - let meshlet_index_stream = mesh.index_streams.iter().find(|is| is.stream_type == mesh_resource_handler::IndexStreamTypes::Meshlets).unwrap(); +#extension GL_EXT_scalar_block_layout: enable +#extension GL_EXT_buffer_reference2: enable +#extension GL_EXT_shader_explicit_arithmetic_types : enable - assert_eq!(meshlet_index_stream.data_type, mesh_resource_handler::IntegralTypes::U8, "Meshlet index stream is not u8"); +struct Mesh { + mat4 model; + uint material_index; + uint32_t base_vertex_index; +}; - struct Meshlet { - vertex_count: u8, - triangle_count: u8, - } +layout(set=0,binding=1,scalar) buffer MeshesBuffer { + Mesh meshes[]; +}; - let meshlet_stream = unsafe { - // assert_eq!(meshlet_count as usize, meshlet_stream_buffer.len() / std::mem::size_of::()); - std::slice::from_raw_parts(meshlet_stream_buffer.as_ptr() as *const Meshlet, meshlet_count as usize) - }; +layout(set=1,binding=0,scalar) buffer MaterialCount { + uint material_count[]; +}; - for i in 0..meshlet_count as usize { - let meshlet = &meshlet_stream[i]; - let meshlet_vertex_count = meshlet.vertex_count; - let meshlet_triangle_count = meshlet.triangle_count; +layout(set=1, binding=7, r32ui) uniform readonly uimage2D instance_index; - let meshlet_data = ShaderMeshletData { - instance_index: self.visiblity_info.instance_count, - vertex_triangles_offset: vertex_triangles_offset as u16 + mesh_vertex_count as u16, - triangle_offset:primitive_triangle_offset as u16 + mesh_triangle_count as u16, - vertex_count: meshlet_vertex_count, - triangle_count: meshlet_triangle_count, - }; - - meshlets.push(meshlet_data); +layout(local_size_x=32, local_size_y=32) in; +void main() { + // If thread is out of bound respect to the material_id texture, return + if (gl_GlobalInvocationID.x >= imageSize(instance_index).x || gl_GlobalInvocationID.y >= imageSize(instance_index).y) { return; } - mesh_vertex_count += meshlet_vertex_count as u32; - mesh_triangle_count += meshlet_triangle_count as u32; - } + uint pixel_instance_index = imageLoad(instance_index, ivec2(gl_GlobalInvocationID.xy)).r; - self.meshes.insert(resource.url.clone(), MeshData{ meshlets, vertex_count: mesh_vertex_count, triangle_count: mesh_triangle_count, vertex_offset: self.visiblity_info.vertex_count }); - } - } - _ => {} - } - } - } + if (pixel_instance_index == 0xFFFFFFFF) { return; } - let meshes_data_slice = render_system.get_mut_buffer_slice(self.meshes_data_buffer); + uint material_index = meshes[pixel_instance_index].material_index; - let mesh_data = self.meshes.get(mesh.resource_id).expect("Mesh not loaded"); + atomicAdd(material_count[material_index], 1); +} +"#; - let shader_mesh_data = ShaderInstanceData { - model: mesh.transform, - material_id: self.material_evaluation_materials.get(mesh.material_id).unwrap().0, - base_vertex_index: mesh_data.vertex_offset, - }; +const MATERIAL_OFFSET_SOURCE: &'static str = r#" +#version 450 +#pragma shader_stage(compute) - let meshes_data_slice = unsafe { std::slice::from_raw_parts_mut(meshes_data_slice.as_mut_ptr() as *mut ShaderInstanceData, MAX_INSTANCES) }; +#extension GL_EXT_scalar_block_layout: enable +#extension GL_EXT_buffer_reference2: enable +#extension GL_EXT_shader_explicit_arithmetic_types : enable - meshes_data_slice[self.visiblity_info.instance_count as usize] = shader_mesh_data; +layout(set=1,binding=0,scalar) buffer MaterialCount { + uint material_count[]; +}; - let meshlets_data_slice = render_system.get_mut_buffer_slice(self.meshlets_data_buffer); +layout(set=1,binding=1,scalar) buffer MaterialOffset { + uint material_offset[]; +}; - let meshlets_data_slice = unsafe { std::slice::from_raw_parts_mut(meshlets_data_slice.as_mut_ptr() as *mut ShaderMeshletData, MAX_MESHLETS) }; +layout(set=1,binding=2,scalar) buffer MaterialOffsetScratch { + uint material_offset_scratch[]; +}; - for (i, meshlet) in mesh_data.meshlets.iter().enumerate() { - let meshlet = ShaderMeshletData { instance_index: self.visiblity_info.instance_count, ..(*meshlet) }; - meshlets_data_slice[self.visiblity_info.meshlet_count as usize + i] = meshlet; - } +layout(set=1,binding=3,scalar) buffer MaterialEvaluationDispatches { + uvec3 material_evaluation_dispatches[]; +}; - self.visiblity_info.meshlet_count += mesh_data.meshlets.len() as u32; - self.visiblity_info.vertex_count += mesh_data.vertex_count; - self.visiblity_info.triangle_count += mesh_data.triangle_count; - self.visiblity_info.instance_count += 1; +layout(local_size_x=1) in; +void main() { + uint sum = 0; - assert!((self.visiblity_info.meshlet_count as usize) < MAX_MESHLETS, "Meshlet count exceeded"); - assert!((self.visiblity_info.instance_count as usize) < MAX_INSTANCES, "Instance count exceeded"); - assert!((self.visiblity_info.vertex_count as usize) < MAX_VERTICES, "Vertex count exceeded"); - assert!((self.visiblity_info.vertex_count as usize) < MAX_PRIMITIVE_TRIANGLES, "Primitive triangle count exceeded"); - assert!((self.visiblity_info.triangle_count as usize) < MAX_TRIANGLES, "Triangle count exceeded"); + for (uint i = 0; i < 4; i++) { + material_offset[i] = sum; + material_offset_scratch[i] = sum; + material_evaluation_dispatches[i] = uvec3((material_count[i] + 31) / 32, 1, 1); + sum += material_count[i]; } } +"#; -impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain { - fn on_create(&mut self, orchestrator: OrchestratorReference, handle: EntityHandle, window: &window_system::Window) { - let render_system = orchestrator.get_by_class::(); - let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); +const PIXEL_MAPPING_SOURCE: &'static str = r#" +#version 450 +#pragma shader_stage(compute) - let window_system = orchestrator.get_by_class::(); - let mut window_system = window_system.get_mut(); - let window_system = window_system.downcast_mut::().unwrap(); +#extension GL_EXT_scalar_block_layout: enable +#extension GL_EXT_buffer_reference2: enable +#extension GL_EXT_shader_explicit_arithmetic_types : enable - let swapchain_handle = render_system.bind_to_window(&window_system.get_os_handles(&handle)); +struct Mesh { + mat4 model; + uint material_index; + uint32_t base_vertex_index; +}; - self.swapchain_handles.push(swapchain_handle); - } -} +layout(set=0,binding=1,scalar) buffer MeshesBuffer { + Mesh meshes[]; +}; -impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain { - fn on_create(&mut self, orchestrator: OrchestratorReference, handle: EntityHandle, light: &DirectionalLight) { - let render_system = orchestrator.get_by_class::(); - let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); +layout(set=1,binding=1,scalar) buffer MaterialOffset { + uint material_offset[]; +}; - let lighting_data = unsafe { (render_system.get_mut_buffer_slice(self.light_data_buffer).as_mut_ptr() as *mut LightingData).as_mut().unwrap() }; +layout(set=1,binding=2,scalar) buffer MaterialOffsetScratch { + uint material_offset_scratch[]; +}; - let light_index = lighting_data.count as usize; +layout(set=1,binding=4,scalar) buffer PixelMapping { + u16vec2 pixel_mapping[]; +}; - lighting_data.lights[light_index].position = crate::Vec3f::new(0.0, 2.0, 0.0); - lighting_data.lights[light_index].color = light.color; - - lighting_data.count += 1; +layout(set=1, binding=7, r32ui) uniform readonly uimage2D instance_index; - assert!(lighting_data.count < MAX_LIGHTS as u32, "Light count exceeded"); - } -} +layout(local_size_x=32, local_size_y=32) in; +void main() { + // If thread is out of bound respect to the material_id texture, return + if (gl_GlobalInvocationID.x >= imageSize(instance_index).x || gl_GlobalInvocationID.y >= imageSize(instance_index).y) { return; } -impl orchestrator::EntitySubscriber for VisibilityWorldRenderDomain { - fn on_create(&mut self, orchestrator: OrchestratorReference, handle: EntityHandle, light: &PointLight) { - let render_system = orchestrator.get_by_class::(); - let mut render_system = render_system.get_mut(); - let render_system = render_system.downcast_mut::().unwrap(); + uint pixel_instance_index = imageLoad(instance_index, ivec2(gl_GlobalInvocationID.xy)).r; - let lighting_data = unsafe { (render_system.get_mut_buffer_slice(self.light_data_buffer).as_mut_ptr() as *mut LightingData).as_mut().unwrap() }; + if (pixel_instance_index == 0xFFFFFFFF) { return; } - let light_index = lighting_data.count as usize; + uint material_index = meshes[pixel_instance_index].material_index; - lighting_data.lights[light_index].position = light.position; - lighting_data.lights[light_index].color = light.color; - - lighting_data.count += 1; + uint offset = atomicAdd(material_offset_scratch[material_index], 1); - assert!(lighting_data.count < MAX_LIGHTS as u32, "Light count exceeded"); - } + pixel_mapping[offset] = u16vec2(gl_GlobalInvocationID.xy); } - -impl Entity for VisibilityWorldRenderDomain {} -impl System for VisibilityWorldRenderDomain {} \ No newline at end of file +"#; \ No newline at end of file diff --git a/src/rendering/vulkan_render_system.rs b/src/rendering/vulkan_render_system.rs index 160bbd84..ffc5604a 100644 --- a/src/rendering/vulkan_render_system.rs +++ b/src/rendering/vulkan_render_system.rs @@ -41,6 +41,7 @@ pub struct VulkanRenderSystem { textures: Vec, allocations: Vec, descriptor_sets_layouts: Vec, + pipeline_layouts: Vec, bindings: Vec, descriptor_sets: Vec, meshes: Vec, @@ -472,7 +473,14 @@ impl render_system::RenderSystem for VulkanRenderSystem { let pipeline_layout = unsafe { self.device.create_pipeline_layout(&pipeline_layout_create_info, None).expect("No pipeline layout") }; - render_system::PipelineLayoutHandle(pipeline_layout.as_raw()) + let handle = render_system::PipelineLayoutHandle(self.pipeline_layouts.len() as u64); + + self.pipeline_layouts.push(PipelineLayout { + pipeline_layout, + descriptor_set_template_indices: descriptor_set_layout_handles.iter().enumerate().map(|(i, handle)| (handle.clone(), i as u32)).collect(), + }); + + handle } fn create_raster_pipeline(&mut self, pipeline_blocks: &[render_system::PipelineConfigurationBlocks]) -> render_system::PipelineHandle { @@ -522,6 +530,8 @@ impl render_system::RenderSystem for VulkanRenderSystem { .data(&specialization_entries_buffer) .map_entries(&spcialization_map_entries); + let pipeline_layout = &self.pipeline_layouts[pipeline_layout_handle.0 as usize]; + let create_infos = [ vk::ComputePipelineCreateInfo::default() .stage(vk::PipelineShaderStageCreateInfo::default() @@ -531,7 +541,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { .specialization_info(&specialization_info) /* .build() */ ) - .layout(vk::PipelineLayout::from_raw(pipeline_layout_handle.0)) + .layout(pipeline_layout.pipeline_layout) ]; let pipeline_handle = unsafe { @@ -600,8 +610,10 @@ impl render_system::RenderSystem for VulkanRenderSystem { } } + let pipeline_layout = &self.pipeline_layouts[pipeline_layout_handle.0 as usize]; + let create_info = vk::RayTracingPipelineCreateInfoKHR::default() - .layout(vk::PipelineLayout::from_raw(pipeline_layout_handle.0)) + .layout(pipeline_layout.pipeline_layout) .stages(&stages) .groups(&groups) .max_pipeline_ray_recursion_depth(1); @@ -632,7 +644,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { handle } - fn create_command_buffer(&mut self) -> render_system::CommandBufferHandle { + fn create_command_buffer(&mut self, name: Option<&str>) -> render_system::CommandBufferHandle { let command_buffer_handle = render_system::CommandBufferHandle(self.command_buffers.len() as u64); let command_buffers = (0..self.frames).map(|_| { @@ -652,7 +664,23 @@ impl render_system::RenderSystem for VulkanRenderSystem { let command_buffers = unsafe { self.device.allocate_command_buffers(&command_buffer_allocate_info).expect("No command buffer") }; - CommandBufferInternal { command_pool, command_buffer: command_buffers[0], } + let command_buffer = command_buffers[0]; + + if let Some(name) = name { + if let Some(debug_utils) = &self.debug_utils { + unsafe { + debug_utils.set_debug_utils_object_name( + self.device.handle(), + &vk::DebugUtilsObjectNameInfoEXT::default() + .object_handle(command_buffer) + .object_name(std::ffi::CString::new(name).unwrap().as_c_str()) + /* .build() */ + ).expect("No debug utils object name"); + } + } + } + + CommandBufferInternal { command_pool, command_buffer, } }).collect::>(); self.command_buffers.push(CommandBuffer { @@ -979,6 +1007,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { let (geometry, primitive_count) = match &description.description { render_system::BottomLevelAccelerationStructureDescriptions::Mesh { vertex_count, vertex_position_encoding, triangle_count, index_format } => { (vk::AccelerationStructureGeometryKHR::default() + .flags(vk::GeometryFlagsKHR::OPAQUE) .geometry_type(vk::GeometryTypeKHR::TRIANGLES) .geometry(vk::AccelerationStructureGeometryDataKHR { triangles: vk::AccelerationStructureGeometryTrianglesDataKHR::default() @@ -998,6 +1027,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { } render_system::BottomLevelAccelerationStructureDescriptions::AABB { transform_count } => { (vk::AccelerationStructureGeometryKHR::default() + .flags(vk::GeometryFlagsKHR::OPAQUE) .geometry_type(vk::GeometryTypeKHR::AABBS) .geometry(vk::AccelerationStructureGeometryDataKHR { aabbs: vk::AccelerationStructureGeometryAabbsDataKHR::default() @@ -1009,6 +1039,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { let geometries = [geometry]; let build_info = vk::AccelerationStructureBuildGeometryInfoKHR::default() + .flags(vk::BuildAccelerationStructureFlagsKHR::PREFER_FAST_TRACE) .ty(vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL) .geometries(&geometries); @@ -1064,7 +1095,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { handle } - fn write_instance(&mut self, instances_buffer: BaseBufferHandle, transform: [[f32; 4]; 3], custom_index: u16, mask: u8, sbt_record_offset: usize, acceleration_structure: render_system::BottomLevelAccelerationStructureHandle) { + fn write_instance(&mut self, instances_buffer: BaseBufferHandle, instance_index: usize, transform: [[f32; 4]; 3], custom_index: u16, mask: u8, sbt_record_offset: usize, acceleration_structure: render_system::BottomLevelAccelerationStructureHandle) { let buffer = self.acceleration_structures[acceleration_structure.0 as usize].buffer; let address = unsafe { self.device.get_buffer_device_address(&vk::BufferDeviceAddressInfo::default().buffer(buffer)) }; @@ -1074,7 +1105,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { matrix: [transform[0][0], transform[0][1], transform[0][2], transform[0][3], transform[1][0], transform[1][1], transform[1][2], transform[1][3], transform[2][0], transform[2][1], transform[2][2], transform[2][3]], }, instance_custom_index_and_mask: vk::Packed24_8::new(custom_index as u32, mask), - instance_shader_binding_table_record_offset_and_flags: vk::Packed24_8::new(sbt_record_offset as u32, 0), + instance_shader_binding_table_record_offset_and_flags: vk::Packed24_8::new(sbt_record_offset as u32, vk::GeometryInstanceFlagsKHR::FORCE_OPAQUE.as_raw() as u8), acceleration_structure_reference: vk::AccelerationStructureReferenceKHR { device_handle: address, }, @@ -1084,7 +1115,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { let instance_buffer_slice = unsafe { std::slice::from_raw_parts_mut(instance_buffer.pointer as *mut vk::AccelerationStructureInstanceKHR, instance_buffer.size / std::mem::size_of::()) }; - instance_buffer_slice[0] = instance; + instance_buffer_slice[instance_index] = instance; } fn write_sbt_entry(&mut self, sbt_buffer_handle: BaseBufferHandle, sbt_record_offset: usize, pipeline_handle: render_system::PipelineHandle, shader_handle: render_system::ShaderHandle) { @@ -1148,7 +1179,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { /// Creates a synchronization primitive (implemented as a semaphore/fence/event).\ /// Multiple underlying synchronization primitives are created, one for each frame - fn create_synchronizer(&mut self, signaled: bool) -> render_system::SynchronizerHandle { + fn create_synchronizer(&mut self, name: Option<&str>, signaled: bool) -> render_system::SynchronizerHandle { let synchronizer_handle = render_system::SynchronizerHandle(self.synchronizers.len() as u64); let mut previous_synchronizer_handle: Option = None; @@ -1157,7 +1188,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { let synchronizer_handle = render_system::SynchronizerHandle(self.synchronizers.len() as u64); self.synchronizers.push(Synchronizer { fence: self.create_vulkan_fence(signaled), - semaphore: self.create_vulkan_semaphore(signaled), + semaphore: self.create_vulkan_semaphore(name, signaled), }); previous_synchronizer_handle = Some(synchronizer_handle); } @@ -1232,7 +1263,7 @@ impl render_system::RenderSystem for VulkanRenderSystem { use ash::{vk::{ValidationFeatureEnableEXT, Handle}, Entry}; use bitflags::Flags; -use super::render_system::{CommandBufferRecording, BaseBufferHandle, RenderSystem, ShaderHandle, FilteringModes, SamplerAddressingModes}; +use super::render_system::*; #[derive(Clone)] pub(crate) struct Swapchain { @@ -1247,6 +1278,12 @@ pub(crate) struct DescriptorSetLayout { descriptor_set_layout: vk::DescriptorSetLayout, } +#[derive(Clone)] +pub(crate) struct PipelineLayout { + pipeline_layout: vk::PipelineLayout, + descriptor_set_template_indices: HashMap, +} + #[derive(Clone, Copy)] pub(crate) struct DescriptorSet { next: Option, @@ -1388,6 +1425,7 @@ fn texture_format_and_resource_use_to_image_layout(_texture_format: render_syste render_system::Layouts::Present => vk::ImageLayout::PRESENT_SRC_KHR, render_system::Layouts::Read => vk::ImageLayout::READ_ONLY_OPTIMAL, render_system::Layouts::General => vk::ImageLayout::GENERAL, + render_system::Layouts::ShaderBindingTable => vk::ImageLayout::UNDEFINED, } } @@ -1409,6 +1447,13 @@ fn to_store_operation(value: bool) -> vk::AttachmentStoreOp { fn to_format(format: render_system::Formats, compression: Option) -> vk::Format { match format { + render_system::Formats::R8(encoding) => { + match encoding { + Encodings::IEEE754 => { vk::Format::UNDEFINED } + Encodings::UnsignedNormalized => { vk::Format::R8_UNORM } + Encodings::SignedNormalized => { vk::Format::R8_SNORM } + } + } render_system::Formats::R16(encoding) => { match encoding { render_system::Encodings::IEEE754 => { @@ -1428,10 +1473,10 @@ fn to_format(format: render_system::Formats, compression: Option { - vk::Format::UNDEFINED + vk::Format::R32_UINT } render_system::Encodings::SignedNormalized => { - vk::Format::UNDEFINED + vk::Format::R32_SINT } } } @@ -1545,6 +1590,10 @@ fn to_pipeline_stage_flags(stages: render_system::Stages) -> vk::PipelineStageFl 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 } @@ -1585,10 +1634,14 @@ fn to_pipeline_stage_flags_with_format(stages: render_system::Stages, format: re pipeline_stage_flags |= vk::PipelineStageFlags2::DRAW_INDIRECT; } + if stages.contains(render_system::Stages::RAYGEN) { + pipeline_stage_flags |= vk::PipelineStageFlags2::RAY_TRACING_SHADER_KHR; + } + pipeline_stage_flags } -fn to_access_flags(accesses: render_system::AccessPolicies, stages: render_system::Stages,) -> vk::AccessFlags2 { +fn to_access_flags(accesses: render_system::AccessPolicies, stages: render_system::Stages, layout: render_system::Layouts) -> vk::AccessFlags2 { let mut access_flags = vk::AccessFlags2::empty(); if accesses.contains(render_system::AccessPolicies::READ) { @@ -1608,6 +1661,13 @@ fn to_access_flags(accesses: render_system::AccessPolicies, stages: render_syste access_flags |= vk::AccessFlags2::INDIRECT_COMMAND_READ } if stages.intersects(render_system::Stages::RAYGEN) { + if layout == render_system::Layouts::ShaderBindingTable { + access_flags |= vk::AccessFlags2::SHADER_BINDING_TABLE_READ_KHR + } else { + access_flags |= vk::AccessFlags2::ACCELERATION_STRUCTURE_READ_KHR + } + } + if stages.intersects(render_system::Stages::ACCELERATION_STRUCTURE_BUILD) { access_flags |= vk::AccessFlags2::ACCELERATION_STRUCTURE_READ_KHR } } @@ -1622,6 +1682,12 @@ fn to_access_flags(accesses: render_system::AccessPolicies, stages: render_syste if stages.intersects(render_system::Stages::FRAGMENT) { access_flags |= vk::AccessFlags2::COLOR_ATTACHMENT_WRITE } + if stages.intersects(render_system::Stages::RAYGEN) { + access_flags |= vk::AccessFlags2::SHADER_WRITE + } + if stages.intersects(render_system::Stages::ACCELERATION_STRUCTURE_BUILD) { + access_flags |= vk::AccessFlags2::ACCELERATION_STRUCTURE_WRITE_KHR + } } access_flags @@ -1650,6 +1716,9 @@ fn to_access_flags_with_format(accesses: render_system::AccessPolicies, stages: 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 + } } if accesses.contains(render_system::AccessPolicies::WRITE) { @@ -1666,6 +1735,9 @@ fn to_access_flags_with_format(accesses: render_system::AccessPolicies, stages: access_flags |= vk::AccessFlags2::DEPTH_STENCIL_ATTACHMENT_WRITE } } + if stages.intersects(render_system::Stages::RAYGEN) { + access_flags |= vk::AccessFlags2::SHADER_WRITE + } } access_flags @@ -1951,11 +2023,19 @@ impl VulkanRenderSystem { (vk::PhysicalDeviceAccelerationStructureFeaturesKHR::default(), vk::PhysicalDeviceRayTracingPipelineFeaturesKHR::default()) }; + let mut shader_atomic_float_features = vk::PhysicalDeviceShaderAtomicFloatFeaturesEXT::default() + .shader_buffer_float32_atomics(true) + .shader_image_float32_atomics(true) + ; + + device_extension_names.push("VK_EXT_shader_atomic_float\0".as_ptr() as *const i8); + let device_create_info = vk::DeviceCreateInfo::default() .push_next(&mut physical_device_vulkan_11_features/* .build() */) .push_next(&mut physical_device_vulkan_12_features/* .build() */) .push_next(&mut physical_device_vulkan_13_features/* .build() */) .push_next(&mut physical_device_mesh_shading_features/* .build() */) + .push_next(&mut shader_atomic_float_features/* .build() */) .queue_create_infos(&queue_create_infos) .enabled_extension_names(&device_extension_names) .enabled_features(&enabled_physical_device_features/* .build() */) @@ -2004,21 +2084,22 @@ impl VulkanRenderSystem { frames: 2, // Assuming double buffering allocations: Vec::new(), - buffers: Vec::new(), - textures: Vec::new(), - descriptor_sets_layouts: Vec::new(), - bindings: Vec::new(), - descriptor_sets: Vec::new(), + buffers: Vec::with_capacity(1024), + textures: Vec::with_capacity(512), + descriptor_sets_layouts: Vec::with_capacity(128), + pipeline_layouts: Vec::with_capacity(64), + bindings: Vec::with_capacity(1024), + descriptor_sets: Vec::with_capacity(512), acceleration_structures: Vec::new(), - pipelines: Vec::new(), + pipelines: Vec::with_capacity(1024), meshes: Vec::new(), - command_buffers: Vec::new(), - synchronizers: Vec::new(), - swapchains: Vec::new(), + command_buffers: Vec::with_capacity(32), + synchronizers: Vec::with_capacity(32), + swapchains: Vec::with_capacity(4), } } - pub fn new_as_system() -> orchestrator::EntityReturn { + pub fn new_as_system() -> orchestrator::EntityReturn<'static, render_system::RenderSystemImplementation> { let settings = Settings { validation: true, ray_tracing: true, @@ -2182,9 +2263,9 @@ impl VulkanRenderSystem { build_block(vulkan_render_system, pipeline_create_info, block_iterator) } render_system::PipelineConfigurationBlocks::Layout { layout } => { - let pipeline_layout = vk::PipelineLayout::from_raw(layout.0); + let pipeline_layout = &vulkan_render_system.pipeline_layouts[layout.0 as usize]; - let pipeline_create_info = pipeline_create_info.layout(pipeline_layout); + let pipeline_create_info = pipeline_create_info.layout(pipeline_layout.pipeline_layout); build_block(vulkan_render_system, pipeline_create_info, block_iterator) } @@ -2452,10 +2533,26 @@ impl VulkanRenderSystem { unsafe { self.device.create_fence(&fence_create_info, None).expect("No fence") } } - fn create_vulkan_semaphore(&self, signaled: bool) -> vk::Semaphore { + fn create_vulkan_semaphore(&self, name: Option<&str>, signaled: bool) -> vk::Semaphore { let semaphore_create_info = vk::SemaphoreCreateInfo::default() /* .build() */; - unsafe { self.device.create_semaphore(&semaphore_create_info, None).expect("No semaphore") } + let handle = unsafe { self.device.create_semaphore(&semaphore_create_info, None).expect("No semaphore") }; + + if let Some(name) = name { + unsafe { + if let Some(debug_utils) = &self.debug_utils { + debug_utils.set_debug_utils_object_name( + self.device.handle(), + &vk::DebugUtilsObjectNameInfoEXT::default() + .object_handle(handle) + .object_name(std::ffi::CString::new(name).unwrap().as_c_str()) + /* .build() */ + ).expect("No debug utils object name"); + } + } + } + + handle } fn create_vulkan_texture_view(&self, name: Option<&str>, texture: &vk::Image, format: render_system::Formats, compression: Option, _mip_levels: u32) -> vk::ImageView { @@ -2736,7 +2833,7 @@ impl VulkanCommandBufferRecording<'_> { let mut i = 0; loop { let texture = &self.render_system.textures[texture_handle.0 as usize]; - if i == self.modulo_frame_index { + if i == self.modulo_frame_index || texture.next.is_none() { return (texture_handle, texture); } texture_handle = texture.next.unwrap(); @@ -2921,18 +3018,22 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> let build_range_infos = build_range_infos.iter().map(|build_range_info| build_range_info.as_slice()).collect::>(); + + unsafe { self.render_system.acceleration_structure.cmd_build_acceleration_structures(command_buffer.command_buffer, &infos, &build_range_infos) } } fn build_bottom_level_acceleration_structures(&mut self, acceleration_structure_builds: &[render_system::BottomLevelAccelerationStructureBuild]) { + if acceleration_structure_builds.is_empty() { return; } + fn visit(this: &mut VulkanCommandBufferRecording, acceleration_structure_builds: &[render_system::BottomLevelAccelerationStructureBuild], mut infos: Vec, mut geometries: Vec>, mut build_range_infos: Vec>,) { if let Some(build) = acceleration_structure_builds.first() { let (acceleration_structure_handle, acceleration_structure) = this.get_bottom_level_acceleration_structure(build.acceleration_structure); let (as_geometries, offsets) = match &build.description { - render_system::BottomLevelAccelerationStructureBuildDescriptions::AABB { aabb_buffer, transform_buffer, transform_count } => { + render_system::BottomLevelAccelerationStructureBuildDescriptions::AABB { .. } => { (vec![], vec![]) } render_system::BottomLevelAccelerationStructureBuildDescriptions::Mesh { vertex_buffer, index_buffer, vertex_position_encoding, index_format, triangle_count, vertex_count } => { @@ -2942,7 +3043,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> &vk::BufferDeviceAddressInfo::default() .buffer(buffer.buffer) /* .build() */ - ) + vertex_buffer.offset + ) + vertex_buffer.offset as u64 }; let index_data_address = unsafe { @@ -2951,7 +3052,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> &vk::BufferDeviceAddressInfo::default() .buffer(buffer.buffer) /* .build() */ - ) + index_buffer.offset + ) + index_buffer.offset as u64 }; let triangles = vk::AccelerationStructureGeometryTrianglesDataKHR::default() @@ -2967,12 +3068,12 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> _ => panic!("Invalid vertex position encoding"), }) .index_type(match index_format { - render_system::DataTypes::U8 => vk::IndexType::UINT16, + render_system::DataTypes::U8 => vk::IndexType::UINT8_EXT, render_system::DataTypes::U16 => vk::IndexType::UINT16, render_system::DataTypes::U32 => vk::IndexType::UINT32, _ => panic!("Invalid index format"), }) - .vertex_stride(vertex_buffer.stride); + .vertex_stride(vertex_buffer.stride as vk::DeviceSize); let build_range_info = vec![vk::AccelerationStructureBuildRangeInfoKHR::default() .primitive_count(*triangle_count) @@ -2982,6 +3083,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> /* .build() */]; (vec![vk::AccelerationStructureGeometryKHR::default() + .flags(vk::GeometryFlagsKHR::OPAQUE) .geometry_type(vk::GeometryTypeKHR::TRIANGLES) .geometry(vk::AccelerationStructureGeometryDataKHR{ triangles })], build_range_info) @@ -3064,7 +3166,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> /// Writes to the push constant register. fn write_to_push_constant(&mut self, pipeline_layout_handle: &render_system::PipelineLayoutHandle, offset: u32, data: &[u8]) { let command_buffer = self.get_command_buffer(); - let pipeline_layout = vk::PipelineLayout::from_raw(pipeline_layout_handle.0); + let pipeline_layout = self.render_system.pipeline_layouts[pipeline_layout_handle.0 as usize].pipeline_layout; unsafe { self.render_system.device.cmd_push_constants(command_buffer.command_buffer, pipeline_layout, vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::MESH_EXT | vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE, offset, data); } } @@ -3110,7 +3212,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } } - fn clear_textures(&mut self, textures: &[(render_system::ImageHandle, render_system::ClearValue)]) { + fn clear_images(&mut self, textures: &[(render_system::ImageHandle, render_system::ClearValue)]) { self.consume_resources(textures.iter().map(|(texture_handle, _)| render_system::Consumption { handle: render_system::Handle::Image(*texture_handle), stages: render_system::Stages::TRANSFER, @@ -3147,7 +3249,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> for consumption in consumptions { let mut new_stage_mask = to_pipeline_stage_flags(consumption.stages); - let mut new_access_mask = to_access_flags(consumption.access, consumption.stages); + let mut new_access_mask = to_access_flags(consumption.access, consumption.stages, consumption.layout); match consumption.handle { render_system::Handle::Image(texture_handle) => { @@ -3340,9 +3442,9 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> let make_strided_range = |range: render_system::BufferStridedRange| -> vk::StridedDeviceAddressRegionKHR { vk::StridedDeviceAddressRegionKHR::default() - .device_address(self.render_system.get_buffer_address(range.buffer) + range.offset) - .stride(range.stride) - .size(range.size) + .device_address(self.render_system.get_buffer_address(range.buffer) as vk::DeviceSize + range.offset as vk::DeviceSize) + .stride(range.stride as vk::DeviceSize) + .size(range.size as vk::DeviceSize) }; let raygen_shader_binding_tables = make_strided_range(binding_tables.raygen); @@ -3605,19 +3707,26 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_> } /// Binds a decriptor set on the GPU. - fn bind_descriptor_sets(&self, pipeline_layout: &render_system::PipelineLayoutHandle, sets: &[(render_system::DescriptorSetHandle, u32)]) { + fn bind_descriptor_sets(&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]; + + let s = sets.iter().map(|set| { + let (_, descriptor_set) = self.get_descriptor_set(set); + let index_in_layout = pipeline_layout.descriptor_set_template_indices.get(&descriptor_set.descriptor_set_layout).unwrap(); + (*index_in_layout, descriptor_set.descriptor_set) + }); - let pipeline_layout = vk::PipelineLayout::from_raw(pipeline_layout.0); + let vulkan_pipeline_layout_handle = pipeline_layout.pipeline_layout; - assert!(sets.is_sorted_by(|a, b| Some(a.1.cmp(&b.1)))); + // TODO: partion sets by index_in_layout - for (descriptor_set_handle, set_index) in sets { - let (_, descriptor_set) = self.get_descriptor_set(descriptor_set_handle); - let descriptor_sets = [descriptor_set.descriptor_set]; + for (i, descriptor_set_handle) in s { + let descriptor_sets = [descriptor_set_handle]; unsafe { - self.render_system.device.cmd_bind_descriptor_sets(command_buffer.command_buffer, self.pipeline_bind_point, pipeline_layout, *set_index, &descriptor_sets, &[]); + self.render_system.device.cmd_bind_descriptor_sets(command_buffer.command_buffer, self.pipeline_bind_point, vulkan_pipeline_layout_handle, i, &descriptor_sets, &[]); } } } diff --git a/src/rendering/world_render_domain.rs b/src/rendering/world_render_domain.rs new file mode 100644 index 00000000..6961a399 --- /dev/null +++ b/src/rendering/world_render_domain.rs @@ -0,0 +1,6 @@ +use super::render_system; + +pub trait WorldRenderDomain { + fn get_descriptor_set_template(&self) -> render_system::DescriptorSetTemplateHandle; + fn get_result_image(&self) -> render_system::ImageHandle; +} \ No newline at end of file diff --git a/src/resource_manager/mesh_resource_handler.rs b/src/resource_manager/mesh_resource_handler.rs index 6bfd6854..e31865ec 100644 --- a/src/resource_manager/mesh_resource_handler.rs +++ b/src/resource_manager/mesh_resource_handler.rs @@ -110,7 +110,7 @@ impl ResourceHandler for MeshResourceHandler { (meshlet.vertices[i] as u16).to_le_bytes().iter().for_each(|byte| buffer.push(*byte)); } } - index_streams.push(IndexStream{ data_type: IntegralTypes::U16, stream_type: IndexStreamTypes::Raw, offset, count: index_count as u32 }); + index_streams.push(IndexStream{ data_type: IntegralTypes::U16, stream_type: IndexStreamTypes::Vertices, offset, count: index_count as u32 }); } _ => panic!("Unsupported index type") } @@ -143,21 +143,23 @@ impl ResourceHandler for MeshResourceHandler { buffer.push(meshlet.triangle_count); } } else { + meshlet_stream = None; + } + + let add_triangle_stream_even_if_using_meshlets = true; + + if !MESHLETIZE || add_triangle_stream_even_if_using_meshlets { let offset = buffer.len(); - { - let index_type = IntegralTypes::U16; - - match index_type { - IntegralTypes::U16 => { - optimized_indices.iter().map(|i| *i as u16).for_each(|i| i.to_le_bytes().iter().for_each(|byte| buffer.push(*byte))); - index_streams.push(IndexStream{ data_type: IntegralTypes::U16, stream_type: IndexStreamTypes::Raw, offset, count: optimized_indices.len() as u32 }); - } - _ => panic!("Unsupported index type") + let index_type = IntegralTypes::U16; + + match index_type { + IntegralTypes::U16 => { + optimized_indices.iter().map(|i| *i as u16).for_each(|i| i.to_le_bytes().iter().for_each(|byte| buffer.push(*byte))); + index_streams.push(IndexStream{ data_type: IntegralTypes::U16, stream_type: IndexStreamTypes::Triangles, offset, count: optimized_indices.len() as u32 }); } + _ => panic!("Unsupported index type") } - - meshlet_stream = None; } let mesh = Mesh { @@ -205,23 +207,32 @@ impl ResourceHandler for MeshResourceHandler { file.seek(std::io::SeekFrom::Start(mesh.vertex_count as u64 * 12)).unwrap(); // 12 bytes per vertex file.read(&mut buffer.buffer[0..(mesh.vertex_count as usize * 12)]).unwrap(); } - "Indices" => { + "TriangleIndices" => { + #[cfg(debug_assertions)] + if !mesh.index_streams.iter().any(|stream| stream.stream_type == IndexStreamTypes::Triangles) { error!("Requested Index stream but mesh does not have triangle indices."); continue; } + + let triangle_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Triangles).unwrap(); + + file.seek(std::io::SeekFrom::Start(triangle_index_stream.offset as u64)).expect("Failed to seek to index buffer"); + file.read(&mut buffer.buffer[0..(triangle_index_stream.count as usize * triangle_index_stream.data_type.size())]).unwrap(); + } + "VertexIndices" => { #[cfg(debug_assertions)] - if !mesh.index_streams.iter().any(|stream| stream.stream_type == IndexStreamTypes::Raw) { error!("Requested Index stream but mesh does not have RAW indices."); continue; } + if !mesh.index_streams.iter().any(|stream| stream.stream_type == IndexStreamTypes::Vertices) { error!("Requested Index stream but mesh does not have vertex indices."); continue; } - let raw_index_stram = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Raw).unwrap(); + let vertex_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Vertices).unwrap(); - file.seek(std::io::SeekFrom::Start(raw_index_stram.offset as u64)).expect("Failed to seek to index buffer"); - file.read(&mut buffer.buffer[0..(raw_index_stram.count as usize * raw_index_stram.data_type.size())]).unwrap(); + file.seek(std::io::SeekFrom::Start(vertex_index_stream.offset as u64)).expect("Failed to seek to index buffer"); + file.read(&mut buffer.buffer[0..(vertex_index_stream.count as usize * vertex_index_stream.data_type.size())]).unwrap(); } "MeshletIndices" => { #[cfg(debug_assertions)] - if !mesh.index_streams.iter().any(|stream| stream.stream_type == IndexStreamTypes::Meshlets) { error!("Requested MeshletIndices stream but mesh does not have meshlet indices indices."); continue; } + if !mesh.index_streams.iter().any(|stream| stream.stream_type == IndexStreamTypes::Meshlets) { error!("Requested MeshletIndices stream but mesh does not have meshlet indices."); continue; } - let meshlet_indices_streams = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Meshlets).unwrap(); + let meshlet_indices_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Meshlets).unwrap(); - file.seek(std::io::SeekFrom::Start(meshlet_indices_streams.offset as u64)).expect("Failed to seek to index buffer"); - file.read(&mut buffer.buffer[0..(meshlet_indices_streams.count as usize * meshlet_indices_streams.data_type.size())]).unwrap(); + file.seek(std::io::SeekFrom::Start(meshlet_indices_stream.offset as u64)).expect("Failed to seek to index buffer"); + file.read(&mut buffer.buffer[0..(meshlet_indices_stream.count as usize * meshlet_indices_stream.data_type.size())]).unwrap(); } "Meshlets" => { #[cfg(debug_assertions)] @@ -280,8 +291,9 @@ pub enum CompressionSchemes { #[derive(Debug, Serialize, Deserialize, PartialEq)] pub enum IndexStreamTypes { - Raw, + Vertices, Meshlets, + Triangles, } #[derive(Debug, Serialize, Deserialize)] @@ -441,31 +453,40 @@ mod tests { assert_eq!(mesh.vertex_components[1].format, "vec3f"); assert_eq!(mesh.vertex_components[1].channel, 1); - assert_eq!(mesh.index_streams.len(), 2); + assert_eq!(mesh.index_streams.len(), 3); - let raw_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Raw).unwrap(); + let triangle_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Triangles).unwrap(); - let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); + // let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); - assert_eq!(raw_index_stream.stream_type, IndexStreamTypes::Raw); - assert_eq!(raw_index_stream.offset, offset); - assert_eq!(raw_index_stream.count, 24); - assert_eq!(raw_index_stream.data_type, IntegralTypes::U16); + assert_eq!(triangle_index_stream.stream_type, IndexStreamTypes::Triangles); + // assert_eq!(vertex_index_stream.offset, offset); + assert_eq!(triangle_index_stream.count, 36); + assert_eq!(triangle_index_stream.data_type, IntegralTypes::U16); + + let vertex_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Vertices).unwrap(); + + // let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); + + assert_eq!(vertex_index_stream.stream_type, IndexStreamTypes::Vertices); + // assert_eq!(vertex_index_stream.offset, offset); + assert_eq!(vertex_index_stream.count, 24); + assert_eq!(vertex_index_stream.data_type, IntegralTypes::U16); let meshlet_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Meshlets).unwrap(); - let offset = offset + mesh.index_streams[0].count as usize * mesh.index_streams[0].data_type.size(); + // let offset = offset + mesh.index_streams[0].count as usize * mesh.index_streams[0].data_type.size(); assert_eq!(meshlet_index_stream.stream_type, IndexStreamTypes::Meshlets); - assert_eq!(meshlet_index_stream.offset, offset); + // assert_eq!(meshlet_index_stream.offset, offset); assert_eq!(meshlet_index_stream.count, 36); assert_eq!(meshlet_index_stream.data_type, IntegralTypes::U8); let meshlet_stream_info = mesh.meshlet_stream.as_ref().unwrap(); - let offset = offset + meshlet_index_stream.count as usize * meshlet_index_stream.data_type.size(); + // let offset = offset + meshlet_index_stream.count as usize * meshlet_index_stream.data_type.size(); - assert_eq!(meshlet_stream_info.offset, offset); + // assert_eq!(meshlet_stream_info.offset, offset); assert_eq!(meshlet_stream_info.count, 1); let resource_request = resource_manager.request_resource("Box"); @@ -483,7 +504,7 @@ mod tests { "Mesh" => { options.resources.push(OptionResource { url: resource.url.clone(), - streams: vec![Stream{ buffer: vertex_buffer.as_mut_slice(), name: "Vertex".to_string() }, Stream{ buffer: index_buffer.as_mut_slice(), name: "Indices".to_string() }], + streams: vec![Stream{ buffer: vertex_buffer.as_mut_slice(), name: "Vertex".to_string() }, Stream{ buffer: index_buffer.as_mut_slice(), name: "TriangleIndices".to_string() }], }); } _ => {} @@ -500,7 +521,7 @@ mod tests { assert_eq!(buffer[0..(mesh.vertex_count * mesh.vertex_components.size() as u32) as usize], vertex_buffer[0..(mesh.vertex_count * mesh.vertex_components.size() as u32) as usize]); - assert_eq!(buffer[576..(576 + mesh.index_streams[0].count * 2) as usize], index_buffer[0..(mesh.index_streams[0].count * 2) as usize]); + assert_eq!(buffer[triangle_index_stream.offset..(triangle_index_stream.offset + triangle_index_stream.count as usize * 2) as usize], index_buffer[0..(triangle_index_stream.count * 2) as usize]); } _ => {} } @@ -534,21 +555,34 @@ mod tests { assert_eq!(mesh.vertex_components[1].format, "vec3f"); assert_eq!(mesh.vertex_components[1].channel, 1); - assert_eq!(mesh.index_streams.len(), 2); + assert_eq!(mesh.index_streams.len(), 3); + + let triangle_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Triangles).unwrap(); + + // let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); - let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); + assert_eq!(triangle_index_stream.stream_type, IndexStreamTypes::Triangles); + // assert_eq!(vertex_index_stream.offset, offset); + assert_eq!(triangle_index_stream.count, 3936 * 3); + assert_eq!(triangle_index_stream.data_type, IntegralTypes::U16); - assert_eq!(mesh.index_streams[0].stream_type, IndexStreamTypes::Raw); - assert_eq!(mesh.index_streams[0].offset, offset); - assert_eq!(mesh.index_streams[0].count, 3936 * 3); - assert_eq!(mesh.index_streams[0].data_type, IntegralTypes::U16); + let vertex_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Vertices).unwrap(); - let offset = offset + mesh.index_streams[0].count as usize * mesh.index_streams[0].data_type.size(); + // let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); - assert_eq!(mesh.index_streams[1].stream_type, IndexStreamTypes::Meshlets); - assert_eq!(mesh.index_streams[1].offset, offset); - assert_eq!(mesh.index_streams[1].count, 3936 * 3); - assert_eq!(mesh.index_streams[1].data_type, IntegralTypes::U8); + assert_eq!(vertex_index_stream.stream_type, IndexStreamTypes::Vertices); + // assert_eq!(mesh.index_streams[0].offset, offset); + assert_eq!(vertex_index_stream.count, 3936 * 3); + assert_eq!(vertex_index_stream.data_type, IntegralTypes::U16); + + let meshlet_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Meshlets).unwrap(); + + // let offset = offset + mesh.index_streams[0].count as usize * mesh.index_streams[0].data_type.size(); + + assert_eq!(meshlet_index_stream.stream_type, IndexStreamTypes::Meshlets); + // assert_eq!(mesh.index_streams[1].offset, offset); + assert_eq!(meshlet_index_stream.count, 3936 * 3); + assert_eq!(meshlet_index_stream.data_type, IntegralTypes::U8); let vertex_positions = unsafe { std::slice::from_raw_parts(buffer.as_ptr() as *const Vector3, mesh.vertex_count as usize) }; @@ -565,6 +599,11 @@ mod tests { assert_eq!(vertex_normals[0], Vector3::new(0.703351f32, -0.228379f32, -0.673156f32)); assert_eq!(vertex_normals[1], Vector3::new(0.818977f32, -0.001884f32, -0.573824f32)); assert_eq!(vertex_normals[2], Vector3::new(0.776439f32, -0.262265f32, -0.573027f32)); + + let triangle_indices = unsafe { std::slice::from_raw_parts(buffer.as_ptr().add(triangle_index_stream.offset) as *const u16, triangle_index_stream.count as usize) }; + + assert_eq!(triangle_indices[0..3], [0, 1, 2]); + assert_eq!(triangle_indices[3935 * 3..3936 * 3], [11805, 11806, 11807]); } #[test] @@ -594,27 +633,38 @@ mod tests { assert_eq!(mesh.vertex_components[1].semantic, VertexSemantics::Normal); assert_eq!(mesh.vertex_components[1].format, "vec3f"); assert_eq!(mesh.vertex_components[1].channel, 1); - assert_eq!(mesh.index_streams.len(), 2); - let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); + assert_eq!(mesh.index_streams.len(), 3); - assert_eq!(mesh.index_streams[0].stream_type, IndexStreamTypes::Raw); - assert_eq!(mesh.index_streams[0].offset, offset); - assert_eq!(mesh.index_streams[0].count, 24); - assert_eq!(mesh.index_streams[0].data_type, IntegralTypes::U16); + let triangle_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Triangles).unwrap(); - let offset = offset + mesh.index_streams[0].count as usize * mesh.index_streams[0].data_type.size(); + // let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); - assert_eq!(mesh.index_streams[1].stream_type, IndexStreamTypes::Meshlets); - assert_eq!(mesh.index_streams[1].offset, offset); - assert_eq!(mesh.index_streams[1].count, 36); - assert_eq!(mesh.index_streams[1].data_type, IntegralTypes::U8); + assert_eq!(triangle_index_stream.stream_type, IndexStreamTypes::Triangles); + // assert_eq!(vertex_index_stream.offset, offset); + assert_eq!(triangle_index_stream.count, 36); + assert_eq!(triangle_index_stream.data_type, IntegralTypes::U16); - let meshlet_stream_info = mesh.meshlet_stream.as_ref().unwrap(); + let vertex_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Vertices).unwrap(); + + // let offset = ((mesh.vertex_count * mesh.vertex_components.size() as u32) as usize).next_multiple_of(16); + + assert_eq!(vertex_index_stream.stream_type, IndexStreamTypes::Vertices); + // assert_eq!(vertex_index_stream.offset, offset); + assert_eq!(vertex_index_stream.count, 24); + assert_eq!(vertex_index_stream.data_type, IntegralTypes::U16); - let offset = offset + mesh.index_streams[1].count as usize * mesh.index_streams[1].data_type.size(); + let meshlet_index_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Meshlets).unwrap(); + + // let offset = offset + mesh.index_streams[0].count as usize * mesh.index_streams[0].data_type.size(); + + assert_eq!(meshlet_index_stream.stream_type, IndexStreamTypes::Meshlets); + // assert_eq!(meshlet_index_stream.offset, offset); + assert_eq!(meshlet_index_stream.count, 36); + assert_eq!(meshlet_index_stream.data_type, IntegralTypes::U8); + + let meshlet_stream_info = mesh.meshlet_stream.as_ref().unwrap(); - assert_eq!(meshlet_stream_info.offset, offset); assert_eq!(meshlet_stream_info.count, 1); // Cast buffer to Vector3 @@ -659,7 +709,7 @@ mod tests { "Mesh" => { options.resources.push(OptionResource { url: resource.url.clone(), - streams: vec![Stream{ buffer: vertex_buffer.as_mut_slice(), name: "Vertex".to_string() }, Stream{ buffer: index_buffer.as_mut_slice(), name: "Indices".to_string() }], + streams: vec![Stream{ buffer: vertex_buffer.as_mut_slice(), name: "Vertex".to_string() }, Stream{ buffer: index_buffer.as_mut_slice(), name: "TriangleIndices".to_string() }], }); } _ => {} @@ -674,6 +724,8 @@ mod tests { "Mesh" => { let mesh = resource.resource.downcast_ref::().unwrap(); + let triangle_indices_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Triangles).unwrap(); + // Cast vertex_buffer to Vector3 let vertex_positions = unsafe { std::slice::from_raw_parts(vertex_buffer.as_ptr() as *const Vector3, mesh.vertex_count as usize) }; @@ -690,11 +742,10 @@ mod tests { assert_eq!(vertex_normals[1], Vector3::new(0f32, 0f32, -1f32)); assert_eq!(vertex_normals[2], Vector3::new(0f32, 0f32, -1f32)); - // Cast index_buffer to u16 - let index_buffer = unsafe { std::slice::from_raw_parts(index_buffer.as_ptr() as *const u16, mesh.index_streams[0].count as usize) }; + let index_buffer = unsafe { std::slice::from_raw_parts(index_buffer.as_ptr() as *const u16, triangle_indices_stream.count as usize) }; - assert_eq!(index_buffer.len(), 24); + assert_eq!(index_buffer.len(), 36); assert_eq!(index_buffer[0], 0); assert_eq!(index_buffer[1], 1); assert_eq!(index_buffer[2], 2); @@ -725,7 +776,7 @@ mod tests { streams: vec![ Stream{ buffer: vertex_positions_buffer.as_mut_slice(), name: "Vertex.Position".to_string() }, Stream{ buffer: vertex_normals_buffer.as_mut_slice(), name: "Vertex.Normal".to_string() }, - Stream{ buffer: index_buffer.as_mut_slice(), name: "Indices".to_string() } + Stream{ buffer: index_buffer.as_mut_slice(), name: "TriangleIndices".to_string() } ], }); } @@ -741,6 +792,8 @@ mod tests { "Mesh" => { let mesh = resource.resource.downcast_ref::().unwrap(); + let triangle_indices_stream = mesh.index_streams.iter().find(|stream| stream.stream_type == IndexStreamTypes::Triangles).unwrap(); + // Cast vertex_positions_buffer to Vector3 let vertex_positions_buffer = unsafe { std::slice::from_raw_parts(vertex_positions_buffer.as_ptr() as *const Vector3, mesh.vertex_count as usize) }; @@ -759,9 +812,9 @@ mod tests { // Cast index_buffer to u16 - let index_buffer = unsafe { std::slice::from_raw_parts(index_buffer.as_ptr() as *const u16, mesh.index_streams[0].count as usize) }; + let index_buffer = unsafe { std::slice::from_raw_parts(index_buffer.as_ptr() as *const u16, triangle_indices_stream.count as usize) }; - assert_eq!(index_buffer.len(), 24); + assert_eq!(index_buffer.len(), 36); assert_eq!(index_buffer[0], 0); assert_eq!(index_buffer[1], 1); assert_eq!(index_buffer[2], 2); diff --git a/src/resource_manager/resource_manager.rs b/src/resource_manager/resource_manager.rs index 1f31bd48..a4acea95 100644 --- a/src/resource_manager/resource_manager.rs +++ b/src/resource_manager/resource_manager.rs @@ -113,7 +113,7 @@ impl ResourceManager { } } - pub fn new_as_system() -> orchestrator::EntityReturn { + pub fn new_as_system() -> orchestrator::EntityReturn<'static, ResourceManager> { orchestrator::EntityReturn::new(Self::new()) } diff --git a/src/window_system.rs b/src/window_system.rs index f7a54fc4..dc5853ba 100644 --- a/src/window_system.rs +++ b/src/window_system.rs @@ -617,7 +617,7 @@ impl WindowSystem { WindowSystem { windows: Vec::new() } } - pub fn new_as_system() -> orchestrator::EntityReturn { + pub fn new_as_system() -> orchestrator::EntityReturn<'static, WindowSystem> { orchestrator::EntityReturn::new(Self::new()).add_listener::() } diff --git a/tests/gallery_shooter.rs b/tests/gallery_shooter.rs index 8ed04ecc..9b3b8806 100644 --- a/tests/gallery_shooter.rs +++ b/tests/gallery_shooter.rs @@ -53,7 +53,7 @@ impl Component for Player { } impl Player { - fn new(lookaround: EntityHandle>) -> orchestrator::EntityReturn { + fn new(lookaround: EntityHandle>) -> orchestrator::EntityReturn<'static, Self> { orchestrator::EntityReturn::new_from_closure(move |orchestrator| { let mut transform = maths_rs::Mat4f::identity();