diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 23075eac447..d1f398493e2 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -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); diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index b0839d2388e..6e1d9ff701b 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -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; diff --git a/src/gallium/drivers/zink/zink_render_pass.c b/src/gallium/drivers/zink/zink_render_pass.c index 8696ffaba8a..a2508141fa4 100644 --- a/src/gallium/drivers/zink/zink_render_pass.c +++ b/src/gallium/drivers/zink/zink_render_pass.c @@ -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)); diff --git a/src/gallium/drivers/zink/zink_render_pass.h b/src/gallium/drivers/zink/zink_render_pass.h index e5fb889a796..e8f1b012345 100644 --- a/src/gallium/drivers/zink/zink_render_pass.h +++ b/src/gallium/drivers/zink/zink_render_pass.h @@ -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,