From: Lionel Landwerlin Date: Tue, 2 Oct 2018 16:09:41 +0000 (+0100) Subject: intel/perf: create a unique list of counters X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3f0c4c2afe4aa669e3f8cac668c3fb4dc359f57f;p=mesa.git intel/perf: create a unique list of counters 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 Reviewed-by: Jason Ekstrand Part-of: --- diff --git a/src/intel/perf/gen_perf.c b/src/intel/perf/gen_perf.c index 13ecdfb18d3..36a9e83857f 100644 --- a/src/intel/perf/gen_perf.c +++ b/src/intel/perf/gen_perf.c @@ -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; } diff --git a/src/intel/perf/gen_perf.h b/src/intel/perf/gen_perf.h index 3f933a664fa..83c6c3b9e3a 100644 --- a/src/intel/perf/gen_perf.h +++ b/src/intel/perf/gen_perf.h @@ -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. * diff --git a/src/intel/perf/gen_perf.py b/src/intel/perf/gen_perf.py index a82259c7edb..e1ee1528ef1 100644 --- a/src/intel/perf/gen_perf.py +++ b/src/intel/perf/gen_perf.py @@ -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") diff --git a/src/intel/perf/gen_perf_private.h b/src/intel/perf/gen_perf_private.h index ac222d53727..2e4568fa9aa 100644 --- a/src/intel/perf/gen_perf_private.h +++ b/src/intel/perf/gen_perf_private.h @@ -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;