diff --git a/piet-gpu-hal/src/backend.rs b/piet-gpu-hal/src/backend.rs index a4422b9..496a6f0 100644 --- a/piet-gpu-hal/src/backend.rs +++ b/piet-gpu-hal/src/backend.rs @@ -218,6 +218,12 @@ pub trait CmdBuf { /// Prepare the timestamps for reading. This isn't required on Vulkan but /// is required on (at least) DX12. unsafe fn finish_timestamps(&mut self, _pool: &D::QueryPool) {} + + /// Begin a labeled section for debugging and profiling purposes. + unsafe fn begin_debug_label(&mut self, label: &str) {} + + /// End a section opened by `begin_debug_label`. + unsafe fn end_debug_label(&mut self) {} } /// A builder for descriptor sets with more complex layouts. diff --git a/piet-gpu-hal/src/hub.rs b/piet-gpu-hal/src/hub.rs index 7b93372..2a7290d 100644 --- a/piet-gpu-hal/src/hub.rs +++ b/piet-gpu-hal/src/hub.rs @@ -569,6 +569,16 @@ impl CmdBuf { self.cmd_buf().finish_timestamps(pool); } + /// Begin a labeled section for debugging and profiling purposes. + pub unsafe fn begin_debug_label(&mut self, label: &str) { + self.cmd_buf().begin_debug_label(label); + } + + /// End a section opened by `begin_debug_label`. + pub unsafe fn end_debug_label(&mut self) { + self.cmd_buf().end_debug_label(); + } + /// Make sure the resource lives until the command buffer completes. /// /// The submitted command buffer will hold this reference until the corresponding diff --git a/piet-gpu-hal/src/mux.rs b/piet-gpu-hal/src/mux.rs index 24fef5c..c67de86 100644 --- a/piet-gpu-hal/src/mux.rs +++ b/piet-gpu-hal/src/mux.rs @@ -734,6 +734,22 @@ impl CmdBuf { CmdBuf::Mtl(c) => c.finish_timestamps(pool.mtl()), } } + + pub unsafe fn begin_debug_label(&mut self, label: &str) { + mux_match! { self; + CmdBuf::Vk(c) => c.begin_debug_label(label), + CmdBuf::Dx12(c) => c.begin_debug_label(label), + CmdBuf::Mtl(c) => c.begin_debug_label(label), + } + } + + pub unsafe fn end_debug_label(&mut self) { + mux_match! { self; + CmdBuf::Vk(c) => c.end_debug_label(), + CmdBuf::Dx12(c) => c.end_debug_label(), + CmdBuf::Mtl(c) => c.end_debug_label(), + } + } } impl Buffer { diff --git a/piet-gpu-hal/src/vulkan.rs b/piet-gpu-hal/src/vulkan.rs index d5b31cb..e34981e 100644 --- a/piet-gpu-hal/src/vulkan.rs +++ b/piet-gpu-hal/src/vulkan.rs @@ -8,6 +8,7 @@ use std::sync::Arc; use ash::extensions::{ext::DebugUtils, khr}; use ash::{vk, Device, Entry, Instance}; +use ash::vk::DebugUtilsLabelEXT; use smallvec::SmallVec; @@ -23,7 +24,7 @@ pub struct VkInstance { entry: Entry, instance: Instance, vk_version: u32, - _dbg_loader: Option, + dbg_loader: Option, _dbg_callbk: Option, } @@ -39,6 +40,7 @@ pub struct VkDevice { struct RawDevice { device: Device, + dbg_loader: Option, } pub struct VkSurface { @@ -202,7 +204,7 @@ impl VkInstance { None, )?; - let (_dbg_loader, _dbg_callbk) = if has_debug_ext { + let (dbg_loader, _dbg_callbk) = if has_debug_ext { let dbg_info = vk::DebugUtilsMessengerCreateInfoEXT::builder() .message_severity( vk::DebugUtilsMessageSeverityFlagsEXT::ERROR @@ -231,7 +233,7 @@ impl VkInstance { entry, instance, vk_version, - _dbg_loader, + dbg_loader, _dbg_callbk, }; @@ -317,7 +319,7 @@ impl VkInstance { let queue_index = 0; let queue = device.get_device_queue(qfi, queue_index); - let device = Arc::new(RawDevice { device }); + let device = Arc::new(RawDevice { device, dbg_loader: self.dbg_loader.clone() }); let props = self.instance.get_physical_device_properties(pdevice); let timestamp_period = props.limits.timestamp_period; @@ -1108,6 +1110,20 @@ impl crate::backend::CmdBuf for CmdBuf { query, ); } + + unsafe fn begin_debug_label(&mut self, label: &str) { + if let Some(utils) = &self.device.dbg_loader { + let label_cstr = CString::new(label).unwrap(); + let label_ext = DebugUtilsLabelEXT::builder().label_name(&label_cstr).build(); + utils.cmd_begin_debug_utils_label(self.cmd_buf, &label_ext); + } + } + + unsafe fn end_debug_label(&mut self) { + if let Some(utils) = &self.device.dbg_loader { + utils.cmd_end_debug_utils_label(self.cmd_buf); + } + } } impl crate::backend::DescriptorSetBuilder for DescriptorSetBuilder { diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index f045d65..aa06c3f 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -342,6 +342,7 @@ impl Renderer { cmd_buf.image_barrier(&self.gradients, ImageLayout::BlitDst, ImageLayout::General); cmd_buf.reset_query_pool(&query_pool); cmd_buf.write_timestamp(&query_pool, 0); + cmd_buf.begin_debug_label("Element bounding box calculation"); self.element_stage.record( cmd_buf, &self.element_code, @@ -351,43 +352,53 @@ impl Renderer { self.n_pathtag as u32, self.n_drawobj as u64, ); + cmd_buf.end_debug_label(); cmd_buf.write_timestamp(&query_pool, 1); cmd_buf.memory_barrier(); + cmd_buf.begin_debug_label("Tile allocation"); cmd_buf.dispatch( &self.tile_pipeline, &self.tile_ds, (((self.n_paths + 255) / 256) as u32, 1, 1), (256, 1, 1), ); + cmd_buf.end_debug_label(); cmd_buf.write_timestamp(&query_pool, 2); cmd_buf.memory_barrier(); + cmd_buf.begin_debug_label("Path flattening"); cmd_buf.dispatch( &self.path_pipeline, &self.path_ds, (((self.n_pathseg + 31) / 32) as u32, 1, 1), (32, 1, 1), ); + cmd_buf.end_debug_label(); cmd_buf.write_timestamp(&query_pool, 3); cmd_buf.memory_barrier(); + cmd_buf.begin_debug_label("Backdrop propagation"); cmd_buf.dispatch( &self.backdrop_pipeline, &self.backdrop_ds, (((self.n_paths + 255) / 256) as u32, 1, 1), (256, self.backdrop_y, 1), ); + cmd_buf.end_debug_label(); cmd_buf.write_timestamp(&query_pool, 4); // Note: this barrier is not needed as an actual dependency between // pipeline stages, but I am keeping it in so that timer queries are // easier to interpret. cmd_buf.memory_barrier(); + cmd_buf.begin_debug_label("Element binning"); cmd_buf.dispatch( &self.bin_pipeline, &self.bin_ds, (((self.n_paths + 255) / 256) as u32, 1, 1), (256, 1, 1), ); + cmd_buf.end_debug_label(); cmd_buf.write_timestamp(&query_pool, 5); cmd_buf.memory_barrier(); + cmd_buf.begin_debug_label("Coarse raster"); cmd_buf.dispatch( &self.coarse_pipeline, &self.coarse_ds, @@ -398,8 +409,10 @@ impl Renderer { ), (256, 1, 1), ); + cmd_buf.end_debug_label(); cmd_buf.write_timestamp(&query_pool, 6); cmd_buf.memory_barrier(); + cmd_buf.begin_debug_label("Fine raster"); cmd_buf.dispatch( &self.k4_pipeline, &self.k4_ds, @@ -410,6 +423,7 @@ impl Renderer { ), (8, 4, 1), ); + cmd_buf.end_debug_label(); cmd_buf.write_timestamp(&query_pool, 7); cmd_buf.memory_barrier(); cmd_buf.image_barrier(&self.image_dev, ImageLayout::General, ImageLayout::BlitSrc);