zink: add special-casing for (not) reordering certain image barriers
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Fri, 12 May 2023 14:21:31 +0000 (10:21 -0400)
committerMarge Bot <emma+marge@anholt.net>
Mon, 22 May 2023 23:26:44 +0000 (23:26 +0000)
in a scenario where an ordered read op occurs for an image,
successive read-only barriers SHOULD be able to be promoted

...but they can't, because there isn't yet a mechanism for handling layout
transitions between the unordered cmdbuf and the ordered cmdbuf,
meaning that promoting e.g., a SHADER_READ_ONLY barrier after a TRANSFER_SRC
barrier will leave the image with the wrong layout for the transfer op:

TRANSFER_SRC(unordered) -> COPY(ordered) -> SHADER_READ_ONLY(unordered)

becomes

TRANSFER_SRC(unordered) -> SHADER_READ_ONLY(unordered) -> COPY(ordered)

ideally I'll get around to figuring this out at some point

affects:
dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.r32i_r32i.texture2d_array_to_renderbuffer

Fixes: bf0af0f8ede ("zink: move all barrier-related functions to c++")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23035>

src/gallium/drivers/zink/zink_synchronization.cpp

index 1f0c8f8..8c2da60 100644 (file)
@@ -324,7 +324,28 @@ zink_resource_image_barrier(struct zink_context *ctx, struct zink_resource *res,
    if (!res->obj->needs_zs_evaluate && !zink_resource_image_needs_barrier(res, new_layout, flags, pipeline))
       return;
    bool is_write = zink_resource_access_is_write(flags);
-   VkCommandBuffer cmdbuf = is_write ? zink_get_cmdbuf(ctx, NULL, res) : zink_get_cmdbuf(ctx, res, NULL);
+   VkCommandBuffer cmdbuf;
+   /* if current batch usage exists with ordered non-transfer access, never promote
+    * this avoids layout dsync
+    * TODO: figure out how to link up unordered layout -> ordered layout and delete
+    */
+   if (zink_resource_usage_matches(res, ctx->batch.state) && !ctx->unordered_blitting &&
+       (!res->obj->unordered_read || !res->obj->unordered_write)) {
+      cmdbuf = ctx->batch.state->cmdbuf;
+      res->obj->unordered_write = false;
+      res->obj->unordered_read = false;
+      /* it's impossible to detect this from the caller
+       * there should be no valid case where this barrier can occur inside a renderpass
+       */
+      zink_batch_no_rp(ctx);
+   } else {
+      cmdbuf = is_write ? zink_get_cmdbuf(ctx, NULL, res) : zink_get_cmdbuf(ctx, res, NULL);
+      /* force subsequent barriers to be ordered to avoid layout desync */
+      if (cmdbuf != ctx->batch.state->barrier_cmdbuf) {
+         res->obj->unordered_write = false;
+         res->obj->unordered_read = false;
+      }
+   }
    assert(new_layout);
    bool marker = zink_cmd_debug_marker_begin(ctx, cmdbuf, "image_barrier(%s->%s)", vk_ImageLayout_to_str(res->layout), vk_ImageLayout_to_str(new_layout));
    enum zink_resource_access rw = is_write ? ZINK_RESOURCE_ACCESS_RW : ZINK_RESOURCE_ACCESS_WRITE;