From bdd9d8b13d8e5448491b31166da66b19e0bdf9b0 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 8 Aug 2025 11:45:48 +0200 Subject: [PATCH] etnaviv: Support PIPE_QUERY_PRIMITIVES_EMITTED Add support for transform feedback primitive counting queries using the hardware TFB query mechanism. The implementation uses dedicated query registers (VIVS_TFB_QUERY_BUFFER and VIVS_TFB_QUERY_COMMAND) to track the number of primitives written during transform feedback operations. The hardware automatically accumulates primitive counts and stores the final result at offset 0 of the query buffer, eliminating the need for manual accumulation. Signed-off-by: Christian Gmeiner Part-of: --- .../drivers/etnaviv/etnaviv_query_acc.c | 2 + .../drivers/etnaviv/etnaviv_query_acc_xfb.c | 71 +++++++++++++++++++ src/gallium/drivers/etnaviv/meson.build | 1 + 3 files changed, 74 insertions(+) create mode 100644 src/gallium/drivers/etnaviv/etnaviv_query_acc_xfb.c diff --git a/src/gallium/drivers/etnaviv/etnaviv_query_acc.c b/src/gallium/drivers/etnaviv/etnaviv_query_acc.c index 000d98bf5e4..bebafcda017 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_query_acc.c +++ b/src/gallium/drivers/etnaviv/etnaviv_query_acc.c @@ -38,11 +38,13 @@ extern const struct etna_acc_sample_provider occlusion_provider; extern const struct etna_acc_sample_provider perfmon_provider; +extern const struct etna_acc_sample_provider xfb_provider; static const struct etna_acc_sample_provider *acc_sample_provider[] = { &occlusion_provider, &perfmon_provider, + &xfb_provider, }; static void diff --git a/src/gallium/drivers/etnaviv/etnaviv_query_acc_xfb.c b/src/gallium/drivers/etnaviv/etnaviv_query_acc_xfb.c new file mode 100644 index 00000000000..85799c02fcf --- /dev/null +++ b/src/gallium/drivers/etnaviv/etnaviv_query_acc_xfb.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2025 Igalia S.L. + * SPDX-License-Identifier: MIT + */ + +#include "hw/state_3d.xml.h" +#include "etnaviv_context.h" +#include "etnaviv_emit.h" +#include "etnaviv_query_acc.h" + +static bool +xfb_supports(struct etna_context *ctx, unsigned query_type) +{ + if (!VIV_FEATURE(ctx->screen, ETNA_FEATURE_HWTFB)) + return false; + + switch (query_type) { + case PIPE_QUERY_PRIMITIVES_EMITTED: + return true; + default: + return false; + } +} + +static struct etna_acc_query * +xfb_allocate(UNUSED struct etna_context *ctx, UNUSED unsigned query_type) +{ + return CALLOC_STRUCT(etna_acc_query); +} + +static void +xfb_resume(struct etna_acc_query *aq, struct etna_context *ctx) +{ + struct etna_buffer_resource *rsc = etna_buffer_resource(aq->prsc); + struct etna_reloc r = { + .bo = rsc->bo, + .flags = ETNA_RELOC_WRITE + }; + + etna_set_state_reloc(ctx->stream, VIVS_TFB_QUERY_BUFFER, &r); + etna_set_state(ctx->stream, VIVS_TFB_QUERY_COMMAND, TFB_QUERY_COMMAND_ENABLE); + resource_written(ctx, aq->prsc); +} + +static void +xfb_suspend(struct etna_acc_query *aq, struct etna_context *ctx) +{ + etna_set_state(ctx->stream, VIVS_TFB_QUERY_COMMAND, TFB_QUERY_COMMAND_DISABLE); + etna_set_state(ctx->stream, VIVS_TFB_FLUSH, 0x1); + resource_written(ctx, aq->prsc); +} + +static bool +xfb_result(UNUSED struct etna_acc_query *aq, void *buf, + union pipe_query_result *result) +{ + /* The GPU stores the final results at offset 0 - no need + * to do any manual accumulation. + */ + result->u64 = *(uint64_t *)buf; + + return true; +} + +const struct etna_acc_sample_provider xfb_provider = { + .supports = xfb_supports, + .allocate = xfb_allocate, + .suspend = xfb_suspend, + .resume = xfb_resume, + .result = xfb_result, +}; diff --git a/src/gallium/drivers/etnaviv/meson.build b/src/gallium/drivers/etnaviv/meson.build index c140897b78d..424ffdcddd0 100644 --- a/src/gallium/drivers/etnaviv/meson.build +++ b/src/gallium/drivers/etnaviv/meson.build @@ -51,6 +51,7 @@ files_etnaviv = files( 'etnaviv_query.h', 'etnaviv_query_acc_occlusion.c', 'etnaviv_query_acc_perfmon.c', + 'etnaviv_query_acc_xfb.c', 'etnaviv_query_acc.c', 'etnaviv_query_acc.h', 'etnaviv_query_sw.c',