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 <cgmeiner@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37320>
This commit is contained in:
Christian Gmeiner 2025-08-08 11:45:48 +02:00 committed by Marge Bot
parent bbac6a8b53
commit bdd9d8b13d
3 changed files with 74 additions and 0 deletions

View file

@ -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

View file

@ -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,
};

View file

@ -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',