From 5e07201b7ce2c09d329fad93ab4e778863e2a13b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 9 Mar 2026 12:14:08 -0700 Subject: [PATCH] freedreno/drm: Shareable stateobjs The special case of CS stateobjs can be shared across contexts/threads. In all other cases, they are private to a single ctx, and it is safe to make single-threaded assumptions when it comes to fast-paths. See also commit b74a07a422a9 ("freedreno/a6xx: Avoid touching long lived stateobj refcnt"). Signed-off-by: Rob Clark Part-of: --- src/freedreno/drm/freedreno_ringbuffer.c | 8 ++++++++ src/freedreno/drm/freedreno_ringbuffer.h | 9 ++++++++- src/freedreno/drm/freedreno_ringbuffer_sp.c | 3 ++- src/gallium/drivers/freedreno/a6xx/fd6_compute.cc | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/freedreno/drm/freedreno_ringbuffer.c b/src/freedreno/drm/freedreno_ringbuffer.c index b4b5937aab4..418172b3fdd 100644 --- a/src/freedreno/drm/freedreno_ringbuffer.c +++ b/src/freedreno/drm/freedreno_ringbuffer.c @@ -79,3 +79,11 @@ fd_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size) { return pipe->funcs->ringbuffer_new_object(pipe, size); } + +struct fd_ringbuffer * +fd_ringbuffer_new_shareable_object(struct fd_pipe *pipe, uint32_t size) +{ + struct fd_ringbuffer *ring = fd_ringbuffer_new_object(pipe, size); + ring->flags |= FD_RINGBUFFER_SHAREABLE; + return ring; +} diff --git a/src/freedreno/drm/freedreno_ringbuffer.h b/src/freedreno/drm/freedreno_ringbuffer.h index 0f0316de620..88a4bca7dd5 100644 --- a/src/freedreno/drm/freedreno_ringbuffer.h +++ b/src/freedreno/drm/freedreno_ringbuffer.h @@ -52,8 +52,13 @@ enum fd_ringbuffer_flags { */ FD_RINGBUFFER_GROWABLE = 0x4, + /* Indicates an _FD_RINGBUFFER_OBJECT that can be shared + * across threads + */ + FD_RINGBUFFER_SHAREABLE = 0x8, + /* Internal use only: */ - _FD_RINGBUFFER_OBJECT = 0x8, + _FD_RINGBUFFER_OBJECT = 0x10, }; /* A submit object manages/tracks all the state buildup for a "submit" @@ -123,6 +128,8 @@ struct fd_ringbuffer { */ struct fd_ringbuffer *fd_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size); +struct fd_ringbuffer * +fd_ringbuffer_new_shareable_object(struct fd_pipe *pipe, uint32_t size); /* * Helpers for ref/unref with some extra debugging.. unref() returns true if diff --git a/src/freedreno/drm/freedreno_ringbuffer_sp.c b/src/freedreno/drm/freedreno_ringbuffer_sp.c index 7b1831cc6e2..7f50fccba80 100644 --- a/src/freedreno/drm/freedreno_ringbuffer_sp.c +++ b/src/freedreno/drm/freedreno_ringbuffer_sp.c @@ -595,7 +595,8 @@ fd_ringbuffer_sp_attach_ring_nonobj(struct fd_ringbuffer *ring, if (!(target->flags & _FD_RINGBUFFER_OBJECT)) return size; - if (fd_submit->seqno != fd_target->u.last_submit_seqno) { + if ((fd_submit->seqno != fd_target->u.last_submit_seqno) || + (target->flags & FD_RINGBUFFER_SHAREABLE)) { for (unsigned i = 0; i < fd_target->u.nr_reloc_bos; i++) { fd_submit_append_bo(fd_submit, fd_target->u.reloc_bos[i]); } diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_compute.cc b/src/gallium/drivers/freedreno/a6xx/fd6_compute.cc index 0a2f206423a..fc6da44260d 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_compute.cc +++ b/src/gallium/drivers/freedreno/a6xx/fd6_compute.cc @@ -170,7 +170,7 @@ fd6_launch_grid(struct fd_context *ctx, const struct pipe_grid_info *info) in_dt struct ir3_shader_variant *v = ir3_shader_variant(ir3_get_shader(hwcso), key, false, &ctx->debug); if (v) { - cp->stateobj = fd_ringbuffer_new_object(ctx->pipe, 0x1000); + cp->stateobj = fd_ringbuffer_new_shareable_object(ctx->pipe, 0x1000); fd_cs cs(cp->stateobj); with_crb (cs, 9) cs_program_emit(screen, crb, v);