From fa6e6545b1ac481f12b2a0dac5132fce996c96a8 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 17 Feb 2023 17:05:45 -0500 Subject: [PATCH] zink: add some tracking for copy box regions this enables tracking per-miplevel pipe_boxes for copy operations that can then be used to avoid emitting barriers for successive copy operations without overlapping regions Part-of: --- src/gallium/drivers/zink/zink_context.c | 4 ++ src/gallium/drivers/zink/zink_resource.c | 64 ++++++++++++++++++++++++ src/gallium/drivers/zink/zink_resource.h | 7 +++ src/gallium/drivers/zink/zink_types.h | 2 + 4 files changed, 77 insertions(+) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 489b72288cc..0eee4da136b 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -3693,6 +3693,8 @@ zink_resource_image_barrier(struct zink_context *ctx, struct zink_resource *res, res->obj->access = imb.dstAccessMask; res->obj->access_stage = pipeline; res->layout = new_layout; + if (new_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) + zink_resource_copies_reset(res); } void @@ -3736,6 +3738,8 @@ zink_resource_image_barrier2(struct zink_context *ctx, struct zink_resource *res res->obj->access = imb.dstAccessMask; res->obj->access_stage = pipeline; res->layout = new_layout; + if (new_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) + zink_resource_copies_reset(res); } diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 2245200173f..41f3b50d87d 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -105,6 +105,8 @@ zink_destroy_resource_object(struct zink_screen *screen, struct zink_resource_ob VKSCR(DestroyImageView)(screen->dev, util_dynarray_pop(&obj->views, VkImageView), NULL); } util_dynarray_fini(&obj->views); + for (unsigned i = 0; i < ARRAY_SIZE(obj->copies); i++) + util_dynarray_fini(&obj->copies[i]); if (obj->is_buffer) { VKSCR(DestroyBuffer)(screen->dev, obj->buffer, NULL); VKSCR(DestroyBuffer)(screen->dev, obj->storage_buffer, NULL); @@ -603,6 +605,7 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t uint64_t *modifiers, int modifiers_count, const void *loader_private) { struct zink_resource_object *obj = CALLOC_STRUCT(zink_resource_object); + unsigned max_level = 0; if (!obj) return NULL; simple_mtx_init(&obj->view_lock, mtx_plain); @@ -699,7 +702,9 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t obj->transfer_dst = true; obj->vkflags = bci.flags; obj->vkusage = bci.usage; + max_level = 1; } else { + max_level = templ->last_level + 1; bool winsys_modifier = (export_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) && whandle && whandle->modifier != DRM_FORMAT_MOD_INVALID; uint64_t mods[10]; bool try_modifiers = false; @@ -1135,6 +1140,8 @@ retry: } } } + for (unsigned i = 0; i < max_level; i++) + util_dynarray_init(&obj->copies[i], NULL); return obj; fail3: @@ -2141,6 +2148,63 @@ zink_transfer_flush_region(struct pipe_context *pctx, } } +/* used to determine whether to emit a TRANSFER_DST barrier on copies */ +bool +zink_resource_copy_box_intersects(struct zink_resource *res, unsigned level, const struct pipe_box *box) +{ + /* if there are no valid copy rects tracked, this needs a barrier */ + if (!res->obj->copies_valid) + return true; + /* untracked huge miplevel */ + if (level >= ARRAY_SIZE(res->obj->copies)) + return true; + struct pipe_box *b = res->obj->copies[level].data; + unsigned num_boxes = util_dynarray_num_elements(&res->obj->copies[level], struct pipe_box); + boolean (*intersect)(const struct pipe_box *, const struct pipe_box *); + /* determine intersection function based on dimensionality */ + switch (res->base.b.target) { + case PIPE_BUFFER: + case PIPE_TEXTURE_1D: + intersect = u_box_test_intersection_1d; + break; + + case PIPE_TEXTURE_1D_ARRAY: + case PIPE_TEXTURE_2D: + intersect = u_box_test_intersection_2d; + break; + + default: + intersect = u_box_test_intersection_3d; + break; + } + /* if any of the tracked boxes intersect with this one, a barrier is needed */ + for (unsigned i = 0; i < num_boxes; i++) { + if (intersect(box, b + i)) + return true; + } + /* no intersection = no barrier */ + return false; +} + +/* track a new region for TRANSFER_DST barrier emission */ +void +zink_resource_copy_box_add(struct zink_resource *res, unsigned level, const struct pipe_box *box) +{ + util_dynarray_append(&res->obj->copies[level], struct pipe_box, *box); + res->obj->copies_valid = true; +} + +void +zink_resource_copies_reset(struct zink_resource *res) +{ + if (!res->obj->copies_valid) + return; + unsigned max_level = res->base.b.target == PIPE_BUFFER ? 1 : (res->base.b.last_level + 1); + for (unsigned i = 0; i < max_level; i++) + util_dynarray_clear(&res->obj->copies[i]); + res->obj->copies_valid = false; +} + static void transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) { diff --git a/src/gallium/drivers/zink/zink_resource.h b/src/gallium/drivers/zink/zink_resource.h index 37da41827c9..d1eee2183b6 100644 --- a/src/gallium/drivers/zink/zink_resource.h +++ b/src/gallium/drivers/zink/zink_resource.h @@ -93,6 +93,13 @@ zink_is_swapchain(const struct zink_resource *res) return res->swapchain; } +bool +zink_resource_copy_box_intersects(struct zink_resource *res, unsigned level, const struct pipe_box *box); +void +zink_resource_copy_box_add(struct zink_resource *res, unsigned level, const struct pipe_box *box); +void +zink_resource_copies_reset(struct zink_resource *res); + #include "zink_batch.h" #include "zink_bo.h" #include "zink_kopper.h" diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 29f03a680dd..bb31859bf4b 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -1118,8 +1118,10 @@ struct zink_resource_object { VkAccessFlags access; bool unordered_read; bool unordered_write; + bool copies_valid; unsigned persistent_maps; //if nonzero, requires vkFlushMappedMemoryRanges during batch use + struct util_dynarray copies[16]; //regions being copied to; for barrier omission VkBuffer storage_buffer; simple_mtx_t view_lock;