diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c index 464667e38d0..1de7b449694 100644 --- a/src/gallium/drivers/zink/zink_batch.c +++ b/src/gallium/drivers/zink/zink_batch.c @@ -180,22 +180,18 @@ zink_batch_reference_resource_rw(struct zink_batch *batch, struct zink_resource zink_get_depth_stencil_resources((struct pipe_resource*)res, NULL, &stencil); - uint32_t cur_uses = zink_get_resource_usage(res); - uint32_t uses_check = cur_uses; - cur_uses &= ~(ZINK_RESOURCE_ACCESS_READ << batch->batch_id); - cur_uses &= ~(ZINK_RESOURCE_ACCESS_WRITE << batch->batch_id); if (batch->batch_id == ZINK_COMPUTE_BATCH_ID) { - if (cur_uses >= ZINK_RESOURCE_ACCESS_WRITE || (write && cur_uses)) + if ((write && zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_RW, ZINK_QUEUE_GFX)) || + (!write && zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_WRITE, ZINK_QUEUE_GFX))) batch_to_flush = 0; } else { - if (cur_uses & (ZINK_RESOURCE_ACCESS_WRITE << ZINK_COMPUTE_BATCH_ID) || - (write && cur_uses & (ZINK_RESOURCE_ACCESS_READ << ZINK_COMPUTE_BATCH_ID))) + if ((write && zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_READ, ZINK_QUEUE_COMPUTE)) || + zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_WRITE, ZINK_QUEUE_COMPUTE)) batch_to_flush = ZINK_COMPUTE_BATCH_ID; } /* if the resource already has usage of any sort set for this batch, we can skip hashing */ - uint32_t check_mask = (ZINK_RESOURCE_ACCESS_READ | ZINK_RESOURCE_ACCESS_WRITE) << batch->batch_id; - if (!(uses_check & check_mask)) { + if (!zink_resource_has_usage_for_id(res, batch->batch_id)) { bool found = false; _mesa_set_search_and_add(batch->resources, res->obj, &found); if (!found) { diff --git a/src/gallium/drivers/zink/zink_query.c b/src/gallium/drivers/zink/zink_query.c index dbc960fb528..afa55f212f0 100644 --- a/src/gallium/drivers/zink/zink_query.c +++ b/src/gallium/drivers/zink/zink_query.c @@ -454,10 +454,7 @@ copy_results_to_buffer(struct zink_context *ctx, struct zink_query *query, struc if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) result_size += base_result_size; if (is_cs_query(query)) { - uint32_t batch_uses = zink_get_resource_usage(res); - batch_uses &= ~(ZINK_RESOURCE_ACCESS_READ << ZINK_COMPUTE_BATCH_ID); - batch_uses &= ~(ZINK_RESOURCE_ACCESS_WRITE << ZINK_COMPUTE_BATCH_ID); - if (batch_uses >= ZINK_RESOURCE_ACCESS_WRITE) + if (zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_WRITE, ZINK_QUEUE_GFX)) ctx->base.flush(&ctx->base, NULL, PIPE_FLUSH_HINT_FINISH); } /* if it's a single query that doesn't need special handling, we can copy it and be done */ diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index c26dbed939d..b96f9e7a2ce 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -53,11 +53,19 @@ debug_describe_zink_resource_object(char *buf, const struct zink_resource_object sprintf(buf, "zink_resource_object"); } +static uint32_t +get_resource_usage(struct zink_resource *res) +{ + uint32_t batch_uses = 0; + for (unsigned i = 0; i < ARRAY_SIZE(res->obj->batch_uses); i++) + batch_uses |= p_atomic_read(&res->obj->batch_uses[i]) << i; + return batch_uses; +} static void resource_sync_writes_from_batch_usage(struct zink_context *ctx, struct zink_resource *res) { - uint32_t batch_uses = zink_get_resource_usage(res); + uint32_t batch_uses = get_resource_usage(res); batch_uses &= ~(ZINK_RESOURCE_ACCESS_READ << ZINK_COMPUTE_BATCH_ID); uint32_t write_mask = 0; @@ -68,7 +76,7 @@ resource_sync_writes_from_batch_usage(struct zink_context *ctx, struct zink_reso if (batch_id == -1) break; zink_wait_on_batch(ctx, batch_id); - batch_uses &= ~((ZINK_RESOURCE_ACCESS_READ | ZINK_RESOURCE_ACCESS_WRITE) << batch_id); + batch_uses &= ~((ZINK_RESOURCE_ACCESS_RW) << batch_id); } } @@ -595,7 +603,7 @@ zink_resource_invalidate(struct pipe_context *pctx, struct pipe_resource *pres) res->bind_history &= ~ZINK_RESOURCE_USAGE_STREAMOUT; util_range_set_empty(&res->valid_buffer_range); - if (!zink_get_resource_usage(res)) + if (!get_resource_usage(res)) return; struct zink_resource_object *old_obj = res->obj; @@ -632,13 +640,32 @@ zink_transfer_copy_bufimage(struct zink_context *ctx, box.y, box.z, trans->base.level, &box, trans->base.usage); } -uint32_t -zink_get_resource_usage(struct zink_resource *res) +#define ALL_GFX_USAGE(batch_uses, usage) (batch_uses & ((usage << ZINK_NUM_GFX_BATCHES) - ((usage & ZINK_RESOURCE_ACCESS_RW)))) +#define ALL_COMPUTE_USAGE(batch_uses, usage) (batch_uses & (usage << ZINK_COMPUTE_BATCH_ID)) + +bool +zink_resource_has_usage(struct zink_resource *res, enum zink_resource_access usage, enum zink_queue queue) { - uint32_t batch_uses = 0; - for (unsigned i = 0; i < ARRAY_SIZE(res->obj->batch_uses); i++) - batch_uses |= p_atomic_read(&res->obj->batch_uses[i]) << i; - return batch_uses; + uint32_t batch_uses = get_resource_usage(res); + switch (queue) { + case ZINK_QUEUE_COMPUTE: + return ALL_COMPUTE_USAGE(batch_uses, usage); + case ZINK_QUEUE_GFX: + return ALL_GFX_USAGE(batch_uses, usage); + case ZINK_QUEUE_ANY: + return ALL_GFX_USAGE(batch_uses, usage) || ALL_COMPUTE_USAGE(batch_uses, usage); + default: + break; + } + unreachable("unknown queue type"); + return false; +} + +bool +zink_resource_has_usage_for_id(struct zink_resource *res, uint32_t id) +{ + uint32_t batch_uses = get_resource_usage(res); + return batch_uses & (ZINK_RESOURCE_ACCESS_RW) << id; } static void * @@ -652,7 +679,6 @@ zink_transfer_map(struct pipe_context *pctx, struct zink_context *ctx = zink_context(pctx); struct zink_screen *screen = zink_screen(pctx->screen); struct zink_resource *res = zink_resource(pres); - uint32_t batch_uses = zink_get_resource_usage(res); struct zink_transfer *trans = slab_alloc(&ctx->transfer_pool); if (!trans) @@ -679,12 +705,11 @@ zink_transfer_map(struct pipe_context *pctx, } if (util_ranges_intersect(&res->valid_buffer_range, box->x, box->x + box->width)) { /* special case compute reads since they aren't handled by zink_fence_wait() */ - if (usage & PIPE_MAP_WRITE && (batch_uses & (ZINK_RESOURCE_ACCESS_READ << ZINK_COMPUTE_BATCH_ID))) + if (usage & PIPE_MAP_WRITE && zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_READ, ZINK_QUEUE_COMPUTE)) zink_wait_on_batch(ctx, ZINK_COMPUTE_BATCH_ID); - batch_uses &= ~(ZINK_RESOURCE_ACCESS_READ << ZINK_COMPUTE_BATCH_ID); - if (usage & PIPE_MAP_READ && batch_uses >= ZINK_RESOURCE_ACCESS_WRITE) + if (usage & PIPE_MAP_READ && zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_WRITE, ZINK_QUEUE_ANY)) resource_sync_writes_from_batch_usage(ctx, res); - else if (usage & PIPE_MAP_WRITE && batch_uses) { + else if (usage & PIPE_MAP_WRITE && zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_RW, ZINK_QUEUE_ANY)) { /* need to wait for all rendering to finish * TODO: optimize/fix this to be much less obtrusive * mesa/mesa#2966 @@ -762,7 +787,7 @@ zink_transfer_map(struct pipe_context *pctx, if (usage & PIPE_MAP_READ) { /* TODO: can probably just do a full cs copy if it's already in a cs batch */ - if (batch_uses & (ZINK_RESOURCE_ACCESS_WRITE << ZINK_COMPUTE_BATCH_ID)) + if (zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_WRITE, ZINK_QUEUE_COMPUTE)) /* don't actually have to stall here, only ensure batch is submitted */ zink_flush_compute(ctx); struct zink_context *ctx = zink_context(pctx); @@ -780,10 +805,9 @@ zink_transfer_map(struct pipe_context *pctx, } else { assert(!res->optimal_tiling); /* special case compute reads since they aren't handled by zink_fence_wait() */ - if (batch_uses & (ZINK_RESOURCE_ACCESS_READ << ZINK_COMPUTE_BATCH_ID)) + if (zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_READ, ZINK_QUEUE_COMPUTE)) zink_wait_on_batch(ctx, ZINK_COMPUTE_BATCH_ID); - batch_uses &= ~(ZINK_RESOURCE_ACCESS_READ << ZINK_COMPUTE_BATCH_ID); - if (batch_uses >= ZINK_RESOURCE_ACCESS_WRITE) { + if (zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_RW, ZINK_QUEUE_ANY)) { if (usage & PIPE_MAP_READ) resource_sync_writes_from_batch_usage(ctx, res); else @@ -828,13 +852,9 @@ zink_transfer_flush_region(struct pipe_context *pctx, if (trans->base.usage & PIPE_MAP_WRITE) { if (trans->staging_res) { struct zink_resource *staging_res = zink_resource(trans->staging_res); - uint32_t batch_uses = zink_get_resource_usage(res) | zink_get_resource_usage(staging_res); - if (batch_uses & (ZINK_RESOURCE_ACCESS_WRITE << ZINK_COMPUTE_BATCH_ID)) { + if (zink_resource_has_usage(res, ZINK_RESOURCE_ACCESS_WRITE, ZINK_QUEUE_COMPUTE)) /* don't actually have to stall here, only ensure batch is submitted */ zink_flush_compute(ctx); - batch_uses &= ~(ZINK_RESOURCE_ACCESS_WRITE << ZINK_COMPUTE_BATCH_ID); - batch_uses &= ~(ZINK_RESOURCE_ACCESS_READ << ZINK_COMPUTE_BATCH_ID); - } if (ptrans->resource->target == PIPE_BUFFER) zink_copy_buffer(ctx, NULL, res, staging_res, box->x, box->x, box->width); diff --git a/src/gallium/drivers/zink/zink_resource.h b/src/gallium/drivers/zink/zink_resource.h index 23575b0d48d..cbe870cf5e3 100644 --- a/src/gallium/drivers/zink/zink_resource.h +++ b/src/gallium/drivers/zink/zink_resource.h @@ -124,8 +124,11 @@ zink_resource_setup_transfer_layouts(struct zink_context *ctx, struct zink_resou int zink_get_resource_latest_batch_usage(struct zink_context *ctx, uint32_t batch_uses); -uint32_t -zink_get_resource_usage(struct zink_resource *res); +bool +zink_resource_has_usage(struct zink_resource *res, enum zink_resource_access usage, enum zink_queue queue); + +bool +zink_resource_has_usage_for_id(struct zink_resource *res, uint32_t id); void zink_resource_desc_set_add(struct zink_resource *res, struct zink_descriptor_set *zds, unsigned idx);