images+commands: sync

- lock pool when allocating command buffers
- store image parent as weak arc in order to not create cycles
This commit is contained in:
Janis 2025-01-05 18:22:50 +01:00
parent 260275d694
commit 0f96689079
2 changed files with 28 additions and 20 deletions

View file

@ -64,6 +64,7 @@ impl SingleUseCommandPool {
} }
/// get the underlying pool, bypassing the mutex /// get the underlying pool, bypassing the mutex
#[allow(dead_code)]
pub unsafe fn pool(&self) -> vk::CommandPool { pub unsafe fn pool(&self) -> vk::CommandPool {
self.pool.data_ptr().read() self.pool.data_ptr().read()
} }
@ -129,6 +130,8 @@ pub enum CommandBufferState {
#[derive(Debug)] #[derive(Debug)]
#[repr(transparent)] #[repr(transparent)]
struct CommandBufferState2(AtomicU8); struct CommandBufferState2(AtomicU8);
#[allow(dead_code)]
impl CommandBufferState2 { impl CommandBufferState2 {
fn initial() -> Self { fn initial() -> Self {
Self(AtomicU8::new(CommandBufferState::Initial as u8)) Self(AtomicU8::new(CommandBufferState::Initial as u8))
@ -188,11 +191,13 @@ impl !Sync for SingleUseCommand {}
impl SingleUseCommand { impl SingleUseCommand {
pub fn new(device: Device, pool: Arc<SingleUseCommandPool>) -> VkResult<Self> { pub fn new(device: Device, pool: Arc<SingleUseCommandPool>) -> VkResult<Self> {
let buffer = unsafe { let buffer = unsafe {
let buffer = pool.pool.with_locked(|pool| {
let alloc_info = vk::CommandBufferAllocateInfo::default() let alloc_info = vk::CommandBufferAllocateInfo::default()
.command_buffer_count(1) .command_buffer_count(1)
.command_pool(pool.pool()) .command_pool(*pool)
.level(vk::CommandBufferLevel::PRIMARY); .level(vk::CommandBufferLevel::PRIMARY);
let buffer = device.dev().allocate_command_buffers(&alloc_info)?[0]; Ok(device.dev().allocate_command_buffers(&alloc_info)?[0])
})?;
device.dev().begin_command_buffer( device.dev().begin_command_buffer(
buffer, buffer,

View file

@ -1,4 +1,8 @@
use std::{borrow::Cow, collections::HashMap, sync::Arc}; use std::{
borrow::Cow,
collections::HashMap,
sync::{Arc, Weak},
};
use crate::{ use crate::{
define_device_owned_handle, define_device_owned_handle,
@ -128,8 +132,8 @@ define_device_owned_handle! {
format: vk::Format, format: vk::Format,
views: Mutex<HashMap<ImageViewDesc, vk::ImageView>>, views: Mutex<HashMap<ImageViewDesc, vk::ImageView>>,
aliases: Mutex<HashMap<ImageDesc, Arc<Image>>>, aliases: Mutex<HashMap<ImageDesc, Arc<Image>>>,
parent: Option<Arc<Image>>, parent: Option<Weak<Image>>,
is_swapchain_image:bool, is_swapchain_image: bool,
} => |this| if !this.is_swapchain_image { } => |this| if !this.is_swapchain_image {
unsafe { unsafe {
for &view in this.views.lock().values() { for &view in this.views.lock().values() {
@ -266,20 +270,19 @@ impl Image {
self.size.depth self.size.depth
} }
fn get_parent(self: &Arc<Self>) -> Arc<Image> { fn get_parent_or_self(self: &Arc<Self>) -> Arc<Image> {
self.parent.clone().unwrap_or_else(|| self.clone()) self.parent
}
fn get_alloc(&self) -> Option<&vk_mem::Allocation> {
self.alloc
.as_ref() .as_ref()
.or(self.parent.as_ref().and_then(|image| image.get_alloc())) .map(|weak| weak.upgrade().unwrap())
.unwrap_or_else(|| self.clone())
} }
pub unsafe fn get_alias(self: &Arc<Self>, desc: ImageDesc) -> VkResult<Arc<Self>> { pub unsafe fn get_alias(self: &Arc<Self>, desc: ImageDesc) -> VkResult<Arc<Self>> {
self.get_parent().get_alias_inner(desc) self.get_parent_or_self().get_alias_inner(desc)
} }
/// must only be called on the primogenitor of an image.
/// get the primogenitor with [`Self::get_parent_or_self()`]
unsafe fn get_alias_inner(self: Arc<Self>, desc: ImageDesc) -> VkResult<Arc<Image>> { unsafe fn get_alias_inner(self: Arc<Self>, desc: ImageDesc) -> VkResult<Arc<Image>> {
use std::collections::hash_map::Entry::*; use std::collections::hash_map::Entry::*;
match self.aliases.lock().entry(desc.clone()) { match self.aliases.lock().entry(desc.clone()) {
@ -327,7 +330,8 @@ impl Image {
.mip_levels(mip_levels); .mip_levels(mip_levels);
let alloc = self let alloc = self
.get_alloc() .alloc
.as_ref()
.expect("no alloc associated with image. is this the framebuffer?"); .expect("no alloc associated with image. is this the framebuffer?");
let image = unsafe { let image = unsafe {
@ -342,7 +346,6 @@ impl Image {
image image
}; };
let parent = self.parent.clone().unwrap_or(self.clone());
let alias = Self::construct( let alias = Self::construct(
self.device().clone(), self.device().clone(),
image, image,
@ -352,8 +355,8 @@ impl Image {
format, format,
Mutex::new(HashMap::new()), Mutex::new(HashMap::new()),
Mutex::new(HashMap::new()), Mutex::new(HashMap::new()),
Some(parent.clone()), Some(Arc::downgrade(&self)),
parent.is_swapchain_image, self.is_swapchain_image,
)?; )?;
Ok(vacant.insert(Arc::new(alias)).clone()) Ok(vacant.insert(Arc::new(alias)).clone())
} }