st/clover: Profiling support

Signed-off-by: Niels Ole Salscheider <niels_ole@salscheider-online.de>
Acked-by: Francisco Jerez <currojerez@riseup.net>
This commit is contained in:
Niels Ole Salscheider 2013-08-09 11:59:25 +02:00 committed by Tom Stellard
parent 4763a032a0
commit 4a3505d548
3 changed files with 142 additions and 18 deletions

View 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

View 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)

View 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;