[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