render: add abstraction for async-upload storage
This commit is contained in:
parent
d99444bd3c
commit
ca134e683b
8 changed files with 149 additions and 93 deletions
|
|
@ -67,7 +67,6 @@ macro_rules! dynload {
|
|||
|
||||
use {
|
||||
crate::{
|
||||
clientmem::ClientMemError,
|
||||
gfx_api::{
|
||||
AcquireSync, CopyTexture, FillRect, GfxApiOpt, GfxContext, GfxError, GfxTexture,
|
||||
ReleaseSync, SyncFile,
|
||||
|
|
@ -95,7 +94,7 @@ use {
|
|||
},
|
||||
isnt::std_1::vec::IsntVecExt,
|
||||
once_cell::sync::Lazy,
|
||||
std::{cell::RefCell, rc::Rc, sync::Arc},
|
||||
std::{cell::RefCell, error::Error, rc::Rc, sync::Arc},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
|
|
@ -199,7 +198,7 @@ enum RenderError {
|
|||
#[error("Buffer format {0} is not supported for shm buffers in OpenGL context")]
|
||||
UnsupportedShmFormat(&'static str),
|
||||
#[error("Could not access the client memory")]
|
||||
AccessFailed(#[source] ClientMemError),
|
||||
AccessFailed(#[source] Box<dyn Error + Sync + Send>),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use {
|
||||
crate::{
|
||||
clientmem::ClientMemOffset,
|
||||
format::Format,
|
||||
gfx_api::{
|
||||
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxError, GfxTexture, PendingShmUpload,
|
||||
ShmGfxTexture,
|
||||
ShmGfxTexture, ShmMemory,
|
||||
},
|
||||
gfx_apis::gl::{
|
||||
gl::texture::GlTexture,
|
||||
|
|
@ -102,12 +101,15 @@ impl AsyncShmGfxTexture for Texture {
|
|||
fn async_upload(
|
||||
self: Rc<Self>,
|
||||
_callback: Rc<dyn AsyncShmGfxTextureCallback>,
|
||||
mem: &Rc<ClientMemOffset>,
|
||||
damage: Region,
|
||||
mem: Rc<dyn ShmMemory>,
|
||||
_damage: Region,
|
||||
) -> Result<Option<PendingShmUpload>, GfxError> {
|
||||
mem.access(|data| self.clone().sync_upload(data, damage))
|
||||
.map_err(RenderError::AccessFailed)??;
|
||||
Ok(None)
|
||||
let mut res = Ok(());
|
||||
mem.access(&mut |data| {
|
||||
res = self.clone().sync_upload(data, Region::default());
|
||||
})
|
||||
.map_err(RenderError::AccessFailed)?;
|
||||
res.map(|_| None)
|
||||
}
|
||||
|
||||
fn sync_upload(self: Rc<Self>, data: &[Cell<u8>], _damage: Region) -> Result<(), GfxError> {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use {
|
||||
crate::{
|
||||
clientmem::ClientMemOffset,
|
||||
format::Format,
|
||||
gfx_api::{
|
||||
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback,
|
||||
AsyncShmGfxTextureUploadCancellable, GfxApiOpt, GfxError, GfxFramebuffer, GfxImage,
|
||||
GfxTexture, PendingShmUpload, ReleaseSync, ShmGfxTexture, SyncFile,
|
||||
GfxTexture, PendingShmUpload, ReleaseSync, ShmGfxTexture, ShmMemory, SyncFile,
|
||||
},
|
||||
gfx_apis::vulkan::{
|
||||
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanModifierLimits,
|
||||
|
|
@ -579,13 +578,13 @@ impl AsyncShmGfxTexture for VulkanImage {
|
|||
fn async_upload(
|
||||
self: Rc<Self>,
|
||||
callback: Rc<dyn AsyncShmGfxTextureCallback>,
|
||||
mem: &Rc<ClientMemOffset>,
|
||||
mem: Rc<dyn ShmMemory>,
|
||||
damage: Region,
|
||||
) -> Result<Option<PendingShmUpload>, GfxError> {
|
||||
let VulkanImageMemory::Internal(shm) = &self.ty else {
|
||||
unreachable!();
|
||||
};
|
||||
let pending = shm.async_upload(&self, mem, damage, callback)?;
|
||||
let pending = shm.async_upload(&self, &mem, damage, callback)?;
|
||||
Ok(pending)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use {
|
||||
crate::{
|
||||
clientmem::ClientMemOffset,
|
||||
cpu_worker::{
|
||||
jobs::{
|
||||
img_copy::ImgCopyWork,
|
||||
|
|
@ -9,7 +8,9 @@ use {
|
|||
CpuJob, CpuWork, CpuWorker,
|
||||
},
|
||||
format::{Format, FormatShmInfo},
|
||||
gfx_api::{AsyncShmGfxTextureCallback, PendingShmUpload, SyncFile},
|
||||
gfx_api::{
|
||||
AsyncShmGfxTextureCallback, PendingShmUpload, ShmMemory, ShmMemoryBacking, SyncFile,
|
||||
},
|
||||
gfx_apis::vulkan::{
|
||||
allocator::VulkanAllocation,
|
||||
command::VulkanCommandBuffer,
|
||||
|
|
@ -329,7 +330,7 @@ impl VulkanShmImage {
|
|||
pub fn async_upload(
|
||||
&self,
|
||||
img: &Rc<VulkanImage>,
|
||||
client_mem: &Rc<ClientMemOffset>,
|
||||
client_mem: &Rc<dyn ShmMemory>,
|
||||
damage: Region,
|
||||
callback: Rc<dyn AsyncShmGfxTextureCallback>,
|
||||
) -> Result<Option<PendingShmUpload>, VulkanError> {
|
||||
|
|
@ -350,13 +351,13 @@ impl VulkanShmImage {
|
|||
&self,
|
||||
img: &Rc<VulkanImage>,
|
||||
data: &VulkanShmImageAsyncData,
|
||||
client_mem: &Rc<ClientMemOffset>,
|
||||
client_mem: &Rc<dyn ShmMemory>,
|
||||
mut damage: Region,
|
||||
) -> Result<(), VulkanError> {
|
||||
if data.busy.get() {
|
||||
return Err(VulkanError::AsyncCopyBusy);
|
||||
}
|
||||
if self.size > client_mem.ptr().len() as u64 {
|
||||
if self.size > client_mem.len() as u64 {
|
||||
return Err(VulkanError::InvalidBufferSize);
|
||||
}
|
||||
data.busy.set(true);
|
||||
|
|
@ -530,7 +531,7 @@ impl VulkanShmImage {
|
|||
fn async_upload_after_allocation(
|
||||
&self,
|
||||
img: &Rc<VulkanImage>,
|
||||
client_mem: &Rc<ClientMemOffset>,
|
||||
client_mem: &Rc<dyn ShmMemory>,
|
||||
res: Result<VulkanStagingBuffer, VulkanError>,
|
||||
) -> Result<(), VulkanError> {
|
||||
let staging = Rc::new(res?);
|
||||
|
|
@ -546,73 +547,76 @@ impl VulkanShmImage {
|
|||
data: &VulkanShmImageAsyncData,
|
||||
staging: &VulkanStagingBuffer,
|
||||
copies: &[BufferImageCopy2],
|
||||
client_mem: &Rc<ClientMemOffset>,
|
||||
client_mem: &Rc<dyn ShmMemory>,
|
||||
) -> Result<(), VulkanError> {
|
||||
img.renderer.check_defunct()?;
|
||||
|
||||
let id = img.renderer.allocate_point();
|
||||
let pending;
|
||||
if client_mem.pool().sigbus_impossible() {
|
||||
let mut job = data.copy_job.take().unwrap_or_else(|| {
|
||||
Box::new(CopyUploadJob {
|
||||
img: None,
|
||||
id,
|
||||
_mem: None,
|
||||
work: unsafe { ImgCopyWork::new() },
|
||||
})
|
||||
});
|
||||
job.id = id;
|
||||
job.img = Some(img.clone());
|
||||
job._mem = Some(client_mem.clone());
|
||||
job.work.src = client_mem.ptr() as _;
|
||||
job.work.dst = staging.allocation.mem.unwrap();
|
||||
job.work.width = img.width as _;
|
||||
job.work.stride = img.stride as _;
|
||||
job.work.bpp = self.shm_info.bpp as _;
|
||||
job.work.rects.clear();
|
||||
for copy in copies {
|
||||
job.work.rects.push(
|
||||
Rect::new_sized(
|
||||
copy.image_offset.x as _,
|
||||
copy.image_offset.y as _,
|
||||
copy.image_extent.width as _,
|
||||
copy.image_extent.height as _,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
match client_mem.safe_access() {
|
||||
ShmMemoryBacking::Ptr(ptr) => {
|
||||
let mut job = data.copy_job.take().unwrap_or_else(|| {
|
||||
Box::new(CopyUploadJob {
|
||||
img: None,
|
||||
id,
|
||||
_mem: None,
|
||||
work: unsafe { ImgCopyWork::new() },
|
||||
})
|
||||
});
|
||||
job.id = id;
|
||||
job.img = Some(img.clone());
|
||||
job._mem = Some(client_mem.clone());
|
||||
job.work.src = ptr as _;
|
||||
job.work.dst = staging.allocation.mem.unwrap();
|
||||
job.work.width = img.width as _;
|
||||
job.work.stride = img.stride as _;
|
||||
job.work.bpp = self.shm_info.bpp as _;
|
||||
job.work.rects.clear();
|
||||
for copy in copies {
|
||||
job.work.rects.push(
|
||||
Rect::new_sized(
|
||||
copy.image_offset.x as _,
|
||||
copy.image_offset.y as _,
|
||||
copy.image_extent.width as _,
|
||||
copy.image_extent.height as _,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
pending = data.cpu.submit(job);
|
||||
}
|
||||
pending = data.cpu.submit(job);
|
||||
} else {
|
||||
let mut min_offset = client_mem.ptr().len() as u64;
|
||||
let mut max_offset = 0;
|
||||
for copy in copies {
|
||||
min_offset = min_offset.min(copy.buffer_offset);
|
||||
let len = img.stride * (copy.image_extent.height - 1)
|
||||
+ copy.image_extent.width * self.shm_info.bpp;
|
||||
max_offset = max_offset.max(copy.buffer_offset + len as u64);
|
||||
ShmMemoryBacking::Fd(fd, offset) => {
|
||||
let mut min_offset = client_mem.len() as u64;
|
||||
let mut max_offset = 0;
|
||||
for copy in copies {
|
||||
min_offset = min_offset.min(copy.buffer_offset);
|
||||
let len = img.stride * (copy.image_extent.height - 1)
|
||||
+ copy.image_extent.width * self.shm_info.bpp;
|
||||
max_offset = max_offset.max(copy.buffer_offset + len as u64);
|
||||
}
|
||||
let mut job = data.io_job.take().unwrap_or_else(|| {
|
||||
Box::new(IoUploadJob {
|
||||
img: None,
|
||||
id,
|
||||
_mem: None,
|
||||
work: unsafe { ReadWriteWork::new() },
|
||||
fd: None,
|
||||
})
|
||||
});
|
||||
job.id = id;
|
||||
job.img = Some(img.clone());
|
||||
job._mem = Some(client_mem.clone());
|
||||
job.fd = Some(fd.clone());
|
||||
unsafe {
|
||||
let config = job.work.config();
|
||||
config.fd = fd.raw();
|
||||
config.offset = offset + min_offset as usize;
|
||||
config.ptr = staging.allocation.mem.unwrap().add(min_offset as _);
|
||||
config.len = max_offset.saturating_sub(min_offset) as usize;
|
||||
config.write = false;
|
||||
}
|
||||
pending = data.cpu.submit(job);
|
||||
}
|
||||
let mut job = data.io_job.take().unwrap_or_else(|| {
|
||||
Box::new(IoUploadJob {
|
||||
img: None,
|
||||
id,
|
||||
_mem: None,
|
||||
work: unsafe { ReadWriteWork::new() },
|
||||
fd: None,
|
||||
})
|
||||
});
|
||||
job.id = id;
|
||||
job.img = Some(img.clone());
|
||||
job._mem = Some(client_mem.clone());
|
||||
job.fd = Some(client_mem.pool().fd().clone());
|
||||
unsafe {
|
||||
let config = job.work.config();
|
||||
config.fd = client_mem.pool().fd().raw();
|
||||
config.offset = client_mem.offset() + min_offset as usize;
|
||||
config.ptr = staging.allocation.mem.unwrap().add(min_offset as _);
|
||||
config.len = max_offset.saturating_sub(min_offset) as usize;
|
||||
config.write = false;
|
||||
}
|
||||
pending = data.cpu.submit(job);
|
||||
}
|
||||
|
||||
img.renderer.pending_cpu_jobs.set(id, pending);
|
||||
|
|
@ -653,7 +657,7 @@ impl VulkanShmImage {
|
|||
pub(super) struct IoUploadJob {
|
||||
img: Option<Rc<VulkanImage>>,
|
||||
id: u64,
|
||||
_mem: Option<Rc<ClientMemOffset>>,
|
||||
_mem: Option<Rc<dyn ShmMemory>>,
|
||||
fd: Option<Rc<OwnedFd>>,
|
||||
work: ReadWriteWork,
|
||||
}
|
||||
|
|
@ -661,7 +665,7 @@ pub(super) struct IoUploadJob {
|
|||
pub(super) struct CopyUploadJob {
|
||||
img: Option<Rc<VulkanImage>>,
|
||||
id: u64,
|
||||
_mem: Option<Rc<ClientMemOffset>>,
|
||||
_mem: Option<Rc<dyn ShmMemory>>,
|
||||
work: ImgCopyWork,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue