struct etna_context *ctx = etna_context(pctx);
struct etna_screen *screen = ctx->screen;
- if (ctx->used_resources) {
- mtx_lock(&screen->lock);
+ mtx_lock(&screen->lock);
+ if (ctx->used_resources_read) {
+
+ /*
+ * There should be no resources tracked in the context when it's being
+ * destroyed. Be sure there are none to avoid memory leaks on buggy
+ * programs.
+ */
+ set_foreach(ctx->used_resources_read, entry) {
+ struct etna_resource *rsc = (struct etna_resource *)entry->key;
+
+ _mesa_set_remove_key(rsc->pending_ctx, ctx);
+ }
+ _mesa_set_destroy(ctx->used_resources_read, NULL);
+
+ }
+ if (ctx->used_resources_write) {
/*
* There should be no resources tracked in the context when it's being
* destroyed. Be sure there are none to avoid memory leaks on buggy
* programs.
*/
- set_foreach(ctx->used_resources, entry) {
+ set_foreach(ctx->used_resources_write, entry) {
struct etna_resource *rsc = (struct etna_resource *)entry->key;
_mesa_set_remove_key(rsc->pending_ctx, ctx);
}
- _mesa_set_destroy(ctx->used_resources, NULL);
+ _mesa_set_destroy(ctx->used_resources_write, NULL);
- mtx_unlock(&screen->lock);
}
+ mtx_unlock(&screen->lock);
if (ctx->dummy_rt)
etna_bo_del(ctx->dummy_rt);
* Go through all _resources_ pending in this _context_ and mark them as
* not pending in this _context_ anymore, since they were just flushed.
*/
- set_foreach(ctx->used_resources, entry) {
+ set_foreach(ctx->used_resources_read, entry) {
struct etna_resource *rsc = (struct etna_resource *)entry->key;
struct pipe_resource *referenced = &rsc->base;
- rsc->status = 0;
+ _mesa_set_remove_key(rsc->pending_ctx, ctx);
+
+ pipe_resource_reference(&referenced, NULL);
+ }
+ _mesa_set_clear(ctx->used_resources_read, NULL);
+
+ set_foreach(ctx->used_resources_write, entry) {
+ struct etna_resource *rsc = (struct etna_resource *)entry->key;
+ struct pipe_resource *referenced = &rsc->base;
_mesa_set_remove_key(rsc->pending_ctx, ctx);
pipe_resource_reference(&referenced, NULL);
}
- _mesa_set_clear(ctx->used_resources, NULL);
+ _mesa_set_clear(ctx->used_resources_write, NULL);
mtx_unlock(&screen->lock);
if (ctx->stream == NULL)
goto fail;
- ctx->used_resources = _mesa_set_create(NULL, _mesa_hash_pointer,
+ ctx->used_resources_read = _mesa_set_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ if (!ctx->used_resources_read)
+ goto fail;
+
+ ctx->used_resources_write = _mesa_set_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
- if (!ctx->used_resources)
+ if (!ctx->used_resources_write)
goto fail;
/* context ctxate setup */
struct etna_reloc dummy_rt_reloc;
/* set of resources used by currently-unsubmitted renders */
- struct set *used_resources;
+ struct set *used_resources_read;
+ struct set *used_resources_write;
};
static inline struct etna_context *
}
}
+enum etna_resource_status
+etna_resource_get_status(struct etna_context *ctx, struct etna_resource *rsc)
+{
+ enum etna_resource_status newstatus = 0;
+
+ set_foreach(rsc->pending_ctx, entry) {
+ struct etna_context *extctx = (struct etna_context *)entry->key;
+ struct pipe_context *pctx = &extctx->base;
+
+ set_foreach(extctx->used_resources_read, entry2) {
+ struct etna_resource *rsc2 = (struct etna_resource *)entry2->key;
+ if (ctx == extctx || rsc2 != rsc)
+ continue;
+
+ newstatus |= ETNA_PENDING_READ;
+ }
+
+ set_foreach(extctx->used_resources_write, entry2) {
+ struct etna_resource *rsc2 = (struct etna_resource *)entry2->key;
+ if (ctx == extctx || rsc2 != rsc)
+ continue;
+
+ newstatus |= ETNA_PENDING_WRITE;
+ }
+ }
+
+ return newstatus;
+}
+
void
etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
enum etna_resource_status status)
if (!prsc)
return;
+ mtx_lock(&screen->lock);
+
rsc = etna_resource(prsc);
- mtx_lock(&screen->lock);
+ enum etna_resource_status newstatus = 0;
- /*
- * 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;
+ set_foreach(rsc->pending_ctx, entry) {
+ struct etna_context *extctx = (struct etna_context *)entry->key;
+ struct pipe_context *pctx = &extctx->base;
+
+ set_foreach(extctx->used_resources_read, entry2) {
+ struct etna_resource *rsc2 = (struct etna_resource *)entry2->key;
+ if (ctx == extctx || rsc2 != rsc)
+ continue;
+
+ if (status & ETNA_PENDING_WRITE)
+ pctx->flush(pctx, NULL, 0);
+ }
- if (extctx == ctx)
+ set_foreach(extctx->used_resources_write, entry2) {
+ struct etna_resource *rsc2 = (struct etna_resource *)entry2->key;
+ if (ctx == extctx || rsc2 != rsc)
continue;
pctx->flush(pctx, NULL, 0);
- /* It's safe to clear the status here. If we need to flush it means
- * either another context had the resource in exclusive (write) use,
- * or we transition the resource to exclusive use in our context.
- * In both cases the new status accurately reflects the resource use
- * after the flush.
- */
- rsc->status = 0;
}
}
- rsc->status |= status;
+ rsc->status = status;
if (!_mesa_set_search(rsc->pending_ctx, ctx)) {
pipe_resource_reference(&referenced, prsc);
- _mesa_set_add(ctx->used_resources, rsc);
+ _mesa_set_add((status & ETNA_PENDING_READ) ?
+ ctx->used_resources_read : ctx->used_resources_write, rsc);
_mesa_set_add(rsc->pending_ctx, ctx);
}
return (struct etna_resource *)p;
}
+enum etna_resource_status
+etna_resource_get_status(struct etna_context *ctx, struct etna_resource *rsc);
+
void
etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
enum etna_resource_status status);