mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 09:08:10 +02:00
freedreno/a6xx: Use counter allocation helper
If the kernel supports PERFCNTR_CONFIG for counter reservation, we can expose perfcntrs by default. Signed-off-by: Rob Clark <rob.clark@oss.qualcomm.com>
This commit is contained in:
parent
cb27d2e1b2
commit
c642bc8c27
5 changed files with 35 additions and 32 deletions
|
|
@ -824,6 +824,7 @@ static const struct fd_acc_sample_provider so_overflow_predicate = {
|
|||
struct fd_batch_query_entry {
|
||||
uint8_t gid; /* group-id */
|
||||
uint8_t cid; /* countable-id within the group */
|
||||
const struct fd_perfcntr_counter *counter;
|
||||
};
|
||||
|
||||
struct fd_batch_query_data {
|
||||
|
|
@ -839,33 +840,23 @@ perfcntr_resume(struct fd_acc_query *aq, struct fd_batch *batch) assert_dt
|
|||
struct fd_screen *screen = data->screen;
|
||||
fd_cs cs(batch->draw);
|
||||
|
||||
unsigned counters_per_group[screen->num_perfcntr_groups];
|
||||
memset(counters_per_group, 0, sizeof(counters_per_group));
|
||||
|
||||
fd_pkt7(cs, CP_WAIT_FOR_IDLE, 0);
|
||||
|
||||
/* configure performance counters for the requested queries: */
|
||||
for (unsigned i = 0; i < data->num_query_entries; i++) {
|
||||
struct fd_batch_query_entry *entry = &data->query_entries[i];
|
||||
const struct fd_perfcntr_group *g = &screen->perfcntr_groups[entry->gid];
|
||||
unsigned counter_idx = counters_per_group[entry->gid]++;
|
||||
|
||||
assert(counter_idx < g->num_counters);
|
||||
|
||||
fd_pkt4(cs, 1).add((fd_reg_pair){
|
||||
.reg = g->counters[counter_idx].select_reg,
|
||||
.reg = entry->counter->select_reg,
|
||||
.value = g->countables[entry->cid].selector,
|
||||
});
|
||||
}
|
||||
|
||||
memset(counters_per_group, 0, sizeof(counters_per_group));
|
||||
|
||||
/* and snapshot the start values */
|
||||
for (unsigned i = 0; i < data->num_query_entries; i++) {
|
||||
struct fd_batch_query_entry *entry = &data->query_entries[i];
|
||||
const struct fd_perfcntr_group *g = &screen->perfcntr_groups[entry->gid];
|
||||
unsigned counter_idx = counters_per_group[entry->gid]++;
|
||||
const struct fd_perfcntr_counter *counter = &g->counters[counter_idx];
|
||||
const struct fd_perfcntr_counter *counter = entry->counter;
|
||||
|
||||
fd_pkt7(cs, CP_REG_TO_MEM, 3)
|
||||
.add(CP_REG_TO_MEM_0(.reg = counter->counter_reg_lo, ._64b = true))
|
||||
|
|
@ -877,12 +868,8 @@ static void
|
|||
perfcntr_pause(struct fd_acc_query *aq, struct fd_batch *batch) assert_dt
|
||||
{
|
||||
struct fd_batch_query_data *data = (struct fd_batch_query_data *)aq->query_data;
|
||||
struct fd_screen *screen = data->screen;
|
||||
fd_cs cs(batch->draw);
|
||||
|
||||
unsigned counters_per_group[screen->num_perfcntr_groups];
|
||||
memset(counters_per_group, 0, sizeof(counters_per_group));
|
||||
|
||||
fd_pkt7(cs, CP_WAIT_FOR_IDLE, 0);
|
||||
|
||||
/* TODO do we need to bother to turn anything off? */
|
||||
|
|
@ -890,9 +877,7 @@ perfcntr_pause(struct fd_acc_query *aq, struct fd_batch *batch) assert_dt
|
|||
/* snapshot the end values: */
|
||||
for (unsigned i = 0; i < data->num_query_entries; i++) {
|
||||
struct fd_batch_query_entry *entry = &data->query_entries[i];
|
||||
const struct fd_perfcntr_group *g = &screen->perfcntr_groups[entry->gid];
|
||||
unsigned counter_idx = counters_per_group[entry->gid]++;
|
||||
const struct fd_perfcntr_counter *counter = &g->counters[counter_idx];
|
||||
const struct fd_perfcntr_counter *counter = entry->counter;
|
||||
|
||||
fd_pkt7(cs, CP_REG_TO_MEM, 3)
|
||||
.add(CP_REG_TO_MEM_0(.reg = counter->counter_reg_lo, ._64b = true))
|
||||
|
|
@ -925,12 +910,24 @@ perfcntr_accumulate_result(struct fd_acc_query *aq,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
perfcntr_cleanup(void *query_data)
|
||||
{
|
||||
struct fd_batch_query_data *data = (struct fd_batch_query_data *)query_data;
|
||||
|
||||
for (unsigned i = 0; i < data->num_query_entries; i++) {
|
||||
struct fd_batch_query_entry *entry = &data->query_entries[i];
|
||||
fd_perfcntr_release(data->screen->perfcntrs, entry->counter);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct fd_acc_sample_provider perfcntr = {
|
||||
.query_type = FD_QUERY_FIRST_PERFCNTR,
|
||||
.always = true,
|
||||
.resume = perfcntr_resume,
|
||||
.pause = perfcntr_pause,
|
||||
.result = perfcntr_accumulate_result,
|
||||
.cleanup = perfcntr_cleanup,
|
||||
};
|
||||
|
||||
static struct pipe_query *
|
||||
|
|
@ -949,13 +946,6 @@ fd6_create_batch_query(struct pipe_context *pctx, unsigned num_queries,
|
|||
data->screen = screen;
|
||||
data->num_query_entries = num_queries;
|
||||
|
||||
/* validate the requested query_types and ensure we don't try
|
||||
* to request more query_types of a given group than we have
|
||||
* counters:
|
||||
*/
|
||||
unsigned counters_per_group[screen->num_perfcntr_groups];
|
||||
memset(counters_per_group, 0, sizeof(counters_per_group));
|
||||
|
||||
for (unsigned i = 0; i < num_queries; i++) {
|
||||
unsigned idx = query_types[i] - FD_QUERY_FIRST_PERFCNTR;
|
||||
|
||||
|
|
@ -985,13 +975,15 @@ fd6_create_batch_query(struct pipe_context *pctx, unsigned num_queries,
|
|||
entry->cid++;
|
||||
}
|
||||
|
||||
if (counters_per_group[entry->gid] >=
|
||||
screen->perfcntr_groups[entry->gid].num_counters) {
|
||||
mesa_loge("too many counters for group %u", entry->gid);
|
||||
const struct fd_perfcntr_group *g = &screen->perfcntr_groups[entry->gid];
|
||||
const struct fd_perfcntr_countable *c = &g->countables[entry->cid];
|
||||
|
||||
entry->counter = fd_perfcntr_reserve(screen->perfcntrs, g, c);
|
||||
|
||||
if (!entry->counter) {
|
||||
mesa_loge("Could not reserve counter for %s.%s", g->name, c->name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
counters_per_group[entry->gid]++;
|
||||
}
|
||||
|
||||
q = fd_acc_create_query2(ctx, 0, 0, &perfcntr);
|
||||
|
|
@ -1004,6 +996,7 @@ fd6_create_batch_query(struct pipe_context *pctx, unsigned num_queries,
|
|||
return (struct pipe_query *)q;
|
||||
|
||||
error:
|
||||
perfcntr_cleanup(data);
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ fd_acc_destroy_query(struct fd_context *ctx, struct fd_query *q) assert_dt
|
|||
|
||||
DBG("%p", q);
|
||||
|
||||
if (aq->provider->cleanup)
|
||||
aq->provider->cleanup(aq->query_data);
|
||||
|
||||
pipe_resource_reference(&aq->prsc, NULL);
|
||||
list_del(&aq->node);
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ struct fd_acc_sample_provider {
|
|||
void (*result_resource)(struct fd_acc_query *aq, struct fd_ringbuffer *ring,
|
||||
enum pipe_query_value_type result_type, int index,
|
||||
struct fd_resource *dst, unsigned offset);
|
||||
void (*cleanup)(void *query_data); /* optional cleanup */
|
||||
};
|
||||
|
||||
struct fd_acc_query {
|
||||
|
|
|
|||
|
|
@ -165,6 +165,8 @@ fd_screen_destroy(struct pipe_screen *pscreen)
|
|||
if (screen->ro)
|
||||
screen->ro->destroy(screen->ro);
|
||||
|
||||
fd_perfcntr_state_free(screen->perfcntrs);
|
||||
|
||||
fd_bc_fini(&screen->batch_cache);
|
||||
fd_gmem_screen_fini(pscreen);
|
||||
|
||||
|
|
@ -1057,7 +1059,10 @@ fd_screen_create(int fd,
|
|||
if (screen->primtypes[i])
|
||||
screen->primtypes_mask |= (1 << i);
|
||||
|
||||
if (FD_DBG(PERFC)) {
|
||||
screen->perfcntrs = fd_perfcntr_state_alloc(screen->dev_id, fd);
|
||||
|
||||
if (FD_DBG(PERFC) ||
|
||||
(screen->perfcntrs && fd_perfcntr_has_reservation(screen->perfcntrs))) {
|
||||
screen->perfcntr_groups =
|
||||
fd_perfcntrs(screen->dev_id, &screen->num_perfcntr_groups);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ struct fd_screen {
|
|||
|
||||
unsigned num_perfcntr_groups;
|
||||
const struct fd_perfcntr_group *perfcntr_groups;
|
||||
struct fd_perfcntr_state *perfcntrs;
|
||||
|
||||
/* generated at startup from the perfcntr groups: */
|
||||
unsigned num_perfcntr_queries;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue