st/clover: Profiling support
authorNiels Ole Salscheider <niels_ole@salscheider-online.de>
Fri, 9 Aug 2013 09:59:25 +0000 (11:59 +0200)
committerTom Stellard <thomas.stellard@amd.com>
Tue, 27 Aug 2013 01:25:17 +0000 (18:25 -0700)
Signed-off-by: Niels Ole Salscheider <niels_ole@salscheider-online.de>
Acked-by: Francisco Jerez <currojerez@riseup.net>
src/gallium/state_trackers/clover/api/event.cpp
src/gallium/state_trackers/clover/core/event.cpp
src/gallium/state_trackers/clover/core/event.hpp

index 39a647b5ee78b02cac3f92cfe065927d03a9bbd0..ea1576cebd78d4cf22f5affc3a53df9bd33a8a01 100644 (file)
@@ -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<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
index 93d3b5819c908f081c36651d982e72899ac1f046..de21f0c6e53eb451f1e2bd7039317a4e4523aab6 100644 (file)
@@ -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<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
@@ -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)
index eb8195383abe5621f1c1284b09396245e114c544..de92de079850d0eccd083c463a3886101700b506 100644 (file)
@@ -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<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;
 };
 
@@ -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<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;