Module: Mesa
Branch: main
Commit: fa6e6545b1ac481f12b2a0dac5132fce996c96a8
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=fa6e6545b1ac481f12b2a0dac5132fce996c96a8

Author: Mike Blumenkrantz <[email protected]>
Date:   Fri Feb 17 17:05:45 2023 -0500

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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21397>

---

 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;

Reply via email to