summaryrefslogtreecommitdiff
path: root/retrace/daemon/glframe_metrics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'retrace/daemon/glframe_metrics.cpp')
-rw-r--r--retrace/daemon/glframe_metrics.cpp496
1 files changed, 4 insertions, 492 deletions
diff --git a/retrace/daemon/glframe_metrics.cpp b/retrace/daemon/glframe_metrics.cpp
index 3e3b57e8..ddbae751 100644
--- a/retrace/daemon/glframe_metrics.cpp
+++ b/retrace/daemon/glframe_metrics.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) Intel Corp. 2015. All Rights Reserved.
+// Copyright (C) Intel Corp. 2017. All Rights Reserved.
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -25,498 +25,10 @@
// * Mark Janes <mark.a.janes@intel.com>
// **********************************************************************/
-#include "glframe_metrics.hpp"
+#include "glframe_metrics_intel.hpp"
-#include <GL/gl.h>
-#include <GL/glext.h>
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "glframe_glhelper.hpp"
-#include "glframe_logger.hpp"
-#include "glretrace.hpp"
-
-using glretrace::ExperimentId;
-using glretrace::GlFunctions;
-using glretrace::MetricId;
-using glretrace::NoAssign;
-using glretrace::NoCopy;
-using glretrace::OnFrameRetrace;
using glretrace::PerfMetrics;
-using glretrace::PerfMetricsContext;
-using glretrace::RenderId;
-using glretrace::SelectionId;
-using glretrace::GL;
-using glretrace::glretrace_delay;
-using glretrace::ID_PREFIX_MASK;
-
-namespace {
-
-struct MetricDescription {
- MetricId id;
- std::string name;
- std::string description;
- MetricDescription() {}
- MetricDescription(MetricId i,
- const std::string &n,
- const std::string &d)
- : id(i), name(n), description(d) {}
-};
-
-class PerfMetric : public NoCopy, NoAssign {
- public:
- PerfMetric(int query_id, int counter_num);
- MetricId id() const;
- const std::string &name() const;
- const std::string &description() const;
- float getMetric(const std::vector<unsigned char> &data) const;
- private:
- const int m_query_id, m_counter_num;
- GLuint m_offset, m_data_size, m_type,
- m_data_type;
- std::string m_name, m_description;
-};
-
-
-class PerfMetricGroup : public NoCopy, NoAssign {
- public:
- explicit PerfMetricGroup(int query_id);
- ~PerfMetricGroup();
- const std::string &name() const { return m_query_name; }
- void metrics(std::vector<MetricDescription> *m) const;
- void begin(RenderId render);
- void end(RenderId render);
- void publish(MetricId metric, PerfMetrics::MetricMap *m);
-
- private:
- std::string m_query_name;
- const int m_query_id;
- unsigned int m_data_size;
- std::vector<unsigned char> m_data_buf;
-
- std::map<MetricId, PerfMetric *> m_metrics;
-
- // represent queries that have not produced results
- std::map<RenderId, int> m_extant_query_handles;
-
- // represent query handles that can be reused
- std::vector<unsigned int> m_free_query_handles;
-};
-
-} // namespace
-
-namespace glretrace {
-
-class PerfMetricsContext : public NoCopy, NoAssign {
- public:
- explicit PerfMetricsContext(OnFrameRetrace *cb);
- ~PerfMetricsContext();
- int groupCount() const;
- void selectMetric(MetricId metric);
- void selectGroup(int index);
- void begin(RenderId render);
- void end();
- void publish(PerfMetrics::MetricMap *metrics);
- private:
- std::vector<PerfMetricGroup *> groups;
- // indicates offset in groups of PerfMetricGroup reporting MetricId
- std::map<MetricId, int> metric_map;
- // indicates the group that will handle subsequent begin/end calls
- PerfMetricGroup *current_group;
- MetricId current_metric;
- RenderId current_render;
-};
-
-} // namespace glretrace
-
-PerfMetricsContext::PerfMetricsContext(OnFrameRetrace *cb)
- : current_group(NULL) {
- GLuint query_id;
- GLint count;
- bool has_metrics = false;
- GlFunctions::GetIntegerv(GL_NUM_EXTENSIONS, &count);
- for (int i = 0; i < count; ++i) {
- const GLubyte *name = GlFunctions::GetStringi(GL_EXTENSIONS, i);
- if (strcmp((const char*)name, "GL_INTEL_performance_query") == 0)
- has_metrics = true;
- }
- if (!has_metrics)
- return;
-
- GlFunctions::GetFirstPerfQueryIdINTEL(&query_id);
- if (query_id == GLuint(-1))
- return;
-
- if (query_id == 0)
- return;
- std::vector<unsigned int> query_ids;
- query_ids.push_back(query_id);
-
- while (true) {
- GlFunctions::GetNextPerfQueryIdINTEL(query_id, &query_id);
- if (!query_id)
- break;
- query_ids.push_back(query_id);
- }
-
- std::map<std::string, MetricDescription> known_metrics;
-
- std::vector<MetricDescription> metrics;
- int group_index = 0;
- for (auto i : query_ids) {
- PerfMetricGroup *g = new PerfMetricGroup(i);
- if (g->name() == "Compute Metrics Extended Gen9") {
- // SKL metrics bug. Queries on this group crash.
- delete g;
- continue;
- }
-
- groups.push_back(g);
- metrics.clear();
- g->metrics(&metrics);
- for (auto &d : metrics) {
- if (known_metrics.find(d.name) == known_metrics.end()) {
- known_metrics[d.name] = d;
- metric_map[d.id] = group_index;
- }
- }
- ++group_index;
- }
- std::vector<MetricId> ids;
- std::vector<std::string> names;
- std::vector<std::string> descriptions;
- for (auto &i : known_metrics) {
- names.push_back(i.second.name);
- ids.push_back(i.second.id);
- descriptions.push_back(i.second.description);
- }
- if (cb)
- // only send metrics list on first context
- cb->onMetricList(ids, names, descriptions);
-}
-
-PerfMetricsContext::~PerfMetricsContext() {
- for (auto g : groups)
- delete g;
- groups.clear();
-}
-
-PerfMetricGroup::PerfMetricGroup(int query_id) : m_query_id(query_id) {
- static GLint max_name_len = 0;
- if (max_name_len == 0)
- GlFunctions::GetIntegerv(GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL,
- &max_name_len);
-
- std::vector<GLchar> query_name(max_name_len);
- unsigned int number_instances, capabilities_mask, number_counters;
- GlFunctions::GetPerfQueryInfoINTEL(m_query_id,
- query_name.size(), query_name.data(),
- &m_data_size, &number_counters,
- &number_instances, &capabilities_mask);
- m_data_buf.resize(m_data_size);
- m_query_name = query_name.data();
- for (unsigned int counter_num = 1; counter_num <= number_counters;
- ++counter_num) {
- PerfMetric *p = new PerfMetric(m_query_id, counter_num);
- m_metrics[p->id()] = p;
- }
-}
-
-PerfMetricGroup::~PerfMetricGroup() {
- for (auto free_query : m_free_query_handles) {
- GlFunctions::DeletePerfQueryINTEL(free_query);
- }
- m_free_query_handles.clear();
- assert(m_extant_query_handles.empty());
- for (auto m : m_metrics)
- delete m.second;
- m_metrics.clear();
-}
-
-void
-PerfMetricGroup::metrics(std::vector<MetricDescription> *m) const {
- for (auto &i : m_metrics) {
- m->push_back(MetricDescription(i.first,
- i.second->name(),
- i.second->description()));
- }
-}
-
-void
-PerfMetricGroup::begin(RenderId render) {
- if (m_free_query_handles.empty()) {
- GLuint query_handle;
- GlFunctions::CreatePerfQueryINTEL(m_query_id, &query_handle);
- m_free_query_handles.push_back(query_handle);
- }
- GLuint query_handle = m_free_query_handles.back();
- m_free_query_handles.pop_back();
-
- // When more than one process requests metrics concurrently,
- // BeginPerfQueryINTEL fails.
- int retry = 0;
- GL::GetError();
- while (true) {
- GlFunctions::BeginPerfQueryINTEL(query_handle);
- if (GL_NO_ERROR == GL::GetError())
- break;
- if (++retry > 20) {
- GRLOG(glretrace::ERR, "failed to begin metrics query, aborting");
- assert(false);
- exit(-1);
- }
- GRLOG(glretrace::WARN, "failed to begin metrics query");
- glretrace_delay(200);
- }
- m_extant_query_handles[render] = query_handle;
-}
-
-static const MetricId ALL_METRICS_IN_GROUP = MetricId(~ID_PREFIX_MASK);
-
-void
-PerfMetricGroup::publish(MetricId metric,
- PerfMetrics::MetricMap *out_metrics) {
- const bool publish_all = (metric == ALL_METRICS_IN_GROUP);
- for (auto extant_query : m_extant_query_handles) {
- memset(m_data_buf.data(), 0, m_data_buf.size());
- GLuint bytes_written;
- GlFunctions::GetPerfQueryDataINTEL(extant_query.second,
- GL_PERFQUERY_WAIT_INTEL,
- m_data_size, m_data_buf.data(),
- &bytes_written);
- assert(bytes_written == m_data_size);
-
- if (publish_all) {
- for (auto desired_metric : m_metrics) {
- MetricId met_id = desired_metric.first;
- (*out_metrics)[met_id][extant_query.first] =
- desired_metric.second->getMetric(m_data_buf);
- }
- } else {
- (*out_metrics)[metric][extant_query.first] =
- m_metrics[metric]->getMetric(m_data_buf);
- }
- m_free_query_handles.push_back(extant_query.second);
- }
- m_extant_query_handles.clear();
- for (auto free_query : m_free_query_handles) {
- GlFunctions::DeletePerfQueryINTEL(free_query);
- }
- m_free_query_handles.clear();
-}
-
-void
-PerfMetricGroup::end(RenderId render) {
- if (m_extant_query_handles.find(render) != m_extant_query_handles.end())
- GlFunctions::EndPerfQueryINTEL(m_extant_query_handles[render]);
-}
-
-
-PerfMetric::PerfMetric(int query_id,
- int counter_num) : m_query_id(query_id),
- m_counter_num(counter_num) {
- static GLint max_name_len = 0, max_desc_len = 0;
- if (max_name_len == 0)
- GlFunctions::GetIntegerv(GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL,
- &max_name_len);
- if (max_desc_len == 0)
- GlFunctions::GetIntegerv(GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL,
- &max_desc_len);
- std::vector<GLchar> counter_name(max_name_len);
- std::vector<GLchar> counter_description(max_desc_len);
- GLuint64 max_value;
- GlFunctions::GetPerfCounterInfoINTEL(m_query_id, m_counter_num,
- counter_name.size(), counter_name.data(),
- counter_description.size(),
- counter_description.data(),
- &m_offset, &m_data_size, &m_type,
- &m_data_type, &max_value);
- m_name = counter_name.data();
- m_description = counter_description.data();
-}
-
-MetricId
-PerfMetric::id() const {
- return MetricId(m_query_id, m_counter_num);
-}
-
-const std::string &
-PerfMetric::name() const {
- return m_name;
-}
-
-const std::string &
-PerfMetric::description() const {
- return m_description;
-}
-
-float
-PerfMetric::getMetric(const std::vector<unsigned char> &data) const {
- const unsigned char *p_value = data.data() + m_offset;
- float fval;
- switch (m_data_type) {
- case GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL: {
- assert(m_data_size == 4);
- const uint32_t val = *reinterpret_cast<const uint32_t *>(p_value);
- fval = static_cast<float>(val);
- break;
- }
- case GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL: {
- assert(m_data_size == 8);
- const uint64_t val = *reinterpret_cast<const uint64_t *>(p_value);
- fval = static_cast<float>(val);
- break;
- }
- case GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL: {
- assert(m_data_size == 4);
- fval = *reinterpret_cast<const float *>(p_value);
- break;
- }
- case GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL: {
- assert(m_data_size == 8);
- const double val = *reinterpret_cast<const double *>(p_value);
- fval = static_cast<float>(val);
- break;
- }
- case GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL: {
- assert(m_data_size == 4);
- const bool val = *reinterpret_cast<const bool*>(p_value);
- fval = val ? 1.0 : 0.0;
- break;
- }
- default:
- assert(false);
- }
- return fval;
-}
-
-void
-PerfMetricsContext::selectMetric(MetricId metric) {
- assert(metric_map.find(metric) != metric_map.end());
- current_metric = metric;
- current_group = groups[metric_map[metric]];
-}
-
-void
-PerfMetricsContext::publish(PerfMetrics::MetricMap *metrics) {
- current_group->publish(current_metric, metrics);
-}
-
-void
-PerfMetricsContext::begin(RenderId render) {
- current_group->begin(render);
- current_render = render;
-}
-
-void
-PerfMetricsContext::end() {
- current_group->end(current_render);
-}
-
-int
-PerfMetricsContext::groupCount() const {
- return groups.size();
-}
-
-void
-PerfMetricsContext::selectGroup(int index) {
- current_group = groups[index];
- current_metric = ALL_METRICS_IN_GROUP;
-}
-
-PerfMetrics::PerfMetrics(OnFrameRetrace *cb)
- : m_current_group(0) {
- Context *c = getCurrentContext();
- m_current_context = new PerfMetricsContext(cb);
- m_contexts[c] = m_current_context;
-}
-
-PerfMetrics::~PerfMetrics() {
- for (auto i : m_contexts) {
- delete i.second;
- }
- m_contexts.clear();
-}
-
-int
-PerfMetrics::groupCount() const {
- assert(!m_contexts.empty());
- return m_contexts.begin()->second->groupCount();
-}
-
-void
-PerfMetrics::selectMetric(MetricId metric) {
- m_data.clear();
- m_current_metric = metric;
- for (auto i : m_contexts)
- i.second->selectMetric(metric);
-}
-
-void
-PerfMetrics::selectGroup(int index) {
- m_current_group = index;
- m_current_metric = ALL_METRICS_IN_GROUP;
- for (auto i : m_contexts)
- i.second->selectGroup(index);
-}
-
-void
-PerfMetrics::begin(RenderId render) {
- if (!m_current_context) {
- beginContext();
- }
- m_current_context->begin(render);
-}
-
-void
-PerfMetrics::end() {
- if (m_current_context)
- m_current_context->end();
-}
-
-void
-PerfMetrics::publish(ExperimentId experimentCount,
- SelectionId selectionCount,
- OnFrameRetrace *callback) {
- for (auto i : m_contexts)
- i.second->publish(&m_data);
-
- for (auto i : m_data) {
- MetricSeries s;
- s.metric = i.first;
- s.data.resize(i.second.rbegin()->first.index() + 1);
- for (auto datapoint : i.second)
- s.data[datapoint.first.index()] = datapoint.second;
- callback->onMetrics(s, experimentCount, selectionCount);
- }
- m_data.clear();
-}
-
-void
-PerfMetrics::beginContext() {
- Context *c = getCurrentContext();
- auto entry = m_contexts.find(c);
- if (entry != m_contexts.end()) {
- m_current_context = entry->second;
- } else {
- // create a new metrics context
- GRLOG(glretrace::WARN, "new context in frame");
- m_current_context = new PerfMetricsContext(NULL);
- m_contexts[c] = m_current_context;
- }
- m_current_context->selectGroup(m_current_group);
- if (m_current_metric() &&
- (m_current_metric != ALL_METRICS_IN_GROUP))
- m_current_context->selectMetric(m_current_metric);
-}
-void
-PerfMetrics::endContext() {
- if (m_current_context) {
- m_current_context->end();
- m_current_context->publish(&m_data);
- }
- m_current_context = NULL;
+PerfMetrics *PerfMetrics::Create(OnFrameRetrace *callback) {
+ return new PerfMetricsIntel(callback);
}