From c59d8a179831fa9fe867c3547839e95f41774b8f Mon Sep 17 00:00:00 2001 From: "Juan A. Suarez Romero" Date: Wed, 21 Apr 2021 14:22:45 +0200 Subject: [PATCH] v3d: move queries to pipe queries All the current queries are pipe-related queries; move them to a different file to add later performance counter queries. v3 (Iago): - Fix copyright. Reviewed-by: Iago Toral Quiroga Signed-off-by: Juan A. Suarez Romero Part-of: --- src/gallium/drivers/v3d/meson.build | 2 + src/gallium/drivers/v3d/v3d_query.c | 138 ++------------------- src/gallium/drivers/v3d/v3d_query.h | 46 +++++++ src/gallium/drivers/v3d/v3d_query_pipe.c | 200 +++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+), 131 deletions(-) create mode 100644 src/gallium/drivers/v3d/v3d_query.h create mode 100644 src/gallium/drivers/v3d/v3d_query_pipe.c diff --git a/src/gallium/drivers/v3d/meson.build b/src/gallium/drivers/v3d/meson.build index 32c512d..1e92fb6 100644 --- a/src/gallium/drivers/v3d/meson.build +++ b/src/gallium/drivers/v3d/meson.build @@ -31,6 +31,8 @@ files_libv3d = files( 'v3d_job.c', 'v3d_program.c', 'v3d_query.c', + 'v3d_query.h', + 'v3d_query_pipe.c', 'v3d_resource.c', 'v3d_resource.h', 'v3d_screen.c', diff --git a/src/gallium/drivers/v3d/v3d_query.c b/src/gallium/drivers/v3d/v3d_query.c index 31bd034..ae9993b 100644 --- a/src/gallium/drivers/v3d/v3d_query.c +++ b/src/gallium/drivers/v3d/v3d_query.c @@ -21,47 +21,21 @@ * IN THE SOFTWARE. */ -/** - * Gallium query object support. - * - * 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. - * - * For the transform feedback PRIMITIVES_GENERATED/WRITTEN queries, we have to - * do the calculations in software at draw time. - */ - -#include "v3d_context.h" -#include "broadcom/cle/v3d_packet_v33_pack.h" - -struct v3d_query -{ - enum pipe_query_type type; - struct v3d_bo *bo; - - uint32_t start, end; -}; +#include "v3d_query.h" static struct pipe_query * v3d_create_query(struct pipe_context *pctx, unsigned query_type, unsigned index) { - struct v3d_query *q = calloc(1, sizeof(*q)); - - q->type = query_type; - - /* Note that struct pipe_query isn't actually defined anywhere. */ - return (struct pipe_query *)q; + return v3d_create_query_pipe(v3d_context(pctx), query_type, index); } static void v3d_destroy_query(struct pipe_context *pctx, struct pipe_query *query) { + struct v3d_context *v3d = v3d_context(pctx); struct v3d_query *q = (struct v3d_query *)query; - v3d_bo_unreference(&q->bo); - free(q); + q->funcs->destroy_query(v3d, q); } static bool @@ -70,40 +44,7 @@ v3d_begin_query(struct pipe_context *pctx, struct pipe_query *query) struct v3d_context *v3d = v3d_context(pctx); struct v3d_query *q = (struct v3d_query *)query; - switch (q->type) { - case PIPE_QUERY_PRIMITIVES_GENERATED: - /* If we are using PRIMITIVE_COUNTS_FEEDBACK to retrieve - * primitive counts from the GPU (which we need when a GS - * is present), then we need to update our counters now - * to discard any primitives generated before this. - */ - if (v3d->prog.gs) - v3d_update_primitive_counters(v3d); - q->start = v3d->prims_generated; - break; - case PIPE_QUERY_PRIMITIVES_EMITTED: - /* If we are inside transform feedback we need to update the - * primitive counts to skip primitives recorded before this. - */ - if (v3d->streamout.num_targets > 0) - v3d_update_primitive_counters(v3d); - q->start = v3d->tf_prims_generated; - break; - case PIPE_QUERY_OCCLUSION_COUNTER: - case PIPE_QUERY_OCCLUSION_PREDICATE: - case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: - q->bo = v3d_bo_alloc(v3d->screen, 4096, "query"); - uint32_t *map = v3d_bo_map(q->bo); - *map = 0; - - v3d->current_oq = q->bo; - v3d->dirty |= V3D_DIRTY_OQ; - break; - default: - unreachable("unsupported query type"); - } - - return true; + return q->funcs->begin_query(v3d, q); } static bool @@ -112,36 +53,7 @@ v3d_end_query(struct pipe_context *pctx, struct pipe_query *query) struct v3d_context *v3d = v3d_context(pctx); struct v3d_query *q = (struct v3d_query *)query; - switch (q->type) { - case PIPE_QUERY_PRIMITIVES_GENERATED: - /* If we are using PRIMITIVE_COUNTS_FEEDBACK to retrieve - * primitive counts from the GPU (which we need when a GS - * is present), then we need to update our counters now. - */ - if (v3d->prog.gs) - v3d_update_primitive_counters(v3d); - q->end = v3d->prims_generated; - break; - case PIPE_QUERY_PRIMITIVES_EMITTED: - /* If transform feedback has ended, then we have already - * updated the primitive counts at glEndTransformFeedback() - * time. Otherwise, we have to do it now. - */ - if (v3d->streamout.num_targets > 0) - v3d_update_primitive_counters(v3d); - q->end = v3d->tf_prims_generated; - break; - case PIPE_QUERY_OCCLUSION_COUNTER: - case PIPE_QUERY_OCCLUSION_PREDICATE: - case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: - v3d->current_oq = NULL; - v3d->dirty |= V3D_DIRTY_OQ; - break; - default: - unreachable("unsupported query type"); - } - - return true; + return q->funcs->end_query(v3d, q); } static bool @@ -150,43 +62,8 @@ v3d_get_query_result(struct pipe_context *pctx, struct pipe_query *query, { struct v3d_context *v3d = v3d_context(pctx); struct v3d_query *q = (struct v3d_query *)query; - uint32_t result = 0; - - if (q->bo) { - v3d_flush_jobs_using_bo(v3d, q->bo); - - if (wait) { - if (!v3d_bo_wait(q->bo, ~0ull, "query")) - return false; - } else { - if (!v3d_bo_wait(q->bo, 0, "query")) - return false; - } - /* XXX: Sum up per-core values. */ - uint32_t *map = v3d_bo_map(q->bo); - result = *map; - - v3d_bo_unreference(&q->bo); - } - - switch (q->type) { - case PIPE_QUERY_OCCLUSION_COUNTER: - vresult->u64 = result; - break; - case PIPE_QUERY_OCCLUSION_PREDICATE: - 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"); - } - - return true; + return q->funcs->get_query_result(v3d, q, wait, vresult); } static void @@ -209,4 +86,3 @@ v3d_query_init(struct pipe_context *pctx) pctx->get_query_result = v3d_get_query_result; pctx->set_active_query_state = v3d_set_active_query_state; } - diff --git a/src/gallium/drivers/v3d/v3d_query.h b/src/gallium/drivers/v3d/v3d_query.h new file mode 100644 index 0000000..12026b2 --- /dev/null +++ b/src/gallium/drivers/v3d/v3d_query.h @@ -0,0 +1,46 @@ +/* + * Copyright © 2021 Raspberry Pi + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef V3D_QUERY_H +#define V3D_QUERY_H + +#include "v3d_context.h" + +struct v3d_query; + +struct v3d_query_funcs { + void (*destroy_query)(struct v3d_context *v3d, struct v3d_query *query); + bool (*begin_query)(struct v3d_context *v3d, struct v3d_query *query); + bool (*end_query)(struct v3d_context *v3d, struct v3d_query *query); + bool (*get_query_result)(struct v3d_context *v3d, struct v3d_query *query, + bool wait, union pipe_query_result *result); +}; + +struct v3d_query +{ + const struct v3d_query_funcs *funcs; +}; + +struct pipe_query *v3d_create_query_pipe(struct v3d_context *v3d, unsigned query_type, unsigned index); + +#endif /* V3D_QUERY_H */ diff --git a/src/gallium/drivers/v3d/v3d_query_pipe.c b/src/gallium/drivers/v3d/v3d_query_pipe.c new file mode 100644 index 0000000..eafb7ec --- /dev/null +++ b/src/gallium/drivers/v3d/v3d_query_pipe.c @@ -0,0 +1,200 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * Gallium query object support. + * + * 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. + * + * For the transform feedback PRIMITIVES_GENERATED/WRITTEN queries, we have to + * do the calculations in software at draw time. + */ + +#include "v3d_query.h" + +struct v3d_query_pipe +{ + struct v3d_query base; + + enum pipe_query_type type; + struct v3d_bo *bo; + + uint32_t start, end; +}; + +static void +v3d_destroy_query_pipe(struct v3d_context *v3d, struct v3d_query *query) +{ + struct v3d_query_pipe *pquery = (struct v3d_query_pipe *)query; + + v3d_bo_unreference(&pquery->bo); + free(pquery); +} + +static bool +v3d_begin_query_pipe(struct v3d_context *v3d, struct v3d_query *query) +{ + struct v3d_query_pipe *pquery = (struct v3d_query_pipe *)query; + + switch (pquery->type) { + case PIPE_QUERY_PRIMITIVES_GENERATED: + /* If we are using PRIMITIVE_COUNTS_FEEDBACK to retrieve + * primitive counts from the GPU (which we need when a GS + * is present), then we need to update our counters now + * to discard any primitives generated before this. + */ + if (v3d->prog.gs) + v3d_update_primitive_counters(v3d); + pquery->start = v3d->prims_generated; + break; + case PIPE_QUERY_PRIMITIVES_EMITTED: + /* If we are inside transform feedback we need to update the + * primitive counts to skip primitives recorded before this. + */ + if (v3d->streamout.num_targets > 0) + v3d_update_primitive_counters(v3d); + pquery->start = v3d->tf_prims_generated; + break; + case PIPE_QUERY_OCCLUSION_COUNTER: + case PIPE_QUERY_OCCLUSION_PREDICATE: + case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: + pquery->bo = v3d_bo_alloc(v3d->screen, 4096, "query"); + uint32_t *map = v3d_bo_map(pquery->bo); + *map = 0; + + v3d->current_oq = pquery->bo; + v3d->dirty |= V3D_DIRTY_OQ; + break; + default: + unreachable("unsupported query type"); + } + + return true; +} + +static bool +v3d_end_query_pipe(struct v3d_context *v3d, struct v3d_query *query) +{ + struct v3d_query_pipe *pquery = (struct v3d_query_pipe *)query; + + switch (pquery->type) { + case PIPE_QUERY_PRIMITIVES_GENERATED: + /* If we are using PRIMITIVE_COUNTS_FEEDBACK to retrieve + * primitive counts from the GPU (which we need when a GS + * is present), then we need to update our counters now. + */ + if (v3d->prog.gs) + v3d_update_primitive_counters(v3d); + pquery->end = v3d->prims_generated; + break; + case PIPE_QUERY_PRIMITIVES_EMITTED: + /* If transform feedback has ended, then we have already + * updated the primitive counts at glEndTransformFeedback() + * time. Otherwise, we have to do it now. + */ + if (v3d->streamout.num_targets > 0) + v3d_update_primitive_counters(v3d); + pquery->end = v3d->tf_prims_generated; + break; + case PIPE_QUERY_OCCLUSION_COUNTER: + case PIPE_QUERY_OCCLUSION_PREDICATE: + case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: + v3d->current_oq = NULL; + v3d->dirty |= V3D_DIRTY_OQ; + break; + default: + unreachable("unsupported query type"); + } + + return true; +} + +static bool +v3d_get_query_result_pipe(struct v3d_context *v3d, struct v3d_query *query, + bool wait, union pipe_query_result *vresult) +{ + struct v3d_query_pipe *pquery = (struct v3d_query_pipe *)query; + uint32_t result = 0; + + if (pquery->bo) { + v3d_flush_jobs_using_bo(v3d, pquery->bo); + + if (wait) { + if (!v3d_bo_wait(pquery->bo, ~0ull, "query")) + return false; + } else { + if (!v3d_bo_wait(pquery->bo, 0, "query")) + return false; + } + + /* XXX: Sum up per-core values. */ + uint32_t *map = v3d_bo_map(pquery->bo); + result = *map; + + v3d_bo_unreference(&pquery->bo); + } + + switch (pquery->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + vresult->u64 = result; + break; + case PIPE_QUERY_OCCLUSION_PREDICATE: + case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: + vresult->b = result != 0; + break; + case PIPE_QUERY_PRIMITIVES_GENERATED: + case PIPE_QUERY_PRIMITIVES_EMITTED: + vresult->u64 = pquery->end - pquery->start; + break; + default: + unreachable("unsupported query type"); + } + + return true; +} + +static const struct v3d_query_funcs pipe_query_funcs = { + .destroy_query = v3d_destroy_query_pipe, + .begin_query = v3d_begin_query_pipe, + .end_query = v3d_end_query_pipe, + .get_query_result = v3d_get_query_result_pipe, +}; + +struct pipe_query * +v3d_create_query_pipe(struct v3d_context *v3d, unsigned query_type, unsigned index) +{ + if (query_type >= PIPE_QUERY_DRIVER_SPECIFIC) + return NULL; + + struct v3d_query_pipe *pquery = calloc(1, sizeof(*pquery)); + struct v3d_query *query = &pquery->base; + + pquery->type = query_type; + query->funcs = &pipe_query_funcs; + + /* Note that struct pipe_query isn't actually defined anywhere. */ + return (struct pipe_query *)query; +} -- 2.7.4