diff options
author | Denis Steckelmacher <steckdenis@yahoo.fr> | 2011-07-27 14:20:09 +0200 |
---|---|---|
committer | Denis Steckelmacher <steckdenis@yahoo.fr> | 2011-07-27 14:20:09 +0200 |
commit | 0567a9ba7a08c76d4b6c81803aa2485ac52666de (patch) | |
tree | 00b7d16978c704d3b1d53d3721c1b6fc42848967 | |
parent | a1f3d501a7a0d73fc7594d5f0c3381744ed867a8 (diff) |
Implement clEnqueueCopyBuffer
-rw-r--r-- | src/api/api_enqueue.cpp | 21 | ||||
-rw-r--r-- | src/core/cpu/worker.cpp | 12 | ||||
-rw-r--r-- | src/core/events.cpp | 90 | ||||
-rw-r--r-- | src/core/events.h | 26 | ||||
-rw-r--r-- | tests/test_commandqueue.cpp | 73 |
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; } |