1
0
Fork 0
forked from wry/wry

vulkan: abstract over the release sync type

This commit is contained in:
Julian Orth 2026-03-01 21:39:06 +01:00
parent 3ecee1b17f
commit 2ac3519f2d
8 changed files with 166 additions and 137 deletions

View file

@ -2,12 +2,12 @@ use {
crate::{ crate::{
async_engine::{AsyncEngine, SpawnedFuture}, async_engine::{AsyncEngine, SpawnedFuture},
format::{FORMATS, Format}, format::{FORMATS, Format},
gfx_api::{FdSync, SyncFile}, gfx_api::FdSync,
io_uring::IoUring, io_uring::IoUring,
rect::{Rect, Region}, rect::{Rect, Region},
utils::{ utils::{
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, queue::AsyncQueue, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell,
stack::Stack, queue::AsyncQueue, stack::Stack,
}, },
video::{ video::{
LINEAR_MODIFIER, LINEAR_STRIDE_ALIGN, Modifier, LINEAR_MODIFIER, LINEAR_STRIDE_ALIGN, Modifier,
@ -15,7 +15,7 @@ use {
}, },
vulkan_core::{ vulkan_core::{
self, VULKAN_API_VERSION, VulkanCoreError, VulkanCoreInstance, device::VulkanDeviceInf, self, VULKAN_API_VERSION, VulkanCoreError, VulkanCoreInstance, device::VulkanDeviceInf,
fence::VulkanDeviceFenceExt, map_extension_properties, map_extension_properties, sync::VulkanDeviceSyncExt,
}, },
}, },
ahash::{AHashMap, AHashSet}, ahash::{AHashMap, AHashSet},
@ -230,7 +230,8 @@ pub struct CopyDeviceCopy {
struct CopyDeviceCopyInner { struct CopyDeviceCopyInner {
dev: Rc<CopyDeviceInner>, dev: Rc<CopyDeviceInner>,
busy: CloneCell<Option<SyncFile>>, busy_id: NumCell<u64>,
busy: CloneCell<Option<FdSync>>,
width: u32, width: u32,
height: u32, height: u32,
command_buffer: CommandBuffer, command_buffer: CommandBuffer,
@ -269,10 +270,11 @@ enum CopyDeviceCopyType {
struct Pending { struct Pending {
dev: Rc<CopyDeviceInner>, dev: Rc<CopyDeviceInner>,
sync_file: Option<SyncFile>, busy_id: u64,
sync: Option<FdSync>,
copy: Rc<CopyDeviceCopyInner>, copy: Rc<CopyDeviceCopyInner>,
semaphore: Option<VulkanSemaphore>, semaphore: Option<VulkanSemaphore>,
fence: Option<Rc<VulkanFence>>, vulkan_sync: VulkanSync,
} }
struct VulkanSemaphore { struct VulkanSemaphore {
@ -281,6 +283,7 @@ struct VulkanSemaphore {
} }
type VulkanFence = vulkan_core::fence::VulkanFence<CopyDeviceInner>; type VulkanFence = vulkan_core::fence::VulkanFence<CopyDeviceInner>;
type VulkanSync = vulkan_core::sync::VulkanSync<CopyDeviceInner>;
struct VulkanBuffer { struct VulkanBuffer {
dev: Rc<CopyDeviceInner>, dev: Rc<CopyDeviceInner>,
@ -733,8 +736,8 @@ async fn wait_for_submissions(
submissions.task_has_pending.set(false); submissions.task_has_pending.set(false);
let pending = submissions.pending.pop().await; let pending = submissions.pending.pop().await;
submissions.task_has_pending.set(true); submissions.task_has_pending.set(true);
if let Some(sync_file) = &pending.sync_file if let Some(sync) = &pending.sync
&& let Err(e) = ring.readable(sync_file).await && let Err(e) = sync.try_signaled(&ring).await
{ {
log::warn!( log::warn!(
"Could not wait for sync file to become readable: {}", "Could not wait for sync file to become readable: {}",
@ -742,6 +745,7 @@ async fn wait_for_submissions(
); );
dev.wait_idle(); dev.wait_idle();
} }
pending.vulkan_sync.handle_validation();
} }
} }
@ -1117,6 +1121,7 @@ impl CopyDevice {
Ok(CopyDeviceCopy { Ok(CopyDeviceCopy {
inner: Rc::new(CopyDeviceCopyInner { inner: Rc::new(CopyDeviceCopyInner {
dev: self.dev.clone(), dev: self.dev.clone(),
busy_id: Default::default(),
busy: Default::default(), busy: Default::default(),
width: src.width as _, width: src.width as _,
height: src.height as _, height: src.height as _,
@ -1256,16 +1261,9 @@ impl CopyDeviceInner {
impl CopyDeviceCopy { impl CopyDeviceCopy {
fn ensure_not_busy(&self) -> Result<(), CopyDeviceError> { fn ensure_not_busy(&self) -> Result<(), CopyDeviceError> {
let slf = &*self.inner; let slf = &*self.inner;
let Some(busy) = slf.busy.get() else { if let Some(sync) = slf.busy.get()
return Ok(()); && sync.is_unsignaled()
}; {
let mut pollfd = c::pollfd {
fd: busy.raw(),
events: c::POLLIN,
revents: 0,
};
let res = uapi::poll(slice::from_mut(&mut pollfd), 0);
if res != Ok(1) {
return Err(CopyDeviceError::Busy); return Err(CopyDeviceError::Busy);
} }
slf.busy.take(); slf.busy.take();
@ -1648,42 +1646,33 @@ impl CopyDeviceCopy {
wait_semaphores.push(info); wait_semaphores.push(info);
wait_semaphore = Some(semaphore); wait_semaphore = Some(semaphore);
} }
let signal_fence = match slf.dev.fences.pop() {
Some(s) => s,
_ => slf.dev.create_fence()?,
};
let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(cmd); let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(cmd);
let submit_info = SubmitInfo2::default() let submit_info = SubmitInfo2::default()
.command_buffer_infos(slice::from_ref(&command_buffer_info)) .command_buffer_infos(slice::from_ref(&command_buffer_info))
.wait_semaphore_infos(&wait_semaphores); .wait_semaphore_infos(&wait_semaphores);
let vulkan_sync = slf.dev.create_sync()?;
unsafe { unsafe {
slf.dev slf.dev
.dev .dev
.queue_submit2( .queue_submit2(
slf.dev.queues[tt], slf.dev.queues[tt],
slice::from_ref(&submit_info), slice::from_ref(&submit_info),
signal_fence.fence, vulkan_sync.fence(),
) )
.map_err(CopyDeviceError::SubmitCopy)?; .map_err(CopyDeviceError::SubmitCopy)?;
} }
let sync_file = match signal_fence.export_sync_file() { let sync = vulkan_sync.to_sync(|| slf.dev.wait_idle());
Ok(f) => f, slf.busy.set(sync.clone());
Err(e) => {
log::error!("Could not export signal fence: {}", ErrorFmt(e));
slf.dev.wait_idle();
None
}
};
slf.busy.set(sync_file.clone());
let pending = Pending { let pending = Pending {
dev: slf.dev.clone(), dev: slf.dev.clone(),
sync_file: sync_file.clone(), busy_id: slf.busy_id.add_fetch(1),
sync: sync.clone(),
copy: self.inner.clone(), copy: self.inner.clone(),
semaphore: wait_semaphore, semaphore: wait_semaphore,
fence: Some(signal_fence), vulkan_sync,
}; };
slf.dev.submissions[tt].pending.push(pending); slf.dev.submissions[tt].pending.push(pending);
Ok(sync_file.map(FdSync::SyncFile)) Ok(sync)
} }
} }
@ -1794,10 +1783,7 @@ impl Drop for Pending {
if let Some(v) = self.semaphore.take() { if let Some(v) = self.semaphore.take() {
self.dev.semaphores.push(v); self.dev.semaphores.push(v);
} }
if let Some(v) = self.fence.take() { if self.copy.busy_id.get() == self.busy_id {
self.dev.fences.push(v);
}
if self.copy.busy.get() == self.sync_file {
self.copy.busy.take(); self.copy.busy.take();
} }
} }

View file

@ -1169,7 +1169,6 @@ impl FdSync {
} }
} }
#[expect(dead_code)]
pub fn is_unsignaled(&self) -> bool { pub fn is_unsignaled(&self) -> bool {
!self.is_signaled() !self.is_signaled()
} }

View file

@ -211,7 +211,7 @@ pub enum VulkanError {
DmaBufBufferOffsetAlignment, DmaBufBufferOffsetAlignment,
} }
type VulkanFence = vulkan_core::fence::VulkanFence<VulkanDevice>; type VulkanSync = vulkan_core::sync::VulkanSync<VulkanDevice>;
impl From<VulkanError> for GfxError { impl From<VulkanError> for GfxError {
fn from(value: VulkanError) -> Self { fn from(value: VulkanError) -> Self {

View file

@ -9,10 +9,10 @@ use {
cpu_worker::PendingJob, cpu_worker::PendingJob,
gfx_api::{ gfx_api::{
AcquireSync, AlphaMode, BufferResv, BufferResvUser, FdSync, GfxApiOpt, GfxBlendBuffer, AcquireSync, AlphaMode, BufferResv, BufferResvUser, FdSync, GfxApiOpt, GfxBlendBuffer,
GfxFormat, GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile, GfxFormat, GfxTexture, GfxWriteModifier, ReleaseSync,
}, },
gfx_apis::vulkan::{ gfx_apis::vulkan::{
VulkanError, VulkanFence, VulkanError, VulkanSync,
allocator::{VulkanAllocator, VulkanThreadedAllocator}, allocator::{VulkanAllocator, VulkanThreadedAllocator},
buffer_cache::{GenericBufferWriter, VulkanBuffer, VulkanBufferCache}, buffer_cache::{GenericBufferWriter, VulkanBuffer, VulkanBufferCache},
command::{VulkanCommandBuffer, VulkanCommandPool}, command::{VulkanCommandBuffer, VulkanCommandPool},
@ -39,7 +39,7 @@ use {
stack::Stack, stack::Stack,
}, },
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},
vulkan_core::fence::VulkanDeviceFenceExt, vulkan_core::sync::VulkanDeviceSyncExt,
}, },
ahash::AHashMap, ahash::AHashMap,
arrayvec::ArrayVec, arrayvec::ArrayVec,
@ -65,7 +65,7 @@ use {
std::{ std::{
any::Any, any::Any,
borrow::Cow, borrow::Cow,
cell::{Cell, RefCell}, cell::{Cell, LazyCell, RefCell},
collections::hash_map::Entry, collections::hash_map::Entry,
fmt::{Debug, Formatter}, fmt::{Debug, Formatter},
mem, mem,
@ -162,8 +162,8 @@ pub(super) struct Memory {
image_barriers: Vec<ImageMemoryBarrier2<'static>>, image_barriers: Vec<ImageMemoryBarrier2<'static>>,
wait_semaphores: Vec<Rc<VulkanSemaphore>>, wait_semaphores: Vec<Rc<VulkanSemaphore>>,
wait_semaphore_infos: Vec<SemaphoreSubmitInfo<'static>>, wait_semaphore_infos: Vec<SemaphoreSubmitInfo<'static>>,
release_fence: Option<Rc<VulkanFence>>, release_vulkan_sync: Option<VulkanSync>,
release_sync_file: Option<SyncFile>, release_sync: Option<FdSync>,
used_buffers: ArrayVec<VulkanBuffer, 4>, used_buffers: ArrayVec<VulkanBuffer, 4>,
paint_bounds: StaticMap<RenderPass, Option<PaintRegion>>, paint_bounds: StaticMap<RenderPass, Option<PaintRegion>>,
paint_regions: StaticMap<RenderPass, Vec<PaintRegion>>, paint_regions: StaticMap<RenderPass, Vec<PaintRegion>>,
@ -249,7 +249,7 @@ pub(super) struct PendingFrame {
_textures: Vec<UsedTexture>, _textures: Vec<UsedTexture>,
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>>, vulkan_sync: Option<VulkanSync>,
_used_buffers: ArrayVec<VulkanBuffer, 4>, _used_buffers: ArrayVec<VulkanBuffer, 4>,
} }
@ -1705,11 +1705,11 @@ impl VulkanRenderer {
fn import_release_semaphore(&self, fb: &VulkanImage, fb_release_sync: ReleaseSync) { fn import_release_semaphore(&self, fb: &VulkanImage, fb_release_sync: ReleaseSync) {
zone!("import_release_semaphore"); zone!("import_release_semaphore");
let memory = &mut *self.memory.borrow_mut(); let memory = &mut *self.memory.borrow_mut();
let sync_file = match memory.release_sync_file.as_ref() { let fd_sync = match memory.release_sync.as_ref() {
Some(sync_file) => sync_file, Some(sync) => sync,
_ => return, _ => return,
}; };
let fd_sync = FdSync::SyncFile(sync_file.clone()); let sync_file = LazyCell::new(|| fd_sync.get_sync_file());
let import = let import =
|img: &VulkanImage, sync: ReleaseSync, resv: Option<Rc<dyn BufferResv>>, flag: u32| { |img: &VulkanImage, sync: ReleaseSync, resv: Option<Rc<dyn BufferResv>>, flag: u32| {
if sync == ReleaseSync::None { if sync == ReleaseSync::None {
@ -1719,7 +1719,8 @@ impl VulkanRenderer {
resv.set_sync(self.buffer_resv_user, &fd_sync); resv.set_sync(self.buffer_resv_user, &fd_sync);
} else if sync == ReleaseSync::Implicit { } else if sync == ReleaseSync::Implicit {
if let VulkanImageMemory::DmaBuf(buf) = &img.ty if let VulkanImageMemory::DmaBuf(buf) = &img.ty
&& let Err(e) = buf.template.dmabuf.import_sync_file(flag, sync_file) && let Some(fd) = &*sync_file
&& let Err(e) = buf.template.dmabuf.import_sync_file(flag, fd)
{ {
log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e)); log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e));
log::warn!("Relying on implicit sync"); log::warn!("Relying on implicit sync");
@ -1739,14 +1740,14 @@ impl VulkanRenderer {
&& let VulkanImageMemory::Internal(shm) = &texture.tex.ty && let VulkanImageMemory::Internal(shm) = &texture.tex.ty
&& let Some(data) = &shm.async_data && let Some(data) = &shm.async_data
{ {
data.last_gfx_use.set(Some(sync_file.clone())); data.last_gfx_use.set(Some(fd_sync.clone()));
} }
} }
if attach_async_shm_sync_file if attach_async_shm_sync_file
&& let VulkanImageMemory::Internal(shm) = &fb.ty && let VulkanImageMemory::Internal(shm) = &fb.ty
&& let Some(data) = &shm.async_data && let Some(data) = &shm.async_data
{ {
data.last_gfx_use.set(Some(sync_file.clone())); data.last_gfx_use.set(Some(fd_sync.clone()));
} }
import(fb, fb_release_sync, None, DMA_BUF_SYNC_WRITE); import(fb, fb_release_sync, None, DMA_BUF_SYNC_WRITE);
} }
@ -1754,33 +1755,24 @@ impl VulkanRenderer {
fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> { fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
zone!("submit"); zone!("submit");
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
let release_fence = self.device.create_fence()?;
let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(buf); let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(buf);
let submit_info = SubmitInfo2::default() let submit_info = SubmitInfo2::default()
.wait_semaphore_infos(&memory.wait_semaphore_infos) .wait_semaphore_infos(&memory.wait_semaphore_infos)
.command_buffer_infos(slice::from_ref(&command_buffer_info)); .command_buffer_infos(slice::from_ref(&command_buffer_info));
let vulkan_sync = self.device.create_sync()?;
unsafe { unsafe {
self.device self.device
.device .device
.queue_submit2( .queue_submit2(
self.device.graphics_queue, self.device.graphics_queue,
slice::from_ref(&submit_info), slice::from_ref(&submit_info),
release_fence.fence, vulkan_sync.fence(),
) )
.inspect_err(self.device.idl()) .inspect_err(self.device.idl())
.map_err(VulkanError::Submit)?; .map_err(VulkanError::Submit)?;
} }
zone!("export_sync_file"); memory.release_sync = vulkan_sync.to_sync(|| self.block());
let release_sync_file = match release_fence.export_sync_file() { memory.release_vulkan_sync = Some(vulkan_sync);
Ok(s) => s,
Err(e) => {
log::error!("Could not export sync file from fence: {}", ErrorFmt(e));
self.block();
None
}
};
memory.release_fence = Some(release_fence);
memory.release_sync_file = release_sync_file;
Ok(()) Ok(())
} }
@ -1819,14 +1811,14 @@ impl VulkanRenderer {
_textures: mem::take(&mut memory.textures), _textures: mem::take(&mut memory.textures),
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(), vulkan_sync: memory.release_vulkan_sync.take(),
_used_buffers: mem::take(&mut memory.used_buffers), _used_buffers: mem::take(&mut memory.used_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(
"await release", "await release",
await_release( await_release(
memory.release_sync_file.clone(), memory.release_sync.clone(),
self.ring.clone(), self.ring.clone(),
frame.clone(), frame.clone(),
self.clone(), self.clone(),
@ -1861,19 +1853,19 @@ impl VulkanRenderer {
blend_buffer, blend_buffer,
blend_cd, blend_cd,
); );
let sync_file = { let sync = {
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
memory.textures.clear(); memory.textures.clear();
memory.dmabuf_sample.clear(); memory.dmabuf_sample.clear();
memory.queue_transfer.clear(); memory.queue_transfer.clear();
memory.wait_semaphores.clear(); memory.wait_semaphores.clear();
memory.release_fence.take(); memory.release_vulkan_sync.take();
memory.used_buffers.clear(); memory.used_buffers.clear();
memory.ops.clear(); memory.ops.clear();
memory.ops_tmp.clear(); memory.ops_tmp.clear();
memory.release_sync_file.take() memory.release_sync.take()
}; };
res.map(|_| sync_file.map(FdSync::SyncFile)) res.map(|_| sync)
} }
fn allocate_semaphore(&self) -> Result<Rc<VulkanSemaphore>, VulkanError> { fn allocate_semaphore(&self) -> Result<Rc<VulkanSemaphore>, VulkanError> {
@ -2190,13 +2182,13 @@ pub(super) fn image_barrier() -> ImageMemoryBarrier2<'static> {
} }
async fn await_release( async fn await_release(
sync_file: Option<SyncFile>, sync: Option<FdSync>,
ring: Rc<IoUring>, ring: Rc<IoUring>,
frame: Rc<PendingFrame>, frame: Rc<PendingFrame>,
renderer: Rc<VulkanRenderer>, renderer: Rc<VulkanRenderer>,
) { ) {
if let Some(sync_file) = sync_file if let Some(sync) = sync
&& let Err(e) = ring.readable(&sync_file).await && let Err(e) = sync.try_signaled(&ring).await
{ {
log::error!( log::error!(
"Could not wait for release semaphore to be signaled: {}", "Could not wait for release semaphore to be signaled: {}",
@ -2204,6 +2196,9 @@ async fn await_release(
); );
frame.renderer.block(); frame.renderer.block();
} }
if let Some(vs) = &frame.vulkan_sync {
vs.handle_validation();
}
if let Some(buf) = frame.cmd.take() { if let Some(buf) = frame.cmd.take() {
frame.renderer.gfx_command_buffers.buffers.push(buf); frame.renderer.gfx_command_buffers.buffers.push(buf);
} }

View file

@ -2,9 +2,9 @@ use {
crate::{ crate::{
cpu_worker::CpuWorker, cpu_worker::CpuWorker,
format::Format, format::Format,
gfx_api::SyncFile, gfx_api::FdSync,
gfx_apis::vulkan::{ gfx_apis::vulkan::{
VulkanError, VulkanFence, VulkanError, VulkanSync,
allocator::VulkanAllocation, allocator::VulkanAllocation,
command::VulkanCommandBuffer, command::VulkanCommandBuffer,
image::{QueueFamily, QueueState, VulkanImage, VulkanImageMemory}, image::{QueueFamily, QueueState, VulkanImage, VulkanImageMemory},
@ -14,7 +14,7 @@ use {
}, },
rect::Rect, rect::Rect,
utils::errorfmt::ErrorFmt, utils::errorfmt::ErrorFmt,
vulkan_core::fence::VulkanDeviceFenceExt, vulkan_core::sync::VulkanDeviceSyncExt,
}, },
ash::vk::{ ash::vk::{
AccessFlags2, Buffer, BufferImageCopy2, BufferMemoryBarrier2, CommandBufferBeginInfo, AccessFlags2, Buffer, BufferImageCopy2, BufferMemoryBarrier2, CommandBufferBeginInfo,
@ -136,7 +136,7 @@ impl VulkanShmImage {
ptr::copy_nonoverlapping(buf, mem, total_size as usize); ptr::copy_nonoverlapping(buf, mem, total_size as usize);
} }
})?; })?;
let (cmd, fence, sync_file, point) = self.submit_buffer_image_copy( let (cmd, vulkan_sync, sync, point) = self.submit_buffer_image_copy(
img, img,
staging.buffer, staging.buffer,
staging.size, staging.size,
@ -147,7 +147,7 @@ impl VulkanShmImage {
)?; )?;
let future = img.renderer.eng.spawn( let future = img.renderer.eng.spawn(
"await upload", "await upload",
await_upload(point, img.clone(), cmd, sync_file, fence, staging), await_upload(point, img.clone(), cmd, sync, vulkan_sync, staging),
); );
img.renderer.pending_submits.set(point, future); img.renderer.pending_submits.set(point, future);
Ok(()) Ok(())
@ -162,15 +162,7 @@ impl VulkanShmImage {
use_transfer_queue: bool, use_transfer_queue: bool,
tt: TransferType, tt: TransferType,
foreign_buffer: bool, foreign_buffer: bool,
) -> Result< ) -> Result<(Rc<VulkanCommandBuffer>, VulkanSync, Option<FdSync>, u64), VulkanError> {
(
Rc<VulkanCommandBuffer>,
Rc<VulkanFence>,
Option<SyncFile>,
u64,
),
VulkanError,
> {
let mut transfer_queue_family_idx = img.renderer.device.graphics_queue_idx; let mut transfer_queue_family_idx = img.renderer.device.graphics_queue_idx;
if use_transfer_queue if use_transfer_queue
&& let Some(idx) = img.renderer.device.distinct_transfer_queue_family_idx && let Some(idx) = img.renderer.device.distinct_transfer_queue_family_idx
@ -281,7 +273,7 @@ impl VulkanShmImage {
SubmitInfo2::default().command_buffer_infos(slice::from_ref(&command_buffer_info)); SubmitInfo2::default().command_buffer_infos(slice::from_ref(&command_buffer_info));
let begin_info = let begin_info =
CommandBufferBeginInfo::default().flags(CommandBufferUsageFlags::ONE_TIME_SUBMIT); CommandBufferBeginInfo::default().flags(CommandBufferUsageFlags::ONE_TIME_SUBMIT);
let release_fence = img.renderer.device.create_fence()?; let vulkan_sync = img.renderer.device.create_sync()?;
unsafe { unsafe {
dev.begin_command_buffer(cmd.buffer, &begin_info) dev.begin_command_buffer(cmd.buffer, &begin_info)
.map_err(VulkanError::BeginCommandBuffer)?; .map_err(VulkanError::BeginCommandBuffer)?;
@ -313,7 +305,7 @@ impl VulkanShmImage {
_ => img.renderer.device.graphics_queue, _ => img.renderer.device.graphics_queue,
}, },
slice::from_ref(&submit_info), slice::from_ref(&submit_info),
release_fence.fence, vulkan_sync.fence(),
) )
.inspect_err(img.renderer.device.idl()) .inspect_err(img.renderer.device.idl())
.map_err(VulkanError::Submit)?; .map_err(VulkanError::Submit)?;
@ -322,16 +314,9 @@ impl VulkanShmImage {
img.is_undefined.set(false); img.is_undefined.set(false);
img.contents_are_undefined.set(false); img.contents_are_undefined.set(false);
} }
let release_sync_file = match release_fence.export_sync_file() { let release_sync = vulkan_sync.to_sync(|| img.renderer.block());
Ok(s) => s,
Err(e) => {
log::error!("Could not export sync file from fence: {}", ErrorFmt(e));
img.renderer.block();
None
}
};
let point = img.renderer.allocate_point(); let point = img.renderer.allocate_point();
Ok((cmd, release_fence, release_sync_file, point)) Ok((cmd, vulkan_sync, release_sync, point))
} }
} }
@ -339,12 +324,12 @@ async fn await_upload(
id: u64, id: u64,
img: Rc<VulkanImage>, img: Rc<VulkanImage>,
buf: Rc<VulkanCommandBuffer>, buf: Rc<VulkanCommandBuffer>,
sync_file: Option<SyncFile>, sync: Option<FdSync>,
_fence: Rc<VulkanFence>, vulkan_sync: VulkanSync,
_staging: VulkanStagingBuffer, _staging: VulkanStagingBuffer,
) { ) {
if let Some(sync_file) = sync_file if let Some(sync) = &sync
&& let Err(e) = img.renderer.ring.readable(&sync_file.0).await && let Err(e) = sync.try_signaled(&img.renderer.ring).await
{ {
log::error!( log::error!(
"Could not wait for sync file to become readable: {}", "Could not wait for sync file to become readable: {}",
@ -352,6 +337,7 @@ async fn await_upload(
); );
img.renderer.block(); img.renderer.block();
} }
vulkan_sync.handle_validation();
img.renderer.gfx_command_buffers.buffers.push(buf); img.renderer.gfx_command_buffers.buffers.push(buf);
img.renderer.pending_submits.remove(&id); img.renderer.pending_submits.remove(&id);
} }

View file

@ -8,10 +8,10 @@ use {
}, },
}, },
gfx_api::{ gfx_api::{
AsyncShmGfxTextureCallback, PendingShmTransfer, ShmMemory, ShmMemoryBacking, SyncFile, AsyncShmGfxTextureCallback, FdSync, PendingShmTransfer, ShmMemory, ShmMemoryBacking,
}, },
gfx_apis::vulkan::{ gfx_apis::vulkan::{
VulkanError, VulkanFence, VulkanError, VulkanSync,
command::VulkanCommandBuffer, command::VulkanCommandBuffer,
dmabuf_buffer::{TRANSFER_QUEUE_BUFFER_ALIGNMENT, VulkanDmabufBuffer}, dmabuf_buffer::{TRANSFER_QUEUE_BUFFER_ALIGNMENT, VulkanDmabufBuffer},
image::{QueueFamily, QueueState, QueueTransfer, VulkanImage, VulkanImageMemory}, image::{QueueFamily, QueueState, QueueTransfer, VulkanImage, VulkanImageMemory},
@ -21,7 +21,7 @@ use {
}, },
rect::{Rect, Region}, rect::{Rect, Region},
utils::{clonecell::CloneCell, errorfmt::ErrorFmt}, utils::{clonecell::CloneCell, errorfmt::ErrorFmt},
vulkan_core::fence::VulkanDeviceFenceExt, vulkan_core::sync::VulkanDeviceSyncExt,
}, },
arrayvec::ArrayVec, arrayvec::ArrayVec,
ash::vk::{ ash::vk::{
@ -48,7 +48,7 @@ pub struct VulkanShmImageAsyncData {
pub(super) callback_id: Cell<u64>, pub(super) callback_id: Cell<u64>,
pub(super) regions: RefCell<Vec<BufferImageCopy2<'static>>>, pub(super) regions: RefCell<Vec<BufferImageCopy2<'static>>>,
pub(super) cpu: Rc<CpuWorker>, pub(super) cpu: Rc<CpuWorker>,
pub(super) last_gfx_use: Cell<Option<SyncFile>>, pub(super) last_gfx_use: Cell<Option<FdSync>>,
pub(super) data_copied: Cell<bool>, pub(super) data_copied: Cell<bool>,
} }
@ -314,7 +314,7 @@ impl VulkanShmImage {
img.renderer.check_defunct()?; img.renderer.check_defunct()?;
let Some(transfer_queue_idx) = img.renderer.device.distinct_transfer_queue_family_idx let Some(transfer_queue_idx) = img.renderer.device.distinct_transfer_queue_family_idx
else { else {
let Some(sync_file) = data.last_gfx_use.take() else { let Some(sync) = data.last_gfx_use.take() else {
img.queue_state.set(QueueState::Released { img.queue_state.set(QueueState::Released {
to: QueueFamily::Transfer, to: QueueFamily::Transfer,
}); });
@ -323,7 +323,7 @@ impl VulkanShmImage {
let id = img.renderer.allocate_point(); let id = img.renderer.allocate_point();
let pending = img.renderer.eng.spawn( let pending = img.renderer.eng.spawn(
"await_transfer_to_transfer", "await_transfer_to_transfer",
await_gfx_queue_release(id, img.clone(), None, None, Some(sync_file), tt), await_gfx_queue_release(id, img.clone(), None, None, Some(sync), tt),
); );
img.renderer.pending_submits.set(id, pending); img.renderer.pending_submits.set(id, pending);
img.queue_state.set(QueueState::Releasing); img.queue_state.set(QueueState::Releasing);
@ -375,7 +375,6 @@ impl VulkanShmImage {
.new_layout(transfer_layout); .new_layout(transfer_layout);
barriers.push(barrier); barriers.push(barrier);
let dep_info = DependencyInfo::default().image_memory_barriers(&barriers); let dep_info = DependencyInfo::default().image_memory_barriers(&barriers);
let release_fence = img.renderer.device.create_fence()?;
let dev = &img.renderer.device.device; let dev = &img.renderer.device.device;
let begin_info = let begin_info =
CommandBufferBeginInfo::default().flags(CommandBufferUsageFlags::ONE_TIME_SUBMIT); CommandBufferBeginInfo::default().flags(CommandBufferUsageFlags::ONE_TIME_SUBMIT);
@ -383,6 +382,7 @@ impl VulkanShmImage {
let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(cmd.buffer); let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(cmd.buffer);
let submit_info = let submit_info =
SubmitInfo2::default().command_buffer_infos(slice::from_ref(&command_buffer_info)); SubmitInfo2::default().command_buffer_infos(slice::from_ref(&command_buffer_info));
let vulkan_sync = img.renderer.device.create_sync()?;
unsafe { unsafe {
dev.begin_command_buffer(cmd.buffer, &begin_info) dev.begin_command_buffer(cmd.buffer, &begin_info)
.map_err(VulkanError::BeginCommandBuffer)?; .map_err(VulkanError::BeginCommandBuffer)?;
@ -392,23 +392,16 @@ impl VulkanShmImage {
dev.queue_submit2( dev.queue_submit2(
img.renderer.device.graphics_queue, img.renderer.device.graphics_queue,
slice::from_ref(&submit_info), slice::from_ref(&submit_info),
release_fence.fence, vulkan_sync.fence(),
) )
.inspect_err(img.renderer.device.idl()) .inspect_err(img.renderer.device.idl())
.map_err(VulkanError::Submit)?; .map_err(VulkanError::Submit)?;
} }
let sync_file = release_fence.export_sync_file()?; let sync = vulkan_sync.to_sync(|| img.renderer.block());
let id = img.renderer.allocate_point(); let id = img.renderer.allocate_point();
let pending = img.renderer.eng.spawn( let pending = img.renderer.eng.spawn(
"await_transfer_to_transfer", "await_transfer_to_transfer",
await_gfx_queue_release( await_gfx_queue_release(id, img.clone(), Some(cmd), Some(vulkan_sync), sync, tt),
id,
img.clone(),
Some(cmd),
Some(release_fence),
sync_file,
tt,
),
); );
img.renderer.pending_submits.set(id, pending); img.renderer.pending_submits.set(id, pending);
img.queue_state.set(QueueState::Releasing); img.queue_state.set(QueueState::Releasing);
@ -555,7 +548,7 @@ impl VulkanShmImage {
(host_buffer.buffer, host_buffer.size, true) (host_buffer.buffer, host_buffer.size, true)
} }
}; };
let (cmd, fence, sync_file, point) = self.submit_buffer_image_copy( let (cmd, vulkan_sync, sync, point) = self.submit_buffer_image_copy(
img, img,
buffer, buffer,
size, size,
@ -571,8 +564,8 @@ impl VulkanShmImage {
point, point,
img.clone(), img.clone(),
cmd, cmd,
fence, vulkan_sync,
sync_file, sync,
TransferType::Upload, TransferType::Upload,
), ),
); );
@ -590,7 +583,7 @@ impl VulkanShmImage {
return Ok(()); return Ok(());
} }
img.renderer.check_defunct()?; img.renderer.check_defunct()?;
let (cmd, fence, sync_file, point) = self.submit_buffer_image_copy( let (cmd, vulkan_sync, sync, point) = self.submit_buffer_image_copy(
img, img,
staging.buffer, staging.buffer,
staging.size, staging.size,
@ -606,8 +599,8 @@ impl VulkanShmImage {
point, point,
img.clone(), img.clone(),
cmd, cmd,
fence, vulkan_sync,
sync_file, sync,
TransferType::Download, TransferType::Download,
), ),
); );
@ -695,12 +688,12 @@ async fn await_gfx_queue_release(
id: u64, id: u64,
img: Rc<VulkanImage>, img: Rc<VulkanImage>,
buf: Option<Rc<VulkanCommandBuffer>>, buf: Option<Rc<VulkanCommandBuffer>>,
_fence: Option<Rc<VulkanFence>>, vulkan_sync: Option<VulkanSync>,
sync_file: Option<SyncFile>, sync: Option<FdSync>,
tt: TransferType, tt: TransferType,
) { ) {
if let Some(sync_file) = sync_file if let Some(sync) = &sync
&& let Err(e) = img.renderer.ring.readable(&sync_file.0).await && let Err(e) = sync.try_signaled(&img.renderer.ring).await
{ {
log::error!( log::error!(
"Could not wait for sync file to become readable: {}", "Could not wait for sync file to become readable: {}",
@ -708,6 +701,9 @@ async fn await_gfx_queue_release(
); );
img.renderer.block(); img.renderer.block();
} }
if let Some(vs) = vulkan_sync {
vs.handle_validation();
}
if let Some(buf) = buf { if let Some(buf) = buf {
img.renderer.gfx_command_buffers.buffers.push(buf); img.renderer.gfx_command_buffers.buffers.push(buf);
} }
@ -738,12 +734,12 @@ pub async fn await_async_transfer_release_to_gfx(
id: u64, id: u64,
img: Rc<VulkanImage>, img: Rc<VulkanImage>,
buf: Rc<VulkanCommandBuffer>, buf: Rc<VulkanCommandBuffer>,
_fence: Rc<VulkanFence>, vulkan_sync: VulkanSync,
sync_file: Option<SyncFile>, sync: Option<FdSync>,
tt: TransferType, tt: TransferType,
) { ) {
if let Some(sync_file) = sync_file if let Some(sync) = &sync
&& let Err(e) = img.renderer.ring.readable(&sync_file.0).await && let Err(e) = sync.try_signaled(&img.renderer.ring).await
{ {
log::error!( log::error!(
"Could not wait for sync file to become readable: {}", "Could not wait for sync file to become readable: {}",
@ -751,6 +747,7 @@ pub async fn await_async_transfer_release_to_gfx(
); );
img.renderer.block(); img.renderer.block();
} }
vulkan_sync.handle_validation();
match &img.renderer.transfer_command_buffers { match &img.renderer.transfer_command_buffers {
Some(b) => b.buffers.push(buf), Some(b) => b.buffers.push(buf),
None => img.renderer.gfx_command_buffers.buffers.push(buf), None => img.renderer.gfx_command_buffers.buffers.push(buf),

View file

@ -27,6 +27,7 @@ use {
pub mod device; pub mod device;
pub mod fence; pub mod fence;
pub mod sync;
static VULKAN_ENTRY: Lazy<Result<Entry, Arc<LoadingError>>> = static VULKAN_ENTRY: Lazy<Result<Entry, Arc<LoadingError>>> =
Lazy::new(|| unsafe { Entry::load() }.map_err(Arc::new)); Lazy::new(|| unsafe { Entry::load() }.map_err(Arc::new));

65
src/vulkan_core/sync.rs Normal file
View file

@ -0,0 +1,65 @@
use {
crate::{
gfx_api::FdSync,
utils::errorfmt::ErrorFmt,
vulkan_core::{
VulkanCoreError,
device::VulkanDeviceInf,
fence::{VulkanDeviceFenceExt, VulkanFence},
},
},
ash::vk::Fence,
std::rc::Rc,
};
pub enum VulkanSync<D>
where
D: VulkanDeviceInf,
{
Fence(Rc<VulkanFence<D>>),
}
impl<D> VulkanSync<D>
where
D: VulkanDeviceInf,
{
pub fn handle_validation(&self) {
// nothing
}
pub fn fence(&self) -> Fence {
match self {
VulkanSync::Fence(f) => f.fence,
}
}
pub fn to_sync(&self, block: impl FnOnce()) -> Option<FdSync> {
match self {
VulkanSync::Fence(release_fence) => {
zone!("export_sync_file");
let release_sync_file = match release_fence.export_sync_file() {
Ok(s) => s,
Err(e) => {
log::error!("Could not export sync file from fence: {}", ErrorFmt(e));
block();
None
}
};
release_sync_file.map(FdSync::SyncFile)
}
}
}
}
pub trait VulkanDeviceSyncExt: VulkanDeviceInf {
fn create_sync(self: &Rc<Self>) -> Result<VulkanSync<Self>, VulkanCoreError>;
}
impl<D> VulkanDeviceSyncExt for D
where
D: VulkanDeviceInf,
{
fn create_sync(self: &Rc<Self>) -> Result<VulkanSync<Self>, VulkanCoreError> {
self.create_fence().map(VulkanSync::Fence)
}
}