diff --git a/blade-render/code/debug-draw.wgsl b/blade-render/code/debug-draw.wgsl index 01065e70..a4f6675c 100644 --- a/blade-render/code/debug-draw.wgsl +++ b/blade-render/code/debug-draw.wgsl @@ -3,6 +3,7 @@ #include "camera.inc.wgsl" var camera: CameraParams; +var debug_lines: array; struct DebugVarying { @builtin(position) pos: vec4, @@ -12,7 +13,7 @@ struct DebugVarying { @vertex fn debug_vs(@builtin(vertex_index) vertex_id: u32, @builtin(instance_index) instance_id: u32) -> DebugVarying { - let line = debug_buf.lines[instance_id]; + let line = debug_lines[instance_id]; var point = line.a; if (vertex_id != 0u) { point = line.b; diff --git a/blade-render/src/render/mod.rs b/blade-render/src/render/mod.rs index e68664a5..7ecee7fd 100644 --- a/blade-render/src/render/mod.rs +++ b/blade-render/src/render/mod.rs @@ -4,7 +4,7 @@ mod env_map; pub use dummy::DummyResources; pub use env_map::EnvironmentMap; -use std::{collections::HashMap, mem, num::NonZeroU32, path::Path, ptr}; +use std::{cell::Cell, collections::HashMap, mem, num::NonZeroU32, path::Path, ptr}; const MAX_RESOURCES: u32 = 1000; const RADIANCE_FORMAT: blade_graphics::TextureFormat = blade_graphics::TextureFormat::Rgba16Float; @@ -62,6 +62,20 @@ pub struct DebugBlit { pub target_size: [u32; 2], } +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct DebugPoint { + pub pos: [f32; 3], + pub color: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct DebugLine { + pub a: DebugPoint, + pub b: DebugPoint, +} + #[derive(Clone, Copy, Debug, Default)] pub struct DebugConfig { pub view_mode: DebugMode, @@ -157,16 +171,119 @@ struct DebugEntry { } struct DebugRender { - _capacity: u32, + capacity: u32, buffer: blade_graphics::Buffer, variance_buffer: blade_graphics::Buffer, entry_buffer: blade_graphics::Buffer, + cpu_lines_buffer: blade_graphics::Buffer, + //Note: allows immutable `add_lines` + cpu_lines_offset: Cell, draw_pipeline: blade_graphics::RenderPipeline, blit_pipeline: blade_graphics::RenderPipeline, line_size: u32, buffer_size: u32, } +impl DebugRender { + fn destroy(&mut self, gpu: &blade_graphics::Context) { + gpu.destroy_buffer(self.buffer); + gpu.destroy_buffer(self.variance_buffer); + gpu.destroy_buffer(self.entry_buffer); + gpu.destroy_buffer(self.cpu_lines_buffer); + } + + fn add_lines(&self, lines: &[DebugLine]) -> (blade_graphics::BufferPiece, u32) { + let required_size = lines.len() as u64 * self.line_size as u64; + let old_offset = self.cpu_lines_offset.get(); + let (original_offset, count) = + if old_offset + required_size <= (self.capacity * self.line_size) as u64 { + (old_offset, lines.len()) + } else { + let count = lines.len().min(self.capacity as usize); + if count < lines.len() { + log::warn!("Reducing the debug lines from {} to {}", lines.len(), count); + } + (0, count) + }; + + unsafe { + ptr::copy_nonoverlapping( + lines.as_ptr(), + self.cpu_lines_buffer.data().add(original_offset as usize) as *mut DebugLine, + count, + ); + } + + self.cpu_lines_offset + .set(original_offset + count as u64 * self.line_size as u64); + (self.cpu_lines_buffer.at(original_offset), count as u32) + } + + fn render_lines( + &self, + debug_lines: &[DebugLine], + fd: &FrameData, + pass: &mut blade_graphics::RenderCommandEncoder, + ) { + let mut pc = pass.with(&self.draw_pipeline); + let lines_offset = 32 + mem::size_of::() + mem::size_of::(); + pc.bind( + 0, + &DebugDrawData { + camera: fd.camera_params, + debug_lines: self.buffer.at(lines_offset as u64), + depth: fd.depth_view, + }, + ); + pc.draw_indirect(self.buffer.at(0)); + + if !debug_lines.is_empty() { + let (lines_buf, count) = self.add_lines(debug_lines); + pc.bind( + 0, + &DebugDrawData { + camera: fd.camera_params, + debug_lines: lines_buf, + depth: fd.depth_view, + }, + ); + pc.draw(0, 2, 0, count); + } + } + + fn render_blits( + &self, + debug_blits: &[DebugBlit], + samp: blade_graphics::Sampler, + screen_size: blade_graphics::Extent, + pass: &mut blade_graphics::RenderCommandEncoder, + ) { + let mut pc = pass.with(&self.blit_pipeline); + for db in debug_blits { + pc.bind( + 0, + &DebugBlitData { + input: db.input, + samp, + params: DebugBlitParams { + target_offset: [ + db.target_offset[0] as f32 / screen_size.width as f32, + db.target_offset[1] as f32 / screen_size.height as f32, + ], + target_size: [ + db.target_size[0] as f32 / screen_size.width as f32, + db.target_size[1] as f32 / screen_size.height as f32, + ], + mip_level: db.mip_level as f32, + unused: 0, + }, + }, + ); + pc.draw(0, 4, 0, 1); + } + } +} + #[allow(dead_code)] struct DoubleRenderTarget { texture: blade_graphics::Texture, @@ -500,6 +617,22 @@ struct AtrousData { output: blade_graphics::TextureView, } +#[repr(C)] +#[derive(Clone, Copy, bytemuck::Zeroable, bytemuck::Pod)] +struct DebugLineParams { + target_offset: [f32; 2], + target_size: [f32; 2], + mip_level: f32, + unused: u32, +} + +#[derive(blade_macros::ShaderData)] +struct DebugLinedata { + input: blade_graphics::TextureView, + output: blade_graphics::Sampler, + params: DebugBlitParams, +} + #[repr(C)] #[derive(Clone, Copy, Default, bytemuck::Zeroable, bytemuck::Pod)] struct ToneMapParams { @@ -521,7 +654,7 @@ struct PostProcData { #[derive(blade_macros::ShaderData)] struct DebugDrawData { camera: CameraParams, - debug_buf: blade_graphics::BufferPiece, + debug_lines: blade_graphics::BufferPiece, depth: blade_graphics::TextureView, } @@ -679,6 +812,8 @@ impl ShaderPipelines { format: blade_graphics::TextureFormat, gpu: &blade_graphics::Context, ) -> blade_graphics::RenderPipeline { + shader.check_struct_size::(); + shader.check_struct_size::(); let layout = ::layout(); gpu.create_render_pipeline(blade_graphics::RenderPipelineDesc { name: "debug-draw", @@ -786,7 +921,7 @@ impl Renderer { let sp = ShaderPipelines::init(&shaders, config, gpu, shader_man).unwrap(); let debug = DebugRender { - _capacity: config.max_debug_lines, + capacity: config.max_debug_lines, buffer: gpu.create_buffer(blade_graphics::BufferDesc { name: "debug", size: (sp.debug_buffer_size + (config.max_debug_lines - 1) * sp.debug_line_size) @@ -803,6 +938,12 @@ impl Renderer { size: mem::size_of::() as u64, memory: blade_graphics::Memory::Shared, }), + cpu_lines_buffer: gpu.create_buffer(blade_graphics::BufferDesc { + name: "CPU debug lines", + size: (config.max_debug_lines * sp.debug_line_size) as u64, + memory: blade_graphics::Memory::Shared, + }), + cpu_lines_offset: Cell::new(0), draw_pipeline: sp.debug_draw, blit_pipeline: sp.debug_blit, line_size: sp.debug_line_size, @@ -917,16 +1058,13 @@ impl Renderer { gpu.destroy_buffer(self.hit_buffer); } gpu.destroy_acceleration_structure(self.acceleration_structure); - // env map, dummy + // env map, dummy, and debug self.env_map.destroy(gpu); self.dummy.destroy(gpu); + self.debug.destroy(gpu); // samplers gpu.destroy_sampler(self.samplers.nearest); gpu.destroy_sampler(self.samplers.linear); - // buffers - gpu.destroy_buffer(self.debug.buffer); - gpu.destroy_buffer(self.debug.variance_buffer); - gpu.destroy_buffer(self.debug.entry_buffer); } #[profiling::function] @@ -1488,6 +1626,7 @@ impl Renderer { pass: &mut blade_graphics::RenderCommandEncoder, debug_config: DebugConfig, pp_config: PostProcConfig, + debug_lines: &[DebugLine], debug_blits: &[DebugBlit], ) { let cur = self.frame_data.first().unwrap(); @@ -1510,41 +1649,10 @@ impl Renderer { ); pc.draw(0, 3, 0, 1); } - if let mut pc = pass.with(&self.debug.draw_pipeline) { - pc.bind( - 0, - &DebugDrawData { - camera: cur.camera_params, - debug_buf: self.debug.buffer.into(), - depth: cur.depth_view, - }, - ); - pc.draw_indirect(self.debug.buffer.at(0)); - } - if let mut pc = pass.with(&self.debug.blit_pipeline) { - for db in debug_blits { - pc.bind( - 0, - &DebugBlitData { - input: db.input, - samp: self.samplers.linear, - params: DebugBlitParams { - target_offset: [ - db.target_offset[0] as f32 / self.screen_size.width as f32, - db.target_offset[1] as f32 / self.screen_size.height as f32, - ], - target_size: [ - db.target_size[0] as f32 / self.screen_size.width as f32, - db.target_size[1] as f32 / self.screen_size.height as f32, - ], - mip_level: db.mip_level as f32, - unused: 0, - }, - }, - ); - pc.draw(0, 4, 0, 1); - } - } + + self.debug.render_lines(debug_lines, cur, pass); + self.debug + .render_blits(debug_blits, self.samplers.linear, self.screen_size, pass); } #[profiling::function] diff --git a/examples/scene/main.rs b/examples/scene/main.rs index ae53a7ae..c4d1c97d 100644 --- a/examples/scene/main.rs +++ b/examples/scene/main.rs @@ -492,8 +492,13 @@ impl Example { } None => &[], }; - self.renderer - .post_proc(&mut pass, self.debug, self.post_proc_config, debug_blits); + self.renderer.post_proc( + &mut pass, + self.debug, + self.post_proc_config, + &[], + debug_blits, + ); } self.gui_painter .paint(&mut pass, gui_primitives, &screen_desc, &self.context);