summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Steckelmacher <steckdenis@yahoo.fr>2011-07-30 16:43:15 +0200
committerDenis Steckelmacher <steckdenis@yahoo.fr>2011-07-30 16:43:15 +0200
commitaac90234d34bc2d6cee8461b692a740c56a140da (patch)
tree7892a8a928d4812e35da285322ae5686fe17933b
parente5f4415b7350c1f6ff59c1e0ea4a50528cfd52b2 (diff)
Implement clCopyImage
-rw-r--r--src/api/api_enqueue.cpp20
-rw-r--r--src/core/cpu/worker.cpp3
-rw-r--r--src/core/events.cpp74
-rw-r--r--src/core/events.h18
-rw-r--r--tests/test_commandqueue.cpp33
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);