diff options
author | Gil Pitney <gil.pitney@linaro.org> | 2015-05-04 22:08:59 +0000 |
---|---|---|
committer | Gil Pitney <gil.pitney@linaro.org> | 2015-05-04 22:08:59 +0000 |
commit | 7c42a1779cb8902133e028c0e6f414f8e3d4c115 (patch) | |
tree | 120d0dfacd6920e263e2abc82e216f71536ce1db | |
parent | 28d612801e84bc25187af84bd385989f31833792 (diff) |
Implemented clEnqueueFillBuffer() v1.2 API.
This implementation is quite simple, and avoids creation of special
OpenCL kernels in favor of using a GNU host builtin, which it is expected
would be sufficiently optimized.
A possible optimization worth exploring would be to use OpenMP on the
host to dispatch the pattern filling across the host cores.
Signed-off-by: Gil Pitney <gil.pitney@linaro.org>
-rw-r--r-- | src/api/api_enqueue.cpp | 51 | ||||
-rw-r--r-- | src/core/commandqueue.h | 1 | ||||
-rw-r--r-- | src/core/cpu/worker.cpp | 16 | ||||
-rw-r--r-- | src/core/events.cpp | 63 | ||||
-rw-r--r-- | src/core/events.h | 28 |
5 files changed, 139 insertions, 20 deletions
diff --git a/src/api/api_enqueue.cpp b/src/api/api_enqueue.cpp index 3c51862..4195f43 100644 --- a/src/api/api_enqueue.cpp +++ b/src/api/api_enqueue.cpp @@ -316,6 +316,37 @@ clEnqueueCopyBuffer(cl_command_queue command_queue, } cl_int +clEnqueueFillBuffer(cl_command_queue command_queue, + cl_mem buffer, + const void * pattern, + size_t pattern_size, + size_t offset, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event ) +{ + cl_int rs = CL_SUCCESS; + + if (!command_queue->isA(Coal::Object::T_CommandQueue)) + return CL_INVALID_COMMAND_QUEUE; + + Coal::FillBufferEvent *command = new Coal::FillBufferEvent( + (Coal::CommandQueue *)command_queue, + (Coal::MemObject *)buffer, + pattern, pattern_size, offset, size, + 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 clEnqueueReadImage(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, @@ -866,26 +897,6 @@ clEnqueueBarrierWithWaitList(cl_command_queue command_queue, return queueEvent(command_queue, command, event, false); } - -cl_int -clEnqueueFillBuffer(cl_command_queue command_queue, - cl_mem buffer, - const void * pattern, - size_t pattern_size, - size_t offset, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event * event_wait_list, - cl_event * event) -{ - cl_int rs = CL_SUCCESS; - - if (!command_queue->isA(Coal::Object::T_CommandQueue)) - return CL_INVALID_COMMAND_QUEUE; - - return rs; -} - cl_int clEnqueueMigrateMemObjects(cl_command_queue command_queue, cl_uint num_mem_objects, diff --git a/src/core/commandqueue.h b/src/core/commandqueue.h index 3f22709..dea1544 100644 --- a/src/core/commandqueue.h +++ b/src/core/commandqueue.h @@ -259,6 +259,7 @@ class Event : public Object ReadBufferRect = CL_COMMAND_READ_BUFFER_RECT, WriteBufferRect = CL_COMMAND_WRITE_BUFFER_RECT, CopyBufferRect = CL_COMMAND_COPY_BUFFER_RECT, + FillBuffer = CL_COMMAND_FILL_BUFFER, User = CL_COMMAND_USER, Barrier, WaitForEvents diff --git a/src/core/cpu/worker.cpp b/src/core/cpu/worker.cpp index 64d422b..3abfce3 100644 --- a/src/core/cpu/worker.cpp +++ b/src/core/cpu/worker.cpp @@ -112,6 +112,22 @@ void *worker(void *data) (char*)src->data() + e->src_offset(), e->cb()); break; } + case Event::FillBuffer: + { + FillBufferEvent *e = (FillBufferEvent *)event; + CPUBuffer *buf = (CPUBuffer *)e->buffer()->deviceBuffer(device); + unsigned char *dst = (unsigned char *)buf->data(); + const unsigned char *pattern = (unsigned char *)e->pattern(); + size_t pattern_size = e->pattern_size(); + size_t offset = e->offset(); + size_t size = e->size(); + + dst += offset; + for (int i = 0; i < size; i+= pattern_size, dst+=pattern_size) { + std::memmove((void *)dst, (void*)pattern, pattern_size); + } + break; + } case Event::ReadBufferRect: case Event::WriteBufferRect: case Event::CopyBufferRect: diff --git a/src/core/events.cpp b/src/core/events.cpp index 03aa656..c7a945e 100644 --- a/src/core/events.cpp +++ b/src/core/events.cpp @@ -516,6 +516,69 @@ Event::Type CopyBufferEvent::type() const return Event::CopyBuffer; } +FillBufferEvent::FillBufferEvent(CommandQueue *parent, + MemObject *buffer, + const void * pattern, + size_t pattern_size, + size_t offset, + size_t size, + cl_uint num_events_in_wait_list, + const Event **event_wait_list, + cl_int *errcode_ret) +: BufferEvent(parent, buffer, num_events_in_wait_list, event_wait_list, errcode_ret), + p_pattern(pattern), p_pattern_size(pattern_size), p_offset(offset), p_size(size) +{ + if (*errcode_ret != CL_SUCCESS) return; + + // Ensure pattern can be written within the buffer: + if (offset + size > buffer->size()) + { + *errcode_ret = CL_INVALID_VALUE; + return; + } + + // Ensure pattern is one of {1,2,4,8,16,32,64,128}: + if (!pattern || __builtin_popcount((unsigned int)(pattern_size &0xFFF)) != 1) + { + *errcode_ret = CL_INVALID_VALUE; + return; + } + + // Ensure both offset and size are a multiple of pattern size: + if ((offset % pattern_size) || (size % pattern_size)) + { + *errcode_ret = CL_INVALID_VALUE; + return; + } +} + +const void * FillBufferEvent::pattern() const +{ + return p_pattern; +} + +size_t FillBufferEvent::pattern_size() const +{ + return p_pattern_size; +} + +size_t FillBufferEvent::offset() const +{ + return p_offset; +} + +size_t FillBufferEvent::size() const +{ + return p_size; +} + + +Event::Type FillBufferEvent::type() const +{ + return Event::FillBuffer; +} + + /* * Native kernel */ diff --git a/src/core/events.h b/src/core/events.h index 4d679f3..213d0ba 100644 --- a/src/core/events.h +++ b/src/core/events.h @@ -290,6 +290,34 @@ class CopyBufferEvent : public BufferEvent }; /** + * \brief Fill a buffer with a pattern + */ +class FillBufferEvent : public BufferEvent +{ + public: + FillBufferEvent(CommandQueue *parent, + MemObject *buffer, + const void * pattern, + size_t pattern_size, + size_t offset, + size_t size, + cl_uint num_events_in_wait_list, + const Event **event_wait_list, + cl_int *errcode_ret); + + Type type() const; /*!< \brief Say the event is a \c Coal::Event::FillBuffer one */ + + const void * pattern() const; /*!< \brief Pattern with which to fill buffer */ + size_t pattern_size() const; /*!< \brief Size of pattern, in bytes */ + size_t offset() const; /*!< \brief Location in buffer to start filling */ + size_t size() const; /*!< \brief Size of region in buffer being filled. */ + + private: + const void * p_pattern; + size_t p_pattern_size, p_offset, p_size; +}; + +/** * \brief Events related to rectangular (or cubic) memory regions * * This event is the base for all the *BufferRect events, and the Image ones. |