From 4a3505d5487fbdab773f5c91edd39e8aea6e90af Mon Sep 17 00:00:00 2001 From: Niels Ole Salscheider Date: Fri, 9 Aug 2013 11:59:25 +0200 Subject: [PATCH] st/clover: Profiling support Signed-off-by: Niels Ole Salscheider Acked-by: Francisco Jerez --- .../state_trackers/clover/api/event.cpp | 26 +++- .../state_trackers/clover/core/event.cpp | 116 ++++++++++++++++-- .../state_trackers/clover/core/event.hpp | 18 ++- 3 files changed, 142 insertions(+), 18 deletions(-) diff --git a/src/gallium/state_trackers/clover/api/event.cpp b/src/gallium/state_trackers/clover/api/event.cpp index 39a647b5ee7..ea1576cebd7 100644 --- a/src/gallium/state_trackers/clover/api/event.cpp +++ b/src/gallium/state_trackers/clover/api/event.cpp @@ -217,7 +217,31 @@ clEnqueueWaitForEvents(cl_command_queue q, cl_uint num_evs, 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(ev); + soft_event *sev = dynamic_cast(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(buf, size, size_ret, hev->ts_queued()); + + case CL_PROFILING_COMMAND_SUBMIT: + return scalar_property(buf, size, size_ret, hev->ts_submit()); + + case CL_PROFILING_COMMAND_START: + return scalar_property(buf, size, size_ret, hev->ts_start()); + + case CL_PROFILING_COMMAND_END: + return scalar_property(buf, size, size_ret, hev->ts_end()); + + default: + return CL_INVALID_VALUE; + } } PUBLIC cl_int diff --git a/src/gallium/state_trackers/clover/core/event.cpp b/src/gallium/state_trackers/clover/core/event.cpp index 93d3b5819c9..de21f0c6e53 100644 --- a/src/gallium/state_trackers/clover/core/event.cpp +++ b/src/gallium/state_trackers/clover/core/event.cpp @@ -37,18 +37,6 @@ _cl_event::_cl_event(clover::context &ctx, _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; @@ -77,14 +65,61 @@ _cl_event::chain(clover::event *ev) { hard_event::hard_event(clover::command_queue &q, cl_command_type command, std::vector 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 @@ -126,6 +161,49 @@ hard_event::wait() const { 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; @@ -140,6 +218,18 @@ soft_event::soft_event(clover::context &ctx, 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) diff --git a/src/gallium/state_trackers/clover/core/event.hpp b/src/gallium/state_trackers/clover/core/event.hpp index eb8195383ab..de92de07985 100644 --- a/src/gallium/state_trackers/clover/core/event.hpp +++ b/src/gallium/state_trackers/clover/core/event.hpp @@ -57,7 +57,7 @@ public: action action_ok, action action_fail); virtual ~_cl_event(); - void trigger(); + virtual void trigger() = 0; void abort(cl_int status); bool signalled() const; @@ -72,12 +72,10 @@ protected: void chain(clover::event *ev); cl_int __status; - std::vector> deps; - -private: unsigned wait_count; action action_ok; action action_fail; + std::vector> deps; std::vector> __chain; }; @@ -101,11 +99,19 @@ namespace clover { 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: @@ -114,6 +120,8 @@ namespace clover { 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; }; /// @@ -128,6 +136,8 @@ namespace clover { soft_event(clover::context &ctx, std::vector 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; -- 2.30.2