freedreno/a4xx: timestamp queries
authorRob Clark <robclark@freedesktop.org>
Sun, 14 Feb 2016 16:14:06 +0000 (11:14 -0500)
committerRob Clark <robdclark@gmail.com>
Sat, 23 Jul 2016 17:39:30 +0000 (13:39 -0400)
Signed-off-by: Rob Clark <robdclark@gmail.com>
src/gallium/drivers/freedreno/a4xx/fd4_query.c
src/gallium/drivers/freedreno/freedreno_query_hw.c
src/gallium/drivers/freedreno/freedreno_screen.c

index 69decbcb251f41a838cf846969f83b9ca66a9695..baa3787f9d3c5fb5d4d2c50ac55f63d60ab124e6 100644 (file)
@@ -224,6 +224,19 @@ time_elapsed_accumulate_result(struct fd_context *ctx,
        result->u64 += n * 1000000000 / ctx->screen->max_freq;
 }
 
+static void
+timestamp_accumulate_result(struct fd_context *ctx,
+               const void *start, const void *end,
+               union pipe_query_result *result)
+{
+       /* just return the value from fist tile: */
+       if (result->u64 != 0)
+               return;
+       uint64_t n = *(uint64_t *)start;
+       /* max_freq is in Hz, convert cycle count to ns: */
+       result->u64 = n * 1000000000 / ctx->screen->max_freq;
+}
+
 static const struct fd_hw_sample_provider occlusion_counter = {
                .query_type = PIPE_QUERY_OCCLUSION_COUNTER,
                .active = FD_STAGE_DRAW,
@@ -246,9 +259,24 @@ static const struct fd_hw_sample_provider time_elapsed = {
                .accumulate_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_hw_sample_provider timestamp = {
+               .query_type = PIPE_QUERY_TIMESTAMP,
+               .active = FD_STAGE_ALL,
+               .enable = time_elapsed_enable,
+               .get_sample = time_elapsed_get_sample,
+               .accumulate_result = timestamp_accumulate_result,
+};
+
 void fd4_query_context_init(struct pipe_context *pctx)
 {
        fd_hw_query_register_provider(pctx, &occlusion_counter);
        fd_hw_query_register_provider(pctx, &occlusion_predicate);
        fd_hw_query_register_provider(pctx, &time_elapsed);
+       fd_hw_query_register_provider(pctx, &timestamp);
 }
index 141dc8a28fe747a7764c64377e9ae569606e2063..7b528f5ccae0ebddb1aeab2b18191de3b172b653 100644 (file)
@@ -47,8 +47,13 @@ static int pidx(unsigned query_type)
                return 0;
        case PIPE_QUERY_OCCLUSION_PREDICATE:
                return 1;
+       /* TODO currently queries only emitted in main pass (not in binning pass)..
+        * which is fine for occlusion query, but pretty much not anything else.
+        */
        case PIPE_QUERY_TIME_ELAPSED:
                return 2;
+       case PIPE_QUERY_TIMESTAMP:
+               return 3;
        default:
                return -1;
        }
index 0aaa4d048997daae8daa903b9b99d750ffb75186..568e6e2840171033b4d6201d4bb6bead4115fb5e 100644 (file)
@@ -332,11 +332,11 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
                return is_a3xx(screen) ? 1 : 0;
 
        /* Queries. */
-       case PIPE_CAP_QUERY_TIMESTAMP:
        case PIPE_CAP_QUERY_BUFFER_OBJECT:
                return 0;
        case PIPE_CAP_OCCLUSION_QUERY:
                return is_a3xx(screen) || is_a4xx(screen);
+       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);