diff --git a/examples/dot_cube.rs b/examples/dot_cube.rs index 02e5b89..b869550 100644 --- a/examples/dot_cube.rs +++ b/examples/dot_cube.rs @@ -9,7 +9,7 @@ use iyes_perf_ui::{ #[cfg(feature = "bevy_wgpu")] use shocovox_rs::octree::{ - raytracing::{OctreeGPUView, Ray, SvxRenderPlugin, Viewport}, + raytracing::{OctreeGPUHost, OctreeGPUView, Ray, SvxRenderPlugin, Viewport}, Albedo, Octree, V3c, VoxelData, }; @@ -22,15 +22,6 @@ const BRICK_DIMENSION: usize = 2; #[cfg(feature = "bevy_wgpu")] const TREE_SIZE: u32 = 16; -#[cfg(feature = "bevy_wgpu")] -#[derive(Resource)] -struct TreeResource -where - T: Default + Clone + PartialEq + VoxelData, -{ - tree: Octree, -} - #[cfg(feature = "bevy_wgpu")] fn main() { App::new() @@ -51,8 +42,6 @@ fn main() { #[cfg(feature = "bevy_wgpu")] fn setup(mut commands: Commands, images: ResMut>) { - // use shocovox_rs::octree::raytracing::bevy::create_viewing_glass; - let origin = V3c::new( TREE_SIZE as f32 * 2., TREE_SIZE as f32 / 2., @@ -64,19 +53,6 @@ fn setup(mut commands: Commands, images: ResMut>) { .ok() .unwrap(); - // +++ DEBUG +++ - // tree.insert(&V3c::new(0, 0, 0), Albedo::from(0x66FFFF)) - // .ok() - // .unwrap(); - // tree.insert(&V3c::new(3, 3, 3), Albedo::from(0x66FFFF)) - // .ok() - // .unwrap(); - // assert!(tree.get(&V3c::new(3, 3, 3)).is_some()); - // tree.insert_at_lod(&V3c::new(0, 0, 0), 128, Albedo::from(0x66FFFF)) - // .ok() - // .unwrap(); - - // ---DEBUG --- for x in 0..TREE_SIZE { for y in 0..TREE_SIZE { for z in 0..TREE_SIZE { @@ -116,8 +92,15 @@ fn setup(mut commands: Commands, images: ResMut>) { } } - let output_texture = tree.create_new_gpu_view( - 42, //TODO: decide actual number + commands.spawn(DomePosition { + yaw: 0., + roll: 0., + radius: tree.get_size() as f32 * 2.2, + }); + + let host = OctreeGPUHost::new(tree); + let output_texture = host.create_new_view( + 40, //TODO: decide actual number Viewport { origin, direction: (V3c::new(0., 0., 0.) - origin).normalized(), @@ -127,12 +110,7 @@ fn setup(mut commands: Commands, images: ResMut>) { &mut commands, images, ); - - commands.spawn(DomePosition { - yaw: 0., - roll: 0., - radius: tree.get_size() as f32 * 2.2, - }); + commands.insert_resource(host); commands.spawn(SpriteBundle { sprite: Sprite { custom_size: Some(Vec2::new(1024., 768.)), @@ -142,7 +120,6 @@ fn setup(mut commands: Commands, images: ResMut>) { ..default() }); commands.spawn(Camera2dBundle::default()); - commands.insert_resource(TreeResource { tree }); commands.spawn(( PerfUiRoot::default(), PerfUiEntryFPS { @@ -174,13 +151,13 @@ fn rotate_camera(angles_query: Query<&mut DomePosition>, mut tree_view: ResMut>, mut tree_view: ResMut, mut angles_query: Query<&mut DomePosition>, - tree: Res>, + tree: Res>, ) { if keys.pressed(KeyCode::Delete) { tree_view.do_the_thing = true; @@ -209,17 +186,16 @@ fn handle_zoom( // Render the current view with CPU let viewport_up_direction = V3c::new(0., 1., 0.); let viewport_right_direction = viewport_up_direction - .cross(tree_view.viewing_glass.viewport.direction) + .cross(tree_view.spyglass.viewport.direction) .normalized(); let pixel_width = - tree_view.viewing_glass.viewport.w_h_fov.x as f32 / DISPLAY_RESOLUTION[0] as f32; + tree_view.spyglass.viewport.w_h_fov.x as f32 / DISPLAY_RESOLUTION[0] as f32; let pixel_height = - tree_view.viewing_glass.viewport.w_h_fov.y as f32 / DISPLAY_RESOLUTION[1] as f32; - let viewport_bottom_left = tree_view.viewing_glass.viewport.origin - + (tree_view.viewing_glass.viewport.direction - * tree_view.viewing_glass.viewport.w_h_fov.z) - - (viewport_up_direction * (tree_view.viewing_glass.viewport.w_h_fov.y / 2.)) - - (viewport_right_direction * (tree_view.viewing_glass.viewport.w_h_fov.x / 2.)); + tree_view.spyglass.viewport.w_h_fov.y as f32 / DISPLAY_RESOLUTION[1] as f32; + let viewport_bottom_left = tree_view.spyglass.viewport.origin + + (tree_view.spyglass.viewport.direction * tree_view.spyglass.viewport.w_h_fov.z) + - (viewport_up_direction * (tree_view.spyglass.viewport.w_h_fov.y / 2.)) + - (viewport_right_direction * (tree_view.spyglass.viewport.w_h_fov.x / 2.)); // define light let diffuse_light_normal = V3c::new(0., -1., 1.).normalized(); @@ -237,8 +213,8 @@ fn handle_zoom( + viewport_right_direction * x as f32 * pixel_width + viewport_up_direction * y as f32 * pixel_height; let ray = Ray { - origin: tree_view.viewing_glass.viewport.origin, - direction: (glass_point - tree_view.viewing_glass.viewport.origin).normalized(), + origin: tree_view.spyglass.viewport.origin, + direction: (glass_point - tree_view.spyglass.viewport.origin).normalized(), }; use std::io::Write; @@ -282,11 +258,9 @@ fn handle_zoom( } if keys.pressed(KeyCode::ArrowLeft) { angles_query.single_mut().yaw = angle_update_fn(angles_query.single().yaw, ADDITION); - // println!("viewport: {:?}", viewing_glass.viewport); } if keys.pressed(KeyCode::ArrowRight) { angles_query.single_mut().yaw = angle_update_fn(angles_query.single().yaw, -ADDITION); - // println!("viewport: {:?}", viewing_glass.viewport); } if keys.pressed(KeyCode::PageUp) { angles_query.single_mut().radius *= 1. - 0.02 * multiplier; @@ -295,12 +269,12 @@ fn handle_zoom( angles_query.single_mut().radius *= 1. + 0.02 * multiplier; } if keys.pressed(KeyCode::Home) { - tree_view.viewing_glass.viewport.w_h_fov.x *= 1. + 0.09 * multiplier; - tree_view.viewing_glass.viewport.w_h_fov.y *= 1. + 0.09 * multiplier; + tree_view.spyglass.viewport.w_h_fov.x *= 1. + 0.09 * multiplier; + tree_view.spyglass.viewport.w_h_fov.y *= 1. + 0.09 * multiplier; } if keys.pressed(KeyCode::End) { - tree_view.viewing_glass.viewport.w_h_fov.x *= 1. - 0.09 * multiplier; - tree_view.viewing_glass.viewport.w_h_fov.y *= 1. - 0.09 * multiplier; + tree_view.spyglass.viewport.w_h_fov.x *= 1. - 0.09 * multiplier; + tree_view.spyglass.viewport.w_h_fov.y *= 1. - 0.09 * multiplier; } } diff --git a/examples/minecraft.rs b/examples/minecraft.rs index d5cc93b..3685a4f 100644 --- a/examples/minecraft.rs +++ b/examples/minecraft.rs @@ -3,7 +3,7 @@ use bevy::{prelude::*, window::WindowPlugin}; #[cfg(feature = "bevy_wgpu")] use shocovox_rs::octree::{ - raytracing::{OctreeGPUView, Ray, SvxRenderPlugin, Viewport}, + raytracing::{OctreeGPUHost, OctreeGPUView, Ray, SvxRenderPlugin, Viewport}, Albedo, Octree, V3c, VoxelData, }; @@ -20,15 +20,6 @@ const DISPLAY_RESOLUTION: [u32; 2] = [1024, 768]; #[cfg(feature = "bevy_wgpu")] const BRICK_DIMENSION: usize = 32; -#[cfg(feature = "bevy_wgpu")] -#[derive(Resource)] -struct TreeResource -where - T: Default + Clone + PartialEq + VoxelData, -{ - tree: Octree, -} - #[cfg(feature = "bevy_wgpu")] fn main() { App::new() @@ -79,7 +70,8 @@ fn setup(mut commands: Commands, images: ResMut>) { radius: tree.get_size() as f32 * 2.2, }); - let output_texture = tree.create_new_gpu_view( + let host = OctreeGPUHost::new(tree); + let output_texture = host.create_new_view( 20, Viewport { origin: V3c { @@ -98,7 +90,7 @@ fn setup(mut commands: Commands, images: ResMut>) { &mut commands, images, ); - + commands.insert_resource(host); commands.spawn(SpriteBundle { sprite: Sprite { custom_size: Some(Vec2::new(1024., 768.)), @@ -108,8 +100,6 @@ fn setup(mut commands: Commands, images: ResMut>) { ..default() }); commands.spawn(Camera2dBundle::default()); - commands.insert_resource(TreeResource { tree }); - commands.spawn(( PerfUiRoot::default(), PerfUiEntryFPS { @@ -142,13 +132,13 @@ fn rotate_camera(angles_query: Query<&mut DomePosition>, mut tree_view: ResMut>, mut tree_view: ResMut, mut angles_query: Query<&mut DomePosition>, - tree: Res>, + tree: Res>, ) { if keys.pressed(KeyCode::Delete) { tree_view.do_the_thing = true; @@ -177,17 +167,16 @@ fn handle_zoom( // Render the current view with CPU let viewport_up_direction = V3c::new(0., 1., 0.); let viewport_right_direction = viewport_up_direction - .cross(tree_view.viewing_glass.viewport.direction) + .cross(tree_view.spyglass.viewport.direction) .normalized(); let pixel_width = - tree_view.viewing_glass.viewport.w_h_fov.x as f32 / DISPLAY_RESOLUTION[0] as f32; + tree_view.spyglass.viewport.w_h_fov.x as f32 / DISPLAY_RESOLUTION[0] as f32; let pixel_height = - tree_view.viewing_glass.viewport.w_h_fov.y as f32 / DISPLAY_RESOLUTION[1] as f32; - let viewport_bottom_left = tree_view.viewing_glass.viewport.origin - + (tree_view.viewing_glass.viewport.direction - * tree_view.viewing_glass.viewport.w_h_fov.z) - - (viewport_up_direction * (tree_view.viewing_glass.viewport.w_h_fov.y / 2.)) - - (viewport_right_direction * (tree_view.viewing_glass.viewport.w_h_fov.x / 2.)); + tree_view.spyglass.viewport.w_h_fov.y as f32 / DISPLAY_RESOLUTION[1] as f32; + let viewport_bottom_left = tree_view.spyglass.viewport.origin + + (tree_view.spyglass.viewport.direction * tree_view.spyglass.viewport.w_h_fov.z) + - (viewport_up_direction * (tree_view.spyglass.viewport.w_h_fov.y / 2.)) + - (viewport_right_direction * (tree_view.spyglass.viewport.w_h_fov.x / 2.)); // define light let diffuse_light_normal = V3c::new(0., -1., 1.).normalized(); @@ -205,8 +194,8 @@ fn handle_zoom( + viewport_right_direction * x as f32 * pixel_width + viewport_up_direction * y as f32 * pixel_height; let ray = Ray { - origin: tree_view.viewing_glass.viewport.origin, - direction: (glass_point - tree_view.viewing_glass.viewport.origin).normalized(), + origin: tree_view.spyglass.viewport.origin, + direction: (glass_point - tree_view.spyglass.viewport.origin).normalized(), }; use std::io::Write; @@ -250,11 +239,9 @@ fn handle_zoom( } if keys.pressed(KeyCode::ArrowLeft) { angles_query.single_mut().yaw = angle_update_fn(angles_query.single().yaw, ADDITION); - // println!("viewport: {:?}", viewing_glass.viewport); } if keys.pressed(KeyCode::ArrowRight) { angles_query.single_mut().yaw = angle_update_fn(angles_query.single().yaw, -ADDITION); - // println!("viewport: {:?}", viewing_glass.viewport); } if keys.pressed(KeyCode::PageUp) { angles_query.single_mut().radius *= 1. - 0.02 * multiplier; @@ -263,12 +250,12 @@ fn handle_zoom( angles_query.single_mut().radius *= 1. + 0.02 * multiplier; } if keys.pressed(KeyCode::Home) { - tree_view.viewing_glass.viewport.w_h_fov.x *= 1. + 0.09 * multiplier; - tree_view.viewing_glass.viewport.w_h_fov.y *= 1. + 0.09 * multiplier; + tree_view.spyglass.viewport.w_h_fov.x *= 1. + 0.09 * multiplier; + tree_view.spyglass.viewport.w_h_fov.y *= 1. + 0.09 * multiplier; } if keys.pressed(KeyCode::End) { - tree_view.viewing_glass.viewport.w_h_fov.x *= 1. - 0.09 * multiplier; - tree_view.viewing_glass.viewport.w_h_fov.y *= 1. - 0.09 * multiplier; + tree_view.spyglass.viewport.w_h_fov.x *= 1. - 0.09 * multiplier; + tree_view.spyglass.viewport.w_h_fov.y *= 1. - 0.09 * multiplier; } } diff --git a/src/octree/convert/bytecode.rs b/src/octree/convert/bytecode.rs index e4c099a..7210069 100644 --- a/src/octree/convert/bytecode.rs +++ b/src/octree/convert/bytecode.rs @@ -409,8 +409,6 @@ where )?; let node_children = Vec::decode_bencode_object(list.next_object()?.unwrap())?; Ok(Self { - #[cfg(feature = "bevy_wgpu")] - views: Vec::new(), auto_simplify, octree_size: root_size, nodes, diff --git a/src/octree/mod.rs b/src/octree/mod.rs index 37dee73..0efe2d3 100644 --- a/src/octree/mod.rs +++ b/src/octree/mod.rs @@ -82,8 +82,6 @@ where let root_node_key = nodes.push(NodeContent::Nothing); // The first element is the root Node assert!(root_node_key == 0); Ok(Self { - #[cfg(feature = "bevy_wgpu")] - views: Vec::new(), auto_simplify: true, octree_size: size, nodes, diff --git a/src/octree/raytracing/bevy/cache.rs b/src/octree/raytracing/bevy/cache.rs index 6b522a9..1a6f81f 100644 --- a/src/octree/raytracing/bevy/cache.rs +++ b/src/octree/raytracing/bevy/cache.rs @@ -2,7 +2,7 @@ use crate::object_pool::empty_marker; use crate::spatial::math::flat_projection; use crate::{ octree::{ - raytracing::bevy::types::{SvxRenderData, Voxelement}, + raytracing::bevy::types::{OctreeRenderData, Voxelement}, types::{NodeChildrenArray, NodeContent}, BrickData, Octree, VoxelData, }, @@ -64,7 +64,7 @@ impl VictimPointer { /// Provides the first available index in the metadata buffer which can be overwritten /// with node related information. It never returns with 0, because that is reserved for the root node, /// which should not be overwritten. - fn first_available_node(&mut self, render_data: &mut SvxRenderData) -> usize { + fn first_available_node(&mut self, render_data: &mut OctreeRenderData) -> usize { // If there is space left in the cache, use it all up if !self.is_full() { render_data.metadata[self.stored_items] |= 0x01; @@ -131,7 +131,7 @@ impl VictimPointer { } /// Finds the first available brick, and marks it as used - fn first_available_brick(&mut self, render_data: &mut SvxRenderData) -> usize { + fn first_available_brick(&mut self, render_data: &mut OctreeRenderData) -> usize { let max_brick_count = render_data.metadata.len() * 8; // If there is space left in the cache, use it all up diff --git a/src/octree/raytracing/bevy/data.rs b/src/octree/raytracing/bevy/data.rs index 995fc3b..5d10ac9 100644 --- a/src/octree/raytracing/bevy/data.rs +++ b/src/octree/raytracing/bevy/data.rs @@ -1,11 +1,8 @@ use crate::object_pool::empty_marker; use crate::octree::{ - raytracing::bevy::{ - create_output_texture, - types::{ - OctreeGPUView, OctreeMetaData, SvxRenderData, SvxRenderPipeline, SvxViewingGlass, - Viewport, Voxelement, - }, + raytracing::bevy::types::{ + OctreeGPUDataHandler, OctreeGPUHost, OctreeGPUView, OctreeMetaData, OctreeRenderData, + OctreeSpyGlass, SvxRenderPipeline, VictimPointer, Viewport, Voxelement, }, Octree, V3c, VoxelData, }; @@ -13,16 +10,21 @@ use bevy::{ ecs::system::{Res, ResMut}, math::Vec4, prelude::{Assets, Commands, Handle, Image}, - render::renderer::RenderDevice, + render::{ + render_asset::RenderAssetUsages, + render_resource::{ + encase::{StorageBuffer, UniformBuffer}, + Extent3d, TextureDimension, TextureFormat, TextureUsages, + }, + renderer::RenderDevice, + }, }; use std::{ collections::HashMap, sync::{Arc, Mutex}, }; -use super::types::{OctreeGPUDataHandler, VictimPointer}; - -impl Octree +impl OctreeGPUHost where T: Default + Clone + Copy + PartialEq + VoxelData, { @@ -53,27 +55,26 @@ where //############################################################################## /// Creates GPU compatible data renderable on the GPU from an octree - pub fn create_new_gpu_view( + pub fn create_new_view( &self, size: usize, viewport: Viewport, resolution: [u32; 2], commands: &mut Commands, - images: ResMut>, + mut images: ResMut>, ) -> Handle { let mut gpu_data_handler = OctreeGPUDataHandler { - debug_gpu_interface: None, - readable_debug_gpu_interface: None, - render_data: SvxRenderData { + read_back: 0, + render_data: OctreeRenderData { debug_gpu_interface: 0, octree_meta: OctreeMetaData { - octree_size: self.octree_size, + octree_size: self.tree.octree_size, voxel_brick_dim: DIM as u32, ambient_light_color: V3c::new(1., 1., 1.), ambient_light_position: V3c::new( - self.octree_size as f32, - self.octree_size as f32, - self.octree_size as f32, + self.tree.octree_size as f32, + self.tree.octree_size as f32, + self.tree.octree_size as f32, ), }, metadata: vec![0; size], @@ -95,7 +96,7 @@ where }; // Push root node and its contents - gpu_data_handler.add_node(&self, Self::ROOT_NODE_KEY as usize, true); + gpu_data_handler.add_node(&self.tree, Octree::::ROOT_NODE_KEY as usize, true); // +++ DEBUG +++ //delete some random bricks from leaf nodes @@ -112,12 +113,26 @@ where // --- DEBUG --- - let output_texture = create_output_texture(resolution, images); + let mut output_texture = Image::new_fill( + Extent3d { + width: resolution[0], + height: resolution[1], + depth_or_array_layers: 1, + }, + TextureDimension::D2, + &[0, 0, 0, 255], + TextureFormat::Rgba8Unorm, + RenderAssetUsages::RENDER_WORLD, + ); + output_texture.texture_descriptor.usage = TextureUsages::COPY_DST + | TextureUsages::STORAGE_BINDING + | TextureUsages::TEXTURE_BINDING; + let output_texture = images.add(output_texture); + commands.insert_resource(OctreeGPUView { do_the_thing: false, - read_back: 0, data_handler: Arc::new(Mutex::new(gpu_data_handler)), - viewing_glass: SvxViewingGlass { + spyglass: OctreeSpyGlass { output_texture: output_texture.clone(), viewport: viewport, }, @@ -162,51 +177,52 @@ pub(crate) fn sync_with_main_world(// tree_view: Option>, //############################################################################## pub(crate) fn handle_gpu_readback( render_device: Res, - mut tree_gpu_view: Option>, + tree_gpu_view: Option>, + svx_pipeline: Option>, ) { // Data updates triggered by debug interface - if let Some(ref mut tree_gpu_view) = tree_gpu_view { + if let (Some(ref mut tree_gpu_view), Some(ref mut pipeline)) = (tree_gpu_view, svx_pipeline) { if tree_gpu_view.do_the_thing { - let received_data; - { - let data_handler = tree_gpu_view.data_handler.lock().unwrap(); - // GPU buffer read - // https://docs.rs/bevy/latest/src/gpu_readback/gpu_readback.rs.html - let buffer_slice = data_handler - .readable_debug_gpu_interface - .as_ref() - .unwrap() - .slice(..); - let (s, r) = crossbeam::channel::unbounded::<()>(); - buffer_slice.map_async(bevy::render::render_resource::MapMode::Read, move |d| { - match d { - Ok(_) => s.send(()).expect("Failed to send map update"), - Err(err) => panic!("Couldn't map debug interface buffer!: {err}"), - } - }); + let mut data_handler = tree_gpu_view.data_handler.lock().unwrap(); + // GPU buffer read + // https://docs.rs/bevy/latest/src/gpu_readback/gpu_readback.rs.html + let buffer_slice = pipeline + .resources + .as_ref() + .unwrap() + .readable_debug_gpu_interface + .slice(..); + let (s, r) = crossbeam::channel::unbounded::<()>(); + buffer_slice.map_async( + bevy::render::render_resource::MapMode::Read, + move |d| match d { + Ok(_) => s.send(()).expect("Failed to send map update"), + Err(err) => panic!("Couldn't map debug interface buffer!: {err}"), + }, + ); - render_device - .poll(bevy::render::render_resource::Maintain::wait()) - .panic_on_timeout(); + render_device + .poll(bevy::render::render_resource::Maintain::wait()) + .panic_on_timeout(); - r.recv().expect("Failed to receive the map_async message"); - { - let buffer_view = buffer_slice.get_mapped_range(); + r.recv().expect("Failed to receive the map_async message"); + { + let buffer_view = buffer_slice.get_mapped_range(); - let data = buffer_view - .chunks(std::mem::size_of::()) - .map(|chunk| u32::from_ne_bytes(chunk.try_into().expect("should be a u32"))) - .collect::>(); - received_data = data[0]; - // println!("received_data: {:?}", data); - } - data_handler - .readable_debug_gpu_interface - .as_ref() - .unwrap() - .unmap(); + let data = buffer_view + .chunks(std::mem::size_of::()) + .map(|chunk| u32::from_ne_bytes(chunk.try_into().expect("should be a u32"))) + .collect::>(); + data_handler.read_back = data[0]; + // println!("received_data: {:?}", data); } - tree_gpu_view.read_back = received_data; + pipeline + .resources + .as_ref() + .unwrap() + .readable_debug_gpu_interface + .unmap(); + std::mem::drop(data_handler); tree_gpu_view.do_the_thing = false; } } @@ -235,23 +251,24 @@ pub(crate) fn write_to_gpu( tree_gpu_view: Option>, svx_pipeline: Option>, ) { - //TODO: Document that all components are lost during extract transition - // Data updates triggered by debug interface - if let Some(tree_gpu_view) = tree_gpu_view { - let svx_pipeline = svx_pipeline.unwrap(); - let render_queue = &svx_pipeline.render_queue.0; + if let (Some(tree_gpu_view), Some(pipeline)) = (tree_gpu_view, svx_pipeline) { + let render_queue = &pipeline.render_queue.0; + + // Data updates for spyglass viewport + if let Some(resources) = &pipeline.resources { + let mut buffer = UniformBuffer::new(Vec::::new()); + buffer.write(&tree_gpu_view.spyglass.viewport).unwrap(); + pipeline + .render_queue + .write_buffer(&resources.viewport_buffer, 0, &buffer.into_inner()); + } + + // Data updates triggered by debug interface if tree_gpu_view.do_the_thing { // GPU buffer Write - use bevy::render::render_resource::encase::StorageBuffer; let data_buffer = StorageBuffer::new(vec![0, 0, 0, 1]); render_queue.write_buffer( - tree_gpu_view - .data_handler - .lock() - .unwrap() - .debug_gpu_interface - .as_ref() - .unwrap(), + &pipeline.resources.as_ref().unwrap().debug_gpu_interface, 0, &data_buffer.into_inner(), ); diff --git a/src/octree/raytracing/bevy/mod.rs b/src/octree/raytracing/bevy/mod.rs index 6f5e451..efe721a 100644 --- a/src/octree/raytracing/bevy/mod.rs +++ b/src/octree/raytracing/bevy/mod.rs @@ -4,48 +4,37 @@ mod pipeline; pub mod types; pub use crate::octree::raytracing::bevy::types::{ - OctreeGPUView, SvxRenderPlugin, SvxViewingGlass, Viewport, + OctreeGPUHost, OctreeGPUView, OctreeSpyGlass, SvxRenderPlugin, Viewport, }; -use crate::octree::raytracing::bevy::{ - data::{handle_gpu_readback, sync_with_main_world, write_to_gpu}, - pipeline::prepare_bind_groups, - types::{SvxLabel, SvxRenderNode, SvxRenderPipeline}, +use crate::octree::{ + raytracing::bevy::{ + data::{handle_gpu_readback, sync_with_main_world, write_to_gpu}, + pipeline::prepare_bind_groups, + types::{SvxLabel, SvxRenderNode, SvxRenderPipeline}, + }, + Octree, VoxelData, }; use bevy::{ app::{App, Plugin}, - asset::{Assets, Handle}, - ecs::system::ResMut, prelude::{ExtractSchedule, IntoSystemConfigs}, render::{ - extract_resource::ExtractResourcePlugin, - prelude::Image, - render_asset::RenderAssetUsages, - render_graph::RenderGraph, - render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages}, - Render, RenderApp, RenderSet, + extract_resource::ExtractResourcePlugin, render_graph::RenderGraph, Render, RenderApp, + RenderSet, }, }; -pub(crate) fn create_output_texture( - resolution: [u32; 2], - mut images: ResMut>, -) -> Handle { - let mut output_texture = Image::new_fill( - Extent3d { - width: resolution[0], - height: resolution[1], - depth_or_array_layers: 1, - }, - TextureDimension::D2, - &[0, 0, 0, 255], - TextureFormat::Rgba8Unorm, - RenderAssetUsages::RENDER_WORLD, - ); - output_texture.texture_descriptor.usage = - TextureUsages::COPY_DST | TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING; - images.add(output_texture) +impl OctreeGPUHost +where + T: Default + Clone + Copy + PartialEq + VoxelData, +{ + pub fn new(tree: Octree) -> Self { + OctreeGPUHost { + tree, + views: Vec::new(), + } + } } impl Plugin for SvxRenderPlugin { diff --git a/src/octree/raytracing/bevy/pipeline.rs b/src/octree/raytracing/bevy/pipeline.rs index 38f9c47..a00dfad 100644 --- a/src/octree/raytracing/bevy/pipeline.rs +++ b/src/octree/raytracing/bevy/pipeline.rs @@ -1,5 +1,5 @@ use crate::octree::raytracing::bevy::types::{ - OctreeGPUView, SvxRenderData, SvxRenderNode, SvxRenderPipeline, SvxViewingGlass, + OctreeGPUView, OctreeRenderData, OctreeSpyGlass, SvxRenderNode, SvxRenderPipeline, }; use bevy::{ @@ -14,7 +14,7 @@ use bevy::{ render_resource::{ encase::{StorageBuffer, UniformBuffer}, AsBindGroup, BufferDescriptor, BufferInitDescriptor, BufferUsages, CachedPipelineState, - ComputePassDescriptor, ComputePipelineDescriptor, PipelineCache, + ComputePassDescriptor, ComputePipelineDescriptor, OwnedBindingResource, PipelineCache, }, renderer::{RenderContext, RenderDevice, RenderQueue}, texture::{FallbackImage, GpuImage}, @@ -22,13 +22,13 @@ use bevy::{ }; use std::borrow::Cow; -use super::types::OctreeGPUDataHandler; +use super::types::OctreeRenderDataResources; impl FromWorld for SvxRenderPipeline { fn from_world(world: &mut World) -> Self { let render_device = world.resource::(); - let viewing_glass_bind_group_layout = SvxViewingGlass::bind_group_layout(render_device); - let render_data_bind_group_layout = SvxRenderData::bind_group_layout(render_device); + let spyglass_bind_group_layout = OctreeSpyGlass::bind_group_layout(render_device); + let render_data_bind_group_layout = OctreeRenderData::bind_group_layout(render_device); let shader = world .resource::() .load("shaders/viewport_render.wgsl"); @@ -36,7 +36,7 @@ impl FromWorld for SvxRenderPipeline { let update_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor { label: None, layout: vec![ - viewing_glass_bind_group_layout.clone(), + spyglass_bind_group_layout.clone(), render_data_bind_group_layout.clone(), ], push_constant_ranges: Vec::new(), @@ -46,21 +46,12 @@ impl FromWorld for SvxRenderPipeline { }); SvxRenderPipeline { - tree_data_handler: None, render_queue: world.resource::().clone(), - octree_meta_buffer: None, - metadata_buffer: None, - node_children_buffer: None, - node_ocbits_buffer: None, - voxels_buffer: None, - color_palette_buffer: None, - readable_metadata_buffer: None, update_tree: true, - viewing_glass_bind_group_layout, + spyglass_bind_group_layout, render_data_bind_group_layout, update_pipeline, - viewing_glass_bind_group: None, - tree_bind_group: None, + resources: None, } } } @@ -109,10 +100,14 @@ impl render_graph::Node for SvxRenderNode { pass.set_bind_group( 0, - svx_pipeline.viewing_glass_bind_group.as_ref().unwrap(), + &svx_pipeline.resources.as_ref().unwrap().spyglass_bind_group, + &[], + ); + pass.set_bind_group( + 1, + &svx_pipeline.resources.as_ref().unwrap().tree_bind_group, &[], ); - pass.set_bind_group(1, svx_pipeline.tree_bind_group.as_ref().unwrap(), &[]); let pipeline = pipeline_cache .get_compute_pipeline(svx_pipeline.update_pipeline) .unwrap(); @@ -125,19 +120,25 @@ impl render_graph::Node for SvxRenderNode { } command_encoder.copy_buffer_to_buffer( - svx_pipeline.metadata_buffer.as_ref().unwrap(), + &svx_pipeline.resources.as_ref().unwrap().metadata_buffer, 0, - svx_pipeline.readable_metadata_buffer.as_ref().unwrap(), + &svx_pipeline + .resources + .as_ref() + .unwrap() + .readable_metadata_buffer, 0, std::mem::size_of::() as u64, ); // +++ DEBUG +++ - let tree_gpu_view = world.resource::(); - let data_handler = tree_gpu_view.data_handler.lock().unwrap(); command_encoder.copy_buffer_to_buffer( - data_handler.debug_gpu_interface.as_ref().unwrap(), + &svx_pipeline.resources.as_ref().unwrap().debug_gpu_interface, 0, - data_handler.readable_debug_gpu_interface.as_ref().unwrap(), + &svx_pipeline + .resources + .as_ref() + .unwrap() + .readable_debug_gpu_interface, 0, std::mem::size_of::() as u64, ) @@ -180,327 +181,209 @@ pub(crate) fn prepare_bind_groups( mut pipeline: ResMut, tree_gpu_view: ResMut, ) { - pipeline.viewing_glass_bind_group = Some( - tree_gpu_view - .viewing_glass - .as_bind_group( - &pipeline.viewing_glass_bind_group_layout, - &render_device, - &gpu_images, - &fallback_image, - ) - .ok() - .unwrap() - .bind_group, - ); + if pipeline.resources.is_some() && !pipeline.update_tree { + return; + } - if pipeline.update_tree { - let mut data_handler = tree_gpu_view.data_handler.lock().unwrap(); + let data_handler = tree_gpu_view.data_handler.lock().unwrap(); + if let Some(resources) = &pipeline.resources { + let mut buffer = UniformBuffer::new(Vec::::new()); + buffer.write(&data_handler.render_data.octree_meta).unwrap(); + pipeline + .render_queue + .write_buffer(&resources.metadata_buffer, 0, &buffer.into_inner()); - // Create the staging buffer helping in reading data from the GPU - //############################################################################## - // █████████ ███████████ █████ █████ - // ███░░░░░███░░███░░░░░███░░███ ░░███ - // ███ ░░░ ░███ ░███ ░███ ░███ - // ░███ ░██████████ ░███ ░███ - // ░███ █████ ░███░░░░░░ ░███ ░███ - // ░░███ ░░███ ░███ ░███ ░███ - // ░░█████████ █████ ░░████████ - // ░░░░░░░░░ ░░░░░ ░░░░░░░░ - // ███████████ ██████████ █████████ ██████████ - // ░░███░░░░░███ ░░███░░░░░█ ███░░░░░███ ░░███░░░░███ - // ░███ ░███ ░███ █ ░ ░███ ░███ ░███ ░░███ - // ░██████████ ░██████ ░███████████ ░███ ░███ - // ░███░░░░░███ ░███░░█ ░███░░░░░███ ░███ ░███ - // ░███ ░███ ░███ ░ █ ░███ ░███ ░███ ███ - // █████ █████ ██████████ █████ █████ ██████████ - // ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ - // ███████████ █████ █████ ███████████ ███████████ ██████████ ███████████ - // ░░███░░░░░███░░███ ░░███ ░░███░░░░░░█░░███░░░░░░█░░███░░░░░█░░███░░░░░███ - // ░███ ░███ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ █ ░ ░███ ░███ - // ░██████████ ░███ ░███ ░███████ ░███████ ░██████ ░██████████ - // ░███░░░░░███ ░███ ░███ ░███░░░█ ░███░░░█ ░███░░█ ░███░░░░░███ - // ░███ ░███ ░███ ░███ ░███ ░ ░███ ░ ░███ ░ █ ░███ ░███ - // ███████████ ░░████████ █████ █████ ██████████ █████ █████ - // ░░░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ - //############################################################################## + let mut buffer = StorageBuffer::new(Vec::::new()); + buffer.write(&data_handler.render_data.metadata).unwrap(); + pipeline + .render_queue + .write_buffer(&resources.metadata_buffer, 0, &buffer.into_inner()); - if pipeline.readable_metadata_buffer.is_none() { - pipeline.readable_metadata_buffer = - Some(render_device.create_buffer(&BufferDescriptor { - mapped_at_creation: false, - size: (data_handler.render_data.metadata.len() * 4) as u64, - label: Some("Octree Node metadata Buffer"), - usage: BufferUsages::COPY_DST | BufferUsages::MAP_READ, - })); - } + let mut buffer = StorageBuffer::new(Vec::::new()); + buffer + .write(&data_handler.render_data.node_children) + .unwrap(); + pipeline.render_queue.write_buffer( + &resources.node_children_buffer, + 0, + &buffer.into_inner(), + ); - // +++ DEBUG +++ - if data_handler.readable_debug_gpu_interface.is_none() { - data_handler.readable_debug_gpu_interface = - Some(render_device.create_buffer(&BufferDescriptor { - mapped_at_creation: false, - size: 4, - label: Some("Octree Debug interface Buffer"), - usage: BufferUsages::COPY_DST | BufferUsages::MAP_READ, - })); - } - // --- DEBUG --- + let mut buffer = StorageBuffer::new(Vec::::new()); + buffer.write(&data_handler.render_data.node_ocbits).unwrap(); + pipeline + .render_queue + .write_buffer(&resources.node_ocbits_buffer, 0, &buffer.into_inner()); - //############################################################################## - // ███████████ ██████████ ██████ █████ ██████████ ██████████ ███████████ - // ░░███░░░░░███ ░░███░░░░░█░░██████ ░░███ ░░███░░░░███ ░░███░░░░░█░░███░░░░░███ - // ░███ ░███ ░███ █ ░ ░███░███ ░███ ░███ ░░███ ░███ █ ░ ░███ ░███ - // ░██████████ ░██████ ░███░░███░███ ░███ ░███ ░██████ ░██████████ - // ░███░░░░░███ ░███░░█ ░███ ░░██████ ░███ ░███ ░███░░█ ░███░░░░░███ - // ░███ ░███ ░███ ░ █ ░███ ░░█████ ░███ ███ ░███ ░ █ ░███ ░███ - // █████ █████ ██████████ █████ ░░█████ ██████████ ██████████ █████ █████ - // ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ - // ██████████ █████████ ███████████ █████████ - // ░░███░░░░███ ███░░░░░███ ░█░░░███░░░█ ███░░░░░███ - // ░███ ░░███ ░███ ░███ ░ ░███ ░ ░███ ░███ - // ░███ ░███ ░███████████ ░███ ░███████████ - // ░███ ░███ ░███░░░░░███ ░███ ░███░░░░░███ - // ░███ ███ ░███ ░███ ░███ ░███ ░███ - // ██████████ █████ █████ █████ █████ █████ - // ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ - // ███████████ █████ █████ ███████████ ███████████ ██████████ ███████████ - // ░░███░░░░░███░░███ ░░███ ░░███░░░░░░█░░███░░░░░░█░░███░░░░░█░░███░░░░░███ - // ░███ ░███ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ █ ░ ░███ ░███ - // ░██████████ ░███ ░███ ░███████ ░███████ ░██████ ░██████████ - // ░███░░░░░███ ░███ ░███ ░███░░░█ ░███░░░█ ░███░░█ ░███░░░░░███ - // ░███ ░███ ░███ ░███ ░███ ░ ░███ ░ ░███ ░ █ ░███ ░███ - // ███████████ ░░████████ █████ █████ ██████████ █████ █████ - // ░░░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ - //############################################################################## + let mut buffer = StorageBuffer::new(Vec::::new()); + buffer.write(&data_handler.render_data.voxels).unwrap(); + pipeline + .render_queue + .write_buffer(&resources.voxels_buffer, 0, &buffer.into_inner()); + + let mut buffer = StorageBuffer::new(Vec::::new()); + buffer + .write(&data_handler.render_data.color_palette) + .unwrap(); + pipeline + .render_queue + .write_buffer(&resources.color_palette_buffer, 0, &buffer.into_inner()) + } else { + // Create the staging buffer helping in reading data from the GPU + let readable_metadata_buffer = render_device.create_buffer(&BufferDescriptor { + mapped_at_creation: false, + size: (data_handler.render_data.metadata.len() * 4) as u64, + label: Some("Octree Node metadata Buffer"), + usage: BufferUsages::COPY_DST | BufferUsages::MAP_READ, + }); - //================================================================= - // Implementation with WGPU - //================================================================= - // Upload data to buffers // +++ DEBUG +++ let buffer = UniformBuffer::new(vec![0, 0, 0, 0]); - if let Some(debug_buffer) = &data_handler.debug_gpu_interface { - pipeline - .render_queue - .write_buffer(debug_buffer, 0, &buffer.into_inner()) - } else { - let debug_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { - label: Some("Octree Debug Buffer"), - contents: &buffer.into_inner(), - usage: BufferUsages::STORAGE | BufferUsages::COPY_DST | BufferUsages::COPY_SRC, - }); - data_handler.debug_gpu_interface = Some(debug_buffer); - } + let debug_gpu_interface = render_device.create_buffer_with_data(&BufferInitDescriptor { + label: Some("Octree Debug Buffer"), + contents: &buffer.into_inner(), + usage: BufferUsages::STORAGE | BufferUsages::COPY_DST | BufferUsages::COPY_SRC, + }); + let readable_debug_gpu_interface = render_device.create_buffer(&BufferDescriptor { + mapped_at_creation: false, + size: 4, + label: Some("Octree Debug interface Buffer"), + usage: BufferUsages::COPY_DST | BufferUsages::MAP_READ, + }); // --- DEBUG --- - let mut buffer = UniformBuffer::new(Vec::::new()); buffer.write(&data_handler.render_data.octree_meta).unwrap(); - if let Some(metadata_buffer) = &pipeline.octree_meta_buffer { - pipeline - .render_queue - .write_buffer(metadata_buffer, 0, &buffer.into_inner()) - } else { - let metadata_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { - label: Some("Octree Metadata Buffer"), - contents: &buffer.into_inner(), - usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST, - }); - pipeline.octree_meta_buffer = Some(metadata_buffer); - } + let octree_meta_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { + label: Some("Octree Metadata Buffer"), + contents: &buffer.into_inner(), + usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST, + }); let mut buffer = StorageBuffer::new(Vec::::new()); buffer.write(&data_handler.render_data.metadata).unwrap(); - if let Some(nodes_buffer) = &pipeline.metadata_buffer { - pipeline - .render_queue - .write_buffer(nodes_buffer, 0, &buffer.into_inner()) - } else { - let nodes_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { - label: Some("Octree Nodes Buffer"), - contents: &buffer.into_inner(), - usage: BufferUsages::STORAGE | BufferUsages::COPY_SRC | BufferUsages::COPY_DST, - }); - pipeline.metadata_buffer = Some(nodes_buffer); - } + let metadata_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { + label: Some("Octree Nodes Buffer"), + contents: &buffer.into_inner(), + usage: BufferUsages::STORAGE | BufferUsages::COPY_SRC | BufferUsages::COPY_DST, + }); let mut buffer = StorageBuffer::new(Vec::::new()); buffer .write(&data_handler.render_data.node_children) .unwrap(); - if let Some(children_buffer) = &pipeline.node_children_buffer { - pipeline - .render_queue - .write_buffer(children_buffer, 0, &buffer.into_inner()) - } else { - let children_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { - label: Some("Octree Node Children Buffer"), - contents: &buffer.into_inner(), - usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, - }); - pipeline.node_children_buffer = Some(children_buffer); - } + let node_children_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { + label: Some("Octree Node Children Buffer"), + contents: &buffer.into_inner(), + usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, + }); let mut buffer = StorageBuffer::new(Vec::::new()); buffer.write(&data_handler.render_data.node_ocbits).unwrap(); - if let Some(ocbits_buffer) = &pipeline.node_ocbits_buffer { - pipeline - .render_queue - .write_buffer(ocbits_buffer, 0, &buffer.into_inner()) - } else { - let ocbits_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { - label: Some("Octree Node Occupied bits Buffer"), - contents: &buffer.into_inner(), - usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, - }); - pipeline.node_ocbits_buffer = Some(ocbits_buffer); - } + let node_ocbits_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { + label: Some("Octree Node Occupied bits Buffer"), + contents: &buffer.into_inner(), + usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, + }); let mut buffer = StorageBuffer::new(Vec::::new()); buffer.write(&data_handler.render_data.voxels).unwrap(); - if let Some(voxels_buffer) = &pipeline.voxels_buffer { - pipeline - .render_queue - .write_buffer(voxels_buffer, 0, &buffer.into_inner()) - } else { - let voxels_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { - label: Some("Octree Voxels Buffer"), - contents: &buffer.into_inner(), - usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, - }); - pipeline.voxels_buffer = Some(voxels_buffer); - } + let voxels_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { + label: Some("Octree Voxels Buffer"), + contents: &buffer.into_inner(), + usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, + }); let mut buffer = StorageBuffer::new(Vec::::new()); buffer .write(&data_handler.render_data.color_palette) .unwrap(); - if let Some(color_palette_buffer) = &pipeline.color_palette_buffer { - pipeline - .render_queue - .write_buffer(color_palette_buffer, 0, &buffer.into_inner()) - } else { - let color_palette_buffer = - render_device.create_buffer_with_data(&BufferInitDescriptor { - label: Some("Octree Color Palette Buffer"), - contents: &buffer.into_inner(), - usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, - }); - pipeline.color_palette_buffer = Some(color_palette_buffer); - } + let color_palette_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { + label: Some("Octree Color Palette Buffer"), + contents: &buffer.into_inner(), + usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, + }); - //############################################################################## - // ███████████ █████ ██████ █████ ██████████ - // ░░███░░░░░███░░███ ░░██████ ░░███ ░░███░░░░███ - // ░███ ░███ ░███ ░███░███ ░███ ░███ ░░███ - // ░██████████ ░███ ░███░░███░███ ░███ ░███ - // ░███░░░░░███ ░███ ░███ ░░██████ ░███ ░███ - // ░███ ░███ ░███ ░███ ░░█████ ░███ ███ - // ███████████ █████ █████ ░░█████ ██████████ - // ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ - // █████████ ███████████ ███████ █████ █████ ███████████ - // ███░░░░░███░░███░░░░░███ ███░░░░░███ ░░███ ░░███ ░░███░░░░░███ - // ███ ░░░ ░███ ░███ ███ ░░███ ░███ ░███ ░███ ░███ - // ░███ ░██████████ ░███ ░███ ░███ ░███ ░██████████ - // ░███ █████ ░███░░░░░███ ░███ ░███ ░███ ░███ ░███░░░░░░ - // ░░███ ░░███ ░███ ░███ ░░███ ███ ░███ ░███ ░███ - // ░░█████████ █████ █████ ░░░███████░ ░░████████ █████ - // ░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░ ░░░░░░░░ ░░░░░ - //############################################################################## // Create bind group let tree_bind_group = render_device.create_bind_group( - SvxRenderData::label(), + OctreeRenderData::label(), &pipeline.render_data_bind_group_layout, &[ bevy::render::render_resource::BindGroupEntry { binding: 0, - resource: pipeline - .octree_meta_buffer - .as_ref() - .unwrap() - .as_entire_binding(), + resource: octree_meta_buffer.as_entire_binding(), }, bevy::render::render_resource::BindGroupEntry { binding: 1, - resource: pipeline - .metadata_buffer - .as_ref() - .unwrap() - .as_entire_binding(), + resource: metadata_buffer.as_entire_binding(), }, bevy::render::render_resource::BindGroupEntry { binding: 2, - resource: pipeline - .node_children_buffer - .as_ref() - .unwrap() - .as_entire_binding(), + resource: node_children_buffer.as_entire_binding(), }, bevy::render::render_resource::BindGroupEntry { binding: 3, - resource: pipeline - .node_ocbits_buffer - .as_ref() - .unwrap() - .as_entire_binding(), + resource: node_ocbits_buffer.as_entire_binding(), }, bevy::render::render_resource::BindGroupEntry { binding: 4, - resource: pipeline.voxels_buffer.as_ref().unwrap().as_entire_binding(), + resource: voxels_buffer.as_entire_binding(), }, bevy::render::render_resource::BindGroupEntry { binding: 5, - resource: pipeline - .color_palette_buffer - .as_ref() - .unwrap() - .as_entire_binding(), + resource: color_palette_buffer.as_entire_binding(), }, // +++ DEBUG +++ bevy::render::render_resource::BindGroupEntry { binding: 6, - resource: data_handler - .debug_gpu_interface - .as_ref() - .unwrap() - .as_entire_binding(), + resource: debug_gpu_interface.as_entire_binding(), }, // --- DEBUG --- ], ); - pipeline.tree_bind_group = Some(tree_bind_group); - //================================================================= - // Implementation with AsBindGroup - //================================================================= - // let tree_bind_group = render_data - // .as_bind_group( - // &pipeline.render_data_bind_group_layout, - // &render_device, - // &gpu_images, - // &fallback_image, - // ) - // .ok() - // .unwrap(); + let spyglass_prepared_bind_group = tree_gpu_view + .spyglass + .as_bind_group( + &pipeline.spyglass_bind_group_layout, + &render_device, + &gpu_images, + &fallback_image, + ) + .ok() + .unwrap(); + let spyglass_bind_group = spyglass_prepared_bind_group.bind_group; - // // println!("bindings: {:?}", tree_bind_group.bindings); - // // let bindings = ; - // //TODO: set buffers by binding index(bindings[x].0), instead of array index - // // if let bevy::render::render_resource::OwnedBindingResource::Buffer(buf) = - // // &tree_bind_group.bindings[2].1 - // // { - // // debug_assert_eq!(tree_bind_group.bindings[2].0, 2); - // // pipeline.nodes_children_buffer = Some(buf.clone()); - // // } - // if let bevy::render::render_resource::OwnedBindingResource::Buffer(buf) = - // &tree_bind_group.bindings[0].1 - // { - // // compare binding to ShocoVoxRenderData field - // debug_assert_eq!(tree_bind_group.bindings[0].0, 5); - // pipeline.cache_bytes_buffer = Some(buf.clone()); - // } + debug_assert_eq!( + 1, spyglass_prepared_bind_group.bindings[1].0, + "Expected Spyglass binding to be 1, instead of {:?}", + spyglass_prepared_bind_group.bindings[1].0 + ); + let viewport_buffer = if let OwnedBindingResource::Buffer(buffer) = + &spyglass_prepared_bind_group.bindings[1].1 + { + buffer.clone() + } else { + panic!( + "Unexpected binding for spyglass bind group; Expected buffer instead of : {:?}", + spyglass_prepared_bind_group.bindings[1].1 + ); + }; - // pipeline.tree_bind_group = Some(tree_bind_group.bind_group); - pipeline.update_tree = false; + pipeline.resources = Some(OctreeRenderDataResources { + spyglass_bind_group, + tree_bind_group, + viewport_buffer, + octree_meta_buffer, + metadata_buffer, + readable_metadata_buffer, + node_children_buffer, + node_ocbits_buffer, + voxels_buffer, + color_palette_buffer, + debug_gpu_interface, + readable_debug_gpu_interface, + }); } + + pipeline.update_tree = false; } diff --git a/src/octree/raytracing/bevy/types.rs b/src/octree/raytracing/bevy/types.rs index ffd1642..8099467 100644 --- a/src/octree/raytracing/bevy/types.rs +++ b/src/octree/raytracing/bevy/types.rs @@ -1,4 +1,4 @@ -use crate::octree::{Albedo, V3cf32}; +use crate::octree::{Albedo, Octree, V3cf32, VoxelData}; use bevy::{ asset::Handle, ecs::system::Resource, @@ -44,14 +44,22 @@ pub struct SvxRenderPlugin { pub resolution: [u32; 2], } +#[derive(Resource)] +pub struct OctreeGPUHost +where + T: Default + Clone + PartialEq + VoxelData, +{ + pub tree: Octree, + pub views: Vec>, +} + #[derive(Resource, Clone, AsBindGroup, TypePath, ExtractResource)] #[type_path = "shocovox::gpu::OctreeGPUView"] pub struct OctreeGPUView { // +++ DEBUG +++ pub do_the_thing: bool, - pub read_back: u32, // --- DEBUG --- - pub viewing_glass: SvxViewingGlass, + pub spyglass: OctreeSpyGlass, pub(crate) data_handler: Arc>, } @@ -66,27 +74,19 @@ pub(crate) struct VictimPointer { #[derive(Resource, Clone, AsBindGroup, TypePath, ExtractResource)] #[type_path = "shocovox::gpu::OctreeGPUDataHandler"] pub struct OctreeGPUDataHandler { - pub(crate) render_data: SvxRenderData, + // +++ DEBUG +++ + pub read_back: u32, + // --- DEBUG --- + pub(crate) render_data: OctreeRenderData, pub(crate) victim_node: VictimPointer, pub(crate) victim_brick: VictimPointer, pub(crate) map_to_node_index_in_metadata: HashMap, pub(crate) map_to_color_index_in_palette: HashMap, - pub(crate) debug_gpu_interface: Option, - pub(crate) readable_debug_gpu_interface: Option, - //TODO: Maybe this? - // Buffers for the RenderData - // pub(crate) octree_meta_buffer: Buffer, - // pub(crate) metadata_buffer: Buffer, - // pub(crate) node_children_buffer: Buffer, - // pub(crate) node_ocbits_buffer: Buffer, - // pub(crate) voxels_buffer: Buffer, - // pub(crate) color_palette_buffer: Buffer, - // pub(crate) readable_metadata_buffer: Buffer, } #[derive(Clone, AsBindGroup, TypePath)] #[type_path = "shocovox::gpu::ShocoVoxViewingGlass"] -pub struct SvxViewingGlass { +pub struct OctreeSpyGlass { #[storage_texture(0, image_format = Rgba8Unorm, access = ReadWrite)] pub output_texture: Handle, @@ -94,9 +94,26 @@ pub struct SvxViewingGlass { pub viewport: Viewport, } +#[derive(Clone)] +pub(crate) struct OctreeRenderDataResources { + pub(crate) spyglass_bind_group: BindGroup, + pub(crate) tree_bind_group: BindGroup, + + pub(crate) viewport_buffer: Buffer, + pub(crate) octree_meta_buffer: Buffer, + pub(crate) metadata_buffer: Buffer, + pub(crate) readable_metadata_buffer: Buffer, + pub(crate) node_children_buffer: Buffer, + pub(crate) node_ocbits_buffer: Buffer, + pub(crate) voxels_buffer: Buffer, + pub(crate) color_palette_buffer: Buffer, + pub(crate) debug_gpu_interface: Buffer, + pub(crate) readable_debug_gpu_interface: Buffer, +} + #[derive(Clone, AsBindGroup, TypePath)] #[type_path = "shocovox::gpu::ShocoVoxRenderData"] -pub struct SvxRenderData { +pub struct OctreeRenderData { // +++ DEBUG +++ #[storage(6, visibility(compute))] pub(crate) debug_gpu_interface: u32, @@ -176,20 +193,10 @@ pub(crate) struct SvxRenderPipeline { pub(crate) render_queue: RenderQueue, pub(crate) update_pipeline: CachedComputePipelineId, - // Render data buffers - pub(crate) octree_meta_buffer: Option, - pub(crate) metadata_buffer: Option, - pub(crate) readable_metadata_buffer: Option, - pub(crate) node_children_buffer: Option, - pub(crate) node_ocbits_buffer: Option, - pub(crate) voxels_buffer: Option, - pub(crate) color_palette_buffer: Option, - pub(crate) tree_data_handler: Option, - - pub(crate) viewing_glass_bind_group_layout: BindGroupLayout, + // Data layout and data + pub(crate) spyglass_bind_group_layout: BindGroupLayout, pub(crate) render_data_bind_group_layout: BindGroupLayout, - pub(crate) viewing_glass_bind_group: Option, - pub(crate) tree_bind_group: Option, + pub(crate) resources: Option, } #[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)] diff --git a/src/octree/raytracing/mod.rs b/src/octree/raytracing/mod.rs index 25d7501..7ff9d95 100644 --- a/src/octree/raytracing/mod.rs +++ b/src/octree/raytracing/mod.rs @@ -7,4 +7,6 @@ pub mod bevy; pub use crate::spatial::raytracing::Ray; #[cfg(feature = "bevy_wgpu")] -pub use bevy::types::{OctreeGPUView, SvxRenderData, SvxRenderPlugin, SvxViewingGlass, Viewport}; +pub use bevy::types::{ + OctreeGPUHost, OctreeGPUView, OctreeRenderData, OctreeSpyGlass, SvxRenderPlugin, Viewport, +}; diff --git a/src/octree/types.rs b/src/octree/types.rs index 6cbfbf8..83b9f45 100644 --- a/src/octree/types.rs +++ b/src/octree/types.rs @@ -88,9 +88,6 @@ where pub(crate) octree_size: u32, pub(crate) nodes: ObjectPool>, pub(crate) node_children: Vec>, // Children index values of each Node - - #[cfg(feature = "bevy_wgpu")] - pub(crate) views: Vec>, } #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]