From: Rob Clark Date: Tue, 30 May 2017 11:52:25 +0000 (-0400) Subject: freedreno/a5xx: timestamp / time-elapsed queries X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=76214b99193a117290be9880a83e5ca9d7ec6f36;p=mesa.git freedreno/a5xx: timestamp / time-elapsed queries Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_query.c b/src/gallium/drivers/freedreno/a5xx/fd5_query.c index 9019a030899..80b84ce54ba 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_query.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_query.c @@ -144,6 +144,99 @@ static const struct fd_acc_sample_provider occlusion_predicate = { .result = occlusion_predicate_result, }; +/* + * Timestamp Queries: + */ + +static void +timestamp_resume(struct fd_acc_query *aq, struct fd_batch *batch) +{ + struct fd_ringbuffer *ring = batch->draw; + + OUT_PKT7(ring, CP_EVENT_WRITE, 4); + OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_AND_INV_EVENT) | + CP_EVENT_WRITE_0_TIMESTAMP); + OUT_RELOCW(ring, query_sample(aq, start)); + OUT_RING(ring, 0x00000000); + + fd_reset_wfi(batch); +} + +static void +timestamp_pause(struct fd_acc_query *aq, struct fd_batch *batch) +{ + struct fd_ringbuffer *ring = batch->draw; + + OUT_PKT7(ring, CP_EVENT_WRITE, 4); + OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_AND_INV_EVENT) | + CP_EVENT_WRITE_0_TIMESTAMP); + OUT_RELOCW(ring, query_sample(aq, stop)); + OUT_RING(ring, 0x00000000); + + fd_reset_wfi(batch); + fd_wfi(batch, ring); + + /* result += stop - start: */ + OUT_PKT7(ring, CP_MEM_TO_MEM, 9); + OUT_RING(ring, CP_MEM_TO_MEM_0_DOUBLE | + CP_MEM_TO_MEM_0_NEG_C); + OUT_RELOCW(ring, query_sample(aq, result)); /* dst */ + OUT_RELOC(ring, query_sample(aq, result)); /* srcA */ + OUT_RELOC(ring, query_sample(aq, stop)); /* srcB */ + OUT_RELOC(ring, query_sample(aq, start)); /* srcC */ +} + +static uint64_t +ticks_to_ns(struct fd_context *ctx, uint32_t ts) +{ + /* This is based on the 19.2MHz always-on rbbm timer. + * + * TODO we should probably query this value from kernel.. + */ + return ts * (1000000000 / 19200000); +} + +static void +time_elapsed_accumulate_result(struct fd_context *ctx, void *buf, + union pipe_query_result *result) +{ + struct fd5_query_sample *sp = buf; + result->u64 = ticks_to_ns(ctx, sp->result); +} + +static void +timestamp_accumulate_result(struct fd_context *ctx, void *buf, + union pipe_query_result *result) +{ + struct fd5_query_sample *sp = buf; + result->u64 = ticks_to_ns(ctx, sp->result); +} + +static const struct fd_acc_sample_provider time_elapsed = { + .query_type = PIPE_QUERY_TIME_ELAPSED, + .active = FD_STAGE_DRAW | FD_STAGE_CLEAR, + .size = sizeof(struct fd5_query_sample), + .resume = timestamp_resume, + .pause = timestamp_pause, + .result = time_elapsed_accumulate_result, +}; + +/* NOTE: timestamp query isn't going to give terribly sensible results + * on a tiler. But it is needed by qapitrace profile heatmap. If you + * add in a binning pass, the results get even more non-sensical. So + * we just return the timestamp on the first tile and hope that is + * kind of good enough. + */ + +static const struct fd_acc_sample_provider timestamp = { + .query_type = PIPE_QUERY_TIMESTAMP, + .active = FD_STAGE_ALL, + .size = sizeof(struct fd5_query_sample), + .resume = timestamp_resume, + .pause = timestamp_pause, + .result = timestamp_accumulate_result, +}; + void fd5_query_context_init(struct pipe_context *pctx) { @@ -154,4 +247,7 @@ fd5_query_context_init(struct pipe_context *pctx) fd_acc_query_register_provider(pctx, &occlusion_counter); fd_acc_query_register_provider(pctx, &occlusion_predicate); + + fd_acc_query_register_provider(pctx, &time_elapsed); + fd_acc_query_register_provider(pctx, ×tamp); } diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 99a6d3c9c86..b1501d5af0e 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -377,7 +377,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_QUERY_TIMESTAMP: case PIPE_CAP_QUERY_TIME_ELAPSED: /* only a4xx, requires new enough kernel so we know max_freq: */ - return (screen->max_freq > 0) && is_a4xx(screen); + return (screen->max_freq > 0) && (is_a4xx(screen) || is_a5xx(screen)); case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET: case PIPE_CAP_MIN_TEXEL_OFFSET: