gallium/radeon: suspend timer queries between IBs
authorMarek Olšák <marek.olsak@amd.com>
Fri, 31 Jul 2015 00:39:02 +0000 (02:39 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 6 Aug 2015 18:44:35 +0000 (20:44 +0200)
When we are measuring the time spent in a draw call, an unexpected flush
can distort the result.

Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
src/gallium/drivers/r600/r600_hw_context.c
src/gallium/drivers/radeon/r600_pipe_common.c
src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeon/r600_query.c
src/gallium/drivers/radeonsi/si_hw_context.c

index 8eb0c6806b99f53a02e4480f71b1d46517d3485a..9155707f86642d8fb676b7a464eb94c252a55095 100644 (file)
@@ -68,7 +68,8 @@ void r600_need_cs_space(struct r600_context *ctx, unsigned num_dw,
        }
 
        /* Count in queries_suspend. */
-       num_dw += ctx->b.num_cs_dw_nontimer_queries_suspend;
+       num_dw += ctx->b.num_cs_dw_nontimer_queries_suspend +
+                 ctx->b.num_cs_dw_timer_queries_suspend;
 
        /* Count in streamout_end at the end of CS. */
        if (ctx->b.streamout.begin_emitted) {
index 75e820144e39cdd046fbee09acf324eafcd97a05..c940f6d35c2ed78f718b0c8dc52599e7009c8e83 100644 (file)
@@ -132,10 +132,11 @@ void r600_preflush_suspend_features(struct r600_common_context *ctx)
        }
 
        /* suspend queries */
-       ctx->nontimer_queries_suspended = false;
+       ctx->queries_suspended_for_flush = false;
        if (ctx->num_cs_dw_nontimer_queries_suspend) {
                r600_suspend_nontimer_queries(ctx);
-               ctx->nontimer_queries_suspended = true;
+               r600_suspend_timer_queries(ctx);
+               ctx->queries_suspended_for_flush = true;
        }
 
        ctx->streamout.suspended = false;
@@ -153,8 +154,9 @@ void r600_postflush_resume_features(struct r600_common_context *ctx)
        }
 
        /* resume queries */
