From fcbf206aa293af2d478e48dc45e4e8b3af0e7737 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sun, 22 Jul 2018 11:44:15 -0400 Subject: [PATCH] freedreno: add fd_ringbuffer_new_object() Add new API for reusable "state objects" which can be re-used multiple times. Backend implementation for msm will follow. (Probably not needed to support this for any device that uses kgsl backend, since this is mostly useful for a5xx+.) Signed-off-by: Rob Clark --- freedreno/freedreno-symbol-check | 2 ++ freedreno/freedreno_priv.h | 7 +++++- freedreno/freedreno_ringbuffer.c | 42 +++++++++++++++++++++++++++++--- freedreno/freedreno_ringbuffer.h | 9 +++++-- freedreno/kgsl/kgsl_priv.h | 2 +- freedreno/kgsl/kgsl_ringbuffer.c | 4 ++- freedreno/msm/msm_priv.h | 2 +- freedreno/msm/msm_ringbuffer.c | 4 ++- 8 files changed, 62 insertions(+), 10 deletions(-) diff --git a/freedreno/freedreno-symbol-check b/freedreno/freedreno-symbol-check index e6e5719d..e732c995 100755 --- a/freedreno/freedreno-symbol-check +++ b/freedreno/freedreno-symbol-check @@ -46,10 +46,12 @@ fd_ringbuffer_emit_reloc_ring_full fd_ringbuffer_flush fd_ringbuffer_grow fd_ringbuffer_new +fd_ringbuffer_new_object fd_ringbuffer_reloc fd_ringbuffer_reloc2 fd_ringbuffer_reset fd_ringbuffer_set_parent +fd_ringbuffer_size fd_ringbuffer_timestamp fd_ringmarker_del fd_ringmarker_dwords diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h index b0a48adf..9d51c368 100644 --- a/freedreno/freedreno_priv.h +++ b/freedreno/freedreno_priv.h @@ -114,8 +114,13 @@ drm_private int fd_bo_cache_free(struct fd_bo_cache *cache, struct fd_bo *bo); /* for where @table_lock is already held: */ drm_private void fd_device_del_locked(struct fd_device *dev); +enum fd_ringbuffer_flags { + FD_RINGBUFFER_OBJECT = 0x1, +}; + struct fd_pipe_funcs { - struct fd_ringbuffer * (*ringbuffer_new)(struct fd_pipe *pipe, uint32_t size); + struct fd_ringbuffer * (*ringbuffer_new)(struct fd_pipe *pipe, uint32_t size, + enum fd_ringbuffer_flags flags); int (*get_param)(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value); int (*wait)(struct fd_pipe *pipe, uint32_t timestamp, uint64_t timeout); void (*destroy)(struct fd_pipe *pipe); diff --git a/freedreno/freedreno_ringbuffer.c b/freedreno/freedreno_ringbuffer.c index 3834b51b..a0be2dbb 100644 --- a/freedreno/freedreno_ringbuffer.c +++ b/freedreno/freedreno_ringbuffer.c @@ -32,15 +32,17 @@ #include "freedreno_priv.h" #include "freedreno_ringbuffer.h" -struct fd_ringbuffer * -fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size) +static struct fd_ringbuffer * +ringbuffer_new(struct fd_pipe *pipe, uint32_t size, + enum fd_ringbuffer_flags flags) { struct fd_ringbuffer *ring; - ring = pipe->funcs->ringbuffer_new(pipe, size); + ring = pipe->funcs->ringbuffer_new(pipe, size, flags); if (!ring) return NULL; + ring->flags = flags; ring->pipe = pipe; ring->start = ring->funcs->hostptr(ring); ring->end = &(ring->start[ring->size/4]); @@ -50,6 +52,23 @@ fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size) return ring; } +struct fd_ringbuffer * +fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size) +{ + return ringbuffer_new(pipe, size, 0); +} + +struct fd_ringbuffer * +fd_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size) +{ + /* we can't really support "growable" rb's in general for + * stateobj's since we need a single gpu addr (ie. can't + * do the trick of a chain of IB packets): + */ + assert(size); + return ringbuffer_new(pipe, size, FD_RINGBUFFER_OBJECT); +} + void fd_ringbuffer_del(struct fd_ringbuffer *ring) { fd_ringbuffer_reset(ring); @@ -63,6 +82,8 @@ void fd_ringbuffer_del(struct fd_ringbuffer *ring) void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, struct fd_ringbuffer *parent) { + /* state objects should not be parented! */ + assert(!(ring->flags & FD_RINGBUFFER_OBJECT)); ring->parent = parent; } @@ -151,6 +172,21 @@ fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, return ring->funcs->emit_reloc_ring(ring, target, cmd_idx, 0, size); } +uint32_t +fd_ringbuffer_size(struct fd_ringbuffer *ring) +{ + /* only really needed for stateobj ringbuffers, and won't really + * do what you expect for growable rb's.. so lets just restrict + * this to stateobj's for now: + */ + assert(ring->flags & FD_RINGBUFFER_OBJECT); + return offset_bytes(ring->cur, ring->start); +} + +/* + * Deprecated ringmarker API: + */ + struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring) { struct fd_ringmarker *marker = NULL; diff --git a/freedreno/freedreno_ringbuffer.h b/freedreno/freedreno_ringbuffer.h index 0a3d6f77..69e7ed99 100644 --- a/freedreno/freedreno_ringbuffer.h +++ b/freedreno/freedreno_ringbuffer.h @@ -33,8 +33,7 @@ /* the ringbuffer object is not opaque so that OUT_RING() type stuff * can be inlined. Note that users should not make assumptions about - * the size of this struct.. more stuff will be added when we eventually - * have a kernel driver that can deal w/ reloc's.. + * the size of this struct. */ struct fd_ringbuffer_funcs; @@ -52,10 +51,15 @@ struct fd_ringbuffer { * ringbuffer data */ void *user; + + uint32_t flags; }; struct fd_ringbuffer * fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size); +struct fd_ringbuffer * fd_ringbuffer_new_object(struct fd_pipe *pipe, + uint32_t size); + void fd_ringbuffer_del(struct fd_ringbuffer *ring); void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, struct fd_ringbuffer *parent); @@ -95,6 +99,7 @@ will_be_deprecated void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring); uint32_t fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, struct fd_ringbuffer *target, uint32_t cmd_idx); +uint32_t fd_ringbuffer_size(struct fd_ringbuffer *ring); will_be_deprecated struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring); will_be_deprecated void fd_ringmarker_del(struct fd_ringmarker *marker); diff --git a/freedreno/kgsl/kgsl_priv.h b/freedreno/kgsl/kgsl_priv.h index 41b13920..a6bf2d40 100644 --- a/freedreno/kgsl/kgsl_priv.h +++ b/freedreno/kgsl/kgsl_priv.h @@ -106,7 +106,7 @@ drm_private struct fd_pipe * kgsl_pipe_new(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio); drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe, - uint32_t size); + uint32_t size, enum fd_ringbuffer_flags flags); drm_private int kgsl_bo_new_handle(struct fd_device *dev, uint32_t size, uint32_t flags, uint32_t *handle); diff --git a/freedreno/kgsl/kgsl_ringbuffer.c b/freedreno/kgsl/kgsl_ringbuffer.c index a756deda..e4fdf342 100644 --- a/freedreno/kgsl/kgsl_ringbuffer.c +++ b/freedreno/kgsl/kgsl_ringbuffer.c @@ -202,11 +202,13 @@ static const struct fd_ringbuffer_funcs funcs = { }; drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe, - uint32_t size) + uint32_t size, enum fd_ringbuffer_flags flags) { struct kgsl_ringbuffer *kgsl_ring; struct fd_ringbuffer *ring = NULL; + assert(!flags); + kgsl_ring = calloc(1, sizeof(*kgsl_ring)); if (!kgsl_ring) { ERROR_MSG("allocation failed"); diff --git a/freedreno/msm/msm_priv.h b/freedreno/msm/msm_priv.h index 88ac3aa4..776859a4 100644 --- a/freedreno/msm/msm_priv.h +++ b/freedreno/msm/msm_priv.h @@ -68,7 +68,7 @@ drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio); drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe, - uint32_t size); + uint32_t size, enum fd_ringbuffer_flags flags); struct msm_bo { struct fd_bo base; diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index a87e1b9a..9812d58b 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c @@ -583,11 +583,13 @@ static const struct fd_ringbuffer_funcs funcs = { }; drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe, - uint32_t size) + uint32_t size, enum fd_ringbuffer_flags flags) { struct msm_ringbuffer *msm_ring; struct fd_ringbuffer *ring; + assert(!flags); + msm_ring = calloc(1, sizeof(*msm_ring)); if (!msm_ring) { ERROR_MSG("allocation failed");