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::{
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! {
#[derive(Debug)]
pub SingleUseCommand(vk::CommandBuffer) {
pool: Arc<SingleUseCommandPool>,
pool: Arc<SingleUseCommandPool>,
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<QueueOwnership>,
) {
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<vk::Semaphore>,
fence: Option<vk::Fence>,
) -> VkResult<()> {
assert_eq!(self.state(), CommandBufferState::Recording);
unsafe { self.device().dev().end_command_buffer(self.handle())? };
let buffers = [self.handle()];