diff options
author | Rob Clark <robclark@freedesktop.org> | 2016-06-28 13:33:07 -0400 |
---|---|---|
committer | Rob Clark <robclark@freedesktop.org> | 2016-07-20 19:42:21 -0400 |
commit | 6a23bd4b3c52fcd7529062b31c36dd03ae0cdd75 (patch) | |
tree | 2bbeb14cd7be273fe2718bf3f9b61ed9131a3e22 /freedreno | |
parent | 419a154dbef839b920689bea72aa9af41b2b114f (diff) |
freedreno/msm: use hashtable to track bo idx
Note: cache the last ring the bo was emitted on, to avoid excess
hashtable lookups. We do this by tracking ring seqno to avoid
problems with dangling pointers.
Signed-off-by: Rob Clark <robclark@freedesktop.org>
Diffstat (limited to 'freedreno')
-rw-r--r-- | freedreno/msm/msm_priv.h | 16 | ||||
-rw-r--r-- | freedreno/msm/msm_ringbuffer.c | 38 |
2 files changed, 31 insertions, 23 deletions
diff --git a/freedreno/msm/msm_priv.h b/freedreno/msm/msm_priv.h index 1f44398d..6d670aab 100644 --- a/freedreno/msm/msm_priv.h +++ b/freedreno/msm/msm_priv.h @@ -40,6 +40,7 @@ struct msm_device { struct fd_device base; struct fd_bo_cache ring_cache; + unsigned ring_cnt; }; static inline struct msm_device * to_msm_device(struct fd_device *x) @@ -72,18 +73,11 @@ struct msm_bo { struct fd_bo base; uint64_t offset; uint64_t presumed; - /* in the common case, a bo won't be referenced by more than a single - * (parent) ring[*]. So to avoid looping over all the bo's in the - * reloc table to find the idx of a bo that might already be in the - * table, we cache the idx in the bo. But in order to detect the - * slow-path where bo is ref'd in multiple rb's, we also must track - * the current_ring for which the idx is valid. See bo2idx(). - * - * [*] in case multiple ringbuffers, ie. one toplevel and other rb(s) - * used for IB target(s), the toplevel rb is the parent which is - * tracking bo's for the submit + /* to avoid excess hashtable lookups, cache the ring this bo was + * last emitted on (since that will probably also be the next ring + * it is emitted on) */ - struct fd_ringbuffer *current_ring; + unsigned current_ring_seqno; uint32_t idx; }; diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index 86fc83e0..fbfaefae 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c @@ -92,6 +92,11 @@ struct msm_ringbuffer { int is_growable; unsigned cmd_count; + + unsigned seqno; + + /* maps fd_bo to idx: */ + void *bo_table; }; static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x) @@ -217,21 +222,24 @@ static uint32_t bo2idx(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t fl struct msm_bo *msm_bo = to_msm_bo(bo); uint32_t idx; pthread_mutex_lock(&idx_lock); - if (!msm_bo->current_ring) { - idx = append_bo(ring, bo); - msm_bo->current_ring = ring; - msm_bo->idx = idx; - } else if (msm_bo->current_ring == ring) { + if (msm_bo->current_ring_seqno == msm_ring->seqno) { idx = msm_bo->idx; } else { - /* slow-path: */ - for (idx = 0; idx < msm_ring->nr_bos; idx++) - if (msm_ring->bos[idx] == bo) - break; - if (idx == msm_ring->nr_bos) { - /* not found */ + void *val; + + if (!msm_ring->bo_table) + msm_ring->bo_table = drmHashCreate(); + + if (!drmHashLookup(msm_ring->bo_table, bo->handle, &val)) { + /* found */ + idx = (uint32_t)val; + } else { idx = append_bo(ring, bo); + val = (void *)idx; + drmHashInsert(msm_ring->bo_table, bo->handle, val); } + msm_bo->current_ring_seqno = msm_ring->seqno; + msm_bo->idx = idx; } pthread_mutex_unlock(&idx_lock); if (flags & FD_RELOC_READ) @@ -318,7 +326,7 @@ static void flush_reset(struct fd_ringbuffer *ring) for (i = 0; i < msm_ring->nr_bos; i++) { struct msm_bo *msm_bo = to_msm_bo(msm_ring->bos[i]); - msm_bo->current_ring = NULL; + msm_bo->current_ring_seqno = 0; fd_bo_del(&msm_bo->base); } @@ -333,6 +341,11 @@ static void flush_reset(struct fd_ringbuffer *ring) msm_ring->nr_cmds = 0; msm_ring->nr_bos = 0; + if (msm_ring->bo_table) { + drmHashDestroy(msm_ring->bo_table); + msm_ring->bo_table = NULL; + } + if (msm_ring->is_growable) { delete_cmds(msm_ring); } else { @@ -551,6 +564,7 @@ drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe, } list_inithead(&msm_ring->cmd_list); + msm_ring->seqno = ++to_msm_device(pipe->dev)->ring_cnt; ring = &msm_ring->base; ring->funcs = &funcs; |