zink: track compatible render passes

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>
This commit is contained in:
Mike Blumenkrantz 2021-06-17 15:51:27 -04:00 committed by Marge Bot
parent d7e36a1831
commit 8dac288c8d
4 changed files with 54 additions and 9 deletions

View 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);

View 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;

View 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));

View 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,