aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGil Pitney <gil.pitney@linaro.org>2015-05-04 22:08:59 +0000
committerGil Pitney <gil.pitney@linaro.org>2015-05-04 22:08:59 +0000
commit7c42a1779cb8902133e028c0e6f414f8e3d4c115 (patch)
tree120d0dfacd6920e263e2abc82e216f71536ce1db
parent28d612801e84bc25187af84bd385989f31833792 (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.cpp51
-rw-r--r--src/core/commandqueue.h1
-rw-r--r--src/core/cpu/worker.cpp16
-rw-r--r--src/core/events.cpp63
-rw-r--r--src/core/events.h28
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.