etnaviv: drm: always use hash to track BO index

Currently the buffer index hash is only used if the BO is used in
multiple streams and the current index is cached on the BO. This
introduces some shared state on the BO, which necessitates the use
of a lock to keep this state consistent across threads, which
negates some of the benefits of caching the index.

Always use the hash to keep track of the submit BOs, to get rid
of the shared state and simplify the code.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14466>
This commit is contained in:
Lucas Stach 2021-12-10 21:35:11 +01:00 committed by Marge Bot
parent 7bb62d9dd8
commit 8997b9579f
2 changed files with 17 additions and 42 deletions

View File

@ -27,11 +27,11 @@
#include <assert.h>
#include <stdlib.h>
#include "util/hash_table.h"
#include "etnaviv_drmif.h"
#include "etnaviv_priv.h"
static simple_mtx_t idx_lock = _SIMPLE_MTX_INITIALIZER_NP;
static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz)
{
if ((nr + 1) > *max) {
@ -117,6 +117,8 @@ struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe,
stream->force_flush = force_flush;
stream->force_flush_priv = priv;
stream->bo_table = _mesa_pointer_hash_table_create(NULL);
return &stream->base;
fail:
@ -130,6 +132,8 @@ void etna_cmd_stream_del(struct etna_cmd_stream *stream)
{
struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
_mesa_hash_table_destroy(priv->bo_table, NULL);
free(stream->buffer);
free(priv->submit.relocs);
free(priv->submit.pmrs);
@ -154,8 +158,6 @@ static uint32_t append_bo(struct etna_cmd_stream *stream, struct etna_bo *bo)
struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
uint32_t idx;
simple_mtx_assert_locked(&idx_lock);
idx = APPEND(&priv->submit, bos);
idx = APPEND(priv, bos);
@ -173,31 +175,19 @@ static uint32_t bo2idx(struct etna_cmd_stream *stream, struct etna_bo *bo,
uint32_t flags)
{
struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
uint32_t hash = _mesa_hash_pointer(bo);
struct hash_entry *entry;
uint32_t idx;
simple_mtx_lock(&idx_lock);
entry = _mesa_hash_table_search_pre_hashed(priv->bo_table, hash, bo);
if (bo->current_stream == stream) {
idx = bo->idx;
if (entry) {
idx = (uint32_t)(uintptr_t)entry->data;
} else {
void *val;
if (!priv->bo_table)
priv->bo_table = drmHashCreate();
if (!drmHashLookup(priv->bo_table, bo->handle, &val)) {
/* found */
idx = (uint32_t)(uintptr_t)val;
} else {
idx = append_bo(stream, bo);
val = (void *)(uintptr_t)idx;
drmHashInsert(priv->bo_table, bo->handle, val);
}
bo->current_stream = stream;
bo->idx = idx;
idx = append_bo(stream, bo);
_mesa_hash_table_insert_pre_hashed(priv->bo_table, hash, bo,
(void *)(uintptr_t)idx);
}
simple_mtx_unlock(&idx_lock);
if (flags & ETNA_RELOC_READ)
priv->submit.bos[idx].flags |= ETNA_SUBMIT_BO_READ;
@ -249,17 +239,10 @@ void etna_cmd_stream_flush(struct etna_cmd_stream *stream, int in_fence_fd,
else
priv->last_timestamp = req.fence;
for (uint32_t i = 0; i < priv->nr_bos; i++) {
struct etna_bo *bo = priv->bos[i];
for (uint32_t i = 0; i < priv->nr_bos; i++)
etna_bo_del(priv->bos[i]);
bo->current_stream = NULL;
etna_bo_del(bo);
}
if (priv->bo_table) {
drmHashDestroy(priv->bo_table);
priv->bo_table = NULL;
}
_mesa_hash_table_clear(priv->bo_table, NULL);
if (out_fence_fd)
*out_fence_fd = req.fence_fd;

View File

@ -113,14 +113,6 @@ struct etna_bo {
uint32_t va; /* GPU virtual address */
int refcnt;
/*
* To avoid excess hashtable lookups, cache the stream this bo was
* last emitted on (since that will probably also be the next ring
* it is emitted on).
*/
struct etna_cmd_stream *current_stream;
uint32_t idx;
int reuse;
struct list_head list; /* bucket-list entry */
time_t free_time; /* time when added to bucket-list */