zink: track compatible render passes
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Thu, 17 Jun 2021 19:51:27 +0000 (15:51 -0400)
committerMarge Bot <eric+marge@anholt.net>
Wed, 1 Sep 2021 03:28:11 +0000 (03:28 +0000)
Two render passes are compatible if their corresponding color, input, resolve, and depth/stencil
attachment references are compatible and if they are otherwise identical except for:
• Initial and final image layout in attachment descriptions
• Load and store operations in attachment descriptions
• Image layout in attachment references

VK 8.2

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12605>

src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_context.h
src/gallium/drivers/zink/zink_render_pass.c
src/gallium/drivers/zink/zink_render_pass.h

index 23075eac447f74fb6f0574d7953e9ad95320346b..d1f398493e221b066f73e2dabe6e14df5d3b8f47 100644 (file)
@@ -1496,6 +1496,26 @@ zink_update_fbfetch(struct zink_context *ctx)
       zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, PIPE_SHADER_FRAGMENT, ZINK_DESCRIPTOR_TYPE_UBO, 0, 1);
 }
 
+static size_t
+rp_state_size(const struct zink_render_pass_pipeline_state *pstate)
+{
+   return offsetof(struct zink_render_pass_pipeline_state, attachments) +
+                   sizeof(pstate->attachments[0]) * pstate->num_attachments;
+}
+
+static uint32_t
+hash_rp_state(const void *key)
+{
+   const struct zink_render_pass_pipeline_state *s = key;
+   return _mesa_hash_data(key, rp_state_size(s));
+}
+
+static bool
+equals_rp_state(const void *a, const void *b)
+{
+   return !memcmp(a, b, rp_state_size(a));
+}
+
 static uint32_t
 hash_render_pass_state(const void *key)
 {
@@ -1574,9 +1594,17 @@ get_render_pass(struct zink_context *ctx)
       rp = entry->data;
       assert(rp->state.clears == clears);
    } else {
-      rp = zink_create_render_pass(screen, &state);
+      struct zink_render_pass_pipeline_state pstate;
+      rp = zink_create_render_pass(screen, &state, &pstate);
       if (!_mesa_hash_table_insert_pre_hashed(ctx->render_pass_cache, hash, &rp->state, rp))
          return NULL;
+      bool found = false;
+      struct set_entry *entry = _mesa_set_search_or_add(&ctx->render_pass_state_cache, &pstate, &found);
+      if (!found) {
+         entry->key = ralloc(ctx, struct zink_render_pass_pipeline_state);
+         memcpy((void*)entry->key, &pstate, rp_state_size(&pstate));
+      }
+      rp->pipeline_state = (void*)entry->key;
    }
    return rp;
 }
@@ -3589,6 +3617,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
       goto fail;
 
    _mesa_hash_table_init(&ctx->compute_program_cache, ctx, _mesa_hash_pointer, _mesa_key_pointer_equal);
+   _mesa_set_init(&ctx->render_pass_state_cache, ctx, hash_rp_state, equals_rp_state);
    ctx->render_pass_cache = _mesa_hash_table_create(NULL,
                                                     hash_render_pass_state,
                                                     equals_render_pass_state);
