Before this patch, Beignet can only import external bo by its handle using clCreateBufferFromLibvaIntel/clCreateImageFromLibvaIntel. Render node is the first choice of access gpu in currect Beignet implementation, it causes DRM_IOCTL_GEM_OPEN fail. So it's necessary to add this extension to support buffer sharing between different libraries.
Signed-off-by: Chuanbo Weng <[email protected]> --- include/CL/cl_intel.h | 24 +++++++++++++ src/cl_api.c | 42 +++++++++++++++++++++++ src/cl_driver.h | 6 ++++ src/cl_driver_defs.c | 2 ++ src/cl_mem.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cl_mem.h | 13 +++++++ src/intel/intel_driver.c | 51 ++++++++++++++++++++++++++-- 7 files changed, 223 insertions(+), 3 deletions(-) diff --git a/include/CL/cl_intel.h b/include/CL/cl_intel.h index 28bcb62..50262cb 100644 --- a/include/CL/cl_intel.h +++ b/include/CL/cl_intel.h @@ -133,6 +133,30 @@ typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetMemObjectFdIntel_fn)( cl_mem /* Memory Obejct */, int* /* returned fd */); +/* Create memory object from external buffer object by fd */ +typedef struct _cl_mem_object_desc { + int fd; + cl_mem_object_type type; + int size; + struct { + cl_image_format fmt; + uint32_t offset; + uint32_t width; + uint32_t height; + uint32_t row_pitch; + } image_info; +} cl_mem_object_desc; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateMemObjectFromFdIntel(cl_context /* context */, + const cl_mem_object_desc * /* desc */, + cl_int * /* errcode_ret */); + +typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateMemObjectFromFdIntel_fn)( + cl_context /* context */, + const cl_mem_object_desc * /* desc */, + cl_int * /* errcode_ret */); + #ifdef __cplusplus } #endif diff --git a/src/cl_api.c b/src/cl_api.c index dbbcbb0..b879a12 100644 --- a/src/cl_api.c +++ b/src/cl_api.c @@ -3187,6 +3187,7 @@ internal_clGetExtensionFunctionAddress(const char *func_name) EXTFUNC(clCreateBufferFromLibvaIntel) EXTFUNC(clCreateImageFromLibvaIntel) EXTFUNC(clGetMemObjectFdIntel) + EXTFUNC(clCreateMemObjectFromFdIntel) return NULL; } @@ -3355,3 +3356,44 @@ clGetMemObjectFdIntel(cl_context context, error: return err; } + +cl_mem +clCreateMemObjectFromFdIntel(cl_context context, + const cl_mem_object_desc* desc, + cl_int *errorcode_ret) +{ + cl_mem mem = NULL; + cl_int err = CL_SUCCESS; + CHECK_CONTEXT (context); + + if (!desc) { + err = CL_INVALID_VALUE; + goto error; + } + + //create buffer object + if(desc->type == CL_MEM_OBJECT_BUFFER){ + mem = cl_mem_new_buffer_from_fd(context, desc->fd, desc->size, &err); + } + /* Create image object from fd. + * We just support creating CL_MEM_OBJECT_IMAGE2D image object now. + * Other image type will be supported later if necessary. + */ + else if(desc->type == CL_MEM_OBJECT_IMAGE2D){ + mem = cl_mem_new_image_from_fd(context, + desc->fd, desc->size, + desc->image_info.offset, + desc->image_info.width, desc->image_info.height, + desc->image_info.fmt, desc->image_info.row_pitch, + &err); + } + else{ + err = CL_INVALID_ARG_VALUE; + goto error; + } + +error: + if (errorcode_ret) + *errorcode_ret = err; + return mem; +} diff --git a/src/cl_driver.h b/src/cl_driver.h index 1ab4dff..369c24c 100644 --- a/src/cl_driver.h +++ b/src/cl_driver.h @@ -381,6 +381,12 @@ extern cl_buffer_get_fd_cb *cl_buffer_get_fd; typedef int (cl_buffer_get_tiling_align_cb)(cl_context ctx, uint32_t tiling_mode, uint32_t dim); extern cl_buffer_get_tiling_align_cb *cl_buffer_get_tiling_align; +typedef cl_buffer (cl_buffer_get_buffer_from_fd_cb)(cl_context ctx, int fd, int size); +extern cl_buffer_get_buffer_from_fd_cb *cl_buffer_get_buffer_from_fd; + +typedef cl_buffer (cl_buffer_get_image_from_fd_cb)(cl_context ctx, int fd, int size, struct _cl_mem_image *image); +extern cl_buffer_get_image_from_fd_cb *cl_buffer_get_image_from_fd; + /* Get the device id */ typedef int (cl_driver_get_device_id_cb)(void); extern cl_driver_get_device_id_cb *cl_driver_get_device_id; diff --git a/src/cl_driver_defs.c b/src/cl_driver_defs.c index b77acdc..d25fd5d 100644 --- a/src/cl_driver_defs.c +++ b/src/cl_driver_defs.c @@ -53,6 +53,8 @@ LOCAL cl_buffer_get_buffer_from_libva_cb *cl_buffer_get_buffer_from_libva = NULL LOCAL cl_buffer_get_image_from_libva_cb *cl_buffer_get_image_from_libva = NULL; LOCAL cl_buffer_get_fd_cb *cl_buffer_get_fd = NULL; LOCAL cl_buffer_get_tiling_align_cb *cl_buffer_get_tiling_align = NULL; +LOCAL cl_buffer_get_buffer_from_fd_cb *cl_buffer_get_buffer_from_fd = NULL; +LOCAL cl_buffer_get_image_from_fd_cb *cl_buffer_get_image_from_fd = NULL; /* cl_khr_gl_sharing */ LOCAL cl_gl_acquire_texture_cb *cl_gl_acquire_texture = NULL; diff --git a/src/cl_mem.c b/src/cl_mem.c index b5671bd..420bb78 100644 --- a/src/cl_mem.c +++ b/src/cl_mem.c @@ -2097,3 +2097,91 @@ cl_mem_get_fd(cl_mem mem, err = CL_INVALID_OPERATION; return err; } + +LOCAL cl_mem cl_mem_new_buffer_from_fd(cl_context ctx, + int fd, + int buffer_sz, + cl_int* errcode) +{ + cl_int err = CL_SUCCESS; + cl_mem mem = NULL; + + mem = cl_mem_allocate(CL_MEM_BUFFER_TYPE, ctx, 0, 0, CL_FALSE, NULL, &err); + if (mem == NULL || err != CL_SUCCESS) + goto error; + + mem->bo = cl_buffer_get_buffer_from_fd(ctx, fd, buffer_sz); + if (mem->bo == NULL) { + err = CL_MEM_OBJECT_ALLOCATION_FAILURE; + goto error; + } + mem->size = buffer_sz; + +exit: + if (errcode) + *errcode = err; + return mem; + +error: + cl_mem_delete(mem); + mem = NULL; + goto exit; +} + +LOCAL cl_mem cl_mem_new_image_from_fd(cl_context ctx, + int fd, int image_sz, + size_t offset, + size_t width, size_t height, + cl_image_format fmt, + size_t row_pitch, + cl_int *errcode) +{ + cl_int err = CL_SUCCESS; + cl_mem mem = NULL; + struct _cl_mem_image *image = NULL; + uint32_t intel_fmt, bpp; + + /* Get the size of each pixel */ + if (UNLIKELY((err = cl_image_byte_per_pixel(&fmt, &bpp)) != CL_SUCCESS)) + goto error; + + intel_fmt = cl_image_get_intel_format(&fmt); + if (intel_fmt == INTEL_UNSUPPORTED_FORMAT) { + err = CL_IMAGE_FORMAT_NOT_SUPPORTED; + goto error; + } + + mem = cl_mem_allocate(CL_MEM_IMAGE_TYPE, ctx, 0, 0, 0, NULL, &err); + if (mem == NULL || err != CL_SUCCESS) { + err = CL_OUT_OF_HOST_MEMORY; + goto error; + } + + image = cl_mem_image(mem); + + mem->bo = cl_buffer_get_image_from_fd(ctx, fd, image_sz, image); + + image->w = width; + image->h = height; + image->image_type = CL_MEM_OBJECT_IMAGE2D; + image->depth = 2; + image->fmt = fmt; + image->intel_fmt = intel_fmt; + image->bpp = bpp; + image->row_pitch = row_pitch; + image->slice_pitch = 0; + // NOTE: tiling of image is set in cl_buffer_get_image_from_fd(). + image->tile_x = 0; + image->tile_y = 0; + image->offset = offset; + +exit: + if (errcode) + *errcode = err; + return mem; + +error: + cl_mem_delete(mem); + mem = NULL; + goto exit; +} diff --git a/src/cl_mem.h b/src/cl_mem.h index e027f15..739f107 100644 --- a/src/cl_mem.h +++ b/src/cl_mem.h @@ -293,8 +293,21 @@ extern cl_mem cl_mem_new_libva_image(cl_context ctx, cl_image_format fmt, size_t row_pitch, cl_int *errcode); + extern cl_int cl_mem_get_fd(cl_mem mem, int* fd); +extern cl_mem cl_mem_new_buffer_from_fd(cl_context ctx, + int fd, + int buffer_sz, + cl_int* errcode); + +extern cl_mem cl_mem_new_image_from_fd(cl_context ctx, + int fd, int image_sz, + size_t offset, + size_t width, size_t height, + cl_image_format fmt, + size_t row_pitch, + cl_int *errcode); #endif /* __CL_MEM_H__ */ diff --git a/src/intel/intel_driver.c b/src/intel/intel_driver.c index 507c910..d19f721 100644 --- a/src/intel/intel_driver.c +++ b/src/intel/intel_driver.c @@ -369,7 +369,7 @@ intel_driver_unlock_hardware(intel_driver_t *driver) } LOCAL dri_bo* -intel_driver_share_buffer(intel_driver_t *driver, const char *sname, uint32_t name) +intel_driver_share_buffer_from_name(intel_driver_t *driver, const char *sname, uint32_t name) { dri_bo *bo = intel_bo_gem_create_from_name(driver->bufmgr, sname, @@ -381,6 +381,19 @@ intel_driver_share_buffer(intel_driver_t *driver, const char *sname, uint32_t na return bo; } +LOCAL dri_bo* +intel_driver_share_buffer_from_fd(intel_driver_t *driver, int fd, int size) +{ + dri_bo *bo = drm_intel_bo_gem_create_from_prime(driver->bufmgr, + fd, + size); + if (bo == NULL) { + fprintf(stderr, "drm_intel_bo_gem_create_from_prime create bo(size %d) from fd %d failed: %s\n", fd, size, strerror(errno)); + return NULL; + } + return bo; +} + LOCAL uint32_t intel_driver_shared_name(intel_driver_t *driver, dri_bo *bo) { @@ -695,7 +708,7 @@ cl_buffer intel_share_buffer_from_libva(cl_context ctx, { drm_intel_bo *intel_bo; - intel_bo = intel_driver_share_buffer((intel_driver_t *)ctx->drv, "shared from libva", bo_name); + intel_bo = intel_driver_share_buffer_from_name((intel_driver_t *)ctx->drv, "shared from libva", bo_name); if (intel_bo == NULL) return NULL; @@ -713,7 +726,37 @@ cl_buffer intel_share_image_from_libva(cl_context ctx, drm_intel_bo *intel_bo; uint32_t intel_tiling, intel_swizzle_mode; - intel_bo = intel_driver_share_buffer((intel_driver_t *)ctx->drv, "shared from libva", bo_name); + intel_bo = intel_driver_share_buffer_from_name((intel_driver_t *)ctx->drv, "shared from libva", bo_name); + + drm_intel_bo_get_tiling(intel_bo, &intel_tiling, &intel_swizzle_mode); + image->tiling = get_cl_tiling(intel_tiling); + + return (cl_buffer)intel_bo; +} + +cl_buffer intel_share_buffer_from_fd(cl_context ctx, + int fd, + int buffer_size) +{ + drm_intel_bo *intel_bo; + + intel_bo = intel_driver_share_buffer_from_fd((intel_driver_t *)ctx->drv, fd, buffer_size); + + if (intel_bo == NULL) + return NULL; + + return (cl_buffer)intel_bo; +} + +cl_buffer intel_share_image_from_fd(cl_context ctx, + int fd, + int image_size, + struct _cl_mem_image *image) +{ + drm_intel_bo *intel_bo; + uint32_t intel_tiling, intel_swizzle_mode; + + intel_bo = intel_driver_share_buffer_from_fd((intel_driver_t *)ctx->drv, fd, image_size); drm_intel_bo_get_tiling(intel_bo, &intel_tiling, &intel_swizzle_mode); image->tiling = get_cl_tiling(intel_tiling); @@ -870,5 +913,7 @@ intel_setup_callbacks(void) cl_buffer_wait_rendering = (cl_buffer_wait_rendering_cb *) drm_intel_bo_wait_rendering; cl_buffer_get_fd = (cl_buffer_get_fd_cb *) drm_intel_bo_gem_export_to_prime; cl_buffer_get_tiling_align = (cl_buffer_get_tiling_align_cb *)intel_buffer_get_tiling_align; + cl_buffer_get_buffer_from_fd = (cl_buffer_get_buffer_from_fd_cb *) intel_share_buffer_from_fd; + cl_buffer_get_image_from_fd = (cl_buffer_get_image_from_fd_cb *) intel_share_image_from_fd; intel_set_gpgpu_callbacks(intel_get_device_id()); } -- 1.9.1 _______________________________________________ Beignet mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/beignet
