intel/perf: create a unique list of counters
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Tue, 2 Oct 2018 16:09:41 +0000 (17:09 +0100)
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>
Wed, 20 May 2020 11:02:27 +0000 (14:02 +0300)
For a future extension we want to be able to list the counters. Our
existing sets counters might contain the same counters multiple times.
This is a side effect of the fixed OA counters in the HW. We track
thoses with a mask so that we know when a counter is available from
multiple metrics.

v2: Use BITFIELD64_BIT() (Jason)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2775>

src/intel/perf/gen_perf.c
src/intel/perf/gen_perf.h
src/intel/perf/gen_perf.py
src/intel/perf/gen_perf_private.h

index 13ecdfb18d3371d50b54606567d8e5b00cf70321..36a9e83857f57e0cdaefe682da2cbfc4cc6fcede 100644 (file)
@@ -572,9 +572,64 @@ i915_get_sseu(int drm_fd, struct drm_i915_gem_context_param_sseu *sseu)
    gen_ioctl(drm_fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &arg);
 }
 
+static int
+compare_counters(const void *_c1, const void *_c2)
+{
+   const struct gen_perf_query_counter * const *c1 = _c1, * const *c2 = _c2;
+   return strcmp((*c1)->symbol_name, (*c2)->symbol_name);
+}
+
+static void
+build_unique_counter_list(struct gen_perf_config *perf)
+{
+   assert(perf->n_queries < 64);
+
+   struct hash_table *counters_table =
+      _mesa_hash_table_create(perf,
+                              _mesa_hash_string,
+                              _mesa_key_string_equal);
+   struct hash_entry *entry;
+   for (int q = 0; q < perf->n_queries ; q++) {
+      struct gen_perf_query_info *query = &perf->queries[q];
+
+      for (int c = 0; c < query->n_counters; c++) {
+         struct gen_perf_query_counter *counter, *unique_counter;
+
+         counter = &query->counters[c];
+         entry = _mesa_hash_table_search(counters_table, counter->symbol_name);
+
+         if (entry) {
+            unique_counter = entry->data;
+            unique_counter->query_mask |= BITFIELD64_BIT(q);
+            continue;
+         }
+
+         unique_counter = counter;
+         unique_counter->query_mask = BITFIELD64_BIT(q);
+
+         _mesa_hash_table_insert(counters_table, unique_counter->symbol_name, unique_counter);
+      }
+   }
+
+   perf->n_counters = _mesa_hash_table_num_entries(counters_table);
+   perf->counters = ralloc_array(perf, struct gen_perf_query_counter *,
+                                 perf->n_counters);
+
+   int c = 0;
+   hash_table_foreach(counters_table, entry) {
+      struct gen_perf_query_counter *counter = entry->data;
+      perf->counters[c++] = counter;
+   }
+
+   _mesa_hash_table_destroy(counters_table, NULL);
+
+   qsort(perf->counters, perf->n_counters, sizeof(perf->counters[0]),
+         compare_counters);
+}
+
 static bool
 load_oa_metrics(struct gen_perf_config *perf, int fd,
-                         const struct gen_device_info *devinfo)
+                const struct gen_device_info *devinfo)
 {
    perf_register_oa_queries_t oa_register = get_register_queries_function(devinfo);
    bool i915_perf_oa_available = false;
@@ -627,6 +682,8 @@ load_oa_metrics(struct gen_perf_config *perf, int fd,
    else
       enumerate_sysfs_metrics(perf, devinfo);
 
+   build_unique_counter_list(perf);
+
    return true;
 }
 
index 3f933a664fad561716e872730070beeb984377cb..83c6c3b9e3a687ab42b1787388ef08ba23c4123e 100644 (file)
@@ -130,10 +130,12 @@ struct gen_perf_query_result {
 struct gen_perf_query_counter {
    const char *name;
    const char *desc;
+   const char *symbol_name;
    enum gen_perf_counter_type type;
    enum gen_perf_counter_data_type data_type;
    uint64_t raw_max;
    size_t offset;
+   uint64_t query_mask;
 
    union {
       uint64_t (*oa_counter_read_uint64)(struct gen_perf_config *perf,
@@ -203,6 +205,9 @@ struct gen_perf_config {
    struct gen_perf_query_info *queries;
    int n_queries;
 
+   struct gen_perf_query_counter **counters;
+   int n_counters;
+
    /* Variables referenced in the XML meta data for OA performance
     * counters, e.g in the normalization equations.
     *
index a82259c7edbcce4db9e3ae59436aa1afe152d9ee..e1ee1528ef1c9ae8fa03905dc06464ebdff68b62 100644 (file)
@@ -378,6 +378,7 @@ def output_counter_report(set, counter, current_offset):
     c("counter->oa_counter_read_" + data_type + " = " + set.read_funcs[counter.get('symbol_name')] + ";\n")
     c("counter->name = \"" + counter.get('name') + "\";\n")
     c("counter->desc = \"" + counter.get('description') + "\";\n")
+    c("counter->symbol_name = \"" + counter.get('symbol_name') + "\";\n")
     c("counter->type = GEN_PERF_COUNTER_TYPE_" + semantic_type_uc + ";\n")
     c("counter->data_type = GEN_PERF_COUNTER_DATA_TYPE_" + data_type_uc + ";\n")
     c("counter->raw_max = " + set.max_values[counter.get('symbol_name')] + ";\n")
index ac222d5372703a99b7dc0f2ed308e78aa1dfa5b4..2e4568fa9aaa89805923124964006c5b6fd0783d 100644 (file)
@@ -41,7 +41,7 @@ gen_perf_query_add_stat_reg(struct gen_perf_query_info *query, uint32_t reg,
    assert(query->n_counters < query->max_counters);
 
    counter = &query->counters[query->n_counters];
-   counter->name = name;
+   counter->name = counter->symbol_name = name;
    counter->desc = description;
    counter->type = GEN_PERF_COUNTER_TYPE_RAW;
    counter->data_type = GEN_PERF_COUNTER_DATA_TYPE_UINT64;