diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index cc19e601a75..a8d0291862e 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -1707,21 +1707,29 @@ iris_transfer_map(struct pipe_context *ctx, usage |= PIPE_TRANSFER_DISCARD_RANGE; } - bool map_would_stall = false; - - if (resource->target != PIPE_BUFFER) { - iris_resource_access_raw(ice, &ice->batches[IRIS_BATCH_RENDER], res, - level, box->z, box->depth, - usage & PIPE_TRANSFER_WRITE); - } - if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED) && can_promote_to_async(res, box, usage)) { usage |= PIPE_TRANSFER_UNSYNCHRONIZED; } + bool need_resolve = false; + bool need_color_resolve = false; + + if (resource->target != PIPE_BUFFER) { + bool need_hiz_resolve = iris_resource_level_has_hiz(res, level); + + need_color_resolve = + (res->aux.usage == ISL_AUX_USAGE_CCS_D || + res->aux.usage == ISL_AUX_USAGE_CCS_E) && + iris_has_color_unresolved(res, level, 1, box->z, box->depth); + + need_resolve = need_color_resolve || need_hiz_resolve; + } + + bool map_would_stall = false; + if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { - map_would_stall = resource_is_busy(ice, res); + map_would_stall = need_resolve || resource_is_busy(ice, res); if (map_would_stall && (usage & PIPE_TRANSFER_DONTBLOCK) && (usage & PIPE_TRANSFER_MAP_DIRECTLY)) @@ -1769,25 +1777,29 @@ iris_transfer_map(struct pipe_context *ctx, * temporary and map that, to avoid the resolve. (It might be better to * a tiled temporary and use the tiled_memcpy paths...) */ - if (!(usage & PIPE_TRANSFER_DISCARD_RANGE) && - res->aux.usage != ISL_AUX_USAGE_CCS_E && - res->aux.usage != ISL_AUX_USAGE_CCS_D) { + if (!(usage & PIPE_TRANSFER_DISCARD_RANGE) && !need_color_resolve) no_gpu = true; - } const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); if (fmtl->txc == ISL_TXC_ASTC) no_gpu = true; if ((map_would_stall || res->aux.usage == ISL_AUX_USAGE_CCS_E) && !no_gpu) { - /* If we need a synchronous mapping and the resource is busy, - * we copy to/from a linear temporary buffer using the GPU. + /* If we need a synchronous mapping and the resource is busy, or needs + * resolving, we copy to/from a linear temporary buffer using the GPU. */ map->batch = &ice->batches[IRIS_BATCH_RENDER]; map->blorp = &ice->blorp; iris_map_copy_region(map); } else { - /* Otherwise we're free to map on the CPU. Flush if needed. */ + /* Otherwise we're free to map on the CPU. */ + + if (need_resolve) { + iris_resource_access_raw(ice, &ice->batches[IRIS_BATCH_RENDER], res, + level, box->z, box->depth, + usage & PIPE_TRANSFER_WRITE); + } + if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { for (int i = 0; i < IRIS_BATCH_COUNT; i++) { if (iris_batch_references(&ice->batches[i], res->bo)) diff --git a/src/gallium/drivers/iris/iris_resource.h b/src/gallium/drivers/iris/iris_resource.h index 1fdabb40733..304339eb470 100644 --- a/src/gallium/drivers/iris/iris_resource.h +++ b/src/gallium/drivers/iris/iris_resource.h @@ -436,6 +436,9 @@ void iris_resource_check_level_layer(const struct iris_resource *res, bool iris_resource_level_has_hiz(const struct iris_resource *res, uint32_t level); +bool iris_has_color_unresolved(const struct iris_resource *res, + unsigned start_level, unsigned num_levels, + unsigned start_layer, unsigned num_layers); enum isl_aux_usage iris_resource_render_aux_usage(struct iris_context *ice, struct iris_resource *res,