From f84934bd9a88c451e0b64a4862b3ad1412740548 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 27 Feb 2025 14:48:10 +0100 Subject: [PATCH] vulkan: replace DescriptorBufferCache by generic cache --- src/gfx_apis/vulkan.rs | 1 + src/gfx_apis/vulkan/buffer_cache.rs | 158 +++++++++++++++++++++++ src/gfx_apis/vulkan/descriptor_buffer.rs | 155 +--------------------- src/gfx_apis/vulkan/renderer.rs | 17 ++- 4 files changed, 169 insertions(+), 162 deletions(-) create mode 100644 src/gfx_apis/vulkan/buffer_cache.rs diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index befd77d2..4a177b79 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -1,6 +1,7 @@ mod allocator; mod blend_buffer; mod bo_allocator; +mod buffer_cache; mod command; mod descriptor; mod descriptor_buffer; diff --git a/src/gfx_apis/vulkan/buffer_cache.rs b/src/gfx_apis/vulkan/buffer_cache.rs new file mode 100644 index 00000000..d6654e73 --- /dev/null +++ b/src/gfx_apis/vulkan/buffer_cache.rs @@ -0,0 +1,158 @@ +use { + crate::{ + gfx_apis::vulkan::{ + VulkanError, + allocator::{VulkanAllocation, VulkanAllocator}, + device::VulkanDevice, + }, + utils::on_drop::OnDrop, + }, + ash::vk::{ + Buffer, BufferCreateInfo, BufferDeviceAddressInfo, BufferUsageFlags, DeviceAddress, + DeviceSize, + }, + gpu_alloc::UsageFlags, + std::{cell::RefCell, mem::ManuallyDrop, rc::Rc}, +}; + +pub struct VulkanBufferCache { + device: Rc, + allocator: Rc, + buffers: RefCell>, + usage: BufferUsageFlags, +} + +pub struct VulkanBuffer { + cache: Rc, + pub buffer: ManuallyDrop, +} + +pub struct VulkanBufferUnused { + device: Rc, + pub size: DeviceSize, + pub buffer: Buffer, + pub allocation: VulkanAllocation, + pub address: DeviceAddress, +} + +impl VulkanBufferCache { + pub fn new( + device: &Rc, + allocator: &Rc, + usage: BufferUsageFlags, + ) -> Rc { + Rc::new(Self { + device: device.clone(), + allocator: allocator.clone(), + buffers: Default::default(), + usage, + }) + } + + pub fn for_descriptor_buffer( + device: &Rc, + allocator: &Rc, + has_sampler: bool, + ) -> Rc { + let mut usage = BufferUsageFlags::RESOURCE_DESCRIPTOR_BUFFER_EXT + | BufferUsageFlags::SHADER_DEVICE_ADDRESS; + if has_sampler { + usage |= BufferUsageFlags::SAMPLER_DESCRIPTOR_BUFFER_EXT; + } + Self::new(device, allocator, usage) + } + + pub fn usage(&self) -> BufferUsageFlags { + self.usage + } + + pub fn allocate(self: &Rc, capacity: DeviceSize) -> Result { + const MIN_ALLOCATION: DeviceSize = 1024; + let capacity = capacity.max(MIN_ALLOCATION); + let mut smallest = None; + let mut smallest_size = DeviceSize::MAX; + let mut fitting = None; + let mut fitting_size = DeviceSize::MAX; + let buffers = &mut *self.buffers.borrow_mut(); + for (idx, buffer) in buffers.iter().enumerate() { + if buffer.size >= capacity { + if buffer.size < fitting_size { + fitting = Some(idx); + fitting_size = buffer.size; + } + } else { + if buffer.size < smallest_size { + smallest = Some(idx); + smallest_size = buffer.size; + } + } + } + if let Some(idx) = fitting { + return Ok(VulkanBuffer { + cache: self.clone(), + buffer: ManuallyDrop::new(buffers.swap_remove(idx)), + }); + } + if let Some(idx) = smallest { + log::debug!("discarding size {}", smallest_size); + buffers.swap_remove(idx); + } + let size = capacity.checked_next_power_of_two().unwrap(); + log::debug!("allocating size {}", size); + let buffer = { + let info = BufferCreateInfo::default().size(size).usage(self.usage); + unsafe { + self.device + .device + .create_buffer(&info, None) + .map_err(VulkanError::CreateBuffer)? + } + }; + let destroy_buffer = OnDrop(|| unsafe { self.device.device.destroy_buffer(buffer, None) }); + let memory_requirements = + unsafe { self.device.device.get_buffer_memory_requirements(buffer) }; + let allocation = { + let flags = UsageFlags::UPLOAD + | UsageFlags::FAST_DEVICE_ACCESS + | UsageFlags::HOST_ACCESS + | UsageFlags::DEVICE_ADDRESS; + self.allocator.alloc(&memory_requirements, flags, true)? + }; + unsafe { + self.device + .device + .bind_buffer_memory(buffer, allocation.memory, allocation.offset) + .map_err(VulkanError::BindBufferMemory)?; + } + destroy_buffer.forget(); + let address = { + let info = BufferDeviceAddressInfo::default().buffer(buffer); + unsafe { self.device.device.get_buffer_device_address(&info) } + }; + Ok(VulkanBuffer { + cache: self.clone(), + buffer: ManuallyDrop::new(VulkanBufferUnused { + device: self.device.clone(), + size, + buffer, + allocation, + address, + }), + }) + } +} + +impl Drop for VulkanBuffer { + fn drop(&mut self) { + let buffer = unsafe { ManuallyDrop::take(&mut self.buffer) }; + self.cache.buffers.borrow_mut().push(buffer); + } +} + +impl Drop for VulkanBufferUnused { + fn drop(&mut self) { + unsafe { + self.device.device.destroy_buffer(self.buffer, None); + } + } +} diff --git a/src/gfx_apis/vulkan/descriptor_buffer.rs b/src/gfx_apis/vulkan/descriptor_buffer.rs index 5f72d7a0..4ee4ddcd 100644 --- a/src/gfx_apis/vulkan/descriptor_buffer.rs +++ b/src/gfx_apis/vulkan/descriptor_buffer.rs @@ -1,41 +1,8 @@ use { - crate::{ - gfx_apis::vulkan::{ - VulkanError, - allocator::{VulkanAllocation, VulkanAllocator}, - descriptor::VulkanDescriptorSetLayout, - device::VulkanDevice, - }, - utils::on_drop::OnDrop, - }, - ash::vk::{ - Buffer, BufferCreateInfo, BufferDeviceAddressInfo, BufferUsageFlags, DeviceAddress, - DeviceSize, - }, - gpu_alloc::UsageFlags, - std::{cell::RefCell, mem::ManuallyDrop, ops::Deref, rc::Rc}, + crate::gfx_apis::vulkan::descriptor::VulkanDescriptorSetLayout, ash::vk::DeviceSize, + std::ops::Deref, }; -pub struct VulkanDescriptorBufferCache { - device: Rc, - allocator: Rc, - buffers: RefCell>, - has_sampler: bool, -} - -pub struct VulkanDescriptorBuffer { - cache: Rc, - pub buffer: ManuallyDrop, -} - -pub struct VulkanDescriptorBufferUnused { - device: Rc, - pub size: DeviceSize, - pub buffer: Buffer, - pub allocation: VulkanAllocation, - pub address: DeviceAddress, -} - #[derive(Default)] pub struct VulkanDescriptorBufferWriter { buffer: Vec, @@ -45,124 +12,6 @@ pub struct VulkanDescriptorBufferSetWriter<'a> { set: &'a mut [u8], } -impl VulkanDescriptorBufferCache { - pub fn new( - device: &Rc, - allocator: &Rc, - has_sampler: bool, - ) -> Self { - Self { - device: device.clone(), - allocator: allocator.clone(), - buffers: Default::default(), - has_sampler, - } - } - - pub fn allocate( - self: &Rc, - capacity: DeviceSize, - ) -> Result { - const MIN_ALLOCATION: DeviceSize = 1024; - let capacity = capacity.max(MIN_ALLOCATION); - let mut smallest = None; - let mut smallest_size = DeviceSize::MAX; - let mut fitting = None; - let mut fitting_size = DeviceSize::MAX; - let buffers = &mut *self.buffers.borrow_mut(); - for (idx, buffer) in buffers.iter().enumerate() { - if buffer.size >= capacity { - if buffer.size < fitting_size { - fitting = Some(idx); - fitting_size = buffer.size; - } - } else { - if buffer.size < smallest_size { - smallest = Some(idx); - smallest_size = buffer.size; - } - } - } - if let Some(idx) = fitting { - return Ok(VulkanDescriptorBuffer { - cache: self.clone(), - buffer: ManuallyDrop::new(buffers.swap_remove(idx)), - }); - } - if let Some(idx) = smallest { - log::debug!("discarding size {}", smallest_size); - buffers.swap_remove(idx); - } - let size = capacity.checked_next_power_of_two().unwrap(); - log::debug!("allocating size {}", size); - let buffer = { - let usage = self.usage(); - let info = BufferCreateInfo::default().size(size).usage(usage); - unsafe { - self.device - .device - .create_buffer(&info, None) - .map_err(VulkanError::CreateBuffer)? - } - }; - let destroy_buffer = OnDrop(|| unsafe { self.device.device.destroy_buffer(buffer, None) }); - let memory_requirements = - unsafe { self.device.device.get_buffer_memory_requirements(buffer) }; - let allocation = { - let flags = UsageFlags::UPLOAD - | UsageFlags::FAST_DEVICE_ACCESS - | UsageFlags::HOST_ACCESS - | UsageFlags::DEVICE_ADDRESS; - self.allocator.alloc(&memory_requirements, flags, true)? - }; - unsafe { - self.device - .device - .bind_buffer_memory(buffer, allocation.memory, allocation.offset) - .map_err(VulkanError::BindBufferMemory)?; - } - destroy_buffer.forget(); - let address = { - let info = BufferDeviceAddressInfo::default().buffer(buffer); - unsafe { self.device.device.get_buffer_device_address(&info) } - }; - Ok(VulkanDescriptorBuffer { - cache: self.clone(), - buffer: ManuallyDrop::new(VulkanDescriptorBufferUnused { - device: self.device.clone(), - size, - buffer, - allocation, - address, - }), - }) - } - - pub fn usage(&self) -> BufferUsageFlags { - let mut usage = BufferUsageFlags::RESOURCE_DESCRIPTOR_BUFFER_EXT - | BufferUsageFlags::SHADER_DEVICE_ADDRESS; - if self.has_sampler { - usage |= BufferUsageFlags::SAMPLER_DESCRIPTOR_BUFFER_EXT; - } - usage - } -} - -impl Drop for VulkanDescriptorBuffer { - fn drop(&mut self) { - let buffer = unsafe { ManuallyDrop::take(&mut self.buffer) }; - self.cache.buffers.borrow_mut().push(buffer); - } -} - -impl Drop for VulkanDescriptorBufferUnused { - fn drop(&mut self) { - unsafe { - self.device.device.destroy_buffer(self.buffer, None); - } - } -} - impl VulkanDescriptorBufferWriter { pub fn clear(&mut self) { self.buffer.clear(); diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 31be1a6b..6272e025 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -10,11 +10,10 @@ use { gfx_apis::vulkan::{ VulkanError, allocator::{VulkanAllocator, VulkanThreadedAllocator}, + buffer_cache::{VulkanBuffer, VulkanBufferCache}, command::{VulkanCommandBuffer, VulkanCommandPool}, descriptor::VulkanDescriptorSetLayout, - descriptor_buffer::{ - VulkanDescriptorBuffer, VulkanDescriptorBufferCache, VulkanDescriptorBufferWriter, - }, + descriptor_buffer::VulkanDescriptorBufferWriter, device::VulkanDevice, fence::VulkanFence, image::{QueueFamily, QueueState, QueueTransfer, VulkanImage, VulkanImageMemory}, @@ -95,8 +94,8 @@ pub struct VulkanRenderer { pub(super) pending_cpu_jobs: CopyHashMap, pub(super) shm_allocator: Rc, pub(super) sampler: Rc, - pub(super) sampler_descriptor_buffer_cache: Rc, - pub(super) resource_descriptor_buffer_cache: Rc, + pub(super) sampler_descriptor_buffer_cache: Rc, + pub(super) resource_descriptor_buffer_cache: Rc, pub(super) blend_buffers: RefCell>>, } @@ -149,7 +148,7 @@ pub(super) struct Memory { wait_semaphore_infos: Vec>, release_fence: Option>, release_sync_file: Option, - descriptor_buffers: ArrayVec, + descriptor_buffers: ArrayVec, paint_bounds: StaticMap>, paint_regions: StaticMap>, clear_rects: StaticMap>, @@ -212,7 +211,7 @@ pub(super) struct PendingFrame { wait_semaphores: Cell>>, waiter: Cell>>, _release_fence: Option>, - _descriptor_buffers: ArrayVec, + _descriptor_buffers: ArrayVec, } pub(super) struct VulkanFormatPipelines { @@ -289,9 +288,9 @@ impl VulkanDevice { let allocator = self.create_allocator()?; let shm_allocator = self.create_threaded_allocator()?; let sampler_descriptor_buffer_cache = - Rc::new(VulkanDescriptorBufferCache::new(self, &allocator, true)); + VulkanBufferCache::for_descriptor_buffer(self, &allocator, true); let resource_descriptor_buffer_cache = - Rc::new(VulkanDescriptorBufferCache::new(self, &allocator, false)); + VulkanBufferCache::for_descriptor_buffer(self, &allocator, false); let render = Rc::new(VulkanRenderer { formats: Rc::new(formats), device: self.clone(),