diff --git a/src/gallium/drivers/iris/iris_batch.c b/src/gallium/drivers/iris/iris_batch.c index b66f990ef6c..d9ddedd7183 100644 --- a/src/gallium/drivers/iris/iris_batch.c +++ b/src/gallium/drivers/iris/iris_batch.c @@ -815,6 +815,36 @@ iris_batch_update_syncobjs(struct iris_batch *batch) } } +/** + * Convert the syncobj which will be signaled when this batch completes + * to a SYNC_FILE object, for use with import/export sync ioctls. + */ +bool +iris_batch_syncobj_to_sync_file_fd(struct iris_batch *batch, int *out_fd) +{ + int drm_fd = batch->screen->fd; + + struct iris_syncobj *batch_syncobj = + iris_batch_get_signal_syncobj(batch); + + struct drm_syncobj_handle syncobj_to_fd_ioctl = { + .handle = batch_syncobj->handle, + .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE, + .fd = -1, + }; + if (intel_ioctl(drm_fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, + &syncobj_to_fd_ioctl)) { + fprintf(stderr, "DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD ioctl failed (%d)\n", + errno); + return false; + } + + assert(syncobj_to_fd_ioctl.fd >= 0); + *out_fd = syncobj_to_fd_ioctl.fd; + + return true; +} + const char * iris_batch_name_to_string(enum iris_batch_name name) { diff --git a/src/gallium/drivers/iris/iris_batch.h b/src/gallium/drivers/iris/iris_batch.h index dcafe53c71d..05cb19e60c7 100644 --- a/src/gallium/drivers/iris/iris_batch.h +++ b/src/gallium/drivers/iris/iris_batch.h @@ -233,6 +233,8 @@ void iris_use_pinned_bo(struct iris_batch *batch, struct iris_bo *bo, enum pipe_reset_status iris_batch_check_for_reset(struct iris_batch *batch); +bool iris_batch_syncobj_to_sync_file_fd(struct iris_batch *batch, int *out_fd); + static inline unsigned iris_batch_bytes_used(struct iris_batch *batch) { diff --git a/src/gallium/drivers/iris/iris_bufmgr.c b/src/gallium/drivers/iris/iris_bufmgr.c index 27a42243aa3..dbe86851171 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.c +++ b/src/gallium/drivers/iris/iris_bufmgr.c @@ -53,6 +53,7 @@ #include "dev/intel_debug.h" #include "common/intel_gem.h" #include "dev/intel_device_info.h" +#include "drm-uapi/dma-buf.h" #include "isl/isl.h" #include "util/os_mman.h" #include "util/u_debug.h" @@ -442,6 +443,68 @@ vma_free(struct iris_bufmgr *bufmgr, util_vma_heap_free(&bufmgr->vma_allocator[memzone], address, size); } +/* Exports a BO's implicit synchronization state to a drm_syncobj, returning + * its wrapping iris_syncobj. The drm_syncobj is created new and has to be + * destroyed by the caller after the execbuf ioctl. + */ +struct iris_syncobj * +iris_bo_export_sync_state(struct iris_bo *bo) +{ + struct iris_bufmgr *bufmgr = bo->bufmgr; + int drm_fd = iris_bufmgr_get_fd(bufmgr); + + struct iris_syncobj *iris_syncobj = iris_create_syncobj(bufmgr); + + struct dma_buf_export_sync_file export_sync_file_ioctl = { + .flags = DMA_BUF_SYNC_RW, /* TODO */ + .fd = -1, + }; + if (intel_ioctl(bo->real.prime_fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, + &export_sync_file_ioctl)) { + fprintf(stderr, "DMA_BUF_IOCTL_EXPORT_SYNC_FILE ioctl failed (%d)\n", + errno); + goto error_export; + } + + int sync_file_fd = export_sync_file_ioctl.fd; + assert(sync_file_fd >= 0); + + struct drm_syncobj_handle syncobj_import_ioctl = { + .handle = iris_syncobj->handle, + .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE, + .fd = sync_file_fd, + }; + if (intel_ioctl(drm_fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, + &syncobj_import_ioctl)) { + fprintf(stderr, "DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE ioctl failed (%d)\n", + errno); + } + + close(sync_file_fd); + + return iris_syncobj; +error_export: + iris_syncobj_destroy(bufmgr, iris_syncobj); + return NULL; +} + +/* Import the state of a sync_file_fd (which we should have gotten from + * batch_syncobj_to_sync_file_fd) into a BO as its implicit synchronization + * state. + */ +void +iris_bo_import_sync_state(struct iris_bo *bo, int sync_file_fd) +{ + struct dma_buf_import_sync_file import_sync_file_ioctl = { + .flags = DMA_BUF_SYNC_WRITE, + .fd = sync_file_fd, + }; + if (intel_ioctl(bo->real.prime_fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, + &import_sync_file_ioctl)) + fprintf(stderr, "DMA_BUF_IOCTL_IMPORT_SYNC_FILE ioctl failed (%d)\n", + errno); +} + /* A timeout of 0 just checks for busyness. */ static int iris_bo_wait_syncobj(struct iris_bo *bo, int64_t timeout_ns) diff --git a/src/gallium/drivers/iris/iris_bufmgr.h b/src/gallium/drivers/iris/iris_bufmgr.h index 3e6de09e9d4..b0db32ecded 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.h +++ b/src/gallium/drivers/iris/iris_bufmgr.h @@ -584,4 +584,7 @@ enum iris_madvice { IRIS_MADVICE_DONT_NEED = 1, }; +void iris_bo_import_sync_state(struct iris_bo *bo, int sync_file_fd); +struct iris_syncobj *iris_bo_export_sync_state(struct iris_bo *bo); + #endif /* IRIS_BUFMGR_H */