diff options
author | Denis Steckelmacher <steckdenis@yahoo.fr> | 2011-07-30 16:43:15 +0200 |
---|---|---|
committer | Denis Steckelmacher <steckdenis@yahoo.fr> | 2011-07-30 16:43:15 +0200 |
commit | aac90234d34bc2d6cee8461b692a740c56a140da (patch) | |
tree | 7892a8a928d4812e35da285322ae5686fe17933b | |
parent | e5f4415b7350c1f6ff59c1e0ea4a50528cfd52b2 (diff) |
Implement clCopyImage
-rw-r--r-- | src/api/api_enqueue.cpp | 20 | ||||
-rw-r--r-- | src/core/cpu/worker.cpp | 3 | ||||
-rw-r--r-- | src/core/events.cpp | 74 | ||||
-rw-r--r-- | src/core/events.h | 18 | ||||
-rw-r--r-- | tests/test_commandqueue.cpp | 33 |
5 files changed, 143 insertions, 5 deletions
diff --git a/src/api/api_enqueue.cpp b/src/api/api_enqueue.cpp index d2ce092..1c28ee0 100644 --- a/src/api/api_enqueue.cpp +++ b/src/api/api_enqueue.cpp @@ -333,7 +333,25 @@ clEnqueueCopyImage(cl_command_queue command_queue, const cl_event * event_wait_list, cl_event * event) { - return 0; + cl_int rs = CL_SUCCESS; + + if (!command_queue) + return CL_INVALID_COMMAND_QUEUE; + + Coal::CopyImageEvent *command = new Coal::CopyImageEvent( + (Coal::CommandQueue *)command_queue, + (Coal::Image2D *)src_image, (Coal::Image2D *)dst_image, + src_origin, dst_origin, region, + num_events_in_wait_list, (const Coal::Event **)event_wait_list, &rs + ); + + if (rs != CL_SUCCESS) + { + delete command; + return rs; + } + + return queueEvent(command_queue, command, event, false); } cl_int diff --git a/src/core/cpu/worker.cpp b/src/core/cpu/worker.cpp index d7606d1..2c055e6 100644 --- a/src/core/cpu/worker.cpp +++ b/src/core/cpu/worker.cpp @@ -91,6 +91,7 @@ void *worker(void *data) case Event::CopyBufferRect: case Event::ReadImage: case Event::WriteImage: + case Event::CopyImage: { // src = buffer and dst = mem if note copy ReadWriteCopyBufferRectEvent *e = (ReadWriteCopyBufferRectEvent *)event; @@ -99,7 +100,7 @@ void *worker(void *data) unsigned char *src = (unsigned char *)src_buf->data(); unsigned char *dst; - if (t == Event::CopyBufferRect) + if (t == Event::CopyBufferRect || t == Event::CopyImage) { CopyBufferRectEvent *cbre = (CopyBufferRectEvent *)e; CPUBuffer *dst_buf = diff --git a/src/core/events.cpp b/src/core/events.cpp index b6923d7..c1ac530 100644 --- a/src/core/events.cpp +++ b/src/core/events.cpp @@ -934,6 +934,26 @@ CopyBufferRectEvent::CopyBufferRectEvent(CommandQueue *parent, return; } + // Check for overlapping + if (source == destination) + { + unsigned char overlapping_dimensions = 0; + + for (unsigned int i=0; i<3; ++i) + { + if (dst_origin[i] < src_origin[i] && dst_origin[i] + region[i] > src_origin[i] || + src_origin[i] < dst_origin[i] && src_origin[i] + region[i] > dst_origin[i]) + overlapping_dimensions++; + } + + if (overlapping_dimensions == 3) + { + // If all the dimensions are overlapping, the region is overlapping + *errcode_ret = CL_MEM_COPY_OVERLAP; + return; + } + } + // Check alignment of destination (source already checked by BufferEvent) DeviceInterface *device = 0; *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *), @@ -997,7 +1017,6 @@ ReadWriteBufferRectEvent::ReadWriteBufferRectEvent(CommandQueue *parent, (buffer_origin[1] + region[1]) * src_row_pitch() > src_slice_pitch() || (buffer_origin[2] + region[2]) * src_slice_pitch() > buffer->size()) { - std::cout << buffer_origin[0] << '+' << region[0] << '*' << bytes_per_element << '>' << src_row_pitch() << std::endl; *errcode_ret = CL_INVALID_VALUE; return; } @@ -1119,3 +1138,56 @@ Event::Type WriteImageEvent::type() const { return Event::WriteImage; } + +static bool operator!=(const cl_image_format &a, const cl_image_format &b) +{ + return (a.image_channel_data_type != b.image_channel_data_type) || + (a.image_channel_order != b.image_channel_order); +} + +CopyImageEvent::CopyImageEvent(CommandQueue *parent, + Image2D *source, + Image2D *destination, + const size_t src_origin[3], + const size_t dst_origin[3], + const size_t region[3], + cl_uint num_events_in_wait_list, + const Event **event_wait_list, + cl_int *errcode_ret) +: CopyBufferRectEvent (parent, source, destination, src_origin, dst_origin, + region, source->row_pitch(), + (source->type() == MemObject::Image3D ? + ((Image3D *)source)->slice_pitch() : 0), + destination->row_pitch(), + (destination->type() == MemObject::Image3D ? + ((Image3D *)destination)->slice_pitch() : 0), + source->pixel_size(), num_events_in_wait_list, + event_wait_list, errcode_ret) +{ + // Check bounds + if (source->type() == MemObject::Image2D && + (src_origin[2] != 0 || region[2] != 1)) + { + *errcode_ret = CL_INVALID_VALUE; + return; + } + + if (destination->type() == MemObject::Image2D && + (dst_origin[2] != 0 || region[2] != 1)) + { + *errcode_ret = CL_INVALID_VALUE; + return; + } + + // Formats must match + if (source->format() != destination->format()) + { + *errcode_ret = CL_IMAGE_FORMAT_MISMATCH; + return; + } +} + +Event::Type CopyImageEvent::type() const +{ + return Event::CopyImage; +} diff --git a/src/core/events.h b/src/core/events.h index fe2b7b0..4d8cd86 100644 --- a/src/core/events.h +++ b/src/core/events.h @@ -203,7 +203,7 @@ class CopyBufferRectEvent : public ReadWriteCopyBufferRectEvent const Event **event_wait_list, cl_int *errcode_ret); - Type type() const; + virtual Type type() const; MemObject *destination() const; private: @@ -323,6 +323,22 @@ class WriteImageEvent : public ReadWriteImageEvent Type type() const; }; +class CopyImageEvent : public CopyBufferRectEvent +{ + public: + CopyImageEvent(CommandQueue *parent, + Image2D *source, + Image2D *destination, + const size_t src_origin[3], + const size_t dst_origin[3], + const size_t region[3], + cl_uint num_events_in_wait_list, + const Event **event_wait_list, + cl_int *errcode_ret); + + Type type() const; +}; + class NativeKernelEvent : public Event { public: diff --git a/tests/test_commandqueue.cpp b/tests/test_commandqueue.cpp index a97b1de..70dc161 100644 --- a/tests/test_commandqueue.cpp +++ b/tests/test_commandqueue.cpp @@ -560,7 +560,7 @@ START_TEST (test_read_write_image) cl_device_id device; cl_context ctx; cl_command_queue queue; - cl_mem image2d; + cl_mem image2d, part2d; cl_int result; unsigned char image2d_data_24bpp[3*3*4] = { @@ -610,6 +610,13 @@ START_TEST (test_read_write_image) "cannot create a valid 3x3 image2D" ); + part2d = clCreateImage2D(ctx, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, &fmt, + 2, 2, 0, image2d_part, &result); + fail_if( + result != CL_SUCCESS || image2d == 0, + "cannot create a valid 2x2 image2D" + ); + // Write data in buffer result = clEnqueueWriteImage(queue, image2d, 1, origin, region, 0, 0, image2d_data_24bpp, 0, 0, 0); @@ -635,6 +642,30 @@ START_TEST (test_read_write_image) "reading and writing images doesn't produce the correct result" ); + // Read it back using a buffer + cl_event event; + std::memset(image2d_part, 0, sizeof(image2d_part)); + + result = clEnqueueCopyImage(queue, image2d, part2d, origin, origin, + region, 0, 0, &event); + fail_if( + result != CL_SUCCESS, + "unable to enqueue a copy image event" + ); + + result = clWaitForEvents(1, &event); + fail_if( + result != CL_SUCCESS, + "unable to wait for events" + ); + + // Compare + fail_if( + std::memcmp(image2d_part, image2d_part_24bpp, sizeof(image2d_part)) != 0, + "copying images doesn't produce the correct result" + ); + + clReleaseMemObject(part2d); clReleaseMemObject(image2d); clReleaseCommandQueue(queue); clReleaseContext(ctx); |