From 1220539a41ad4e76d14061f100fdd1e42dca3553 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sat, 22 Feb 2025 11:46:33 +0100 Subject: [PATCH] vulkan: make descriptor buffer code more generic --- src/gfx_apis/vulkan/descriptor.rs | 27 ++++++--- src/gfx_apis/vulkan/descriptor_buffer.rs | 20 +++---- src/gfx_apis/vulkan/renderer.rs | 70 ++++++++++++------------ 3 files changed, 60 insertions(+), 57 deletions(-) diff --git a/src/gfx_apis/vulkan/descriptor.rs b/src/gfx_apis/vulkan/descriptor.rs index 64807b38..1d4ae94f 100644 --- a/src/gfx_apis/vulkan/descriptor.rs +++ b/src/gfx_apis/vulkan/descriptor.rs @@ -1,9 +1,12 @@ use { crate::gfx_apis::vulkan::{VulkanError, device::VulkanDevice, sampler::VulkanSampler}, arrayvec::ArrayVec, - ash::vk::{ - DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateFlags, - DescriptorSetLayoutCreateInfo, DescriptorType, DeviceSize, ShaderStageFlags, + ash::{ + ext::descriptor_buffer, + vk::{ + DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateFlags, + DescriptorSetLayoutCreateInfo, DescriptorType, DeviceSize, ShaderStageFlags, + }, }, std::{rc::Rc, slice}, }; @@ -14,7 +17,6 @@ pub(super) struct VulkanDescriptorSetLayout { pub(super) size: DeviceSize, pub(super) offsets: ArrayVec, pub(super) _sampler: Option>, - pub(super) has_sampler: bool, } impl Drop for VulkanDescriptorSetLayout { @@ -28,7 +30,7 @@ impl Drop for VulkanDescriptorSetLayout { } impl VulkanDevice { - pub(super) fn create_descriptor_set_layout( + pub(super) fn create_tex_descriptor_set_layout( self: &Rc, sampler: &Rc, ) -> Result, VulkanError> { @@ -52,9 +54,7 @@ impl VulkanDevice { let mut size = 0; let mut offsets = ArrayVec::new(); if let Some(db) = &self.descriptor_buffer { - size = unsafe { db.get_descriptor_set_layout_size(layout) }; - size = - (size + self.descriptor_buffer_offset_mask) & !self.descriptor_buffer_offset_mask; + size = self.get_descriptor_set_size(db, layout); unsafe { offsets.push(db.get_descriptor_set_layout_binding_offset(layout, 0)); } @@ -65,7 +65,16 @@ impl VulkanDevice { size, offsets, _sampler: Some(sampler.clone()), - has_sampler: true, })) } + + fn get_descriptor_set_size( + &self, + db: &descriptor_buffer::Device, + layout: DescriptorSetLayout, + ) -> DeviceSize { + let mut size = unsafe { db.get_descriptor_set_layout_size(layout) }; + size = (size + self.descriptor_buffer_offset_mask) & !self.descriptor_buffer_offset_mask; + size + } } diff --git a/src/gfx_apis/vulkan/descriptor_buffer.rs b/src/gfx_apis/vulkan/descriptor_buffer.rs index 4bdb18a9..5f72d7a0 100644 --- a/src/gfx_apis/vulkan/descriptor_buffer.rs +++ b/src/gfx_apis/vulkan/descriptor_buffer.rs @@ -36,8 +36,8 @@ pub struct VulkanDescriptorBufferUnused { pub address: DeviceAddress, } +#[derive(Default)] pub struct VulkanDescriptorBufferWriter { - set_size: usize, buffer: Vec, } @@ -49,13 +49,13 @@ impl VulkanDescriptorBufferCache { pub fn new( device: &Rc, allocator: &Rc, - layout: &VulkanDescriptorSetLayout, + has_sampler: bool, ) -> Self { Self { device: device.clone(), allocator: allocator.clone(), buffers: Default::default(), - has_sampler: layout.has_sampler, + has_sampler, } } @@ -164,13 +164,6 @@ impl Drop for VulkanDescriptorBufferUnused { } impl VulkanDescriptorBufferWriter { - pub fn new(layout: &VulkanDescriptorSetLayout) -> Self { - Self { - set_size: layout.size as usize, - buffer: Default::default(), - } - } - pub fn clear(&mut self) { self.buffer.clear(); } @@ -179,10 +172,13 @@ impl VulkanDescriptorBufferWriter { self.buffer.len() as DeviceSize } - pub fn add_set(&mut self) -> VulkanDescriptorBufferSetWriter<'_> { + pub fn add_set( + &mut self, + layout: &VulkanDescriptorSetLayout, + ) -> VulkanDescriptorBufferSetWriter<'_> { let buffer = &mut self.buffer; let lo = buffer.len(); - buffer.resize(lo + self.set_size, 0); + buffer.resize(lo + layout.size as usize, 0); VulkanDescriptorBufferSetWriter { set: &mut buffer[lo..], } diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 5bf9224d..543b479a 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -36,6 +36,7 @@ use { video::dmabuf::{DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, dma_buf_export_sync_file}, }, ahash::AHashMap, + arrayvec::ArrayVec, ash::{ Device, vk::{ @@ -86,8 +87,7 @@ pub struct VulkanRenderer { pub(super) pending_cpu_jobs: CopyHashMap, pub(super) shm_allocator: Rc, pub(super) sampler: Rc, - pub(super) tex_sampler_descriptor_buffer_cache: Rc, - pub(super) tex_descriptor_buffer_writer: RefCell, + pub(super) sampler_descriptor_buffer_cache: Rc, } pub(super) struct CachedCommandBuffers { @@ -139,10 +139,11 @@ pub(super) struct Memory { wait_semaphore_infos: Vec>, release_fence: Option>, release_sync_file: Option, - descriptor_buffer: Option, + descriptor_buffers: ArrayVec, paint_regions: Vec, clear_rects: Vec, image_copy_regions: Vec>, + sampler_descriptor_buffer_writer: VulkanDescriptorBufferWriter, } struct PaintRegion { @@ -162,7 +163,7 @@ pub(super) struct PendingFrame { wait_semaphores: Cell>>, waiter: Cell>>, _release_fence: Option>, - _descriptor_buffer: Option, + _descriptor_buffers: ArrayVec, } pub(super) struct VulkanFormatPipelines { @@ -179,7 +180,7 @@ impl VulkanDevice { let fill_vert_shader = self.create_shader(FILL_VERT)?; let fill_frag_shader = self.create_shader(FILL_FRAG)?; let sampler = self.create_sampler()?; - let tex_descriptor_set_layout = self.create_descriptor_set_layout(&sampler)?; + let tex_descriptor_set_layout = self.create_tex_descriptor_set_layout(&sampler)?; let tex_vert_shader = self.create_shader(TEX_VERT)?; let tex_frag_shader = self.create_shader(TEX_FRAG)?; let gfx_command_buffers = self.create_command_pool(self.graphics_queue_idx)?; @@ -220,14 +221,8 @@ impl VulkanDevice { .collect(); let allocator = self.create_allocator()?; let shm_allocator = self.create_threaded_allocator()?; - let tex_descriptor_buffer_cache = Rc::new(VulkanDescriptorBufferCache::new( - self, - &allocator, - &tex_descriptor_set_layout, - )); - let tex_descriptor_buffer_writer = RefCell::new(VulkanDescriptorBufferWriter::new( - &tex_descriptor_set_layout, - )); + let sampler_descriptor_buffer_cache = + Rc::new(VulkanDescriptorBufferCache::new(self, &allocator, true)); let render = Rc::new(VulkanRenderer { formats: Rc::new(formats), device: self.clone(), @@ -252,8 +247,7 @@ impl VulkanDevice { pending_cpu_jobs: Default::default(), shm_allocator, sampler, - tex_sampler_descriptor_buffer_cache: tex_descriptor_buffer_cache, - tex_descriptor_buffer_writer, + sampler_descriptor_buffer_cache, }); render.get_or_create_pipelines(XRGB8888.vk_format)?; Ok(render) @@ -316,7 +310,7 @@ impl VulkanRenderer { self.last_point.fetch_add(1) + 1 } - fn create_descriptor_buffer( + fn create_descriptor_buffers( &self, buf: CommandBuffer, opts: &[GfxApiOpt], @@ -324,11 +318,12 @@ impl VulkanRenderer { let Some(db) = &self.device.descriptor_buffer else { return Ok(()); }; - zone!("create_descriptor_buffer"); + zone!("create_descriptor_buffers"); let version = self.allocate_point(); let memory = &mut *self.memory.borrow_mut(); - let writer = &mut *self.tex_descriptor_buffer_writer.borrow_mut(); - writer.clear(); + memory.descriptor_buffers.clear(); + let sampler_writer = &mut memory.sampler_descriptor_buffer_writer; + sampler_writer.clear(); for cmd in opts { let GfxApiOpt::CopyTexture(c) = cmd else { continue; @@ -337,27 +332,30 @@ impl VulkanRenderer { if tex.descriptor_buffer_version.replace(version) == version { continue; } - let offset = writer.next_offset(); + let offset = sampler_writer.next_offset(); tex.descriptor_buffer_offset.set(offset); - let mut writer = writer.add_set(); + let mut writer = sampler_writer.add_set(&self.tex_descriptor_set_layout); writer.write( self.tex_descriptor_set_layout.offsets[0], &tex.shader_read_only_optimal_descriptor, ); } - let buffer = self - .tex_sampler_descriptor_buffer_cache - .allocate(writer.len() as DeviceSize)?; - buffer.buffer.allocation.upload(|ptr, _| unsafe { - ptr::copy_nonoverlapping(writer.as_ptr(), ptr, writer.len()) - })?; - let info = DescriptorBufferBindingInfoEXT::default() - .usage(self.tex_sampler_descriptor_buffer_cache.usage()) - .address(buffer.buffer.address); - unsafe { - db.cmd_bind_descriptor_buffers(buf, slice::from_ref(&info)); + let mut infos = ArrayVec::<_, 2>::new(); + #[expect(clippy::single_element_loop)] + for (writer, cache) in [(&sampler_writer, &self.sampler_descriptor_buffer_cache)] { + let buffer = cache.allocate(writer.len() as DeviceSize)?; + buffer.buffer.allocation.upload(|ptr, _| unsafe { + ptr::copy_nonoverlapping(writer.as_ptr(), ptr, writer.len()) + })?; + let info = DescriptorBufferBindingInfoEXT::default() + .usage(cache.usage()) + .address(buffer.buffer.address); + infos.push(info); + memory.descriptor_buffers.push(buffer); + } + unsafe { + db.cmd_bind_descriptor_buffers(buf, &infos); } - memory.descriptor_buffer = Some(buffer); Ok(()) } @@ -1026,7 +1024,7 @@ impl VulkanRenderer { wait_semaphores: Cell::new(mem::take(&mut memory.wait_semaphores)), waiter: Cell::new(None), _release_fence: memory.release_fence.take(), - _descriptor_buffer: memory.descriptor_buffer.take(), + _descriptor_buffers: mem::take(&mut memory.descriptor_buffers), }); self.pending_frames.set(frame.point, frame.clone()); let future = self.eng.spawn( @@ -1059,7 +1057,7 @@ impl VulkanRenderer { memory.queue_transfer.clear(); memory.wait_semaphores.clear(); memory.release_fence.take(); - memory.descriptor_buffer.take(); + memory.descriptor_buffers.clear(); memory.release_sync_file.take() }; res.map(|_| sync_file) @@ -1127,7 +1125,7 @@ impl VulkanRenderer { let buf = self.gfx_command_buffers.allocate()?; self.collect_memory(opts); self.begin_command_buffer(buf.buffer)?; - self.create_descriptor_buffer(buf.buffer, opts)?; + self.create_descriptor_buffers(buf.buffer, opts)?; self.initial_barriers(buf.buffer, fb)?; self.begin_rendering(buf.buffer, fb, clear); self.set_viewport(buf.buffer, fb);