[Beignet] [PATCH] Improve the clEnqueueMapBuffer and clCreateBuffer API
junyan.he at inbox.com
junyan.he at inbox.com
Wed Jul 10 00:50:44 PDT 2013
From: Junyan He <junyan.he at linux.intel.com>
In clCreateBuffer API, add the CL_MEM_ALLOC_HOST_PTR and
CL_MEM_USE_HOST_PTR flag support.
CL_MEM_ALLOC_HOST_PTR flag seem nothings special to do.
CL_MEM_USE_HOST_PTR flag will request clEnqueueMapBuffer API:
1> The host_ptr specified in clCreateBuffer is guaranteed to
contain the latest bits in the region being mapped when the
clEnqueueMapBuffer command has completed.
2> The pointer value returned by clEnqueueMapBuffer will be
derived from the host_ptr specified when the buffer object is created.
We improve the clEnqueueMapBuffer to setup a map for the mapped
address and do the data sync problem based on the address when
mapped and unmapped.
Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
src/cl_api.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/cl_mem.c | 43 ++++++++++++++++----
src/cl_mem.h | 10 +++++
3 files changed, 169 insertions(+), 9 deletions(-)
diff --git a/src/cl_api.c b/src/cl_api.c
index dc52f0a..115c07a 100644
--- a/src/cl_api.c
+++ b/src/cl_api.c
@@ -1467,7 +1467,9 @@ clEnqueueMapBuffer(cl_command_queue command_queue,
cl_int * errcode_ret)
{
void *ptr = NULL;
+ void *mem_ptr = NULL;
cl_int err = CL_SUCCESS;
+ int slot = -1;
CHECK_QUEUE(command_queue);
CHECK_MEM(buffer);
@@ -1500,10 +1502,66 @@ clEnqueueMapBuffer(cl_command_queue command_queue,
ptr = (char*)ptr + offset;
+ if(buffer->flags & CL_MEM_USE_HOST_PTR) {
+ assert(buffer->host_ptr);
+ memcpy(buffer->host_ptr + offset, ptr, size);
+ mem_ptr = buffer->host_ptr + offset;
+ } else {
+ mem_ptr = ptr;
+ }
+
+ /* Record the mapped address. */
+ if (!buffer->mapped_ptr_sz) {
+ buffer->mapped_ptr_sz = 16;
+ buffer->mapped_ptr = (cl_mapped_ptr *)malloc(
+ sizeof(cl_mapped_ptr) * buffer->mapped_ptr_sz);
+ if (!buffer->mapped_ptr) {
+ cl_mem_unmap_auto (buffer);
+ err = CL_OUT_OF_HOST_MEMORY;
+ ptr = NULL;
+ goto error;
+ }
+
+ memset(buffer->mapped_ptr, 0, buffer->mapped_ptr_sz * sizeof(cl_mapped_ptr));
+ slot = 0;
+ } else {
+ int i = 0;
+ for (; i < buffer->mapped_ptr_sz; i++) {
+ if (buffer->mapped_ptr[i].ptr == NULL) {
+ slot = i;
+ break;
+ }
+ }
+
+ if (i == buffer->mapped_ptr_sz) {
+ cl_mapped_ptr *new_ptr = (cl_mapped_ptr *)malloc(
+ sizeof(cl_mapped_ptr) * buffer->mapped_ptr_sz * 2);
+ if (!new_ptr) {
+ cl_mem_unmap_auto (buffer);
+ err = CL_OUT_OF_HOST_MEMORY;
+ ptr = NULL;
+ goto error;
+ }
+ memset(new_ptr, 0, 2 * buffer->mapped_ptr_sz * sizeof(cl_mapped_ptr));
+ memcpy(new_ptr, buffer->mapped_ptr,
+ buffer->mapped_ptr_sz * sizeof(cl_mapped_ptr));
+ slot = buffer->mapped_ptr_sz;
+ buffer->mapped_ptr_sz *= 2;
+ free(buffer->mapped_ptr);
+ buffer->mapped_ptr = new_ptr;
+ }
+ }
+
+ assert(slot != -1);
+ buffer->mapped_ptr[slot].ptr = mem_ptr;
+ buffer->mapped_ptr[slot].v_ptr = ptr;
+ buffer->mapped_ptr[slot].size = size;
+ buffer->map_ref++;
+
error:
if (errcode_ret)
*errcode_ret = err;
- return ptr;
+ return mem_ptr;
}
void *
@@ -1578,7 +1636,70 @@ clEnqueueUnmapMemObject(cl_command_queue command_queue,
const cl_event * event_wait_list,
cl_event * event)
{
- return cl_mem_unmap_auto(memobj);
+ cl_int err = CL_SUCCESS;
+ int i;
+ size_t mapped_size = 0;
+ void * v_ptr = NULL;
+
+ CHECK_QUEUE(command_queue);
+ CHECK_MEM(memobj);
+ if (command_queue->ctx != memobj->ctx) {
+ err = CL_INVALID_CONTEXT;
+ goto error;
+ }
+
+ assert(memobj->mapped_ptr_sz >= memobj->map_ref);
+ INVALID_VALUE_IF(!mapped_ptr);
+ for (i = 0; i < memobj->mapped_ptr_sz; i++) {
+ if (memobj->mapped_ptr[i].ptr == mapped_ptr) {
+ memobj->mapped_ptr[i].ptr = NULL;
+ mapped_size = memobj->mapped_ptr[i].size;
+ v_ptr = memobj->mapped_ptr[i].v_ptr;
+ memobj->mapped_ptr[i].size = 0;
+ memobj->mapped_ptr[i].v_ptr = NULL;
+ memobj->map_ref--;
+ break;
+ }
+ }
+ /* can not find a mapped address? */
+ INVALID_VALUE_IF(i == memobj->mapped_ptr_sz);
+
+ if (memobj->flags & CL_MEM_USE_HOST_PTR) {
+ assert(mapped_ptr >= memobj->host_ptr &&
+ mapped_ptr + mapped_size <= memobj->host_ptr + memobj->size);
+ /* Sync the data. */
+ memcpy(v_ptr, mapped_ptr, mapped_size);
+ } else {
+ assert(v_ptr == mapped_ptr);
+ }
+
+ cl_mem_unmap_auto(memobj);
+
+ /* shrink the mapped slot. */
+ if (memobj->mapped_ptr_sz/2 > memobj->map_ref) {
+ int j = 0;
+ cl_mapped_ptr *new_ptr = (cl_mapped_ptr *)malloc(
+ sizeof(cl_mapped_ptr) * (memobj->mapped_ptr_sz/2));
+ if (!new_ptr) {
+ /* Just do nothing. */
+ goto error;
+ }
+ memset(new_ptr, 0, (memobj->mapped_ptr_sz/2) * sizeof(cl_mapped_ptr));
+
+ for (i = 0; i < memobj->mapped_ptr_sz; i++) {
+ if (memobj->mapped_ptr[i].ptr) {
+ new_ptr[j] = memobj->mapped_ptr[i];
+ j++;
+ assert(j < memobj->mapped_ptr_sz/2);
+ }
+ }
+ memobj->mapped_ptr_sz = memobj->mapped_ptr_sz/2;
+ free(memobj->mapped_ptr);
+ memobj->mapped_ptr = new_ptr;
+ }
+
+error:
+ return err;
}
cl_int
diff --git a/src/cl_mem.c b/src/cl_mem.c
index 5465aa9..ce70305 100644
--- a/src/cl_mem.c
+++ b/src/cl_mem.c
@@ -106,10 +106,6 @@ cl_mem_allocate(cl_context ctx,
cl_ulong max_mem_size;
assert(ctx);
- FATAL_IF (flags & CL_MEM_ALLOC_HOST_PTR,
- "CL_MEM_ALLOC_HOST_PTR unsupported"); /* XXX */
- FATAL_IF (flags & CL_MEM_USE_HOST_PTR,
- "CL_MEM_USE_HOST_PTR unsupported"); /* XXX */
if ((err = cl_get_device_info(ctx->device,
CL_DEVICE_MAX_MEM_ALLOC_SIZE,
@@ -172,11 +168,35 @@ cl_mem_new(cl_context ctx,
void *data,
cl_int *errcode_ret)
{
+ /* Possible mem type combination:
+ CL_MEM_ALLOC_HOST_PTR
+ CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR
+ CL_MEM_USE_HOST_PTR
+ CL_MEM_COPY_HOST_PTR */
+
cl_int err = CL_SUCCESS;
cl_mem mem = NULL;
- /* Check flags consistency */
- if (UNLIKELY(flags & CL_MEM_COPY_HOST_PTR && data == NULL)) {
+ /* This flag is valid only if host_ptr is not NULL */
+ if (UNLIKELY((flags & CL_MEM_COPY_HOST_PTR ||
+ flags & CL_MEM_USE_HOST_PTR) &&
+ data == NULL)) {
+ err = CL_INVALID_HOST_PTR;
+ goto error;
+ }
+
+ /* CL_MEM_ALLOC_HOST_PTR and CL_MEM_USE_HOST_PTR
+ are mutually exclusive. */
+ if (UNLIKELY(flags & CL_MEM_ALLOC_HOST_PTR &&
+ flags & CL_MEM_USE_HOST_PTR)) {
+ err = CL_INVALID_HOST_PTR;
+ goto error;
+ }
+
+ /* CL_MEM_COPY_HOST_PTR and CL_MEM_USE_HOST_PTR
+ are mutually exclusive. */
+ if (UNLIKELY(flags & CL_MEM_COPY_HOST_PTR &&
+ flags & CL_MEM_USE_HOST_PTR)) {
err = CL_INVALID_HOST_PTR;
goto error;
}
@@ -187,9 +207,12 @@ cl_mem_new(cl_context ctx,
goto error;
/* Copy the data if required */
- if (flags & CL_MEM_COPY_HOST_PTR) /* TODO check other flags too */
+ if (flags & CL_MEM_COPY_HOST_PTR || flags & CL_MEM_USE_HOST_PTR)
cl_buffer_subdata(mem->bo, 0, sz, data);
+ if (flags & CL_MEM_USE_HOST_PTR)
+ mem->host_ptr = data;
+
exit:
if (errcode_ret)
*errcode_ret = err;
@@ -418,6 +441,12 @@ cl_mem_delete(cl_mem mem)
pthread_mutex_unlock(&mem->ctx->buffer_lock);
cl_context_delete(mem->ctx);
+ /* Someone still mapped? */
+ assert(mem->map_ref);
+
+ if (mem->mapped_ptr)
+ free(mem->mapped_ptr);
+
cl_free(mem);
}
diff --git a/src/cl_mem.h b/src/cl_mem.h
index c204992..6d98698 100644
--- a/src/cl_mem.h
+++ b/src/cl_mem.h
@@ -49,6 +49,12 @@ typedef enum cl_image_tiling {
CL_TILE_Y = 2
} cl_image_tiling_t;
+typedef struct _cl_mapped_ptr {
+ void * ptr;
+ void * v_ptr;
+ size_t size;
+}cl_mapped_ptr;
+
/* Used for buffers and images */
struct _cl_mem {
DEFINE_ICD(dispatch)
@@ -68,6 +74,10 @@ struct _cl_mem {
uint32_t intel_fmt; /* format to provide in the surface state */
uint32_t bpp; /* number of bytes per pixel */
cl_image_tiling_t tiling; /* only IVB+ supports TILE_[X,Y] (image only) */
+ void * host_ptr; /* Pointer of the host mem specified by CL_MEM_ALLOC_HOST_PTR */
+ cl_mapped_ptr* mapped_ptr;/* Store the mapped addresses and size by caller. */
+ int mapped_ptr_sz; /* The array size of mapped_ptr. */
+ int map_ref; /* The mapped count. */
};
/* Query information about a memory object */
--
1.7.9.5
More information about the Beignet
mailing list