-       if (ctx->nontimer_queries_suspended) {
+       if (ctx->queries_suspended_for_flush) {
                r600_resume_nontimer_queries(ctx);
+               r600_resume_timer_queries(ctx);
        }
 
        /* Re-enable render condition. */
index e2a60c59c821e0e45721afd8fd1b4765b87ab2b2..fbd2a21da177b726f75c4e8092b7edde1995f78a 100644 (file)
@@ -384,11 +384,14 @@ struct r600_common_context {
        int                             num_occlusion_queries;
        /* Keep track of non-timer queries, because they should be suspended
         * during context flushing.
-        * The timer queries (TIME_ELAPSED) shouldn't be suspended. */
+        * The timer queries (TIME_ELAPSED) shouldn't be suspended for blits,
+        * but they should be suspended between IBs. */
        struct list_head                active_nontimer_queries;
+       struct list_head                active_timer_queries;
        unsigned                        num_cs_dw_nontimer_queries_suspend;
+       unsigned                        num_cs_dw_timer_queries_suspend;
        /* If queries have been suspended. */
-       bool                            nontimer_queries_suspended;
+       bool                            queries_suspended_for_flush;
        /* Additional hardware info. */
        unsigned                        backend_mask;
        unsigned                        max_db; /* for OQ */
@@ -503,6 +506,8 @@ unsigned r600_gpu_load_end(struct r600_common_screen *rscreen, uint64_t begin);
 void r600_query_init(struct r600_common_context *rctx);
 void r600_suspend_nontimer_queries(struct r600_common_context *ctx);
 void r600_resume_nontimer_queries(struct r600_common_context *ctx);
+void r600_suspend_timer_queries(struct r600_common_context *ctx);
+void r600_resume_timer_queries(struct r600_common_context *ctx);
 void r600_query_init_backend_mask(struct r600_common_context *ctx);
 
 /* r600_streamout.c */
index 909d5029bfa7a93eea614eb5dba5f7fbc193365d..7fc22537f43db49b231e7a1a36dcbaf6768f8b73 100644 (file)
@@ -226,9 +226,10 @@ static void r600_emit_query_begin(struct r600_common_context *ctx, struct r600_q
        r600_emit_reloc(ctx, &ctx->rings.gfx, query->buffer.buf, RADEON_USAGE_WRITE,
                        RADEON_PRIO_MIN);
 
-       if (!r600_is_timer_query(query->type)) {
+       if (r600_is_timer_query(query->type))
+               ctx->num_cs_dw_timer_queries_suspend += query->num_cs_dw;
+       else
                ctx->num_cs_dw_nontimer_queries_suspend += query->num_cs_dw;
-       }
 }
 
 static void r600_emit_query_end(struct r600_common_context *ctx, struct r600_query *query)
@@ -290,9 +291,10 @@ static void r600_emit_query_end(struct r600_common_context *ctx, struct r600_que
        query->buffer.results_end += query->result_size;
 
        if (r600_query_needs_begin(query->type)) {
-               if (!r600_is_timer_query(query->type)) {
+               if (r600_is_timer_query(query->type))
+                       ctx->num_cs_dw_timer_queries_suspend -= query->num_cs_dw;
+               else
                        ctx->num_cs_dw_nontimer_queries_suspend -= query->num_cs_dw;
-               }
        }
 
        r600_update_occlusion_query_state(ctx, query->type, -1);
@@ -503,9 +505,10 @@ static boolean r600_begin_query(struct pipe_context *ctx,
 
        r600_emit_query_begin(rctx, rquery);
 
-       if (!r600_is_timer_query(rquery->type)) {
+       if (r600_is_timer_query(rquery->type))
+               LIST_ADDTAIL(&rquery->list, &rctx->active_timer_queries);
+       else
                LIST_ADDTAIL(&rquery->list, &rctx->active_nontimer_queries);
-       }
    return true;
 }
 
@@ -561,9 +564,8 @@ static void r600_end_query(struct pipe_context *ctx, struct pipe_query *query)
 
        r600_emit_query_end(rctx, rquery);
 
-       if (r600_query_needs_begin(rquery->type) && !r600_is_timer_query(rquery->type)) {
+       if (r600_query_needs_begin(rquery->type))
                LIST_DELINIT(&rquery->list);
-       }
 }
 
 static unsigned r600_query_read_result(char *map, unsigned start_index, unsigned end_index,
@@ -838,22 +840,37 @@ static void r600_render_condition(struct pipe_context *ctx,
        }
 }
 
-void r600_suspend_nontimer_queries(struct r600_common_context *ctx)
+static void r600_suspend_queries(struct r600_common_context *ctx,
+                                struct list_head *query_list,
+                                unsigned *num_cs_dw_queries_suspend)
 {
        struct r600_query *query;
 
-       LIST_FOR_EACH_ENTRY(query, &ctx->active_nontimer_queries, list) {
+       LIST_FOR_EACH_ENTRY(query, query_list, list) {
                r600_emit_query_end(ctx, query);
        }
-       assert(ctx->num_cs_dw_nontimer_queries_suspend == 0);
+       assert(*num_cs_dw_queries_suspend == 0);
+}
+
+void r600_suspend_nontimer_queries(struct r600_common_context *ctx)
+{
+       r600_suspend_queries(ctx, &ctx->active_nontimer_queries,
+                            &ctx->num_cs_dw_nontimer_queries_suspend);
 }
 
-static unsigned r600_queries_num_cs_dw_for_resuming(struct r600_common_context *ctx)
+void r600_suspend_timer_queries(struct r600_common_context *ctx)
+{
+       r600_suspend_queries(ctx, &ctx->active_timer_queries,
+                            &ctx->num_cs_dw_timer_queries_suspend);
+}
+
+static unsigned r600_queries_num_cs_dw_for_resuming(struct r600_common_context *ctx,
+                                                   struct list_head *query_list)
 {
        struct r600_query *query;
        unsigned num_dw = 0;
 
-       LIST_FOR_EACH_ENTRY(query, &ctx->active_nontimer_queries, list) {
+       LIST_FOR_EACH_ENTRY(query, query_list, list) {
                /* begin + end */
                num_dw += query->num_cs_dw * 2;
 
@@ -872,21 +889,35 @@ static unsigned r600_queries_num_cs_dw_for_resuming(struct r600_common_context *
        return num_dw;
 }
 
-void r600_resume_nontimer_queries(struct r600_common_context *ctx)
+static void r600_resume_queries(struct r600_common_context *ctx,
+                               struct list_head *query_list,
+                               unsigned *num_cs_dw_queries_suspend)
 {
        struct r600_query *query;
+       unsigned num_cs_dw = r600_queries_num_cs_dw_for_resuming(ctx, query_list);
 
-       assert(ctx->num_cs_dw_nontimer_queries_suspend == 0);
+       assert(*num_cs_dw_queries_suspend == 0);
 
        /* Check CS space here. Resuming must not be interrupted by flushes. */
-       ctx->need_gfx_cs_space(&ctx->b,
-                              r600_queries_num_cs_dw_for_resuming(ctx), TRUE);
+       ctx->need_gfx_cs_space(&ctx->b, num_cs_dw, TRUE);
 
-       LIST_FOR_EACH_ENTRY(query, &ctx->active_nontimer_queries, list) {
+       LIST_FOR_EACH_ENTRY(query, query_list, list) {
                r600_emit_query_begin(ctx, query);
        }
 }
 
+void r600_resume_nontimer_queries(struct r600_common_context *ctx)
+{
+       r600_resume_queries(ctx, &ctx->active_nontimer_queries,
+                           &ctx->num_cs_dw_nontimer_queries_suspend);
+}
+
+void r600_resume_timer_queries(struct r600_common_context *ctx)
+{
+       r600_resume_queries(ctx, &ctx->active_timer_queries,
+                           &ctx->num_cs_dw_timer_queries_suspend);
+}
+
 /* Get backends mask */
 void r600_query_init_backend_mask(struct r600_common_context *ctx)
 {
@@ -979,4 +1010,5 @@ void r600_query_init(struct r600_common_context *rctx)
            rctx->b.render_condition = r600_render_condition;
 
        LIST_INITHEAD(&rctx->active_nontimer_queries);
+       LIST_INITHEAD(&rctx->active_timer_queries);
 }
index 581b130caecdabfad508a0b26286552eefe5903e..b80245c97850c8d241d6f5ad0284eda053eb4d9a 100644 (file)
@@ -63,7 +63,8 @@ void si_need_cs_space(struct si_context *ctx, unsigned num_dw,
        }
 
        /* Count in queries_suspend. */
-       num_dw += ctx->b.num_cs_dw_nontimer_queries_suspend;
+       num_dw += ctx->b.num_cs_dw_nontimer_queries_suspend +
+                 ctx->b.num_cs_dw_timer_queries_suspend;
 
        /* Count in streamout_end at the end of CS. */
        if (ctx->b.streamout.begin_emitted) {