[Beignet] [Patch V2 3/3] OCL20: add svm enqueue apis and svm's sub buffer support.
Yang Rong
rong.r.yang at intel.com
Mon Nov 9 23:52:14 PST 2015
Signed-off-by: Yang Rong <rong.r.yang at intel.com>
---
src/cl_api.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/cl_context.c | 5 +-
src/cl_context.h | 2 +-
src/cl_enqueue.c | 65 +++++++++++++++++++++++
src/cl_enqueue.h | 9 ++++
src/cl_khr_icd.c | 6 +--
6 files changed, 235 insertions(+), 6 deletions(-)
diff --git a/src/cl_api.c b/src/cl_api.c
index 134870d..c5cb67a 100644
--- a/src/cl_api.c
+++ b/src/cl_api.c
@@ -599,6 +599,63 @@ error:
}
cl_int
+clEnqueueSVMFree (cl_command_queue command_queue,
+ cl_uint num_svm_pointers,
+ void *svm_pointers[],
+ void (CL_CALLBACK *pfn_free_func)( cl_command_queue queue,
+ cl_uint num_svm_pointers,
+ void *svm_pointers[],
+ void *user_data),
+ void *user_data,
+ cl_uint num_events_in_wait_list,
+ const cl_event *event_wait_list,
+ cl_event *event)
+{
+ cl_int err = CL_SUCCESS;
+ cl_int i = 0;
+ void** pointers = NULL;
+ enqueue_data *data, defer_enqueue_data = { 0 };
+ CHECK_QUEUE(command_queue);
+
+ if(num_svm_pointers == 0 || svm_pointers == NULL) {
+ err = CL_INVALID_VALUE;
+ goto error;
+ }
+ for(i=0; i<num_svm_pointers; i++) {
+ if(svm_pointers[i] == NULL) {
+ err = CL_INVALID_VALUE;
+ goto error;
+ }
+ }
+
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
+
+ pointers = malloc(num_svm_pointers * sizeof(void *));
+ if(UNLIKELY(pointers == NULL)) {
+ err = CL_OUT_OF_HOST_MEMORY;
+ goto error;
+ }
+ memcpy(pointers, svm_pointers, num_svm_pointers * sizeof(void *));
+
+ data = &defer_enqueue_data;
+ data->type = EnqueueSVMFree;
+ data->queue = command_queue;
+ data->pointers = pointers;
+ data->free_func = pfn_free_func;
+ data->size = num_svm_pointers;
+ data->ptr = user_data;
+
+ if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
+ event, data, CL_COMMAND_SVM_FREE) == CL_ENQUEUE_EXECUTE_IMM) {
+ err = cl_enqueue_handle(event ? *event : NULL, data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
+ }
+
+error:
+ return err;
+}
+
+cl_int
clEnqueueSVMMap (cl_command_queue command_queue,
cl_bool blocking_map,
cl_map_flags map_flags,
@@ -620,6 +677,8 @@ clEnqueueSVMMap (cl_command_queue command_queue,
clEnqueueMapBuffer(command_queue, buffer, blocking_map, map_flags, 0, size,
num_events_in_wait_list, event_wait_list, event, &err);
+ if(event)
+ (*event)->type = CL_COMMAND_SVM_MAP;
error:
return err;
}
@@ -643,11 +702,106 @@ clEnqueueSVMUnmap (cl_command_queue command_queue,
err = clEnqueueUnmapMemObject(command_queue, buffer, svm_ptr,
num_events_in_wait_list, event_wait_list, event);
+ if(event)
+ (*event)->type = CL_COMMAND_SVM_UNMAP;
+
+error:
+ return err;
+}
+
+cl_int clEnqueueSVMMemcpy (cl_command_queue command_queue,
+ cl_bool blocking_copy,
+ void *dst_ptr,
+ const void *src_ptr,
+ size_t size,
+ cl_uint num_events_in_wait_list,
+ const cl_event *event_wait_list,
+ cl_event *event)
+{
+ cl_int err = CL_SUCCESS;
+ enqueue_data *data, defer_enqueue_data = { 0 };
+
+ if(UNLIKELY(dst_ptr == NULL || src_ptr == NULL || size == 0 )) {
+ err = CL_INVALID_VALUE;
+ goto error;
+ }
+
+ if(((size_t)src_ptr < (size_t)dst_ptr && ((size_t)src_ptr + size > (size_t)dst_ptr)) ||
+ ((size_t)dst_ptr < (size_t)src_ptr && ((size_t)dst_ptr + size > (size_t)src_ptr))) {
+ err = CL_MEM_COPY_OVERLAP;
+ goto error;
+ }
+
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
+
+ data = &defer_enqueue_data;
+ data->type = EnqueueSVMMemCopy;
+ data->queue = command_queue;
+ data->ptr = dst_ptr;
+ data->const_ptr = src_ptr;
+ data->size = size;
+
+ if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
+ event, data, CL_COMMAND_SVM_MEMCPY) == CL_ENQUEUE_EXECUTE_IMM) {
+ err = cl_enqueue_handle(event ? *event : NULL, data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
+ }
error:
return err;
}
+cl_int clEnqueueSVMMemFill (cl_command_queue command_queue,
+ void *svm_ptr,
+ const void *pattern,
+ size_t pattern_size,
+ size_t size,
+ cl_uint num_events_in_wait_list,
+ const cl_event *event_wait_list,
+ cl_event *event)
+{
+ cl_int err = CL_SUCCESS;
+ enqueue_data *data, defer_enqueue_data = { 0 };
+
+ CHECK_QUEUE(command_queue);
+ if(UNLIKELY(svm_ptr == NULL ||
+ ((size_t)svm_ptr & (pattern_size - 1)) != 0)) {
+ err = CL_INVALID_VALUE;
+ goto error;
+ }
+
+ if(UNLIKELY(pattern == NULL ||
+ (pattern_size & (pattern_size - 1)) != 0 ||
+ pattern_size > 128)) {
+ err = CL_INVALID_VALUE;
+ goto error;
+ }
+
+ if(UNLIKELY(size == 0 ||
+ (size % pattern_size) != 0)) {
+ err = CL_INVALID_VALUE;
+ goto error;
+ }
+
+ TRY(cl_event_check_waitlist, num_events_in_wait_list, event_wait_list, event, command_queue->ctx);
+
+ data = &defer_enqueue_data;
+ data->type = EnqueueSVMMemFill;
+ data->queue = command_queue;
+ data->ptr = svm_ptr;
+ data->const_ptr = pattern;
+ data->pattern_size = pattern_size;
+ data->size = size;
+
+ if(handle_events(command_queue, num_events_in_wait_list, event_wait_list,
+ event, data, CL_COMMAND_SVM_MEMFILL) == CL_ENQUEUE_EXECUTE_IMM) {
+ err = cl_enqueue_handle(event ? *event : NULL, data);
+ if(event) cl_event_set_status(*event, CL_COMPLETE);
+ }
+
+error:
+ return err;
+}
cl_mem
clCreateImage2D(cl_context context,
diff --git a/src/cl_context.c b/src/cl_context.c
index 3fcdb63..6bdf272 100644
--- a/src/cl_context.c
+++ b/src/cl_context.c
@@ -330,12 +330,13 @@ unlock:
}
cl_mem
-cl_context_get_svm_from_ptr(cl_context ctx, void * p)
+cl_context_get_svm_from_ptr(cl_context ctx, const void * p)
{
cl_mem buf = ctx->svm_buffers;
while(buf) {
assert(buf->host_ptr && buf->is_svm);
- if(buf->host_ptr == p)
+ if((size_t)buf->host_ptr <= (size_t)p &&
+ (size_t)p < ((size_t)buf->host_ptr + buf->size))
return buf;
buf = buf->next;
}
diff --git a/src/cl_context.h b/src/cl_context.h
index 365ec32..8c462b1 100644
--- a/src/cl_context.h
+++ b/src/cl_context.h
@@ -171,6 +171,6 @@ extern cl_kernel cl_context_get_static_kernel_from_bin(cl_context ctx, cl_int in
const char * str_kernel, size_t size, const char * str_option);
/* Get the SVM from pointer, return NULL if pointer is not from SVM */
-extern cl_mem cl_context_get_svm_from_ptr(cl_context ctx, void *p);
+extern cl_mem cl_context_get_svm_from_ptr(cl_context ctx, const void *p);
#endif /* __CL_CONTEXT_H__ */
diff --git a/src/cl_enqueue.c b/src/cl_enqueue.c
index 371b2d4..4fea6f9 100644
--- a/src/cl_enqueue.c
+++ b/src/cl_enqueue.c
@@ -443,6 +443,65 @@ error:
return err;
}
+cl_int cl_enqueue_svm_free(enqueue_data *data) {
+ int i;
+ void **pointers = data->pointers;
+ uint num_svm_ptrs = data->size;
+
+ if(data->free_func) {
+ data->free_func(data->queue, num_svm_ptrs, pointers, data->ptr);
+ } else {
+ for(i=0; i<num_svm_ptrs; i++)
+ cl_mem_svm_delete(data->queue->ctx, pointers[i]);
+ }
+
+ free(pointers);
+ return CL_SUCCESS;
+}
+
+cl_int cl_enqueue_svm_mem_copy(enqueue_data *data) {
+ cl_mem mem;
+ size_t size = data->size;
+ const char* src_ptr = (const char *)data->const_ptr;
+ char *dst_ptr = (char *)data->ptr;
+ int i;
+
+ if((mem = cl_context_get_svm_from_ptr(data->queue->ctx, data->ptr)) != NULL) {
+ dst_ptr = (char *)cl_mem_map_auto(mem, 1);
+ }
+
+ if((mem = cl_context_get_svm_from_ptr(data->queue->ctx, data->const_ptr)) != NULL) {
+ src_ptr = (const char *)cl_mem_map_auto(mem, 0);
+ }
+
+ for(i=0; i<size; i++) {
+ dst_ptr[i] = src_ptr[i];
+ }
+
+ return CL_SUCCESS;
+}
+
+cl_int cl_enqueue_svm_mem_fill(enqueue_data *data) {
+ cl_mem mem;
+ size_t size = data->size;
+ size_t pattern_size = data->pattern_size;
+ const char* pattern = (const char *)data->const_ptr;
+ char *ptr = (char *)data->ptr;
+ int i, j;
+
+ if((mem = cl_context_get_svm_from_ptr(data->queue->ctx, data->ptr)) != NULL) {
+ ptr = (char *)cl_mem_map_auto(mem, 1);
+ }
+
+ for(i=0; i<size; ) {
+ for(j=0; j<pattern_size; j++) {
+ ptr[i++] = pattern[j];
+ }
+ }
+
+ return CL_SUCCESS;
+}
+
cl_int cl_enqueue_handle(cl_event event, enqueue_data* data)
{
/* if need profiling, add the submit timestamp here. */
@@ -481,6 +540,12 @@ cl_int cl_enqueue_handle(cl_event event, enqueue_data* data)
return cl_event_flush(event);
case EnqueueNativeKernel:
return cl_enqueue_native_kernel(data);
+ case EnqueueSVMFree:
+ return cl_enqueue_svm_free(data);
+ case EnqueueSVMMemCopy:
+ return cl_enqueue_svm_mem_copy(data);
+ case EnqueueSVMMemFill:
+ return cl_enqueue_svm_mem_fill(data);
case EnqueueMigrateMemObj:
default:
return CL_SUCCESS;
diff --git a/src/cl_enqueue.h b/src/cl_enqueue.h
index 09305af..faa85d2 100644
--- a/src/cl_enqueue.h
+++ b/src/cl_enqueue.h
@@ -45,6 +45,9 @@ typedef enum {
EnqueueFillBuffer,
EnqueueFillImage,
EnqueueMigrateMemObj,
+ EnqueueSVMFree,
+ EnqueueSVMMemCopy,
+ EnqueueSVMMemFill,
EnqueueInvalid
} enqueue_type;
@@ -66,7 +69,13 @@ typedef struct _enqueue_data {
const cl_mem* mem_list; /* mem_list of clEnqueueNativeKernel */
uint8_t unsync_map; /* Indicate the clEnqueueMapBuffer/Image is unsync map */
uint8_t write_map; /* Indicate if the clEnqueueMapBuffer is write enable */
+ void ** pointers; /* The svm_pointers of clEnqueueSVMFree */
+ size_t pattern_size; /* the pattern_size of clEnqueueSVMMemFill */
void (*user_func)(void *); /* pointer to a host-callable user function */
+ void (CL_CALLBACK *free_func)( cl_command_queue queue,
+ cl_uint num_svm_pointers,
+ void *svm_pointers[],
+ void *user_data); /* pointer to pfn_free_func of clEnqueueSVMFree */
} enqueue_data;
/* Do real enqueue commands */
diff --git a/src/cl_khr_icd.c b/src/cl_khr_icd.c
index 0894d61..73d1924 100644
--- a/src/cl_khr_icd.c
+++ b/src/cl_khr_icd.c
@@ -177,9 +177,9 @@ struct _cl_icd_dispatch const cl_khr_icd_dispatch = {
(void *) NULL /* clGetPipeInfo */,
clSVMAlloc,
clSVMFree,
- (void *) NULL /* clEnqueueSVMFree */,
- (void *) NULL /* clEnqueueSVMMemcpy */,
- (void *) NULL /* clEnqueueSVMMemFill */,
+ (void *) clEnqueueSVMFree,
+ (void *) clEnqueueSVMMemcpy,
+ (void *) clEnqueueSVMMemFill,
(void *) clEnqueueSVMMap,
(void *) clEnqueueSVMUnmap,
(void *) NULL /* clCreateSamplerWithProperties */,
--
2.1.4
More information about the Beignet
mailing list