#include "etnaviv_query.h"
#include "etnaviv_query_hw.h"
#include "etnaviv_rasterizer.h"
+#include "etnaviv_resource.h"
#include "etnaviv_screen.h"
#include "etnaviv_shader.h"
#include "etnaviv_state.h"
etna_cmd_stream_reset_notify(struct etna_cmd_stream *stream, void *priv)
{
struct etna_context *ctx = priv;
- struct etna_resource *rsc, *rsc_tmp;
+ struct etna_screen *screen = ctx->screen;
+ struct set_entry *entry;
etna_set_state(stream, VIVS_GL_API_MODE, VIVS_GL_API_MODE_OPENGL);
etna_set_state(stream, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x00000001);
ctx->dirty = ~0L;
ctx->dirty_sampler_views = ~0L;
- /* go through all the used resources and clear their status flag */
- LIST_FOR_EACH_ENTRY_SAFE(rsc, rsc_tmp, &ctx->used_resources, list)
- {
- debug_assert(rsc->status != 0);
- rsc->status = 0;
- rsc->pending_ctx = NULL;
- list_delinit(&rsc->list);
- }
+ /*
+ * Go through all _resources_ associated with this _screen_, pending
+ * in this _context_ and mark them as not pending in this _context_
+ * anymore, since they were just flushed.
+ */
+ mtx_lock(&screen->lock);
+ set_foreach(screen->used_resources, entry) {
+ struct etna_resource *rsc = (struct etna_resource *)entry->key;
- assert(LIST_IS_EMPTY(&ctx->used_resources));
+ _mesa_set_remove_key(rsc->pending_ctx, ctx);
+ }
+ mtx_unlock(&screen->lock);
}
static void
/* need some sane default in case state tracker doesn't set some state: */
ctx->sample_mask = 0xffff;
- list_inithead(&ctx->used_resources);
-
/* Set sensible defaults for state */
etna_cmd_stream_reset_notify(ctx->stream, ctx);
uint32_t prim_hwsupport;
struct primconvert_context *primconvert;
- /* list of resources used by currently-unsubmitted renders */
- struct list_head used_resources;
-
struct slab_child_pool transfer_pool;
struct blitter_context *blitter;
#include "etnaviv_screen.h"
#include "etnaviv_translate.h"
+#include "util/hash_table.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
rsc->addressing_mode = mode;
pipe_reference_init(&rsc->base.reference, 1);
- list_inithead(&rsc->list);
size = setup_miptree(rsc, paddingX, paddingY, msaa_xscale, msaa_yscale);
memset(map, 0, size);
}
+ rsc->pending_ctx = _mesa_set_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ if (!rsc->pending_ctx)
+ goto free_rsc;
+
return &rsc->base;
free_rsc:
static void
etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
{
+ struct etna_screen *screen = etna_screen(pscreen);
struct etna_resource *rsc = etna_resource(prsc);
+ mtx_lock(&screen->lock);
+ _mesa_set_remove_key(screen->used_resources, rsc);
+ _mesa_set_destroy(rsc->pending_ctx, NULL);
+ mtx_unlock(&screen->lock);
+
if (rsc->bo)
etna_bo_del(rsc->bo);
if (rsc->scanout)
renderonly_scanout_destroy(rsc->scanout, etna_screen(pscreen)->ro);
- list_delinit(&rsc->list);
-
pipe_resource_reference(&rsc->texture, NULL);
pipe_resource_reference(&rsc->external, NULL);
*prsc = *tmpl;
pipe_reference_init(&prsc->reference, 1);
- list_inithead(&rsc->list);
prsc->screen = pscreen;
rsc->bo = etna_screen_bo_from_handle(pscreen, handle, &level->stride);
goto fail;
}
+ rsc->pending_ctx = _mesa_set_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ if (!rsc->pending_ctx)
+ goto fail;
+
if (rsc->layout == ETNA_LAYOUT_LINEAR) {
/*
* Both sampler and pixel pipes can't handle linear, create a compatible
etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
enum etna_resource_status status)
{
+ struct etna_screen *screen = ctx->screen;
+ struct set_entry *entry;
struct etna_resource *rsc;
if (!prsc)
return;
rsc = etna_resource(prsc);
+
+ mtx_lock(&screen->lock);
+
+ /*
+ * if we are pending read or write by any other context or
+ * if reading a resource pending a write, then
+ * flush all the contexts to maintain coherency
+ */
+ if (((status & ETNA_PENDING_WRITE) && rsc->status) ||
+ ((status & ETNA_PENDING_READ) && (rsc->status & ETNA_PENDING_WRITE))) {
+ set_foreach(rsc->pending_ctx, entry) {
+ struct etna_context *extctx = (struct etna_context *)entry->key;
+ struct pipe_context *pctx = &extctx->base;
+
+ pctx->flush(pctx, NULL, 0);
+ }
+ rsc->status = 0;
+ }
+
rsc->status |= status;
- /* TODO resources can actually be shared across contexts,
- * so I'm not sure a single list-head will do the trick? */
- debug_assert((rsc->pending_ctx == ctx) || !rsc->pending_ctx);
- list_delinit(&rsc->list);
- list_addtail(&rsc->list, &ctx->used_resources);
- rsc->pending_ctx = ctx;
+ _mesa_set_add(screen->used_resources, rsc);
+ _mesa_set_add(rsc->pending_ctx, ctx);
+
+ mtx_unlock(&screen->lock);
}
bool
#include "etnaviv_tiling.h"
#include "pipe/p_state.h"
#include "util/list.h"
+#include "util/set.h"
+#include "util/u_helpers.h"
+struct etna_context;
struct pipe_screen;
struct util_dynarray;
enum etna_resource_status status;
- /* resources accessed by queued but not flushed draws are tracked
- * in the used_resources list. */
- struct list_head list;
- struct etna_context *pending_ctx;
+ struct set *pending_ctx;
};
/* returns TRUE if a is newer than b */
#include "etnaviv_resource.h"
#include "etnaviv_translate.h"
+#include "util/hash_table.h"
#include "util/os_time.h"
#include "util/u_math.h"
#include "util/u_memory.h"
{
struct etna_screen *screen = etna_screen(pscreen);
+ _mesa_set_destroy(screen->used_resources, NULL);
+ mtx_destroy(&screen->lock);
+
if (screen->perfmon)
etna_perfmon_del(screen->perfmon);
if (screen->drm_version >= ETNA_DRM_VERSION_PERFMON)
etna_pm_query_setup(screen);
+ mtx_init(&screen->lock, mtx_recursive);
+ screen->used_resources = _mesa_set_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ if (!screen->used_resources)
+ goto fail2;
+
return pscreen;
+fail2:
+ mtx_destroy(&screen->lock);
fail:
etna_screen_destroy(pscreen);
return NULL;
#include "os/os_thread.h"
#include "pipe/p_screen.h"
#include "renderonly/renderonly.h"
+#include "util/set.h"
#include "util/slab.h"
#include "util/u_dynarray.h"
+#include "util/u_helpers.h"
struct etna_bo;
struct etna_specs specs;
uint32_t drm_version;
+
+ /* set of resources used by currently-unsubmitted renders */
+ mtx_t lock;
+ struct set *used_resources;
};
static inline struct etna_screen *
* transfers without a temporary resource.
*/
if (trans->rsc || !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
+ struct etna_screen *screen = ctx->screen;
uint32_t prep_flags = 0;
/*
* current GPU usage (reads must wait for GPU writes, writes must have
* exclusive access to the buffer).
*/
+ mtx_lock(&screen->lock);
+
if ((trans->rsc && (etna_resource(trans->rsc)->status & ETNA_PENDING_WRITE)) ||
(!trans->rsc &&
(((usage & PIPE_TRANSFER_READ) && (rsc->status & ETNA_PENDING_WRITE)) ||
((usage & PIPE_TRANSFER_WRITE) && rsc->status))))
pctx->flush(pctx, NULL, 0);
+ mtx_unlock(&screen->lock);
+
if (usage & PIPE_TRANSFER_READ)
prep_flags |= DRM_ETNA_PREP_READ;
if (usage & PIPE_TRANSFER_WRITE)