[Beignet] [PATCH 2/2] runtime: fix image1d buffer allocation.
Zhigang Gong
zhigang.gong at intel.com
Fri Jun 20 00:47:04 PDT 2014
Per bspec, a image should has a at least 2 line vertical alignment,
thus we can't simply attach a buffer to a 1d image surface which has the same size.
We have to create a new image, and copy the buffer data to this new image.
And replace all the buffer object's reference to this image.
Signed-off-by: Zhigang Gong <zhigang.gong at intel.com>
---
src/cl_mem.c | 73 ++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 54 insertions(+), 19 deletions(-)
diff --git a/src/cl_mem.c b/src/cl_mem.c
index a1d3b25..b27e64a 100644
--- a/src/cl_mem.c
+++ b/src/cl_mem.c
@@ -480,6 +480,23 @@ error:
goto exit;
}
+void cl_mem_replace_buffer(cl_mem buffer, cl_buffer new_bo)
+{
+ cl_buffer_unreference(buffer->bo);
+ buffer->bo = new_bo;
+ cl_buffer_reference(new_bo);
+ if (buffer->type != CL_MEM_SUBBUFFER_TYPE)
+ return;
+
+ struct _cl_mem_buffer *it = ((struct _cl_mem_buffer*)buffer)->sub_next;
+ for( ; it != (struct _cl_mem_buffer*)buffer; it = it->sub_next)
+ {
+ cl_buffer_unreference(it->base.bo);
+ it->base.bo = new_bo;
+ cl_buffer_reference(new_bo);
+ }
+}
+
void
cl_mem_copy_image_region(const size_t *origin, const size_t *region,
void *dst, size_t dst_row_pitch, size_t dst_slice_pitch,
@@ -598,10 +615,12 @@ _cl_mem_new_image(cl_context ctx,
if (UNLIKELY(w == 0)) DO_IMAGE_ERROR;
if (UNLIKELY(h == 0 && (image_type != CL_MEM_OBJECT_IMAGE1D &&
- image_type != CL_MEM_OBJECT_IMAGE1D_ARRAY)))
+ image_type != CL_MEM_OBJECT_IMAGE1D_ARRAY &&
+ image_type != CL_MEM_OBJECT_IMAGE1D_BUFFER)))
DO_IMAGE_ERROR;
- if (image_type == CL_MEM_OBJECT_IMAGE1D) {
+ if (image_type == CL_MEM_OBJECT_IMAGE1D ||
+ image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER) {
size_t min_pitch = bpp * w;
if (data && pitch == 0)
pitch = min_pitch;
@@ -809,27 +828,43 @@ _cl_mem_new_image_from_buffer(cl_context ctx,
merged_flags &= ~(CL_MEM_HOST_WRITE_ONLY|CL_MEM_HOST_READ_ONLY|CL_MEM_HOST_NO_ACCESS);
merged_flags |= flags & (CL_MEM_HOST_WRITE_ONLY|CL_MEM_HOST_READ_ONLY|CL_MEM_HOST_NO_ACCESS);
}
-
- /* Because the buffer is NO_TILING, the image should be no tiling. */
- image = cl_mem_allocate(CL_MEM_IMAGE_TYPE, ctx, flags, merged_flags, CL_FALSE, &err);
- if (image == NULL || err != CL_SUCCESS)
- goto error;
-
- cl_buffer_reference(buffer->bo);
- image->bo = buffer->bo;
- image->size = buffer->size;
- /* If it is a sub buffer, we need to start from the sub offset. */
+ struct _cl_mem_buffer *mem_buffer = (struct _cl_mem_buffer*)buffer;
if (buffer->type == CL_MEM_SUBBUFFER_TYPE) {
offset = ((struct _cl_mem_buffer *)buffer)->sub_offset;
+ mem_buffer = mem_buffer->parent;
}
- if (image->flags & CL_MEM_USE_HOST_PTR) {
- /* Now point to the right offset if buffer is a SUB_BUFFER. */
- image->host_ptr = buffer->host_ptr + offset;
- }
+ /* Get the size of each pixel */
+ if (UNLIKELY((err = cl_image_byte_per_pixel(image_format, &bpp)) != CL_SUCCESS))
+ goto error;
- cl_mem_image_init(cl_mem_image(image), image_desc->image_width, 1, image_desc->image_type,
- 1, *image_format, intel_fmt, bpp, image_desc->image_width*bpp, 0, CL_NO_TILE,
- 0, 0, offset);
+ // Per bspec, a image should has a at least 2 line vertical alignment,
+ // thus we can't simply attach a buffer to a 1d image surface which has the same size.
+ // We have to create a new image, and copy the buffer data to this new image.
+ // And replace all the buffer object's reference to this image.
+ image = _cl_mem_new_image(ctx, flags, image_format, image_desc->image_type,
+ mem_buffer->base.size / bpp, 0, 0, 0, 0, NULL, errcode_ret);
+ if (image == NULL)
+ return NULL;
+ void *src = cl_mem_map(buffer);
+ void *dst = cl_mem_map(image);
+ //
+ // FIXME, we could use copy buffer to image to do this on GPU latter.
+ // currently the copy buffer to image function doesn't support 1D image.
+ memcpy(dst, src, mem_buffer->base.size);
+ cl_mem_unmap(buffer);
+ cl_mem_unmap(image);
+
+ if (err != 0)
+ goto error;
+
+ // Now replace buffer's bo to this new bo, need to take care of sub buffer
+ // case.
+ cl_mem_replace_buffer(buffer, image->bo);
+ /* Now point to the right offset if buffer is a SUB_BUFFER. */
+ if (buffer->flags & CL_MEM_USE_HOST_PTR)
+ image->host_ptr = buffer->host_ptr + offset;
+ cl_mem_image(image)->offset = offset;
+ cl_mem_image(image)->w = image_desc->image_width;
cl_mem_add_ref(buffer);
cl_mem_image(image)->buffer_1d = buffer;
return image;
--
1.8.3.2
More information about the Beignet
mailing list