rt(vk): use manuallydrop for VulkanBuffer rather than Option

This commit is contained in:
chyyran 2024-08-24 23:26:00 -04:00 committed by Ronny Chan
parent 8fb5d48a1e
commit e90c27ebbd
3 changed files with 56 additions and 68 deletions

View file

@ -9,7 +9,7 @@ use crate::options::{FilterChainOptionsVulkan, FrameOptionsVulkan};
use crate::queue_selection::get_graphics_queue; use crate::queue_selection::get_graphics_queue;
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage}; use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage};
use crate::{error, util}; use crate::{error, memory, util};
use ash::vk; use ash::vk;
use librashader_common::{ImageFormat, Size, Viewport}; use librashader_common::{ImageFormat, Size, Viewport};
@ -80,7 +80,7 @@ impl TryFrom<VulkanInstance> for VulkanObjects {
// let memory_properties = // let memory_properties =
// instance.get_physical_device_memory_properties(vulkan.physical_device); // instance.get_physical_device_memory_properties(vulkan.physical_device);
let alloc = util::create_allocator(device.clone(), instance, vulkan.physical_device)?; let alloc = memory::create_allocator(device.clone(), instance, vulkan.physical_device)?;
Ok(VulkanObjects { Ok(VulkanObjects {
device: Arc::new(device), device: Arc::new(device),
@ -103,7 +103,7 @@ impl TryFrom<(vk::PhysicalDevice, ash::Instance, ash::Device)> for VulkanObjects
// let memory_properties = value.1.get_physical_device_memory_properties(value.0); // let memory_properties = value.1.get_physical_device_memory_properties(value.0);
let alloc = util::create_allocator(device.clone(), value.1, value.0)?; let alloc = memory::create_allocator(device.clone(), value.1, value.0)?;
Ok(VulkanObjects { Ok(VulkanObjects {
alloc, alloc,

View file

@ -1,8 +1,10 @@
use crate::error; use crate::error;
use crate::error::FilterChainError; use crate::error::FilterChainError;
use ash::vk; use ash::vk;
use gpu_allocator::vulkan::{Allocation, AllocationCreateDesc, AllocationScheme, Allocator}; use gpu_allocator::vulkan::{
use gpu_allocator::MemoryLocation; Allocation, AllocationCreateDesc, AllocationScheme, Allocator, AllocatorCreateDesc,
};
use gpu_allocator::{AllocationSizes, MemoryLocation};
use librashader_runtime::uniforms::UniformStorageAccess; use librashader_runtime::uniforms::UniformStorageAccess;
use parking_lot::Mutex; use parking_lot::Mutex;
@ -56,7 +58,7 @@ impl Drop for VulkanImageMemory {
pub struct VulkanBuffer { pub struct VulkanBuffer {
pub handle: vk::Buffer, pub handle: vk::Buffer,
device: Arc<ash::Device>, device: Arc<ash::Device>,
memory: Option<Allocation>, allocation: ManuallyDrop<Allocation>,
allocator: Arc<Mutex<Allocator>>, allocator: Arc<Mutex<Allocator>>,
size: vk::DeviceSize, size: vk::DeviceSize,
} }
@ -85,12 +87,11 @@ impl VulkanBuffer {
allocation_scheme: AllocationScheme::DedicatedBuffer(buffer), allocation_scheme: AllocationScheme::DedicatedBuffer(buffer),
})?; })?;
// let alloc = device.allocate_memory(&alloc_info, None)?;
device.bind_buffer_memory(buffer, alloc.memory(), 0)?; device.bind_buffer_memory(buffer, alloc.memory(), 0)?;
Ok(VulkanBuffer { Ok(VulkanBuffer {
handle: buffer, handle: buffer,
memory: Some(alloc), allocation: ManuallyDrop::new(alloc),
allocator: Arc::clone(allocator), allocator: Arc::clone(allocator),
size: size as vk::DeviceSize, size: size as vk::DeviceSize,
device: device.clone(), device: device.clone(),
@ -99,10 +100,7 @@ impl VulkanBuffer {
} }
pub fn as_mut_slice(&mut self) -> error::Result<&mut [u8]> { pub fn as_mut_slice(&mut self) -> error::Result<&mut [u8]> {
let Some(allocation) = self.memory.as_mut() else { let Some(allocation) = self.allocation.mapped_slice_mut() else {
return Err(FilterChainError::AllocationDoesNotExist);
};
let Some(allocation) = allocation.mapped_slice_mut() else {
return Err(FilterChainError::AllocationDoesNotExist); return Err(FilterChainError::AllocationDoesNotExist);
}; };
Ok(allocation) Ok(allocation)
@ -112,12 +110,10 @@ impl VulkanBuffer {
impl Drop for VulkanBuffer { impl Drop for VulkanBuffer {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if let Some(allocation) = self.memory.take() { // SAFETY: things can not be double dropped.
if let Err(e) = self.allocator.lock().free(allocation) { let allocation = ManuallyDrop::take(&mut self.allocation);
println!( if let Err(e) = self.allocator.lock().free(allocation) {
"librashader-runtime-vk: [warn] failed to deallocate buffer memory {e}" println!("librashader-runtime-vk: [warn] failed to deallocate buffer memory {e}")
)
}
} }
if self.handle != vk::Buffer::null() { if self.handle != vk::Buffer::null() {
@ -147,7 +143,7 @@ impl RawVulkanBuffer {
) -> error::Result<Self> { ) -> error::Result<Self> {
let buffer = ManuallyDrop::new(VulkanBuffer::new(device, allocator, usage, size)?); let buffer = ManuallyDrop::new(VulkanBuffer::new(device, allocator, usage, size)?);
let Some(ptr) = buffer.memory.as_ref().map(|m| m.mapped_ptr()).flatten() else { let Some(ptr) = buffer.allocation.mapped_ptr() else {
return Err(FilterChainError::AllocationDoesNotExist); return Err(FilterChainError::AllocationDoesNotExist);
}; };
@ -204,3 +200,44 @@ impl DerefMut for RawVulkanBuffer {
} }
} }
} }
#[allow(unused)]
pub fn find_vulkan_memory_type(
props: &vk::PhysicalDeviceMemoryProperties,
device_reqs: u32,
host_reqs: vk::MemoryPropertyFlags,
) -> error::Result<u32> {
for i in 0..vk::MAX_MEMORY_TYPES {
if device_reqs & (1 << i) != 0
&& props.memory_types[i].property_flags & host_reqs == host_reqs
{
return Ok(i as u32);
}
}
if host_reqs == vk::MemoryPropertyFlags::empty() {
Err(FilterChainError::VulkanMemoryError(device_reqs))
} else {
Ok(find_vulkan_memory_type(
props,
device_reqs,
vk::MemoryPropertyFlags::empty(),
)?)
}
}
pub fn create_allocator(
device: ash::Device,
instance: ash::Instance,
physical_device: vk::PhysicalDevice,
) -> error::Result<Arc<Mutex<Allocator>>> {
let alloc = Allocator::new(&AllocatorCreateDesc {
instance,
device,
physical_device,
debug_settings: Default::default(),
buffer_device_address: false,
allocation_sizes: AllocationSizes::default(),
})?;
Ok(Arc::new(Mutex::new(alloc)))
}

View file

@ -1,12 +1,4 @@
use ash::vk; use ash::vk;
use gpu_allocator::vulkan::{Allocator, AllocatorCreateDesc};
use gpu_allocator::AllocationSizes;
use parking_lot::Mutex;
use std::sync::Arc;
use crate::error;
use crate::error::FilterChainError;
use librashader_reflect::reflect::semantics::BindingStage; use librashader_reflect::reflect::semantics::BindingStage;
pub fn binding_stage_to_vulkan_stage(stage_mask: BindingStage) -> vk::ShaderStageFlags { pub fn binding_stage_to_vulkan_stage(stage_mask: BindingStage) -> vk::ShaderStageFlags {
@ -22,31 +14,6 @@ pub fn binding_stage_to_vulkan_stage(stage_mask: BindingStage) -> vk::ShaderStag
mask mask
} }
#[allow(unused)]
pub fn find_vulkan_memory_type(
props: &vk::PhysicalDeviceMemoryProperties,
device_reqs: u32,
host_reqs: vk::MemoryPropertyFlags,
) -> error::Result<u32> {
for i in 0..vk::MAX_MEMORY_TYPES {
if device_reqs & (1 << i) != 0
&& props.memory_types[i].property_flags & host_reqs == host_reqs
{
return Ok(i as u32);
}
}
if host_reqs == vk::MemoryPropertyFlags::empty() {
Err(FilterChainError::VulkanMemoryError(device_reqs))
} else {
Ok(find_vulkan_memory_type(
props,
device_reqs,
vk::MemoryPropertyFlags::empty(),
)?)
}
}
#[inline(always)] #[inline(always)]
pub unsafe fn vulkan_image_layout_transition_levels( pub unsafe fn vulkan_image_layout_transition_levels(
device: &ash::Device, device: &ash::Device,
@ -90,19 +57,3 @@ pub unsafe fn vulkan_image_layout_transition_levels(
) )
} }
} }
pub fn create_allocator(
device: ash::Device,
instance: ash::Instance,
physical_device: vk::PhysicalDevice,
) -> error::Result<Arc<Mutex<Allocator>>> {
let alloc = Allocator::new(&AllocatorCreateDesc {
instance,
device,
physical_device,
debug_settings: Default::default(),
buffer_device_address: false,
allocation_sizes: AllocationSizes::default(),
})?;
Ok(Arc::new(Mutex::new(alloc)))
}