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:

committed by
Marge Bot

parent
9643f0b8fc
commit
c552d99b09
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user