etnaviv: Implement stream output target management

Add infrastructure for stream output by implementing the required Gallium
interface functions for creating, destroying, and binding stream output targets.

This lays the groundwork for transform feedback support in etnaviv.

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 12:19:19 +02:00 committed by Marge Bot
parent bdd9d8b13d
commit 52bc3c2d20
3 changed files with 66 additions and 3 deletions

View file

@ -385,6 +385,13 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
etna_update_sampler_source(ctx->sampler_view[i], i);
}
/* Mark streamout buffers as being written. */
if (ctx->dirty & ETNA_DIRTY_STREAMOUT) {
for (unsigned i = 0; i < ctx->streamout.num_targets; i++) {
resource_written(ctx, ctx->streamout.targets[i]->buffer);
}
}
if (indirect) {
/*
* When the indirect buffer is written by the GPU, e.g. by a compute shader,

View file

@ -92,6 +92,11 @@ struct etna_shader_state {
struct etna_shader_variant *vs, *fs;
};
struct etna_streamout {
struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS];
unsigned num_targets;
};
enum etna_uniform_contents {
ETNA_UNIFORM_UNUSED = 0,
ETNA_UNIFORM_CONSTANT,
@ -151,6 +156,7 @@ struct etna_context {
ETNA_DIRTY_DERIVE_TS = (1 << 19),
ETNA_DIRTY_SCISSOR_CLIP = (1 << 20),
ETNA_DIRTY_SHADER_CACHES = (1 << 21),
ETNA_DIRTY_STREAMOUT = (1 << 22),
} dirty;
struct slab_child_pool transfer_pool;
@ -221,6 +227,8 @@ struct etna_context {
struct pipe_query *cond_query;
bool cond_cond; /* inverted rendering condition */
uint cond_mode;
struct etna_streamout streamout;
};
static inline struct etna_context *

View file

@ -719,13 +719,59 @@ etna_vertex_elements_state_bind(struct pipe_context *pctx, void *ve)
ctx->dirty |= ETNA_DIRTY_VERTEX_ELEMENTS;
}
static struct pipe_stream_output_target *
etna_create_stream_output_target(struct pipe_context *pctx,
struct pipe_resource *prsc,
unsigned buffer_offset,
unsigned buffer_size)
{
struct pipe_stream_output_target *target;
target = CALLOC_STRUCT(pipe_stream_output_target);
if (!target)
return NULL;
pipe_reference_init(&target->reference, 1);
pipe_resource_reference(&target->buffer, prsc);
target->context = pctx;
target->buffer_offset = buffer_offset;
target->buffer_size = buffer_size;
return target;
}
static void
etna_stream_output_target_destroy(UNUSED struct pipe_context *ctx,
struct pipe_stream_output_target *state)
{
pipe_resource_reference(&state->buffer, NULL);
FREE(state);
}
static void
etna_set_stream_output_targets(struct pipe_context *pctx,
unsigned num_targets, struct pipe_stream_output_target **targets,
const unsigned *offsets,
enum mesa_prim output_prim)
UNUSED const unsigned *offsets,
UNUSED enum mesa_prim output_prim)
{
/* stub */
struct etna_context *ctx = etna_context(pctx);
struct etna_streamout *so = &ctx->streamout;
assert(num_targets <= ARRAY_SIZE(so->targets));
for (unsigned i = 0; i < num_targets; i++)
pipe_so_target_reference(&so->targets[i], targets[i]);
for (unsigned i = num_targets; i < so->num_targets; i++)
pipe_so_target_reference(&so->targets[i], NULL);
so->num_targets = num_targets;
/* There is no need to emit streamout information unless it is active. */
if (so->num_targets > 0)
ctx->dirty |= ETNA_DIRTY_STREAMOUT;
}
static bool
@ -1032,5 +1078,7 @@ etna_state_init(struct pipe_context *pctx)
pctx->delete_vertex_elements_state = etna_vertex_elements_state_delete;
pctx->bind_vertex_elements_state = etna_vertex_elements_state_bind;
pctx->create_stream_output_target = etna_create_stream_output_target;
pctx->stream_output_target_destroy = etna_stream_output_target_destroy;
pctx->set_stream_output_targets = etna_set_stream_output_targets;
}