diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 3ffdd30b0e0..ef692f223eb 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -55,6 +55,7 @@ #include "nir_builder_opcodes.h" #include "nir_intrinsics.h" #include "nir_intrinsics_indices.h" +#include "nir_xfb_info.h" #include "pool.h" void @@ -2059,6 +2060,18 @@ agx_shader_initialize(struct agx_device *dev, struct agx_uncompiled_shader *so, so->nir_sha1); so->has_xfb_info = (nir->xfb_info != NULL); + + static_assert( + ARRAY_SIZE(so->xfb_strides) == ARRAY_SIZE(nir->info.xfb_stride), + "known target count"); + + if (so->has_xfb_info) { + struct nir_xfb_info *xfb = nir->xfb_info; + + for (unsigned i = 0; i < ARRAY_SIZE(so->xfb_strides); ++i) { + so->xfb_strides[i] = xfb->buffers[i].stride; + } + } } static void * @@ -4202,6 +4215,22 @@ agx_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, (ctx->dirty & AGX_DIRTY_VERTEX)) ctx->dirty |= AGX_DIRTY_VS; + /* Transform feedback always happens via the geometry shader, so look there + * to get the XFB strides. + */ + if (ctx->stage[PIPE_SHADER_GEOMETRY].shader) { + struct agx_uncompiled_shader *gs = + ctx->stage[PIPE_SHADER_GEOMETRY].shader; + + for (unsigned i = 0; i < ctx->streamout.num_targets; ++i) { + struct agx_streamout_target *tgt = + agx_so_target(ctx->streamout.targets[i]); + + if (tgt != NULL) + tgt->stride = gs->xfb_strides[i]; + } + } + agx_update_gs(ctx, info, indirect); if (ctx->gs) { diff --git a/src/gallium/drivers/asahi/agx_state.h b/src/gallium/drivers/asahi/agx_state.h index 184c870de13..ef0486c8298 100644 --- a/src/gallium/drivers/asahi/agx_state.h +++ b/src/gallium/drivers/asahi/agx_state.h @@ -42,6 +42,9 @@ struct agx_streamout_target { struct pipe_stream_output_target base; struct pipe_resource *offset; + + /* Current stride (bytes per vertex) */ + uint32_t stride; }; static inline struct agx_streamout_target * @@ -206,6 +209,8 @@ struct agx_uncompiled_shader { struct agx_uncompiled_shader_info info; struct hash_table *variants; struct agx_uncompiled_shader *passthrough_progs[MESA_PRIM_COUNT][3][2]; + + uint32_t xfb_strides[4]; bool has_xfb_info; /* Whether the shader accesses indexed samplers via the bindless heap */ diff --git a/src/gallium/drivers/asahi/agx_streamout.c b/src/gallium/drivers/asahi/agx_streamout.c index 9dde9cee916..2e8e19bebd3 100644 --- a/src/gallium/drivers/asahi/agx_streamout.c +++ b/src/gallium/drivers/asahi/agx_streamout.c @@ -121,10 +121,13 @@ agx_draw_vbo_from_xfb(struct pipe_context *pctx, { perf_debug_ctx(agx_context(pctx), "draw auto"); - unsigned count = 0; - pipe_buffer_read(pctx, - agx_so_target(indirect->count_from_stream_output)->offset, - 0, 4, &count); + struct agx_streamout_target *so = + agx_so_target(indirect->count_from_stream_output); + + unsigned offset_B; + pipe_buffer_read(pctx, so->offset, 0, 4, &offset_B); + + unsigned count = offset_B / so->stride; /* XXX: Probably need to divide here */