commandbuffer: tracking state and fn end()

This commit is contained in:
Janis 2025-01-05 03:11:44 +01:00
parent f3cc43e49e
commit 2fc7d3e179

View file

@ -1,4 +1,4 @@
use std::sync::Arc; use std::sync::{atomic::AtomicU8, Arc};
use crate::{ use crate::{
define_device_owned_handle, define_device_owned_handle,
@ -116,10 +116,66 @@ impl<T: CommandBuffer> CommandList<T> {
} }
} }
#[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::<CommandBufferState>() }
}
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! { define_device_owned_handle! {
#[derive(Debug)] #[derive(Debug)]
pub SingleUseCommand(vk::CommandBuffer) { pub SingleUseCommand(vk::CommandBuffer) {
pool: Arc<SingleUseCommandPool>, pool: Arc<SingleUseCommandPool>,
state: CommandBufferState2,
} => |this| unsafe { } => |this| unsafe {
this.pool this.pool
.pool .pool
@ -147,7 +203,20 @@ impl SingleUseCommand {
buffer 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 /// Safety: commandbuffer must not be accessed from multiple threads at the same time
@ -169,6 +238,7 @@ impl SingleUseCommand {
new_layout: vk::ImageLayout, new_layout: vk::ImageLayout,
queue_ownership_op: Option<QueueOwnership>, queue_ownership_op: Option<QueueOwnership>,
) { ) {
assert_eq!(self.state(), CommandBufferState::Recording);
let (src_family, dst_family) = queue_ownership_op let (src_family, dst_family) = queue_ownership_op
.map(|t| (t.src, t.dst)) .map(|t| (t.src, t.dst))
.unwrap_or((vk::QUEUE_FAMILY_IGNORED, vk::QUEUE_FAMILY_IGNORED)); .unwrap_or((vk::QUEUE_FAMILY_IGNORED, vk::QUEUE_FAMILY_IGNORED));
@ -209,6 +279,7 @@ impl SingleUseCommand {
dst: &Image, dst: &Image,
dst_region: util::Rect2D, dst_region: util::Rect2D,
) { ) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device().dev().cmd_blit_image( self.device().dev().cmd_blit_image(
self.buffer(), self.buffer(),
@ -241,6 +312,7 @@ impl SingleUseCommand {
layout: vk::ImageLayout, layout: vk::ImageLayout,
regions: &[vk::BufferImageCopy], regions: &[vk::BufferImageCopy],
) { ) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device().dev().cmd_copy_buffer_to_image( self.device().dev().cmd_copy_buffer_to_image(
self.handle(), self.handle(),
@ -253,6 +325,7 @@ impl SingleUseCommand {
} }
pub fn copy_buffers(&self, src: vk::Buffer, dst: vk::Buffer, regions: &[vk::BufferCopy]) { pub fn copy_buffers(&self, src: vk::Buffer, dst: vk::Buffer, regions: &[vk::BufferCopy]) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device() self.device()
.dev() .dev()
@ -268,6 +341,7 @@ impl SingleUseCommand {
dst_layout: vk::ImageLayout, dst_layout: vk::ImageLayout,
regions: &[vk::ImageCopy], regions: &[vk::ImageCopy],
) { ) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device().dev().cmd_copy_image( self.device().dev().cmd_copy_image(
self.handle(), self.handle(),
@ -288,6 +362,7 @@ impl SingleUseCommand {
color: crate::Rgba, color: crate::Rgba,
subresources: &[vk::ImageSubresourceRange], subresources: &[vk::ImageSubresourceRange],
) { ) {
assert_eq!(self.state(), CommandBufferState::Recording);
let clear_colors = match format.get_component_kind() { let clear_colors = match format.get_component_kind() {
crate::util::FormatComponentKind::Float => vk::ClearColorValue { crate::util::FormatComponentKind::Float => vk::ClearColorValue {
float32: color.into_f32(), float32: color.into_f32(),
@ -312,6 +387,7 @@ impl SingleUseCommand {
} }
pub fn begin_rendering(&self, rendering_info: vk::RenderingInfo<'_>) { pub fn begin_rendering(&self, rendering_info: vk::RenderingInfo<'_>) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device() self.device()
.dev() .dev()
@ -320,6 +396,7 @@ impl SingleUseCommand {
} }
pub fn set_viewport(&self, viewports: &[vk::Viewport]) { pub fn set_viewport(&self, viewports: &[vk::Viewport]) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device() self.device()
.dev() .dev()
@ -327,6 +404,7 @@ impl SingleUseCommand {
} }
} }
pub fn set_scissors(&self, scissors: &[vk::Rect2D]) { pub fn set_scissors(&self, scissors: &[vk::Rect2D]) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device() self.device()
.dev() .dev()
@ -340,6 +418,7 @@ impl SingleUseCommand {
offset: u32, offset: u32,
bytes: &[u8], bytes: &[u8],
) { ) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device().dev().cmd_push_constants( self.device().dev().cmd_push_constants(
self.handle(), self.handle(),
@ -351,6 +430,7 @@ impl SingleUseCommand {
} }
} }
pub fn bind_pipeline(&self, pipeline: &Pipeline) { pub fn bind_pipeline(&self, pipeline: &Pipeline) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device().dev().cmd_bind_pipeline( self.device().dev().cmd_bind_pipeline(
self.buffer(), self.buffer(),
@ -360,6 +440,7 @@ impl SingleUseCommand {
} }
} }
pub fn bind_vertices(&self, buffer: vk::Buffer, offset: u64) { pub fn bind_vertices(&self, buffer: vk::Buffer, offset: u64) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device() self.device()
.dev() .dev()
@ -367,6 +448,7 @@ impl SingleUseCommand {
} }
} }
pub fn bind_indices(&self, buffer: vk::Buffer, offset: u64, kind: vk::IndexType) { pub fn bind_indices(&self, buffer: vk::Buffer, offset: u64, kind: vk::IndexType) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device() self.device()
.dev() .dev()
@ -380,6 +462,7 @@ impl SingleUseCommand {
bind_point: vk::PipelineBindPoint, bind_point: vk::PipelineBindPoint,
descriptor_sets: &[vk::DescriptorSet], descriptor_sets: &[vk::DescriptorSet],
) { ) {
assert_eq!(self.state(), CommandBufferState::Recording);
use crate::device::DeviceOwned; use crate::device::DeviceOwned;
unsafe { unsafe {
self.device().dev().cmd_bind_descriptor_sets( self.device().dev().cmd_bind_descriptor_sets(
@ -402,6 +485,7 @@ impl SingleUseCommand {
vertex_offset: i32, vertex_offset: i32,
instance_offset: u32, instance_offset: u32,
) { ) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device().dev().cmd_draw_indexed( self.device().dev().cmd_draw_indexed(
self.buffer(), self.buffer(),
@ -415,6 +499,7 @@ impl SingleUseCommand {
} }
pub fn draw_indexed_indirect(&self, buffer: vk::Buffer, offset: u64, count: u32, stride: u32) { pub fn draw_indexed_indirect(&self, buffer: vk::Buffer, offset: u64, count: u32, stride: u32) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device().dev().cmd_draw_indexed_indirect( self.device().dev().cmd_draw_indexed_indirect(
self.buffer(), self.buffer(),
@ -427,6 +512,7 @@ impl SingleUseCommand {
} }
pub fn end_rendering(&self) { pub fn end_rendering(&self) {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { unsafe {
self.device().dev().cmd_end_rendering(self.buffer()); self.device().dev().cmd_end_rendering(self.buffer());
} }
@ -438,6 +524,7 @@ impl SingleUseCommand {
signal: Option<vk::Semaphore>, signal: Option<vk::Semaphore>,
fence: Option<vk::Fence>, fence: Option<vk::Fence>,
) -> VkResult<()> { ) -> VkResult<()> {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { self.device().dev().end_command_buffer(self.handle())? }; unsafe { self.device().dev().end_command_buffer(self.handle())? };
let buffers = [self.handle()]; let buffers = [self.handle()];