render: add support for explicit sync
This commit is contained in:
parent
1b4492c670
commit
816315170f
22 changed files with 531 additions and 94 deletions
|
|
@ -68,8 +68,8 @@ macro_rules! dynload {
|
|||
use {
|
||||
crate::{
|
||||
gfx_api::{
|
||||
CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxTexture,
|
||||
SampleRect,
|
||||
AcquireSync, CopyTexture, FillRect, GfxApiOpt, GfxContext, GfxError, GfxTexture,
|
||||
ReleaseSync, SyncFile,
|
||||
},
|
||||
gfx_apis::gl::{
|
||||
gl::texture::image_target,
|
||||
|
|
@ -80,8 +80,9 @@ use {
|
|||
},
|
||||
},
|
||||
theme::Color,
|
||||
utils::{rc_eq::rc_eq, vecstorage::VecStorage},
|
||||
utils::{errorfmt::ErrorFmt, rc_eq::rc_eq, vecstorage::VecStorage},
|
||||
video::{
|
||||
dmabuf::DMA_BUF_SYNC_READ,
|
||||
drm::{Drm, DrmError},
|
||||
gbm::GbmError,
|
||||
},
|
||||
|
|
@ -181,6 +182,14 @@ enum RenderError {
|
|||
NoSupportedFormats,
|
||||
#[error("Cannot convert a shm texture into a framebuffer")]
|
||||
ShmTextureToFb,
|
||||
#[error("Could not create EGLSyncKHR")]
|
||||
CreateEglSync,
|
||||
#[error("Could not destroy EGLSyncKHR")]
|
||||
DestroyEglSync,
|
||||
#[error("Could not export sync file")]
|
||||
ExportSyncFile,
|
||||
#[error("Could not insert wait for EGLSyncKHR")]
|
||||
WaitSync,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -190,7 +199,7 @@ struct GfxGlState {
|
|||
copy_tex: VecStorage<&'static CopyTexture>,
|
||||
}
|
||||
|
||||
fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) {
|
||||
fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) -> Option<SyncFile> {
|
||||
let mut state = fb.ctx.gl_state.borrow_mut();
|
||||
let state = &mut *state;
|
||||
let mut fill_rect = state.fill_rect.take();
|
||||
|
|
@ -256,9 +265,30 @@ fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) {
|
|||
}
|
||||
}
|
||||
for tex in &*copy_tex {
|
||||
render_texture(&fb.ctx, &tex.tex.as_gl(), &tex.target, &tex.source)
|
||||
render_texture(&fb.ctx, tex);
|
||||
}
|
||||
}
|
||||
if fb.ctx.ctx.dpy.explicit_sync {
|
||||
let file = match fb.ctx.ctx.export_sync_file() {
|
||||
Ok(f) => SyncFile(Rc::new(f)),
|
||||
Err(e) => {
|
||||
log::error!("Could not create sync file: {}", ErrorFmt(e));
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let user = fb.ctx.buffer_resv_user;
|
||||
for op in ops {
|
||||
if let GfxApiOpt::CopyTexture(ct) = op {
|
||||
if ct.release_sync == ReleaseSync::Explicit {
|
||||
if let Some(resv) = &ct.buffer_resv {
|
||||
resv.set_sync_file(user, &file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Some(file);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn fill_boxes3(ctx: &GlRenderContext, boxes: &[[f32; 2]], color: &Color) {
|
||||
|
|
@ -280,15 +310,13 @@ fn fill_boxes3(ctx: &GlRenderContext, boxes: &[[f32; 2]], color: &Color) {
|
|||
}
|
||||
}
|
||||
|
||||
fn render_texture(
|
||||
ctx: &GlRenderContext,
|
||||
texture: &Texture,
|
||||
target_rect: &FramebufferRect,
|
||||
src: &SampleRect,
|
||||
) {
|
||||
fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
|
||||
let texture = tex.tex.as_gl();
|
||||
assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx));
|
||||
let gles = ctx.ctx.dpy.gles;
|
||||
unsafe {
|
||||
handle_explicit_sync(ctx, texture, &tex.acquire_sync);
|
||||
|
||||
(gles.glActiveTexture)(GL_TEXTURE0);
|
||||
|
||||
let target = image_target(texture.gl.external_only);
|
||||
|
|
@ -321,8 +349,8 @@ fn render_texture(
|
|||
|
||||
(gles.glUniform1i)(prog.tex, 0);
|
||||
|
||||
let texcoord = src.to_points();
|
||||
let pos = target_rect.to_points();
|
||||
let texcoord = tex.source.to_points();
|
||||
let pos = tex.target.to_points();
|
||||
|
||||
(gles.glVertexAttribPointer)(
|
||||
prog.texcoord as _,
|
||||
|
|
@ -346,6 +374,36 @@ fn render_texture(
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_explicit_sync(ctx: &GlRenderContext, texture: &Texture, sync: &AcquireSync) {
|
||||
let sync_file = match sync {
|
||||
AcquireSync::None | AcquireSync::Implicit => return,
|
||||
AcquireSync::SyncFile { sync_file } => sync_file,
|
||||
};
|
||||
let sync_file = match uapi::fcntl_dupfd_cloexec(sync_file.raw(), 0) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
log::error!("Could not dup sync file: {}", ErrorFmt(e));
|
||||
return;
|
||||
}
|
||||
};
|
||||
if ctx.ctx.dpy.explicit_sync {
|
||||
let sync = match ctx.ctx.create_sync(Some(sync_file)) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
log::error!("Could import sync file: {}", ErrorFmt(e));
|
||||
return;
|
||||
}
|
||||
};
|
||||
sync.wait();
|
||||
} else {
|
||||
if let Some(img) = &texture.gl.img {
|
||||
if let Err(e) = img.dmabuf.import_sync_file(DMA_BUF_SYNC_READ, &sync_file) {
|
||||
log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn GfxTexture {
|
||||
fn as_gl(&self) -> &Texture {
|
||||
self.as_any()
|
||||
|
|
|
|||
|
|
@ -24,9 +24,10 @@ use {
|
|||
PROCS,
|
||||
},
|
||||
ext::{
|
||||
get_display_ext, get_gl_ext, DisplayExt, GlExt, EXT_CREATE_CONTEXT_ROBUSTNESS,
|
||||
EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS, GL_OES_EGL_IMAGE, GL_OES_EGL_IMAGE_EXTERNAL,
|
||||
KHR_IMAGE_BASE, KHR_NO_CONFIG_CONTEXT, KHR_SURFACELESS_CONTEXT,
|
||||
get_display_ext, get_gl_ext, DisplayExt, GlExt, ANDROID_NATIVE_FENCE_SYNC,
|
||||
EXT_CREATE_CONTEXT_ROBUSTNESS, EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS,
|
||||
GL_OES_EGL_IMAGE, GL_OES_EGL_IMAGE_EXTERNAL, KHR_FENCE_SYNC, KHR_IMAGE_BASE,
|
||||
KHR_NO_CONFIG_CONTEXT, KHR_SURFACELESS_CONTEXT, KHR_WAIT_SYNC,
|
||||
MESA_CONFIGLESS_CONTEXT,
|
||||
},
|
||||
proc::ExtProc,
|
||||
|
|
@ -65,6 +66,7 @@ pub struct EglDisplay {
|
|||
pub formats: AHashMap<u32, EglFormat>,
|
||||
pub gbm: Rc<GbmDevice>,
|
||||
pub dpy: EGLDisplay,
|
||||
pub explicit_sync: bool,
|
||||
}
|
||||
|
||||
impl EglDisplay {
|
||||
|
|
@ -99,6 +101,7 @@ impl EglDisplay {
|
|||
formats: AHashMap::new(),
|
||||
gbm: Rc::new(gbm),
|
||||
dpy,
|
||||
explicit_sync: false,
|
||||
};
|
||||
let mut major = 0;
|
||||
let mut minor = 0;
|
||||
|
|
@ -122,6 +125,9 @@ impl EglDisplay {
|
|||
return Err(RenderError::SurfacelessContext);
|
||||
}
|
||||
dpy.formats = query_formats(procs, dpy.dpy)?;
|
||||
dpy.explicit_sync = dpy
|
||||
.exts
|
||||
.contains(KHR_FENCE_SYNC | KHR_WAIT_SYNC | ANDROID_NATIVE_FENCE_SYNC);
|
||||
|
||||
Ok(Rc::new(dpy))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ pub type EGLBoolean = c::c_uint;
|
|||
#[allow(dead_code)]
|
||||
pub type EGLuint64KHR = u64;
|
||||
pub type EGLAttrib = isize;
|
||||
pub type EGLSyncKHR = *mut u8;
|
||||
|
||||
egl_transparent!(EGLDisplay);
|
||||
egl_transparent!(EGLSurface);
|
||||
|
|
@ -83,6 +84,8 @@ pub const EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT: EGLint = 0x3449;
|
|||
pub const EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT: EGLint = 0x344A;
|
||||
pub const EGL_IMAGE_PRESERVED_KHR: EGLint = 0x30D2;
|
||||
pub const EGL_LINUX_DMA_BUF_EXT: EGLint = 0x3270;
|
||||
pub const EGL_SYNC_NATIVE_FENCE_ANDROID: EGLenum = 0x3144;
|
||||
pub const EGL_SYNC_NATIVE_FENCE_FD_ANDROID: EGLint = 0x3145;
|
||||
|
||||
dynload! {
|
||||
EGL: Egl from "libEGL.so" {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ bitflags! {
|
|||
KHR_SURFACELESS_CONTEXT = 1 << 5,
|
||||
IMG_CONTEXT_PRIORITY = 1 << 6,
|
||||
EXT_CREATE_CONTEXT_ROBUSTNESS = 1 << 7,
|
||||
KHR_FENCE_SYNC = 1 << 8,
|
||||
KHR_WAIT_SYNC = 1 << 9,
|
||||
ANDROID_NATIVE_FENCE_SYNC = 1 << 10,
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn get_display_ext(dpy: EGLDisplay) -> DisplayExt {
|
||||
|
|
@ -96,6 +99,9 @@ pub(crate) unsafe fn get_display_ext(dpy: EGLDisplay) -> DisplayExt {
|
|||
"EGL_EXT_create_context_robustness",
|
||||
EXT_CREATE_CONTEXT_ROBUSTNESS,
|
||||
),
|
||||
("EGL_KHR_fence_sync", KHR_FENCE_SYNC),
|
||||
("EGL_KHR_wait_sync", KHR_WAIT_SYNC),
|
||||
("EGL_ANDROID_native_fence_sync", ANDROID_NATIVE_FENCE_SYNC),
|
||||
];
|
||||
match get_dpy_extensions(dpy) {
|
||||
Some(exts) => get_typed_ext(&exts, DisplayExt::none(), &map),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
pub(super) mod context;
|
||||
pub(super) mod framebuffer;
|
||||
pub(super) mod image;
|
||||
pub(super) mod sync;
|
||||
pub(super) mod texture;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use {
|
|||
crate::{
|
||||
format::{Format, XRGB8888},
|
||||
gfx_api::{
|
||||
GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage, GfxTexture,
|
||||
ResetStatus,
|
||||
BufferResvUser, GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage,
|
||||
GfxTexture, ResetStatus,
|
||||
},
|
||||
gfx_apis::gl::{
|
||||
egl::{context::EglContext, display::EglDisplay, image::EglImage},
|
||||
|
|
@ -65,6 +65,8 @@ pub(in crate::gfx_apis::gl) struct GlRenderContext {
|
|||
|
||||
pub(crate) gfx_ops: RefCell<Vec<GfxApiOpt>>,
|
||||
pub(in crate::gfx_apis::gl) gl_state: RefCell<GfxGlState>,
|
||||
|
||||
pub(in crate::gfx_apis::gl) buffer_resv_user: BufferResvUser,
|
||||
}
|
||||
|
||||
impl Debug for GlRenderContext {
|
||||
|
|
@ -141,6 +143,8 @@ impl GlRenderContext {
|
|||
|
||||
gfx_ops: Default::default(),
|
||||
gl_state: Default::default(),
|
||||
|
||||
buffer_resv_user: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use {
|
||||
crate::{
|
||||
format::Format,
|
||||
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer},
|
||||
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, SyncFile},
|
||||
gfx_apis::gl::{
|
||||
gl::{
|
||||
frame_buffer::GlFrameBuffer,
|
||||
|
|
@ -65,7 +65,11 @@ impl Framebuffer {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>) -> Result<(), RenderError> {
|
||||
pub fn render(
|
||||
&self,
|
||||
ops: Vec<GfxApiOpt>,
|
||||
clear: Option<&Color>,
|
||||
) -> Result<Option<SyncFile>, RenderError> {
|
||||
let gles = self.ctx.ctx.dpy.gles;
|
||||
let res = self.ctx.ctx.with_current(|| {
|
||||
unsafe {
|
||||
|
|
@ -77,11 +81,13 @@ impl Framebuffer {
|
|||
}
|
||||
(gles.glBlendFunc)(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
run_ops(self, &ops);
|
||||
unsafe {
|
||||
(gles.glFlush)();
|
||||
let fd = run_ops(self, &ops);
|
||||
if fd.is_none() {
|
||||
unsafe {
|
||||
(gles.glFlush)();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(fd)
|
||||
});
|
||||
*self.ctx.gfx_ops.borrow_mut() = ops;
|
||||
res
|
||||
|
|
@ -103,7 +109,11 @@ impl GfxFramebuffer for Framebuffer {
|
|||
(self.gl.width, self.gl.height)
|
||||
}
|
||||
|
||||
fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>) -> Result<(), GfxError> {
|
||||
fn render(
|
||||
&self,
|
||||
ops: Vec<GfxApiOpt>,
|
||||
clear: Option<&Color>,
|
||||
) -> Result<Option<SyncFile>, GfxError> {
|
||||
self.render(ops, clear).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
|
|
|
|||
107
src/gfx_apis/gl/renderer/sync.rs
Normal file
107
src/gfx_apis/gl/renderer/sync.rs
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
use {
|
||||
crate::{
|
||||
gfx_apis::gl::{
|
||||
egl::context::EglContext,
|
||||
sys::{
|
||||
EGLBoolean, EGLSyncKHR, EGL_NONE, EGL_SYNC_NATIVE_FENCE_ANDROID,
|
||||
EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_TRUE,
|
||||
},
|
||||
RenderError,
|
||||
},
|
||||
utils::errorfmt::ErrorFmt,
|
||||
},
|
||||
std::rc::Rc,
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct EglSync {
|
||||
ctx: Rc<EglContext>,
|
||||
sync: EGLSyncKHR,
|
||||
}
|
||||
|
||||
impl EglContext {
|
||||
pub fn export_sync_file(self: &Rc<Self>) -> Result<OwnedFd, RenderError> {
|
||||
self.create_sync(None)?.export_sync_file()
|
||||
}
|
||||
|
||||
pub fn create_sync(self: &Rc<Self>, file: Option<OwnedFd>) -> Result<EglSync, RenderError> {
|
||||
let mut attribs = [EGL_NONE; 3];
|
||||
if let Some(file) = &file {
|
||||
attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID;
|
||||
attribs[1] = file.raw();
|
||||
}
|
||||
self.with_current(|| unsafe {
|
||||
let sync = self.dpy.procs.eglCreateSyncKHR(
|
||||
self.dpy.dpy,
|
||||
EGL_SYNC_NATIVE_FENCE_ANDROID,
|
||||
attribs.as_ptr(),
|
||||
);
|
||||
if sync.is_null() {
|
||||
Err(RenderError::CreateEglSync)
|
||||
} else {
|
||||
if let Some(file) = file {
|
||||
file.unwrap();
|
||||
}
|
||||
Ok(EglSync {
|
||||
ctx: self.clone(),
|
||||
sync,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl EglSync {
|
||||
pub fn wait(&self) {
|
||||
let res = self.ctx.with_current(|| unsafe {
|
||||
let res = self
|
||||
.ctx
|
||||
.dpy
|
||||
.procs
|
||||
.eglWaitSyncKHR(self.ctx.dpy.dpy, self.sync, 0);
|
||||
if res as EGLBoolean == EGL_TRUE {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(RenderError::WaitSync)
|
||||
}
|
||||
});
|
||||
if let Err(e) = res {
|
||||
log::warn!("Could not insert wait point: {}", ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn export_sync_file(&self) -> Result<OwnedFd, RenderError> {
|
||||
self.ctx.with_current(|| unsafe {
|
||||
let fd = self
|
||||
.ctx
|
||||
.dpy
|
||||
.procs
|
||||
.eglDupNativeFenceFDANDROID(self.ctx.dpy.dpy, self.sync);
|
||||
if fd == -1 {
|
||||
Err(RenderError::ExportSyncFile)
|
||||
} else {
|
||||
Ok(OwnedFd::new(fd))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EglSync {
|
||||
fn drop(&mut self) {
|
||||
let res = self.ctx.with_current(|| unsafe {
|
||||
let res = self
|
||||
.ctx
|
||||
.dpy
|
||||
.procs
|
||||
.eglDestroySyncKHR(self.ctx.dpy.dpy, self.sync);
|
||||
if res == EGL_TRUE {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(RenderError::DestroyEglSync)
|
||||
}
|
||||
});
|
||||
if let Err(e) = res {
|
||||
log::error!("{}", ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
use {
|
||||
crate::{
|
||||
format::Format,
|
||||
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture},
|
||||
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture, SyncFile},
|
||||
gfx_apis::vulkan::{
|
||||
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanMaxExtents,
|
||||
renderer::VulkanRenderer, util::OnDrop, VulkanError,
|
||||
|
|
@ -525,7 +525,11 @@ impl GfxFramebuffer for VulkanImage {
|
|||
(self.width as _, self.height as _)
|
||||
}
|
||||
|
||||
fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>) -> Result<(), GfxError> {
|
||||
fn render(
|
||||
&self,
|
||||
ops: Vec<GfxApiOpt>,
|
||||
clear: Option<&Color>,
|
||||
) -> Result<Option<SyncFile>, GfxError> {
|
||||
self.renderer
|
||||
.execute(self, &ops, clear)
|
||||
.map_err(|e| e.into())
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use {
|
|||
async_engine::SpawnedFuture,
|
||||
format::Format,
|
||||
gfx_api::{
|
||||
BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer, GfxTexture, SyncFile,
|
||||
AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer,
|
||||
GfxTexture, ReleaseSync, SyncFile,
|
||||
},
|
||||
gfx_apis::vulkan::{
|
||||
allocator::VulkanAllocator,
|
||||
|
|
@ -48,6 +49,7 @@ use {
|
|||
rc::Rc,
|
||||
slice,
|
||||
},
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct VulkanRenderer {
|
||||
|
|
@ -70,6 +72,8 @@ pub struct VulkanRenderer {
|
|||
pub(super) struct UsedTexture {
|
||||
tex: Rc<VulkanImage>,
|
||||
resv: Option<Rc<dyn BufferResv>>,
|
||||
acquire_sync: AcquireSync,
|
||||
release_sync: ReleaseSync,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -185,6 +189,8 @@ impl VulkanRenderer {
|
|||
memory.textures.push(UsedTexture {
|
||||
tex,
|
||||
resv: c.buffer_resv.clone(),
|
||||
acquire_sync: c.acquire_sync.clone(),
|
||||
release_sync: c.release_sync,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -538,12 +544,11 @@ impl VulkanRenderer {
|
|||
let import = |infos: &mut Vec<SemaphoreSubmitInfoKHR>,
|
||||
semaphores: &mut Vec<Rc<VulkanSemaphore>>,
|
||||
img: &VulkanImage,
|
||||
sync: &AcquireSync,
|
||||
flag: u32|
|
||||
-> Result<(), VulkanError> {
|
||||
if let VulkanImageMemory::DmaBuf(buf) = &img.ty {
|
||||
for plane in &buf.template.dmabuf.planes {
|
||||
let fd = dma_buf_export_sync_file(&plane.fd, flag)
|
||||
.map_err(VulkanError::IoctlExportSyncFile)?;
|
||||
let mut import_sync_file = |fd: OwnedFd| -> Result<(), VulkanError> {
|
||||
let semaphore = self.allocate_semaphore()?;
|
||||
semaphore.import_sync_file(fd)?;
|
||||
infos.push(
|
||||
|
|
@ -553,6 +558,22 @@ impl VulkanRenderer {
|
|||
.build(),
|
||||
);
|
||||
semaphores.push(semaphore);
|
||||
Ok(())
|
||||
};
|
||||
match sync {
|
||||
AcquireSync::None => {}
|
||||
AcquireSync::Implicit { .. } => {
|
||||
for plane in &buf.template.dmabuf.planes {
|
||||
let fd = dma_buf_export_sync_file(&plane.fd, flag)
|
||||
.map_err(VulkanError::IoctlExportSyncFile)?;
|
||||
import_sync_file(fd)?;
|
||||
}
|
||||
}
|
||||
AcquireSync::SyncFile { sync_file } => {
|
||||
let fd = uapi::fcntl_dupfd_cloexec(sync_file.raw(), 0)
|
||||
.map_err(|e| VulkanError::Dupfd(e.into()))?;
|
||||
import_sync_file(fd)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -562,6 +583,7 @@ impl VulkanRenderer {
|
|||
&mut memory.wait_semaphore_infos,
|
||||
&mut memory.wait_semaphores,
|
||||
&texture.tex,
|
||||
&texture.acquire_sync,
|
||||
DMA_BUF_SYNC_READ,
|
||||
)?;
|
||||
}
|
||||
|
|
@ -569,6 +591,7 @@ impl VulkanRenderer {
|
|||
&mut memory.wait_semaphore_infos,
|
||||
&mut memory.wait_semaphores,
|
||||
fb,
|
||||
&AcquireSync::Implicit,
|
||||
DMA_BUF_SYNC_WRITE,
|
||||
)?;
|
||||
Ok(())
|
||||
|
|
@ -580,20 +603,31 @@ impl VulkanRenderer {
|
|||
Some(sync_file) => sync_file,
|
||||
_ => return,
|
||||
};
|
||||
let import = |img: &VulkanImage, resv: Option<Rc<dyn BufferResv>>, flag: u32| {
|
||||
if let Some(resv) = resv {
|
||||
resv.set_sync_file(self.buffer_resv_user, sync_file);
|
||||
} else if let VulkanImageMemory::DmaBuf(buf) = &img.ty {
|
||||
if let Err(e) = buf.template.dmabuf.import_sync_file(flag, sync_file) {
|
||||
log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e));
|
||||
log::warn!("Relying on implicit sync");
|
||||
let import =
|
||||
|img: &VulkanImage, sync: ReleaseSync, resv: Option<Rc<dyn BufferResv>>, flag: u32| {
|
||||
if sync == ReleaseSync::None {
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
if let Some(resv) = resv {
|
||||
resv.set_sync_file(self.buffer_resv_user, sync_file);
|
||||
} else if sync == ReleaseSync::Implicit {
|
||||
if let VulkanImageMemory::DmaBuf(buf) = &img.ty {
|
||||
if let Err(e) = buf.template.dmabuf.import_sync_file(flag, sync_file) {
|
||||
log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e));
|
||||
log::warn!("Relying on implicit sync");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
for texture in &mut memory.textures {
|
||||
import(&texture.tex, texture.resv.take(), DMA_BUF_SYNC_READ);
|
||||
import(
|
||||
&texture.tex,
|
||||
texture.release_sync,
|
||||
texture.resv.take(),
|
||||
DMA_BUF_SYNC_READ,
|
||||
);
|
||||
}
|
||||
import(fb, None, DMA_BUF_SYNC_WRITE);
|
||||
import(fb, ReleaseSync::Implicit, None, DMA_BUF_SYNC_WRITE);
|
||||
}
|
||||
|
||||
fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
|
||||
|
|
@ -656,7 +690,7 @@ impl VulkanRenderer {
|
|||
});
|
||||
self.pending_frames.set(frame.point, frame.clone());
|
||||
let future = self.device.instance.eng.spawn(await_release(
|
||||
memory.release_sync_file.take(),
|
||||
memory.release_sync_file.clone(),
|
||||
self.device.instance.ring.clone(),
|
||||
frame.clone(),
|
||||
self.clone(),
|
||||
|
|
@ -699,7 +733,13 @@ impl VulkanRenderer {
|
|||
true,
|
||||
)?;
|
||||
(&*tmp_tex as &dyn GfxFramebuffer)
|
||||
.copy_texture(&(tex.clone() as _), x, y)
|
||||
.copy_texture(
|
||||
&(tex.clone() as _),
|
||||
AcquireSync::None,
|
||||
ReleaseSync::None,
|
||||
x,
|
||||
y,
|
||||
)
|
||||
.map_err(VulkanError::GfxError)?;
|
||||
self.read_all_pixels(&tmp_tex, stride, dst)
|
||||
}
|
||||
|
|
@ -839,9 +879,9 @@ impl VulkanRenderer {
|
|||
fb: &VulkanImage,
|
||||
opts: &[GfxApiOpt],
|
||||
clear: Option<&Color>,
|
||||
) -> Result<(), VulkanError> {
|
||||
) -> Result<Option<SyncFile>, VulkanError> {
|
||||
let res = self.try_execute(fb, opts, clear);
|
||||
{
|
||||
let sync_file = {
|
||||
let mut memory = self.memory.borrow_mut();
|
||||
memory.flush.clear();
|
||||
memory.textures.clear();
|
||||
|
|
@ -849,9 +889,9 @@ impl VulkanRenderer {
|
|||
memory.sample.clear();
|
||||
memory.wait_semaphores.clear();
|
||||
memory.release_fence.take();
|
||||
memory.release_sync_file.take();
|
||||
}
|
||||
res
|
||||
memory.release_sync_file.take()
|
||||
};
|
||||
res.map(|_| sync_file)
|
||||
}
|
||||
|
||||
fn allocate_command_buffer(&self) -> Result<Rc<VulkanCommandBuffer>, VulkanError> {
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ impl VulkanSemaphore {
|
|||
.external_semaphore_fd
|
||||
.import_semaphore_fd(&fd_info)
|
||||
};
|
||||
mem::forget(sync_file);
|
||||
res.map_err(VulkanError::ImportSyncFile)?;
|
||||
mem::forget(sync_file);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue