From 9ccb6621be2f40a74f75efe30d83b7813e3c3f56 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 6 Nov 2017 16:59:05 -0800 Subject: [PATCH] broadcom/vc5: Add partial transform feedback query support. We have to compute the queries in software, so we're counting the primitives by hand. We still need to make sure to not increment the PRIMITIVES_EMITTED if we overflowed, but leave that for later. --- src/gallium/drivers/vc5/vc5_context.h | 3 ++ src/gallium/drivers/vc5/vc5_draw.c | 21 ++++++++++ src/gallium/drivers/vc5/vc5_query.c | 57 +++++++++++++++++++-------- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/gallium/drivers/vc5/vc5_context.h b/src/gallium/drivers/vc5/vc5_context.h index 2fec7a77da4..4917153fd46 100644 --- a/src/gallium/drivers/vc5/vc5_context.h +++ b/src/gallium/drivers/vc5/vc5_context.h @@ -363,6 +363,9 @@ struct vc5_context { bool active_queries; + uint32_t tf_prims_generated; + uint32_t prims_generated; + struct pipe_poly_stipple stipple; struct pipe_clip_state clip; struct pipe_viewport_state viewport; diff --git a/src/gallium/drivers/vc5/vc5_draw.c b/src/gallium/drivers/vc5/vc5_draw.c index 8020e26802a..55a2e49b98d 100644 --- a/src/gallium/drivers/vc5/vc5_draw.c +++ b/src/gallium/drivers/vc5/vc5_draw.c @@ -270,6 +270,25 @@ vc5_emit_gl_shader_state(struct vc5_context *vc5, job->shader_rec_count++; } +/** + * Computes the various transform feedback statistics, since they can't be + * recorded by CL packets. + */ +static void +vc5_tf_statistics_record(struct vc5_context *vc5, + const struct pipe_draw_info *info, + bool prim_tf) +{ + uint32_t prims = u_prims_for_vertices(info->mode, info->count); + + vc5->prims_generated += prims; + + if (prim_tf) { + /* XXX: Only count if we didn't overflow. */ + vc5->tf_prims_generated += prims; + } +} + static void vc5_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) { @@ -363,6 +382,8 @@ vc5_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) if (vc5->prog.bind_vs->num_tf_outputs) prim_tf_enable = (V3D_PRIM_POINTS_TF - V3D_PRIM_POINTS); + vc5_tf_statistics_record(vc5, info, prim_tf_enable); + /* Note that the primitive type fields match with OpenGL/gallium * definitions, up to but not including QUADS. */ diff --git a/src/gallium/drivers/vc5/vc5_query.c b/src/gallium/drivers/vc5/vc5_query.c index a412b384081..5ec9be2e356 100644 --- a/src/gallium/drivers/vc5/vc5_query.c +++ b/src/gallium/drivers/vc5/vc5_query.c @@ -24,12 +24,13 @@ /** * Gallium query object support. * - * So far we just support occlusion queries. The HW has native support for - * them, with the query result being loaded and stored by the TLB unit. + * The HW has native support for occlusion queries, with the query result + * being loaded and stored by the TLB unit. From a SW perspective, we have to + * be careful to make sure that the jobs that need to be tracking queries are + * bracketed by the start and end of counting, even across FBO transitions. * - * From a SW perspective, we have to be careful to make sure that the jobs - * that need to be tracking queries are bracketed by the start and end of - * counting, even across FBO transitions. + * For the transform feedback PRIMITIVES_GENERATED/WRITTEN queries, we have to + * do the calculations in software at draw time. */ #include "vc5_context.h" @@ -39,6 +40,8 @@ struct vc5_query { enum pipe_query_type type; struct vc5_bo *bo; + + uint32_t start, end; }; static struct pipe_query * @@ -46,10 +49,6 @@ vc5_create_query(struct pipe_context *pctx, unsigned query_type, unsigned index) { struct vc5_query *q = calloc(1, sizeof(*q)); - assert(query_type == PIPE_QUERY_OCCLUSION_COUNTER || - query_type == PIPE_QUERY_OCCLUSION_PREDICATE || - query_type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE); - q->type = query_type; /* Note that struct pipe_query isn't actually defined anywhere. */ @@ -71,13 +70,22 @@ vc5_begin_query(struct pipe_context *pctx, struct pipe_query *query) struct vc5_context *vc5 = vc5_context(pctx); struct vc5_query *q = (struct vc5_query *)query; - q->bo = vc5_bo_alloc(vc5->screen, 4096, "query"); - - uint32_t *map = vc5_bo_map(q->bo); - *map = 0; + switch (q->type) { + case PIPE_QUERY_PRIMITIVES_GENERATED: + q->start = vc5->prims_generated; + break; + case PIPE_QUERY_PRIMITIVES_EMITTED: + q->start = vc5->tf_prims_generated; + break; + default: + q->bo = vc5_bo_alloc(vc5->screen, 4096, "query"); - vc5->current_oq = q->bo; - vc5->dirty |= VC5_DIRTY_OQ; + uint32_t *map = vc5_bo_map(q->bo); + *map = 0; + vc5->current_oq = q->bo; + vc5->dirty |= VC5_DIRTY_OQ; + break; + } return true; } @@ -86,9 +94,20 @@ static bool vc5_end_query(struct pipe_context *pctx, struct pipe_query *query) { struct vc5_context *vc5 = vc5_context(pctx); + struct vc5_query *q = (struct vc5_query *)query; - vc5->current_oq = NULL; - vc5->dirty |= VC5_DIRTY_OQ; + switch (q->type) { + case PIPE_QUERY_PRIMITIVES_GENERATED: + q->end = vc5->prims_generated; + break; + case PIPE_QUERY_PRIMITIVES_EMITTED: + q->end = vc5->tf_prims_generated; + break; + default: + vc5->current_oq = NULL; + vc5->dirty |= VC5_DIRTY_OQ; + break; + } return true; } @@ -127,6 +146,10 @@ vc5_get_query_result(struct pipe_context *pctx, struct pipe_query *query, case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: vresult->b = result != 0; break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + case PIPE_QUERY_PRIMITIVES_EMITTED: + vresult->u64 = q->end - q->start; + break; default: unreachable("unsupported query type"); } -- 2.30.2