From 2fc7d3e179a9ef7c23c344d8c4832b5226c0d608 Mon Sep 17 00:00:00 2001 From: Janis Date: Sun, 5 Jan 2025 03:11:44 +0100 Subject: [PATCH] commandbuffer: tracking state and fn end() --- crates/renderer/src/commands.rs | 93 +++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/crates/renderer/src/commands.rs b/crates/renderer/src/commands.rs index a65f7d2..daac485 100644 --- a/crates/renderer/src/commands.rs +++ b/crates/renderer/src/commands.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::sync::{atomic::AtomicU8, Arc}; use crate::{ define_device_owned_handle, @@ -116,10 +116,66 @@ impl CommandList { } } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[repr(u8)] +pub enum CommandBufferState { + Initial = 0, + Recording, + Executable, + Pending, + Invalid, +} + +#[derive(Debug)] +#[repr(transparent)] +struct CommandBufferState2(AtomicU8); +impl CommandBufferState2 { + fn initial() -> Self { + Self(AtomicU8::new(CommandBufferState::Initial as u8)) + } + fn recording() -> Self { + Self(AtomicU8::new(CommandBufferState::Recording as u8)) + } + + fn state(&self) -> CommandBufferState { + let value = self.0.load(std::sync::atomic::Ordering::Relaxed); + unsafe { *<*const _>::from(&value).cast::() } + } + + fn is_initial(&self) -> bool { + self.0.load(std::sync::atomic::Ordering::Relaxed) == 0 + } + fn set_executable(&self) { + self.0.store( + CommandBufferState::Executable as u8, + std::sync::atomic::Ordering::Relaxed, + ); + } + fn set_recording(&self) { + self.0.store( + CommandBufferState::Recording as u8, + std::sync::atomic::Ordering::Relaxed, + ); + } + fn set_pending(&self) { + self.0.store( + CommandBufferState::Pending as u8, + std::sync::atomic::Ordering::Relaxed, + ); + } + fn set_invalid(&self) { + self.0.store( + CommandBufferState::Invalid as u8, + std::sync::atomic::Ordering::Relaxed, + ); + } +} + define_device_owned_handle! { #[derive(Debug)] pub SingleUseCommand(vk::CommandBuffer) { - pool: Arc, + pool: Arc, + state: CommandBufferState2, } => |this| unsafe { this.pool .pool @@ -147,7 +203,20 @@ impl SingleUseCommand { buffer }; - Self::construct(device, buffer, None, pool) + Self::construct(device, buffer, None, pool, CommandBufferState2::recording()) + } + + pub fn state(&self) -> CommandBufferState { + self.state.state() + } + + pub fn end(&self) -> VkResult<()> { + assert_eq!(self.state(), CommandBufferState::Recording); + unsafe { + self.inner.dev().dev().end_command_buffer(self.handle())?; + } + self.state.set_executable(); + Ok(()) } /// Safety: commandbuffer must not be accessed from multiple threads at the same time @@ -169,6 +238,7 @@ impl SingleUseCommand { new_layout: vk::ImageLayout, queue_ownership_op: Option, ) { + assert_eq!(self.state(), CommandBufferState::Recording); let (src_family, dst_family) = queue_ownership_op .map(|t| (t.src, t.dst)) .unwrap_or((vk::QUEUE_FAMILY_IGNORED, vk::QUEUE_FAMILY_IGNORED)); @@ -209,6 +279,7 @@ impl SingleUseCommand { dst: &Image, dst_region: util::Rect2D, ) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().cmd_blit_image( self.buffer(), @@ -241,6 +312,7 @@ impl SingleUseCommand { layout: vk::ImageLayout, regions: &[vk::BufferImageCopy], ) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().cmd_copy_buffer_to_image( self.handle(), @@ -253,6 +325,7 @@ impl SingleUseCommand { } pub fn copy_buffers(&self, src: vk::Buffer, dst: vk::Buffer, regions: &[vk::BufferCopy]) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device() .dev() @@ -268,6 +341,7 @@ impl SingleUseCommand { dst_layout: vk::ImageLayout, regions: &[vk::ImageCopy], ) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().cmd_copy_image( self.handle(), @@ -288,6 +362,7 @@ impl SingleUseCommand { color: crate::Rgba, subresources: &[vk::ImageSubresourceRange], ) { + assert_eq!(self.state(), CommandBufferState::Recording); let clear_colors = match format.get_component_kind() { crate::util::FormatComponentKind::Float => vk::ClearColorValue { float32: color.into_f32(), @@ -312,6 +387,7 @@ impl SingleUseCommand { } pub fn begin_rendering(&self, rendering_info: vk::RenderingInfo<'_>) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device() .dev() @@ -320,6 +396,7 @@ impl SingleUseCommand { } pub fn set_viewport(&self, viewports: &[vk::Viewport]) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device() .dev() @@ -327,6 +404,7 @@ impl SingleUseCommand { } } pub fn set_scissors(&self, scissors: &[vk::Rect2D]) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device() .dev() @@ -340,6 +418,7 @@ impl SingleUseCommand { offset: u32, bytes: &[u8], ) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().cmd_push_constants( self.handle(), @@ -351,6 +430,7 @@ impl SingleUseCommand { } } pub fn bind_pipeline(&self, pipeline: &Pipeline) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().cmd_bind_pipeline( self.buffer(), @@ -360,6 +440,7 @@ impl SingleUseCommand { } } pub fn bind_vertices(&self, buffer: vk::Buffer, offset: u64) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device() .dev() @@ -367,6 +448,7 @@ impl SingleUseCommand { } } pub fn bind_indices(&self, buffer: vk::Buffer, offset: u64, kind: vk::IndexType) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device() .dev() @@ -380,6 +462,7 @@ impl SingleUseCommand { bind_point: vk::PipelineBindPoint, descriptor_sets: &[vk::DescriptorSet], ) { + assert_eq!(self.state(), CommandBufferState::Recording); use crate::device::DeviceOwned; unsafe { self.device().dev().cmd_bind_descriptor_sets( @@ -402,6 +485,7 @@ impl SingleUseCommand { vertex_offset: i32, instance_offset: u32, ) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().cmd_draw_indexed( self.buffer(), @@ -415,6 +499,7 @@ impl SingleUseCommand { } pub fn draw_indexed_indirect(&self, buffer: vk::Buffer, offset: u64, count: u32, stride: u32) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().cmd_draw_indexed_indirect( self.buffer(), @@ -427,6 +512,7 @@ impl SingleUseCommand { } pub fn end_rendering(&self) { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().cmd_end_rendering(self.buffer()); } @@ -438,6 +524,7 @@ impl SingleUseCommand { signal: Option, fence: Option, ) -> VkResult<()> { + assert_eq!(self.state(), CommandBufferState::Recording); unsafe { self.device().dev().end_command_buffer(self.handle())? }; let buffers = [self.handle()];