zink: use imageless framebuffers

this feature lets zink avoid the screen-based framebuffer cache with locks
in favor of a context-based one that doesn't need any complicated wizardry
to work since it doesn't need to track refcounts for attachments or work
across contexts since the surface info gets passed in when the renderpass
is begun

also expand the dummy surface to an array for use with multisampling and simplify
surface refs there for non-imageless case

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12661>
This commit is contained in:
Mike Blumenkrantz
2021-06-30 11:51:31 -04:00
committed by Marge Bot
parent 9643f0b8fc
commit c552d99b09
7 changed files with 265 additions and 80 deletions

View File

@@ -94,7 +94,8 @@ zink_context_destroy(struct pipe_context *pctx)
pipe_resource_reference(&ctx->dummy_vertex_buffer, NULL);
pipe_resource_reference(&ctx->dummy_xfb_buffer, NULL);
zink_surface_reference(screen, (struct zink_surface**)&ctx->dummy_surface, NULL);
for (unsigned i = 0; i < ARRAY_SIZE(ctx->dummy_surface); i++)
zink_surface_reference(screen, (struct zink_surface**)&ctx->dummy_surface[i], NULL);
zink_buffer_view_reference(screen, &ctx->dummy_bufferview, NULL);
simple_mtx_destroy(&ctx->batch_mtx);
@@ -110,7 +111,10 @@ zink_context_destroy(struct pipe_context *pctx)
zink_batch_state_destroy(screen, *bs);
}
if (ctx->framebuffer) {
if (screen->info.have_KHR_imageless_framebuffer) {
hash_table_foreach(&ctx->framebuffer_cache, he)
zink_destroy_framebuffer(screen, he->data);
} else if (ctx->framebuffer) {
simple_mtx_lock(&screen->framebuffer_mtx);
struct hash_entry *entry = _mesa_hash_table_search(&screen->framebuffer_cache, &ctx->framebuffer->state);
if (zink_framebuffer_reference(screen, &ctx->framebuffer, NULL))
@@ -502,7 +506,7 @@ update_descriptor_state_sampler(struct zink_context *ctx, enum pipe_shader_type
ctx->di.textures[shader][slot].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ctx->di.tbos[shader][slot] = VK_NULL_HANDLE;
} else {
struct zink_surface *null_surface = zink_surface(ctx->dummy_surface);
struct zink_surface *null_surface = zink_surface(ctx->dummy_surface[0]);
struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview;
ctx->di.textures[shader][slot].imageView = null_surface->image_view;
ctx->di.textures[shader][slot].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -538,7 +542,7 @@ update_descriptor_state_image(struct zink_context *ctx, enum pipe_shader_type sh
memset(&ctx->di.images[shader][slot], 0, sizeof(ctx->di.images[shader][slot]));
ctx->di.texel_images[shader][slot] = VK_NULL_HANDLE;
} else {
struct zink_surface *null_surface = zink_surface(ctx->dummy_surface);
struct zink_surface *null_surface = zink_surface(ctx->dummy_surface[0]);
struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview;
ctx->di.images[shader][slot].imageView = null_surface->image_view;
ctx->di.images[shader][slot].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -1479,7 +1483,7 @@ zink_update_fbfetch(struct zink_context *ctx)
ctx->di.fbfetch.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ctx->di.fbfetch.imageView = zink_screen(ctx->base.screen)->info.rb2_feats.nullDescriptor ?
VK_NULL_HANDLE :
zink_surface(ctx->dummy_surface)->image_view;
zink_surface(ctx->dummy_surface[0])->image_view;
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, PIPE_SHADER_FRAGMENT, ZINK_DESCRIPTOR_TYPE_UBO, 0, 1);
return;
}
@@ -1554,7 +1558,7 @@ get_render_pass(struct zink_context *ctx)
state.rts[i].swapchain = surf->texture->bind & PIPE_BIND_SCANOUT;
} else {
state.rts[i].format = VK_FORMAT_R8_UINT;
state.rts[i].samples = MAX2(fb->samples, 1);
state.rts[i].samples = fb->samples;
}
state.num_rts++;
}
@@ -1612,6 +1616,20 @@ get_render_pass(struct zink_context *ctx)
return rp;
}
static uint32_t
hash_framebuffer_imageless(const void *key)
{
struct zink_framebuffer_state* s = (struct zink_framebuffer_state*)key;
return _mesa_hash_data(key, offsetof(struct zink_framebuffer_state, infos) + sizeof(s->infos[0]) * s->num_attachments);
}
static bool
equals_framebuffer_imageless(const void *a, const void *b)
{
struct zink_framebuffer_state *s = (struct zink_framebuffer_state*)a;
return memcmp(a, b, offsetof(struct zink_framebuffer_state, infos) + sizeof(s->infos[0]) * s->num_attachments) == 0;
}
static void
setup_framebuffer(struct zink_context *ctx)
{
@@ -1652,11 +1670,30 @@ setup_framebuffer(struct zink_context *ctx)
if (!ctx->fb_changed)
return;
zink_init_framebuffer(screen, ctx->framebuffer, rp);
ctx->init_framebuffer(screen, ctx->framebuffer, rp);
ctx->fb_changed = false;
ctx->gfx_pipeline_state.render_pass = rp;
}
static VkImageView
prep_fb_attachment(struct zink_context *ctx, struct pipe_surface *psurf, unsigned i)
{
if (!psurf)
return zink_surface(ctx->dummy_surface[util_logbase2_ceil(ctx->fb_state.samples)])->image_view;
struct zink_surface *surf = zink_surface(psurf);
zink_batch_resource_usage_set(&ctx->batch, zink_resource(surf->base.texture), true);
zink_batch_usage_set(&surf->batch_uses, ctx->batch.state);
struct zink_resource *res = zink_resource(surf->base.texture);
VkAccessFlags access;
VkPipelineStageFlags pipeline;
VkImageLayout layout = zink_render_pass_attachment_get_barrier_info(ctx->gfx_pipeline_state.render_pass,
i, &pipeline, &access);
zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline);
return surf->image_view;
}
static unsigned
begin_render_pass(struct zink_context *ctx)
{
@@ -1715,20 +1752,17 @@ begin_render_pass(struct zink_context *ctx)
assert(ctx->gfx_pipeline_state.render_pass && ctx->framebuffer);
for (int i = 0; i < ctx->framebuffer->state.num_attachments; i++) {
if (ctx->framebuffer->surfaces[i]) {
struct zink_surface *surf = zink_surface(ctx->framebuffer->surfaces[i]);
zink_batch_resource_usage_set(batch, zink_resource(surf->base.texture), true);
zink_batch_usage_set(&surf->batch_uses, batch->state);
struct zink_resource *res = zink_resource(surf->base.texture);
VkAccessFlags access;
VkPipelineStageFlags pipeline;
VkImageLayout layout = zink_render_pass_attachment_get_barrier_info(ctx->gfx_pipeline_state.render_pass,
i, &pipeline, &access);
zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline);
}
}
VkRenderPassAttachmentBeginInfo infos;
VkImageView att[PIPE_MAX_COLOR_BUFS + 1];
infos.sType = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO;
infos.pNext = NULL;
infos.attachmentCount = ctx->framebuffer->state.num_attachments;
infos.pAttachments = att;
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++)
att[i] = prep_fb_attachment(ctx, ctx->fb_state.cbufs[i], i);
att[ctx->fb_state.nr_cbufs] = prep_fb_attachment(ctx, ctx->fb_state.zsbuf, ctx->fb_state.nr_cbufs);
if (zink_screen(ctx->base.screen)->info.have_KHR_imageless_framebuffer)
rpbi.pNext = &infos;
vkCmdBeginRenderPass(batch->state->cmdbuf, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
batch->in_rp = true;
@@ -2021,13 +2055,15 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
if (ctx->fb_state.width != w || ctx->fb_state.height != h)
ctx->scissor_changed = true;
rebind_fb_state(ctx, NULL, true);
/* zink_get_framebuffer adds a ref if the fb is reused or created;
ctx->fb_state.samples = util_framebuffer_get_num_samples(state);
uint8_t rast_samples = ctx->fb_state.samples - 1;
/* get_framebuffer adds a ref if the fb is reused or created;
* always do get_framebuffer first to avoid deleting the same fb
* we're about to use
*/
struct zink_framebuffer *fb = zink_get_framebuffer(ctx);
if (ctx->framebuffer) {
struct zink_screen *screen = zink_screen(pctx->screen);
struct zink_framebuffer *fb = ctx->get_framebuffer(ctx);
struct zink_screen *screen = zink_screen(ctx->base.screen);
if (ctx->framebuffer && !screen->info.have_KHR_imageless_framebuffer) {
simple_mtx_lock(&screen->framebuffer_mtx);
struct hash_entry *he = _mesa_hash_table_search(&screen->framebuffer_cache, &ctx->framebuffer->state);
if (ctx->framebuffer && !ctx->framebuffer->state.num_attachments) {
@@ -2040,7 +2076,7 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
}
/* a framebuffer loses 1 ref every time we unset it;
* we do NOT add refs here, as the ref has already been added in
* zink_get_framebuffer()
* get_framebuffer()
*/
if (zink_framebuffer_reference(screen, &ctx->framebuffer, NULL) && he)
_mesa_hash_table_remove(&screen->framebuffer_cache, he);
@@ -2049,7 +2085,6 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
ctx->fb_changed |= ctx->framebuffer != fb;
ctx->framebuffer = fb;
uint8_t rast_samples = util_framebuffer_get_num_samples(state) - 1;
/* in vulkan, gl_SampleMask needs to be explicitly ignored for sampleCount == 1 */
if ((ctx->gfx_pipeline_state.rast_samples > 0) != (rast_samples > 0))
ctx->dirty_shader_stages |= 1 << PIPE_SHADER_FRAGMENT;
@@ -2685,10 +2720,8 @@ zink_texture_barrier(struct pipe_context *pctx, unsigned flags)
bmb.pNext = NULL;
bmb.srcAccessMask = 0;
bmb.dstAccessMask = 0;
struct zink_surface *surf = zink_surface(ctx->framebuffer->surfaces[ctx->framebuffer->state.num_attachments - 1]);
struct zink_resource *res = zink_resource(surf->base.texture);
zink_batch_no_rp(ctx);
if (res->aspect != VK_IMAGE_ASPECT_COLOR_BIT) {
if (ctx->fb_state.zsbuf) {
VkMemoryBarrier dmb;
dmb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
dmb.pNext = NULL;
@@ -2707,7 +2740,7 @@ zink_texture_barrier(struct pipe_context *pctx, unsigned flags)
bmb.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
bmb.dstAccessMask |= VK_ACCESS_SHADER_READ_BIT;
}
if (ctx->framebuffer->state.num_attachments > 1) {
if (ctx->fb_state.nr_cbufs > 0) {
bmb.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
bmb.dstAccessMask |= VK_ACCESS_SHADER_READ_BIT;
}
@@ -3134,11 +3167,15 @@ zink_rebind_framebuffer(struct zink_context *ctx, struct zink_resource *res)
{
if (!ctx->framebuffer)
return;
for (unsigned i = 0; i < ctx->framebuffer->state.num_attachments; i++) {
if (!ctx->framebuffer->surfaces[i] ||
zink_resource(ctx->framebuffer->surfaces[i]->texture) != res)
for (unsigned i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (!ctx->fb_state.cbufs[i] ||
zink_resource(ctx->fb_state.cbufs[i]->texture) != res)
continue;
zink_rebind_surface(ctx, &ctx->framebuffer->surfaces[i]);
zink_rebind_surface(ctx, &ctx->fb_state.cbufs[i]);
zink_batch_no_rp(ctx);
}
if (ctx->fb_state.zsbuf && zink_resource(ctx->fb_state.zsbuf->texture) != res) {
zink_rebind_surface(ctx, &ctx->fb_state.zsbuf);
zink_batch_no_rp(ctx);
}
if (rebind_fb_state(ctx, res, false))
@@ -3488,6 +3525,14 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
ctx->base.screen = pscreen;
ctx->base.priv = priv;
if (screen->info.have_KHR_imageless_framebuffer) {
ctx->get_framebuffer = zink_get_framebuffer_imageless;
ctx->init_framebuffer = zink_init_framebuffer_imageless;
} else {
ctx->get_framebuffer = zink_get_framebuffer;
ctx->init_framebuffer = zink_init_framebuffer;
}
ctx->base.destroy = zink_context_destroy;
ctx->base.get_device_reset_status = zink_get_device_reset_status;
ctx->base.set_device_reset_callback = zink_set_device_reset_callback;
@@ -3576,6 +3621,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_hash_table_init(&ctx->framebuffer_cache, ctx, hash_framebuffer_imageless, equals_framebuffer_imageless);
_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,
@@ -3592,9 +3638,13 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
PIPE_BIND_STREAM_OUTPUT, PIPE_USAGE_DEFAULT, sizeof(data));
if (!ctx->dummy_xfb_buffer)
goto fail;
ctx->dummy_surface = zink_surface_create_null(ctx, PIPE_TEXTURE_2D, 1, 1, 1);
if (!ctx->dummy_surface)
goto fail;
for (unsigned i = 0; i < ARRAY_SIZE(ctx->dummy_surface); i++) {
if (!(screen->info.props.limits.framebufferDepthSampleCounts & BITFIELD_BIT(i)))
continue;
ctx->dummy_surface[i] = zink_surface_create_null(ctx, PIPE_TEXTURE_2D, 1024, 1024, BITFIELD_BIT(i));
if (!ctx->dummy_surface[i])
goto fail;
}
ctx->dummy_bufferview = get_buffer_view(ctx, zink_resource(ctx->dummy_vertex_buffer), PIPE_FORMAT_R8_UNORM, 0, sizeof(data));
if (!ctx->dummy_bufferview)
goto fail;
@@ -3627,7 +3677,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
}
}
if (!screen->info.rb2_feats.nullDescriptor)
ctx->di.fbfetch.imageView = zink_surface(ctx->dummy_surface)->image_view;
ctx->di.fbfetch.imageView = zink_surface(ctx->dummy_surface[0])->image_view;
p_atomic_inc(&screen->base.num_contexts);
zink_select_draw_vbo(ctx);

View File

@@ -200,6 +200,9 @@ struct zink_context {
struct zink_image_view image_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
struct pipe_framebuffer_state fb_state;
struct zink_framebuffer *(*get_framebuffer)(struct zink_context*);
void (*init_framebuffer)(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp);
struct hash_table framebuffer_cache;
struct zink_vertex_elements_state *element_state;
struct zink_rasterizer_state *rast_state;
@@ -284,7 +287,7 @@ struct zink_context {
struct pipe_resource *dummy_vertex_buffer;
struct pipe_resource *dummy_xfb_buffer;
struct pipe_surface *dummy_surface;
struct pipe_surface *dummy_surface[7];
struct zink_buffer_view *dummy_bufferview;
unsigned buffer_rebind_counter;

View File

@@ -104,6 +104,10 @@ EXTENSIONS = [
alias="index_uint8",
features=True,
conditions=["$feats.indexTypeUint8"]),
Extension("VK_KHR_imageless_framebuffer",
alias="imgless",
features=True,
conditions=["$feats.imagelessFramebuffer"]),
Extension("VK_EXT_robustness2",
alias="rb2",
properties=True,

View File

@@ -45,13 +45,134 @@ zink_destroy_framebuffer(struct zink_screen *screen,
#endif
}
if (fb->null_surface)
pipe_resource_reference(&fb->null_surface->texture, NULL);
zink_surface_reference(screen, (struct zink_surface**)&fb->null_surface, NULL);
ralloc_free(fb);
}
void
zink_init_framebuffer_imageless(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp)
{
VkFramebuffer ret;
if (fb->rp == rp)
return;
uint32_t hash = _mesa_hash_pointer(rp);
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&fb->objects, hash, rp);
if (he) {
#if defined(_WIN64) || defined(__x86_64__)
ret = (VkFramebuffer)he->data;
#else
VkFramebuffer *ptr = he->data;
ret = *ptr;
#endif
goto out;
}
VkFramebufferCreateInfo fci;
fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fci.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
fci.renderPass = rp->render_pass;
fci.attachmentCount = fb->state.num_attachments;
fci.pAttachments = NULL;
fci.width = fb->state.width;
fci.height = fb->state.height;
fci.layers = fb->state.layers + 1;
VkFramebufferAttachmentsCreateInfo attachments;
attachments.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO;
attachments.pNext = NULL;
attachments.attachmentImageInfoCount = fb->state.num_attachments;
attachments.pAttachmentImageInfos = fb->infos;
fci.pNext = &attachments;
if (vkCreateFramebuffer(screen->dev, &fci, NULL, &ret) != VK_SUCCESS)
return;
#if defined(_WIN64) || defined(__x86_64__)
_mesa_hash_table_insert_pre_hashed(&fb->objects, hash, rp, ret);
#else
VkFramebuffer *ptr = ralloc(fb, VkFramebuffer);
if (!ptr) {
vkDestroyFramebuffer(screen->dev, ret, NULL);
return;
}
*ptr = ret;
_mesa_hash_table_insert_pre_hashed(&fb->objects, hash, rp, ptr);
#endif
out:
fb->rp = rp;
fb->fb = ret;
}
static void
populate_attachment_info(VkFramebufferAttachmentImageInfo *att, struct zink_surface_info *info)
{
att->sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO;
att->pNext = NULL;
memcpy(&att->flags, &info->flags, offsetof(struct zink_surface_info, format));
att->viewFormatCount = 1;
att->pViewFormats = &info->format;
}
static struct zink_framebuffer *
create_framebuffer_imageless(struct zink_context *ctx, struct zink_framebuffer_state *state)
{
struct zink_screen *screen = zink_screen(ctx->base.screen);
struct zink_framebuffer *fb = rzalloc(ctx, struct zink_framebuffer);
if (!fb)
return NULL;
pipe_reference_init(&fb->reference, 1);
if (!_mesa_hash_table_init(&fb->objects, fb, _mesa_hash_pointer, _mesa_key_pointer_equal))
goto fail;
memcpy(&fb->state, state, sizeof(struct zink_framebuffer_state));
for (int i = 0; i < state->num_attachments; i++)
populate_attachment_info(&fb->infos[i], &fb->state.infos[i]);
return fb;
fail:
zink_destroy_framebuffer(screen, fb);
return NULL;
}
struct zink_framebuffer *
zink_get_framebuffer_imageless(struct zink_context *ctx)
{
assert(zink_screen(ctx->base.screen)->info.have_KHR_imageless_framebuffer);
struct zink_framebuffer_state state;
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
if (!psurf)
psurf = ctx->dummy_surface[util_logbase2_ceil(ctx->gfx_pipeline_state.rast_samples+1)];
struct zink_surface *surface = zink_surface(psurf);
memcpy(&state.infos[i], &surface->info, sizeof(surface->info));
}
state.num_attachments = ctx->fb_state.nr_cbufs;
if (ctx->fb_state.zsbuf) {
struct pipe_surface *psurf = ctx->fb_state.zsbuf;
struct zink_surface *surface = zink_surface(psurf);
memcpy(&state.infos[state.num_attachments], &surface->info, sizeof(surface->info));
state.num_attachments++;
}
state.width = MAX2(ctx->fb_state.width, 1);
state.height = MAX2(ctx->fb_state.height, 1);
state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1;
state.samples = ctx->gfx_pipeline_state.rast_samples;
struct zink_framebuffer *fb;
struct hash_entry *entry = _mesa_hash_table_search(&ctx->framebuffer_cache, &state);
if (entry)
return entry->data;
fb = create_framebuffer_imageless(ctx, &state);
_mesa_hash_table_insert(&ctx->framebuffer_cache, &fb->state, fb);
return fb;
}
void
zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp)
{
@@ -80,7 +201,7 @@ zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, s
fci.pAttachments = fb->state.attachments;
fci.width = fb->state.width;
fci.height = fb->state.height;
fci.layers = fb->state.layers;
fci.layers = fb->state.layers + 1;
if (vkCreateFramebuffer(screen->dev, &fci, NULL, &ret) != VK_SUCCESS)
return;
@@ -100,10 +221,10 @@ out:
fb->fb = ret;
}
struct zink_framebuffer *
zink_create_framebuffer(struct zink_context *ctx,
struct zink_framebuffer_state *state,
struct pipe_surface **attachments)
static struct zink_framebuffer *
create_framebuffer(struct zink_context *ctx,
struct zink_framebuffer_state *state,
struct pipe_surface **attachments)
{
struct zink_screen *screen = zink_screen(ctx->base.screen);
struct zink_framebuffer *fb = rzalloc(NULL, struct zink_framebuffer);
@@ -118,13 +239,11 @@ zink_create_framebuffer(struct zink_context *ctx,
/* no ref! */
fb->surfaces[i] = attachments[i];
num_attachments++;
util_dynarray_append(&surf->framebuffer_refs, struct zink_framebuffer*, fb);
} else {
if (!fb->null_surface)
fb->null_surface = zink_surface_create_null(ctx, PIPE_TEXTURE_2D, state->width, state->height, state->samples);
surf = zink_surface(fb->null_surface);
state->attachments[i] = zink_surface(fb->null_surface)->image_view;
surf = zink_surface(ctx->dummy_surface[util_logbase2_ceil(state->samples+1)]);
state->attachments[i] = surf->image_view;
}
util_dynarray_append(&surf->framebuffer_refs, struct zink_framebuffer*, fb);
}
pipe_reference_init(&fb->reference, 1 + num_attachments);
@@ -148,6 +267,9 @@ struct zink_framebuffer *
zink_get_framebuffer(struct zink_context *ctx)
{
struct zink_screen *screen = zink_screen(ctx->base.screen);
assert(!screen->info.have_KHR_imageless_framebuffer);
struct pipe_surface *attachments[PIPE_MAX_COLOR_BUFS + 1] = {0};
struct zink_framebuffer_state state = {0};
@@ -166,8 +288,8 @@ zink_get_framebuffer(struct zink_context *ctx)
state.width = MAX2(ctx->fb_state.width, 1);
state.height = MAX2(ctx->fb_state.height, 1);
state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1);
state.samples = ctx->fb_state.samples;
state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1;
state.samples = ctx->gfx_pipeline_state.rast_samples;
struct zink_framebuffer *fb;
simple_mtx_lock(&screen->framebuffer_mtx);
@@ -182,7 +304,7 @@ zink_get_framebuffer(struct zink_context *ctx)
* going to be bound; necessary to handle framebuffers which have no "real" attachments
* and are only using null surfaces since the only ref they get is the extra one here
*/
fb = zink_create_framebuffer(ctx, &state, attachments);
fb = create_framebuffer(ctx, &state, attachments);
_mesa_hash_table_insert(&screen->framebuffer_cache, &fb->state, fb);
}
simple_mtx_unlock(&screen->framebuffer_mtx);

View File

@@ -36,10 +36,14 @@ struct zink_render_pass;
struct zink_framebuffer_state {
uint32_t width;
uint16_t height, layers;
uint8_t samples;
uint8_t num_attachments;
VkImageView attachments[PIPE_MAX_COLOR_BUFS + 1];
uint16_t height;
uint32_t layers:6;
uint32_t samples:6;
uint32_t num_attachments:4;
union {
VkImageView attachments[PIPE_MAX_COLOR_BUFS + 1];
struct zink_surface_info infos[PIPE_MAX_COLOR_BUFS + 1];
};
};
struct zink_framebuffer {
@@ -49,19 +53,18 @@ struct zink_framebuffer {
VkFramebuffer fb;
struct zink_render_pass *rp;
struct pipe_surface *surfaces[PIPE_MAX_COLOR_BUFS + 1];
struct pipe_surface *null_surface; /* for use with unbound attachments */
struct zink_framebuffer_state state;
union {
struct pipe_surface *surfaces[PIPE_MAX_COLOR_BUFS + 1];
VkFramebufferAttachmentImageInfo infos[PIPE_MAX_COLOR_BUFS + 1];
};
struct hash_table objects;
};
struct zink_framebuffer *
zink_create_framebuffer(struct zink_context *ctx,
struct zink_framebuffer_state *fb,
struct pipe_surface **attachments);
void
zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp);
void
zink_init_framebuffer_imageless(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp);
void
zink_destroy_framebuffer(struct zink_screen *screen,
@@ -87,6 +90,9 @@ zink_framebuffer_reference(struct zink_screen *screen,
return ret;
}
struct zink_framebuffer *
zink_get_framebuffer_imageless(struct zink_context *ctx);
struct zink_framebuffer *
zink_get_framebuffer(struct zink_context *ctx);
#endif

View File

@@ -1059,14 +1059,16 @@ zink_destroy_screen(struct pipe_screen *pscreen)
zink_buffer_view_reference(screen, &bv, NULL);
}
hash_table_foreach(&screen->framebuffer_cache, entry) {
struct zink_framebuffer* fb = (struct zink_framebuffer*)entry->data;
zink_destroy_framebuffer(screen, fb);
if (!screen->info.have_KHR_imageless_framebuffer) {
hash_table_foreach(&screen->framebuffer_cache, entry) {
struct zink_framebuffer* fb = (struct zink_framebuffer*)entry->data;
zink_destroy_framebuffer(screen, fb);
}
simple_mtx_destroy(&screen->framebuffer_mtx);
}
simple_mtx_destroy(&screen->surface_mtx);
simple_mtx_destroy(&screen->bufferview_mtx);
simple_mtx_destroy(&screen->framebuffer_mtx);
u_transfer_helper_destroy(pscreen->transfer_helper);
#ifdef ENABLE_SHADER_CACHE
@@ -1919,9 +1921,11 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
simple_mtx_init(&screen->surface_mtx, mtx_plain);
simple_mtx_init(&screen->bufferview_mtx, mtx_plain);
simple_mtx_init(&screen->framebuffer_mtx, mtx_plain);
_mesa_hash_table_init(&screen->framebuffer_cache, screen, hash_framebuffer_state, equals_framebuffer_state);
if (!screen->info.have_KHR_imageless_framebuffer) {
simple_mtx_init(&screen->framebuffer_mtx, mtx_plain);
_mesa_hash_table_init(&screen->framebuffer_cache, screen, hash_framebuffer_state, equals_framebuffer_state);
}
_mesa_hash_table_init(&screen->surface_cache, screen, NULL, equals_ivci);
_mesa_hash_table_init(&screen->bufferview_cache, screen, NULL, equals_bvci);

View File

@@ -222,11 +222,6 @@ surface_clear_fb_refs(struct zink_screen *screen, struct pipe_surface *psurface)
simple_mtx_unlock(&screen->framebuffer_mtx);
break;
}
/* null surface doesn't get a ref but it will double-free
* if the pointer isn't unset
*/
if (fb->null_surface == psurface)
fb->null_surface = NULL;
}
}
util_dynarray_fini(&surface->framebuffer_refs);
@@ -242,7 +237,8 @@ zink_destroy_surface(struct zink_screen *screen, struct pipe_surface *psurface)
assert(he->data == surface);
_mesa_hash_table_remove(&screen->surface_cache, he);
simple_mtx_unlock(&screen->surface_mtx);
surface_clear_fb_refs(screen, psurface);
if (!screen->info.have_KHR_imageless_framebuffer)
surface_clear_fb_refs(screen, psurface);
zink_descriptor_set_refs_clear(&surface->desc_set_refs, surface);
util_dynarray_fini(&surface->framebuffer_refs);
pipe_resource_reference(&psurface->texture, NULL);