index b0839d2388eaa13dffec81eb624c1c7b8dbca031..6e1d9ff701ba3514978c6eaf696a3765cad5316c 100644 (file)
@@ -232,6 +232,7 @@ struct zink_context {
    unsigned dirty_shader_stages : 6; /* mask of changed shader stages */
    bool last_vertex_stage_dirty;
 
+   struct set render_pass_state_cache;
    struct hash_table *render_pass_cache;
    bool new_swapchain;
    bool fb_changed;
index 8696ffaba8aa4c2745ae8273ae82e39241951181..a2508141fa4e9f848212ca1a3091c5b50fc3f954 100644 (file)
@@ -29,7 +29,7 @@
 #include "util/u_string.h"
 
 static VkRenderPass
-create_render_pass(VkDevice dev, struct zink_render_pass_state *state)
+create_render_pass(VkDevice dev, struct zink_render_pass_state *state, struct zink_render_pass_pipeline_state *pstate)
 {
 
    VkAttachmentReference color_refs[PIPE_MAX_COLOR_BUFS], zs_ref;
@@ -39,11 +39,12 @@ create_render_pass(VkDevice dev, struct zink_render_pass_state *state)
    VkAccessFlags dep_access = 0;
    unsigned input_count = 0;
 
+   pstate->num_attachments = state->num_cbufs;
    for (int i = 0; i < state->num_cbufs; i++) {
       struct zink_rt_attrib *rt = state->rts + i;
       attachments[i].flags = 0;
-      attachments[i].format = rt->format;
-      attachments[i].samples = rt->samples;
+      pstate->attachments[i].format = attachments[i].format = rt->format;
+      pstate->attachments[i].samples = attachments[i].samples = rt->samples;
       attachments[i].loadOp = rt->clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR :
                                                 state->swapchain_init && rt->swapchain ?
                                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE :
@@ -72,8 +73,8 @@ create_render_pass(VkDevice dev, struct zink_render_pass_state *state)
       VkImageLayout write_layout = rt->fbfetch ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
       VkImageLayout layout = rt->needs_write || has_clear ? write_layout : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
       attachments[num_attachments].flags = 0;
-      attachments[num_attachments].format = rt->format;
-      attachments[num_attachments].samples = rt->samples;
+      pstate->attachments[num_attachments].format = attachments[num_attachments].format = rt->format;
+      pstate->attachments[num_attachments].samples = attachments[num_attachments].samples = rt->samples;
       attachments[num_attachments].loadOp = rt->clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
       attachments[num_attachments].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
       attachments[num_attachments].stencilLoadOp = rt->clear_stencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
@@ -91,6 +92,7 @@ create_render_pass(VkDevice dev, struct zink_render_pass_state *state)
 
       zs_ref.attachment = num_attachments++;
       zs_ref.layout = layout;
+      pstate->num_attachments++;
    }
 
    VkSubpassDependency deps[] = {
@@ -126,13 +128,14 @@ create_render_pass(VkDevice dev, struct zink_render_pass_state *state)
 
 struct zink_render_pass *
 zink_create_render_pass(struct zink_screen *screen,
-                        struct zink_render_pass_state *state)
+                        struct zink_render_pass_state *state,
+                        struct zink_render_pass_pipeline_state *pstate)
 {
    struct zink_render_pass *rp = CALLOC_STRUCT(zink_render_pass);
    if (!rp)
       goto fail;
 
-   rp->render_pass = create_render_pass(screen->dev, state);
+   rp->render_pass = create_render_pass(screen->dev, state, pstate);
    if (!rp->render_pass)
       goto fail;
    memcpy(&rp->state, state, sizeof(struct zink_render_pass_state));
index e5fb889a7962ed3e9339ee03ce6bd8e2038c7bd3..e8f1b012345049fe1552c6316f9d8115f53eb9fa 100644 (file)
@@ -52,14 +52,26 @@ struct zink_render_pass_state {
    uint32_t clears; //for extra verification and update flagging
 };
 
+struct zink_pipeline_rt {
+   VkFormat format;
+   VkSampleCountFlagBits samples;
+};
+
+struct zink_render_pass_pipeline_state {
+   uint32_t num_attachments;
+   struct zink_pipeline_rt attachments[PIPE_MAX_COLOR_BUFS + 1];
+};
+
 struct zink_render_pass {
    VkRenderPass render_pass;
    struct zink_render_pass_state state;
+   struct zink_render_pass_pipeline_state *pipeline_state;
 };
 
 struct zink_render_pass *
 zink_create_render_pass(struct zink_screen *screen,
-                        struct zink_render_pass_state *state);
+                        struct zink_render_pass_state *state,
+                        struct zink_render_pass_pipeline_state *pstate);
 
 void
 zink_destroy_render_pass(struct zink_screen *screen,