From 57245cce52d544c61f03fc966850f0f94e8118d5 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Fri, 31 Jul 2015 02:39:02 +0200 Subject: gallium/radeon: suspend timer queries between IBs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we are measuring the time spent in a draw call, an unexpected flush can distort the result. Reviewed-by: Michel Dänzer --- src/gallium/drivers/radeon/r600_pipe_common.c | 8 ++-- src/gallium/drivers/radeon/r600_pipe_common.h | 9 +++- src/gallium/drivers/radeon/r600_query.c | 68 ++++++++++++++++++++------- 3 files changed, 62 insertions(+), 23 deletions(-) (limited to 'src/gallium/drivers/radeon') diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c index 75e820144e3..c940f6d35c2 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.c +++ b/src/gallium/drivers/radeon/r600_pipe_common.c @@ -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. */ diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index e2a60c59c82..fbd2a21da17 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -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 */ diff --git a/src/gallium/drivers/radeon/r600_query.c b/src/gallium/drivers/radeon/r600_query.c index 909d5029bfa..7fc22537f43 100644 --- a/src/gallium/drivers/radeon/r600_query.c +++ b/src/gallium/drivers/radeon/r600_query.c @@ -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); } -- cgit v1.2.3