1
0
Fork 0
forked from wry/wry

vulkan: make descriptor buffer code more generic

This commit is contained in:
Julian Orth 2025-02-22 11:46:33 +01:00
parent 52624455b3
commit 1220539a41
3 changed files with 60 additions and 57 deletions

View file

@ -1,9 +1,12 @@
use { use {
crate::gfx_apis::vulkan::{VulkanError, device::VulkanDevice, sampler::VulkanSampler}, crate::gfx_apis::vulkan::{VulkanError, device::VulkanDevice, sampler::VulkanSampler},
arrayvec::ArrayVec, arrayvec::ArrayVec,
ash::vk::{ ash::{
DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateFlags, ext::descriptor_buffer,
DescriptorSetLayoutCreateInfo, DescriptorType, DeviceSize, ShaderStageFlags, vk::{
DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateFlags,
DescriptorSetLayoutCreateInfo, DescriptorType, DeviceSize, ShaderStageFlags,
},
}, },
std::{rc::Rc, slice}, std::{rc::Rc, slice},
}; };
@ -14,7 +17,6 @@ pub(super) struct VulkanDescriptorSetLayout {
pub(super) size: DeviceSize, pub(super) size: DeviceSize,
pub(super) offsets: ArrayVec<DeviceSize, 1>, pub(super) offsets: ArrayVec<DeviceSize, 1>,
pub(super) _sampler: Option<Rc<VulkanSampler>>, pub(super) _sampler: Option<Rc<VulkanSampler>>,
pub(super) has_sampler: bool,
} }
impl Drop for VulkanDescriptorSetLayout { impl Drop for VulkanDescriptorSetLayout {
@ -28,7 +30,7 @@ impl Drop for VulkanDescriptorSetLayout {
} }
impl VulkanDevice { impl VulkanDevice {
pub(super) fn create_descriptor_set_layout( pub(super) fn create_tex_descriptor_set_layout(
self: &Rc<Self>, self: &Rc<Self>,
sampler: &Rc<VulkanSampler>, sampler: &Rc<VulkanSampler>,
) -> Result<Rc<VulkanDescriptorSetLayout>, VulkanError> { ) -> Result<Rc<VulkanDescriptorSetLayout>, VulkanError> {
@ -52,9 +54,7 @@ impl VulkanDevice {
let mut size = 0; let mut size = 0;
let mut offsets = ArrayVec::new(); let mut offsets = ArrayVec::new();
if let Some(db) = &self.descriptor_buffer { if let Some(db) = &self.descriptor_buffer {
size = unsafe { db.get_descriptor_set_layout_size(layout) }; size = self.get_descriptor_set_size(db, layout);
size =
(size + self.descriptor_buffer_offset_mask) & !self.descriptor_buffer_offset_mask;
unsafe { unsafe {
offsets.push(db.get_descriptor_set_layout_binding_offset(layout, 0)); offsets.push(db.get_descriptor_set_layout_binding_offset(layout, 0));
} }
@ -65,7 +65,16 @@ impl VulkanDevice {
size, size,
offsets, offsets,
_sampler: Some(sampler.clone()), _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
}
} }

View file

@ -36,8 +36,8 @@ pub struct VulkanDescriptorBufferUnused {
pub address: DeviceAddress, pub address: DeviceAddress,
} }
#[derive(Default)]
pub struct VulkanDescriptorBufferWriter { pub struct VulkanDescriptorBufferWriter {
set_size: usize,
buffer: Vec<u8>, buffer: Vec<u8>,
} }
@ -49,13 +49,13 @@ impl VulkanDescriptorBufferCache {
pub fn new( pub fn new(
device: &Rc<VulkanDevice>, device: &Rc<VulkanDevice>,
allocator: &Rc<VulkanAllocator>, allocator: &Rc<VulkanAllocator>,
layout: &VulkanDescriptorSetLayout, has_sampler: bool,
) -> Self { ) -> Self {
Self { Self {
device: device.clone(), device: device.clone(),
allocator: allocator.clone(), allocator: allocator.clone(),
buffers: Default::default(), buffers: Default::default(),
has_sampler: layout.has_sampler, has_sampler,
} }
} }
@ -164,13 +164,6 @@ impl Drop for VulkanDescriptorBufferUnused {
} }
impl VulkanDescriptorBufferWriter { impl VulkanDescriptorBufferWriter {
pub fn new(layout: &VulkanDescriptorSetLayout) -> Self {
Self {
set_size: layout.size as usize,
buffer: Default::default(),
}
}
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.buffer.clear(); self.buffer.clear();
} }
@ -179,10 +172,13 @@ impl VulkanDescriptorBufferWriter {
self.buffer.len() as DeviceSize 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 buffer = &mut self.buffer;
let lo = buffer.len(); let lo = buffer.len();
buffer.resize(lo + self.set_size, 0); buffer.resize(lo + layout.size as usize, 0);
VulkanDescriptorBufferSetWriter { VulkanDescriptorBufferSetWriter {
set: &mut buffer[lo..], set: &mut buffer[lo..],
} }

View file

@ -36,6 +36,7 @@ use {
video::dmabuf::{DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, dma_buf_export_sync_file}, video::dmabuf::{DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, dma_buf_export_sync_file},
}, },
ahash::AHashMap, ahash::AHashMap,
arrayvec::ArrayVec,
ash::{ ash::{
Device, Device,
vk::{ vk::{
@ -86,8 +87,7 @@ pub struct VulkanRenderer {
pub(super) pending_cpu_jobs: CopyHashMap<u64, PendingJob>, pub(super) pending_cpu_jobs: CopyHashMap<u64, PendingJob>,
pub(super) shm_allocator: Rc<VulkanThreadedAllocator>, pub(super) shm_allocator: Rc<VulkanThreadedAllocator>,
pub(super) sampler: Rc<VulkanSampler>, pub(super) sampler: Rc<VulkanSampler>,
pub(super) tex_sampler_descriptor_buffer_cache: Rc<VulkanDescriptorBufferCache>, pub(super) sampler_descriptor_buffer_cache: Rc<VulkanDescriptorBufferCache>,
pub(super) tex_descriptor_buffer_writer: RefCell<VulkanDescriptorBufferWriter>,
} }
pub(super) struct CachedCommandBuffers { pub(super) struct CachedCommandBuffers {
@ -139,10 +139,11 @@ pub(super) struct Memory {
wait_semaphore_infos: Vec<SemaphoreSubmitInfo<'static>>, wait_semaphore_infos: Vec<SemaphoreSubmitInfo<'static>>,
release_fence: Option<Rc<VulkanFence>>, release_fence: Option<Rc<VulkanFence>>,
release_sync_file: Option<SyncFile>, release_sync_file: Option<SyncFile>,
descriptor_buffer: Option<VulkanDescriptorBuffer>, descriptor_buffers: ArrayVec<VulkanDescriptorBuffer, 1>,
paint_regions: Vec<PaintRegion>, paint_regions: Vec<PaintRegion>,
clear_rects: Vec<ClearRect>, clear_rects: Vec<ClearRect>,
image_copy_regions: Vec<ImageCopy2<'static>>, image_copy_regions: Vec<ImageCopy2<'static>>,
sampler_descriptor_buffer_writer: VulkanDescriptorBufferWriter,
} }
struct PaintRegion { struct PaintRegion {
@ -162,7 +163,7 @@ pub(super) struct PendingFrame {
wait_semaphores: Cell<Vec<Rc<VulkanSemaphore>>>, wait_semaphores: Cell<Vec<Rc<VulkanSemaphore>>>,
waiter: Cell<Option<SpawnedFuture<()>>>, waiter: Cell<Option<SpawnedFuture<()>>>,
_release_fence: Option<Rc<VulkanFence>>, _release_fence: Option<Rc<VulkanFence>>,
_descriptor_buffer: Option<VulkanDescriptorBuffer>, _descriptor_buffers: ArrayVec<VulkanDescriptorBuffer, 1>,
} }
pub(super) struct VulkanFormatPipelines { pub(super) struct VulkanFormatPipelines {
@ -179,7 +180,7 @@ impl VulkanDevice {
let fill_vert_shader = self.create_shader(FILL_VERT)?; let fill_vert_shader = self.create_shader(FILL_VERT)?;
let fill_frag_shader = self.create_shader(FILL_FRAG)?; let fill_frag_shader = self.create_shader(FILL_FRAG)?;
let sampler = self.create_sampler()?; 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_vert_shader = self.create_shader(TEX_VERT)?;
let tex_frag_shader = self.create_shader(TEX_FRAG)?; let tex_frag_shader = self.create_shader(TEX_FRAG)?;
let gfx_command_buffers = self.create_command_pool(self.graphics_queue_idx)?; let gfx_command_buffers = self.create_command_pool(self.graphics_queue_idx)?;
@ -220,14 +221,8 @@ impl VulkanDevice {
.collect(); .collect();
let allocator = self.create_allocator()?; let allocator = self.create_allocator()?;
let shm_allocator = self.create_threaded_allocator()?; let shm_allocator = self.create_threaded_allocator()?;
let tex_descriptor_buffer_cache = Rc::new(VulkanDescriptorBufferCache::new( let sampler_descriptor_buffer_cache =
self, Rc::new(VulkanDescriptorBufferCache::new(self, &allocator, true));
&allocator,
&tex_descriptor_set_layout,
));
let tex_descriptor_buffer_writer = RefCell::new(VulkanDescriptorBufferWriter::new(
&tex_descriptor_set_layout,
));
let render = Rc::new(VulkanRenderer { let render = Rc::new(VulkanRenderer {
formats: Rc::new(formats), formats: Rc::new(formats),
device: self.clone(), device: self.clone(),
@ -252,8 +247,7 @@ impl VulkanDevice {
pending_cpu_jobs: Default::default(), pending_cpu_jobs: Default::default(),
shm_allocator, shm_allocator,
sampler, sampler,
tex_sampler_descriptor_buffer_cache: tex_descriptor_buffer_cache, sampler_descriptor_buffer_cache,
tex_descriptor_buffer_writer,
}); });
render.get_or_create_pipelines(XRGB8888.vk_format)?; render.get_or_create_pipelines(XRGB8888.vk_format)?;
Ok(render) Ok(render)
@ -316,7 +310,7 @@ impl VulkanRenderer {
self.last_point.fetch_add(1) + 1 self.last_point.fetch_add(1) + 1
} }
fn create_descriptor_buffer( fn create_descriptor_buffers(
&self, &self,
buf: CommandBuffer, buf: CommandBuffer,
opts: &[GfxApiOpt], opts: &[GfxApiOpt],
@ -324,11 +318,12 @@ impl VulkanRenderer {
let Some(db) = &self.device.descriptor_buffer else { let Some(db) = &self.device.descriptor_buffer else {
return Ok(()); return Ok(());
}; };
zone!("create_descriptor_buffer"); zone!("create_descriptor_buffers");
let version = self.allocate_point(); let version = self.allocate_point();
let memory = &mut *self.memory.borrow_mut(); let memory = &mut *self.memory.borrow_mut();
let writer = &mut *self.tex_descriptor_buffer_writer.borrow_mut(); memory.descriptor_buffers.clear();
writer.clear(); let sampler_writer = &mut memory.sampler_descriptor_buffer_writer;
sampler_writer.clear();
for cmd in opts { for cmd in opts {
let GfxApiOpt::CopyTexture(c) = cmd else { let GfxApiOpt::CopyTexture(c) = cmd else {
continue; continue;
@ -337,27 +332,30 @@ impl VulkanRenderer {
if tex.descriptor_buffer_version.replace(version) == version { if tex.descriptor_buffer_version.replace(version) == version {
continue; continue;
} }
let offset = writer.next_offset(); let offset = sampler_writer.next_offset();
tex.descriptor_buffer_offset.set(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( writer.write(
self.tex_descriptor_set_layout.offsets[0], self.tex_descriptor_set_layout.offsets[0],
&tex.shader_read_only_optimal_descriptor, &tex.shader_read_only_optimal_descriptor,
); );
} }
let buffer = self let mut infos = ArrayVec::<_, 2>::new();
.tex_sampler_descriptor_buffer_cache #[expect(clippy::single_element_loop)]
.allocate(writer.len() as DeviceSize)?; for (writer, cache) in [(&sampler_writer, &self.sampler_descriptor_buffer_cache)] {
buffer.buffer.allocation.upload(|ptr, _| unsafe { let buffer = cache.allocate(writer.len() as DeviceSize)?;
ptr::copy_nonoverlapping(writer.as_ptr(), ptr, writer.len()) 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()) let info = DescriptorBufferBindingInfoEXT::default()
.address(buffer.buffer.address); .usage(cache.usage())
unsafe { .address(buffer.buffer.address);
db.cmd_bind_descriptor_buffers(buf, slice::from_ref(&info)); infos.push(info);
memory.descriptor_buffers.push(buffer);
}
unsafe {
db.cmd_bind_descriptor_buffers(buf, &infos);
} }
memory.descriptor_buffer = Some(buffer);
Ok(()) Ok(())
} }
@ -1026,7 +1024,7 @@ impl VulkanRenderer {
wait_semaphores: Cell::new(mem::take(&mut memory.wait_semaphores)), wait_semaphores: Cell::new(mem::take(&mut memory.wait_semaphores)),
waiter: Cell::new(None), waiter: Cell::new(None),
_release_fence: memory.release_fence.take(), _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()); self.pending_frames.set(frame.point, frame.clone());
let future = self.eng.spawn( let future = self.eng.spawn(
@ -1059,7 +1057,7 @@ impl VulkanRenderer {
memory.queue_transfer.clear(); memory.queue_transfer.clear();
memory.wait_semaphores.clear(); memory.wait_semaphores.clear();
memory.release_fence.take(); memory.release_fence.take();
memory.descriptor_buffer.take(); memory.descriptor_buffers.clear();
memory.release_sync_file.take() memory.release_sync_file.take()
}; };
res.map(|_| sync_file) res.map(|_| sync_file)
@ -1127,7 +1125,7 @@ impl VulkanRenderer {
let buf = self.gfx_command_buffers.allocate()?; let buf = self.gfx_command_buffers.allocate()?;
self.collect_memory(opts); self.collect_memory(opts);
self.begin_command_buffer(buf.buffer)?; 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.initial_barriers(buf.buffer, fb)?;
self.begin_rendering(buf.buffer, fb, clear); self.begin_rendering(buf.buffer, fb, clear);
self.set_viewport(buf.buffer, fb); self.set_viewport(buf.buffer, fb);