vulkan: make descriptor buffer code more generic
This commit is contained in:
parent
52624455b3
commit
1220539a41
3 changed files with 60 additions and 57 deletions
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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..],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue