diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c index 5df3887b449..28c60d8af00 100644 --- a/src/gallium/drivers/zink/zink_batch.c +++ b/src/gallium/drivers/zink/zink_batch.c @@ -804,8 +804,8 @@ zink_batch_usage_check_completion(struct zink_context *ctx, const struct zink_ba return zink_check_batch_completion(ctx, u->usage); } -void -zink_batch_usage_wait(struct zink_context *ctx, struct zink_batch_usage *u) +static void +batch_usage_wait(struct zink_context *ctx, struct zink_batch_usage *u, bool trywait) { if (!zink_batch_usage_exists(u)) return; @@ -814,9 +814,25 @@ zink_batch_usage_wait(struct zink_context *ctx, struct zink_batch_usage *u) ctx->base.flush(&ctx->base, NULL, PIPE_FLUSH_HINT_FINISH); else { //multi-context mtx_lock(&u->mtx); - cnd_wait(&u->flush, &u->mtx); + if (trywait) { + struct timespec ts = {0, 10000}; + cnd_timedwait(&u->flush, &u->mtx, &ts); + } else + cnd_wait(&u->flush, &u->mtx); mtx_unlock(&u->mtx); } } zink_wait_on_batch(ctx, u->usage); } + +void +zink_batch_usage_wait(struct zink_context *ctx, struct zink_batch_usage *u) +{ + batch_usage_wait(ctx, u, false); +} + +void +zink_batch_usage_try_wait(struct zink_context *ctx, struct zink_batch_usage *u) +{ + batch_usage_wait(ctx, u, true); +} diff --git a/src/gallium/drivers/zink/zink_batch.h b/src/gallium/drivers/zink/zink_batch.h index f911a4fd9df..9c9caa17e3a 100644 --- a/src/gallium/drivers/zink/zink_batch.h +++ b/src/gallium/drivers/zink/zink_batch.h @@ -121,6 +121,9 @@ zink_batch_usage_check_completion(struct zink_context *ctx, const struct zink_ba void zink_batch_usage_wait(struct zink_context *ctx, struct zink_batch_usage *u); +void +zink_batch_usage_try_wait(struct zink_context *ctx, struct zink_batch_usage *u); + #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/zink/zink_bo.h b/src/gallium/drivers/zink/zink_bo.h index 4d3a89b2b42..b58c6c2576c 100644 --- a/src/gallium/drivers/zink/zink_bo.h +++ b/src/gallium/drivers/zink/zink_bo.h @@ -182,6 +182,15 @@ zink_bo_usage_wait(struct zink_context *ctx, struct zink_bo *bo, enum zink_resou zink_batch_usage_wait(ctx, bo->writes); } +static inline void +zink_bo_usage_try_wait(struct zink_context *ctx, struct zink_bo *bo, enum zink_resource_access access) +{ + if (access & ZINK_RESOURCE_ACCESS_READ) + zink_batch_usage_try_wait(ctx, bo->reads); + if (access & ZINK_RESOURCE_ACCESS_WRITE) + zink_batch_usage_try_wait(ctx, bo->writes); +} + static inline void zink_bo_usage_set(struct zink_bo *bo, struct zink_batch_state *bs, bool write) { diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index af55ab236a0..e3b793ee7f6 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -1859,6 +1859,7 @@ zink_buffer_map(struct pipe_context *pctx, !res->obj->host_visible)) { assert(!(usage & (TC_TRANSFER_MAP_THREADED_UNSYNC | PIPE_MAP_THREAD_SAFE))); if (!res->obj->host_visible || !(usage & PIPE_MAP_ONCE)) { +overwrite: trans->offset = box->x % screen->info.props.limits.minMemoryMapAlignment; trans->staging_res = pipe_buffer_create(&screen->base, PIPE_BIND_LINEAR, PIPE_USAGE_STAGING, box->width + trans->offset); if (!trans->staging_res) @@ -1880,9 +1881,14 @@ zink_buffer_map(struct pipe_context *pctx, } if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) { - if (usage & PIPE_MAP_WRITE) + if (usage & PIPE_MAP_WRITE) { + if (!(usage & PIPE_MAP_READ)) { + zink_resource_usage_try_wait(ctx, res, ZINK_RESOURCE_ACCESS_RW); + if (zink_resource_has_unflushed_usage(res)) + goto overwrite; + } zink_resource_usage_wait(ctx, res, ZINK_RESOURCE_ACCESS_RW); - else + } else zink_resource_usage_wait(ctx, res, ZINK_RESOURCE_ACCESS_WRITE); res->obj->access = 0; res->obj->access_stage = 0; diff --git a/src/gallium/drivers/zink/zink_resource.h b/src/gallium/drivers/zink/zink_resource.h index 4f2eb8ff64d..652585cc7ab 100644 --- a/src/gallium/drivers/zink/zink_resource.h +++ b/src/gallium/drivers/zink/zink_resource.h @@ -131,6 +131,12 @@ zink_resource_usage_check_completion(struct zink_screen *screen, struct zink_res return zink_bo_usage_check_completion(screen, res->obj->bo, access); } +static inline void +zink_resource_usage_try_wait(struct zink_context *ctx, struct zink_resource *res, enum zink_resource_access access) +{ + zink_bo_usage_try_wait(ctx, res->obj->bo, access); +} + static inline void zink_resource_usage_wait(struct zink_context *ctx, struct zink_resource *res, enum zink_resource_access access) {