diff --git a/src/virtio/vulkan/vn_renderer.h b/src/virtio/vulkan/vn_renderer.h index 3bd1f421324..08f34df0454 100644 --- a/src/virtio/vulkan/vn_renderer.h +++ b/src/virtio/vulkan/vn_renderer.h @@ -165,6 +165,9 @@ struct vn_renderer_bo_ops { int (*export_dma_buf)(struct vn_renderer *renderer, struct vn_renderer_bo *bo); + int (*export_sync_file)(struct vn_renderer *renderer, + struct vn_renderer_bo *bo); + /* map is not thread-safe */ void *(*map)(struct vn_renderer *renderer, struct vn_renderer_bo *bo, @@ -375,6 +378,13 @@ vn_renderer_bo_export_dma_buf(struct vn_renderer *renderer, return renderer->bo_ops.export_dma_buf(renderer, bo); } +static inline int +vn_renderer_bo_export_sync_file(struct vn_renderer *renderer, + struct vn_renderer_bo *bo) +{ + return renderer->bo_ops.export_sync_file(renderer, bo); +} + static inline void * vn_renderer_bo_map(struct vn_renderer *renderer, struct vn_renderer_bo *bo, diff --git a/src/virtio/vulkan/vn_renderer_internal.c b/src/virtio/vulkan/vn_renderer_internal.c index 331978a953f..5e29b190cf8 100644 --- a/src/virtio/vulkan/vn_renderer_internal.c +++ b/src/virtio/vulkan/vn_renderer_internal.c @@ -5,6 +5,12 @@ #include "vn_renderer_internal.h" +#ifdef HAVE_LIBDRM +#include + +#include "drm-uapi/dma-buf.h" +#endif + /* 3 seconds */ #define VN_RENDERER_SHMEM_CACHE_EXPIRACY (3ll * 1000 * 1000) @@ -180,3 +186,40 @@ vn_renderer_shmem_cache_get(struct vn_renderer_shmem_cache *cache, return shmem; } + +int +vn_renderer_bo_export_sync_file_internal(struct vn_renderer *renderer, + struct vn_renderer_bo *bo) +{ +#ifdef HAVE_LIBDRM + /* Don't keep trying an IOCTL that doesn't exist. */ + static bool no_dma_buf_sync_file = false; + if (no_dma_buf_sync_file) + return -1; + + /* For simplicity, export dma-buf here and rely on the dma-buf sync file + * export api. On legacy kernels without the new uapi, for virtgpu backend, + * we do have the fallback option of doing DRM_IOCTL_VIRTGPU_WAIT instead. + */ + int dma_buf_fd = vn_renderer_bo_export_dma_buf(renderer, bo); + if (dma_buf_fd < 0) + return -1; + + struct dma_buf_export_sync_file export = { + .flags = DMA_BUF_SYNC_RW, + .fd = -1, + }; + int ret = drmIoctl(dma_buf_fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &export); + + close(dma_buf_fd); + + if (ret && (errno == ENOTTY || errno == EBADF || errno == ENOSYS)) { + no_dma_buf_sync_file = true; + return -1; + } + + return export.fd; +#else /* HAVE_LIBDRM */ + return -1; +#endif /* HAVE_LIBDRM */ +} diff --git a/src/virtio/vulkan/vn_renderer_internal.h b/src/virtio/vulkan/vn_renderer_internal.h index df17ddb0566..4ccea4d6282 100644 --- a/src/virtio/vulkan/vn_renderer_internal.h +++ b/src/virtio/vulkan/vn_renderer_internal.h @@ -51,4 +51,8 @@ struct vn_renderer_shmem * vn_renderer_shmem_cache_get(struct vn_renderer_shmem_cache *cache, size_t size); +int +vn_renderer_bo_export_sync_file_internal(struct vn_renderer *renderer, + struct vn_renderer_bo *bo); + #endif /* VN_RENDERER_INTERNAL_H */ diff --git a/src/virtio/vulkan/vn_renderer_virtgpu.c b/src/virtio/vulkan/vn_renderer_virtgpu.c index cc50bbb37c5..575ab9cc4fe 100644 --- a/src/virtio/vulkan/vn_renderer_virtgpu.c +++ b/src/virtio/vulkan/vn_renderer_virtgpu.c @@ -1796,6 +1796,8 @@ virtgpu_init(struct virtgpu *gpu) gpu->base.bo_ops.create_from_dma_buf = virtgpu_bo_create_from_dma_buf; gpu->base.bo_ops.destroy = virtgpu_bo_destroy; gpu->base.bo_ops.export_dma_buf = virtgpu_bo_export_dma_buf; + gpu->base.bo_ops.export_sync_file = + vn_renderer_bo_export_sync_file_internal; gpu->base.bo_ops.map = virtgpu_bo_map; gpu->base.bo_ops.flush = virtgpu_bo_flush; gpu->base.bo_ops.invalidate = virtgpu_bo_invalidate; diff --git a/src/virtio/vulkan/vn_renderer_vtest.c b/src/virtio/vulkan/vn_renderer_vtest.c index c734e5ffe05..5fad0b02f84 100644 --- a/src/virtio/vulkan/vn_renderer_vtest.c +++ b/src/virtio/vulkan/vn_renderer_vtest.c @@ -1073,6 +1073,8 @@ vtest_init(struct vtest *vtest) vtest->base.bo_ops.create_from_dma_buf = NULL; vtest->base.bo_ops.destroy = vtest_bo_destroy; vtest->base.bo_ops.export_dma_buf = vtest_bo_export_dma_buf; + vtest->base.bo_ops.export_sync_file = + vn_renderer_bo_export_sync_file_internal; vtest->base.bo_ops.map = vtest_bo_map; vtest->base.bo_ops.flush = vtest_bo_flush; vtest->base.bo_ops.invalidate = vtest_bo_invalidate;