PUBLIC cl_int
clGetEventProfilingInfo(cl_event ev, cl_profiling_info param,
size_t size, void *buf, size_t *size_ret) {
- return CL_PROFILING_INFO_NOT_AVAILABLE;
+ hard_event *hev = dynamic_cast<hard_event *>(ev);
+ soft_event *sev = dynamic_cast<soft_event *>(ev);
+
+ if (!hev && !sev)
+ return CL_INVALID_EVENT;
+ if (!hev || !(hev->queue()->props() & CL_QUEUE_PROFILING_ENABLE) ||
+ hev->status() != CL_COMPLETE)
+ return CL_PROFILING_INFO_NOT_AVAILABLE;
+
+ switch (param) {
+ case CL_PROFILING_COMMAND_QUEUED:
+ return scalar_property<cl_ulong>(buf, size, size_ret, hev->ts_queued());
+
+ case CL_PROFILING_COMMAND_SUBMIT:
+ return scalar_property<cl_ulong>(buf, size, size_ret, hev->ts_submit());
+
+ case CL_PROFILING_COMMAND_START:
+ return scalar_property<cl_ulong>(buf, size, size_ret, hev->ts_start());
+
+ case CL_PROFILING_COMMAND_END:
+ return scalar_property<cl_ulong>(buf, size, size_ret, hev->ts_end());
+
+ default:
+ return CL_INVALID_VALUE;
+ }
}
PUBLIC cl_int
_cl_event::~_cl_event() {
}
-void
-_cl_event::trigger() {
- if (!--wait_count) {
- action_ok(*this);
-
- while (!__chain.empty()) {
- __chain.back()->trigger();
- __chain.pop_back();
- }
- }
-}
-
void
_cl_event::abort(cl_int status) {
__status = status;
hard_event::hard_event(clover::command_queue &q, cl_command_type command,
std::vector<clover::event *> deps, action action) :
_cl_event(q.ctx, deps, action, [](event &ev){}),
- __queue(q), __command(command), __fence(NULL) {
+ __queue(q), __command(command), __fence(NULL),
+ __query_start(NULL), __query_end(NULL) {
q.sequence(this);
+
+ if(q.props() & CL_QUEUE_PROFILING_ENABLE) {
+ pipe_screen *screen = q.dev.pipe;
+ __ts_queued = screen->get_timestamp(screen);
+ }
+
trigger();
}
hard_event::~hard_event() {
pipe_screen *screen = queue()->dev.pipe;
+ pipe_context *pipe = queue()->pipe;
screen->fence_reference(screen, &__fence, NULL);
+
+ if(__query_start) {
+ pipe->destroy_query(pipe, __query_start);
+ __query_start = 0;
+ }
+
+ if(__query_end) {
+ pipe->destroy_query(pipe, __query_end);
+ __query_end = 0;
+ }
+}
+
+void
+hard_event::trigger() {
+ if (!--wait_count) {
+ /* XXX: Currently, a timestamp query gives wrong results for memory
+ * transfers. This is, because we use memcpy instead of the DMA engines. */
+
+ if(queue()->props() & CL_QUEUE_PROFILING_ENABLE) {
+ pipe_context *pipe = queue()->pipe;
+ __query_start = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP);
+ pipe->end_query(queue()->pipe, __query_start);
+ }
+
+ action_ok(*this);
+
+ if(queue()->props() & CL_QUEUE_PROFILING_ENABLE) {
+ pipe_context *pipe = queue()->pipe;
+ pipe_screen *screen = queue()->dev.pipe;
+ __query_end = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP);
+ pipe->end_query(pipe, __query_end);
+ __ts_submit = screen->get_timestamp(screen);
+ }
+
+ while (!__chain.empty()) {
+ __chain.back()->trigger();
+ __chain.pop_back();
+ }
+ }
}
cl_int
throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
}
+cl_ulong
+hard_event::ts_queued() const {
+ return __ts_queued;
+}
+
+cl_ulong
+hard_event::ts_submit() const {
+ return __ts_submit;
+}
+
+cl_ulong
+hard_event::ts_start() {
+ get_query_results();
+ return __ts_start;
+}
+
+cl_ulong
+hard_event::ts_end() {
+ get_query_results();
+ return __ts_end;
+}
+
+void
+hard_event::get_query_results() {
+ pipe_context *pipe = queue()->pipe;
+
+ if(__query_start) {
+ pipe_query_result result;
+ pipe->get_query_result(pipe, __query_start, true, &result);
+ __ts_start = result.u64;
+ pipe->destroy_query(pipe, __query_start);
+ __query_start = 0;
+ }
+
+ if(__query_end) {
+ pipe_query_result result;
+ pipe->get_query_result(pipe, __query_end, true, &result);
+ __ts_end = result.u64;
+ pipe->destroy_query(pipe, __query_end);
+ __query_end = 0;
+ }
+}
+
void
hard_event::fence(pipe_fence_handle *fence) {
pipe_screen *screen = queue()->dev.pipe;
trigger();
}
+void
+soft_event::trigger() {
+ if (!--wait_count) {
+ action_ok(*this);
+
+ while (!__chain.empty()) {
+ __chain.back()->trigger();
+ __chain.pop_back();
+ }
+ }
+}
+
cl_int
soft_event::status() const {
if (__status < 0)
action action_ok, action action_fail);
virtual ~_cl_event();
- void trigger();
+ virtual void trigger() = 0;
void abort(cl_int status);
bool signalled() const;
void chain(clover::event *ev);
cl_int __status;
- std::vector<clover::ref_ptr<clover::event>> deps;
-
-private:
unsigned wait_count;
action action_ok;
action action_fail;
+ std::vector<clover::ref_ptr<clover::event>> deps;
std::vector<clover::ref_ptr<clover::event>> __chain;
};
action action = [](event &){});
~hard_event();
+ virtual void trigger();
+
virtual cl_int status() const;
virtual cl_command_queue queue() const;
virtual cl_command_type command() const;
virtual void wait() const;
+ cl_ulong ts_queued() const;
+ cl_ulong ts_submit() const;
+ cl_ulong ts_start();
+ cl_ulong ts_end();
+ void get_query_results();
+
friend class ::_cl_command_queue;
private:
clover::command_queue &__queue;
cl_command_type __command;
pipe_fence_handle *__fence;
+ cl_ulong __ts_queued, __ts_submit, __ts_start, __ts_end;
+ struct pipe_query *__query_start, *__query_end;
};
///
soft_event(clover::context &ctx, std::vector<clover::event *> deps,
bool trigger, action action = [](event &){});
+ virtual void trigger();
+
virtual cl_int status() const;
virtual cl_command_queue queue() const;
virtual cl_command_type command() const;