summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Steckelmacher <steckdenis@yahoo.fr>2011-07-27 14:20:09 +0200
committerDenis Steckelmacher <steckdenis@yahoo.fr>2011-07-27 14:20:09 +0200
commit0567a9ba7a08c76d4b6c81803aa2485ac52666de (patch)
tree00b7d16978c704d3b1d53d3721c1b6fc42848967
parenta1f3d501a7a0d73fc7594d5f0c3381744ed867a8 (diff)
Implement clEnqueueCopyBuffer
-rw-r--r--src/api/api_enqueue.cpp21
-rw-r--r--src/core/cpu/worker.cpp12
-rw-r--r--src/core/events.cpp90
-rw-r--r--src/core/events.h26
-rw-r--r--tests/test_commandqueue.cpp73
5 files changed, 220 insertions, 2 deletions
diff --git a/src/api/api_enqueue.cpp b/src/api/api_enqueue.cpp
index f07bf6b..f6c1c26 100644
--- a/src/api/api_enqueue.cpp
+++ b/src/api/api_enqueue.cpp
@@ -189,7 +189,26 @@ clEnqueueCopyBuffer(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::CopyBufferEvent *command = new Coal::CopyBufferEvent(
+ (Coal::CommandQueue *)command_queue,
+ (Coal::MemObject *)src_buffer,
+ (Coal::MemObject *)dst_buffer,
+ src_offset, dst_offset, cb,
+ 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 74c5caf..576caa3 100644
--- a/src/core/cpu/worker.cpp
+++ b/src/core/cpu/worker.cpp
@@ -76,6 +76,16 @@ void *worker(void *data)
break;
}
+ case Event::CopyBuffer:
+ {
+ CopyBufferEvent *e = (CopyBufferEvent *)event;
+ CPUBuffer *src = (CPUBuffer *)e->source()->deviceBuffer(device);
+ CPUBuffer *dst = (CPUBuffer *)e->destination()->deviceBuffer(device);
+
+ std::memcpy(dst->data(), src->data(), e->cb());
+
+ break;
+ }
case Event::ReadBufferRect:
case Event::WriteBufferRect:
{
@@ -114,6 +124,8 @@ void *worker(void *data)
std::memcpy(b, h, e->region(0));
}
}
+
+ break;
}
case Event::MapBuffer:
// All was already done in CPUBuffer::initEventDeviceData()
diff --git a/src/core/events.cpp b/src/core/events.cpp
index 7dfdac8..024c588 100644
--- a/src/core/events.cpp
+++ b/src/core/events.cpp
@@ -245,6 +245,96 @@ void *UnmapBufferEvent::mapping() const
return p_mapping;
}
+CopyBufferEvent::CopyBufferEvent(CommandQueue *parent,
+ MemObject *source,
+ MemObject *destination,
+ size_t src_offset,
+ size_t dst_offset,
+ size_t cb,
+ cl_uint num_events_in_wait_list,
+ const Event **event_wait_list,
+ cl_int *errcode_ret)
+: BufferEvent(parent, source, num_events_in_wait_list, event_wait_list,
+ errcode_ret), p_destination(destination), p_src_offset(src_offset),
+ p_dst_offset(dst_offset), p_cb(cb)
+{
+ if (!destination)
+ {
+ *errcode_ret = CL_INVALID_MEM_OBJECT;
+ return;
+ }
+
+ // Check for out-of-bounds
+ if (src_offset + cb > source->size() ||
+ dst_offset + cb > destination->size())
+ {
+ *errcode_ret = CL_INVALID_VALUE;
+ return;
+ }
+
+ // Check for overlap
+ if (source == destination)
+ {
+ if ((src_offset < dst_offset && src_offset + cb > dst_offset) ||
+ (dst_offset < src_offset && dst_offset + cb > src_offset))
+ {
+ *errcode_ret = CL_MEM_COPY_OVERLAP;
+ return;
+ }
+ }
+
+ // Check alignement of destination
+ DeviceInterface *device = 0;
+ *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *),
+ &device, 0);
+
+ if (errcode_ret != CL_SUCCESS)
+ return;
+
+ if (!isSubBufferAligned(destination, device))
+ {
+ *errcode_ret = CL_MISALIGNED_SUB_BUFFER_OFFSET;
+ return;
+ }
+
+ // Allocate the buffer for the device
+ if (!destination->allocate(device))
+ {
+ *errcode_ret = CL_MEM_OBJECT_ALLOCATION_FAILURE;
+ return;
+ }
+}
+
+MemObject *CopyBufferEvent::source() const
+{
+ return buffer();
+}
+
+MemObject *CopyBufferEvent::destination() const
+{
+ return p_destination;
+}
+
+size_t CopyBufferEvent::src_offset() const
+{
+ return p_src_offset;
+}
+
+size_t CopyBufferEvent::dst_offset() const
+{
+ return p_dst_offset;
+}
+
+size_t CopyBufferEvent::cb() const
+{
+ return p_cb;
+}
+
+Event::Type CopyBufferEvent::type() const
+{
+ return Event::CopyBuffer;
+}
+
/*
* Native kernel
*/
diff --git a/src/core/events.h b/src/core/events.h
index 6702ff0..c08680c 100644
--- a/src/core/events.h
+++ b/src/core/events.h
@@ -126,6 +126,32 @@ class UnmapBufferEvent : public BufferEvent
void *p_mapping;
};
+class CopyBufferEvent : public BufferEvent
+{
+ public:
+ CopyBufferEvent(CommandQueue *parent,
+ MemObject *source,
+ MemObject *destination,
+ size_t src_offset,
+ size_t dst_offset,
+ size_t cb,
+ cl_uint num_events_in_wait_list,
+ const Event **event_wait_list,
+ cl_int *errcode_ret);
+
+ Type type() const;
+
+ MemObject *source() const;
+ MemObject *destination() const;
+ size_t src_offset() const;
+ size_t dst_offset() const;
+ size_t cb() const;
+
+ private:
+ MemObject *p_destination;
+ size_t p_src_offset, p_dst_offset, p_cb;
+};
+
class ReadWriteBufferRectEvent : public BufferEvent
{
public:
diff --git a/tests/test_commandqueue.cpp b/tests/test_commandqueue.cpp
index b3394e9..cbf7c1f 100644
--- a/tests/test_commandqueue.cpp
+++ b/tests/test_commandqueue.cpp
@@ -417,7 +417,6 @@ START_TEST (test_read_write_rect)
// Write grid into buffer
result = clEnqueueWriteBufferRect(queue, buf, 1, buf_origin, host_origin,
region, 0, 0, 0, 0, grid, 0, 0, 0);
- std::cout << result << std::endl;
fail_if(
result != CL_SUCCESS,
"cannot enqueue a blocking write buffer rect event with pitches guessed"
@@ -453,6 +452,77 @@ START_TEST (test_read_write_rect)
}
END_TEST
+START_TEST (test_copy_buffer)
+{
+ cl_platform_id platform = 0;
+ cl_device_id device;
+ cl_context ctx;
+ cl_command_queue queue;
+ cl_int result;
+ cl_mem src_buf, dst_buf;
+ cl_event event;
+
+ char src[] = "This is the data.";
+ char dst[] = "Overwrite this...";
+
+ result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_DEFAULT, 1, &device, 0);
+ fail_if(
+ result != CL_SUCCESS,
+ "unable to get the default device"
+ );
+
+ ctx = clCreateContext(0, 1, &device, 0, 0, &result);
+ fail_if(
+ result != CL_SUCCESS || ctx == 0,
+ "unable to create a valid context"
+ );
+
+ queue = clCreateCommandQueue(ctx, device, 0, &result);
+ fail_if(
+ result != CL_SUCCESS || queue == 0,
+ "cannot create a command queue"
+ );
+
+ src_buf = clCreateBuffer(ctx, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
+ sizeof(src), src, &result);
+ fail_if(
+ result != CL_SUCCESS,
+ "cannot create the source buffer"
+ );
+
+ dst_buf = clCreateBuffer(ctx, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
+ sizeof(dst), dst, &result);
+ fail_if(
+ result != CL_SUCCESS,
+ "cannot create the destination buffer"
+ );
+
+ result = clEnqueueCopyBuffer(queue, src_buf, dst_buf, 0, 0, sizeof(src),
+ 0, 0, &event);
+ fail_if(
+ result != CL_SUCCESS,
+ "unable to queue a copy buffer event"
+ );
+
+ result = clWaitForEvents(1, &event);
+ fail_if(
+ result != CL_SUCCESS,
+ "unable to wait for the event"
+ );
+
+ fail_if(
+ std::memcmp(src, dst, sizeof(src)) != 0,
+ "the buffer wasn't copied"
+ );
+
+ clReleaseEvent(event);
+ clReleaseMemObject(src_buf);
+ clReleaseMemObject(dst_buf);
+ clReleaseCommandQueue(queue);
+ clReleaseContext(ctx);
+}
+END_TEST
+
TCase *cl_commandqueue_tcase_create(void)
{
TCase *tc = NULL;
@@ -462,5 +532,6 @@ TCase *cl_commandqueue_tcase_create(void)
tcase_add_test(tc, test_object_tree);
tcase_add_test(tc, test_events);
tcase_add_test(tc, test_read_write_rect);
+ tcase_add_test(tc, test_copy_buffer);
return tc;
}