From 1ee598cfed3de5d220900efcd93f158da324cb10 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 29 May 2020 16:23:49 -0400 Subject: [PATCH] zink: handle empty attachments create an empty buffer and surface to reuse for the fb attachment here this fixes most of the arb_framebuffer_object tests in piglit Reviewed-by: Erik Faye-Lund Part-of: --- src/gallium/drivers/zink/zink_context.c | 28 +++++++++++----- src/gallium/drivers/zink/zink_context.h | 1 + src/gallium/drivers/zink/zink_framebuffer.c | 37 +++++++++++++++++++-- src/gallium/drivers/zink/zink_framebuffer.h | 5 ++- 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 2a7ddee5687..2367269e147 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -58,6 +58,8 @@ zink_context_destroy(struct pipe_context *pctx) if (vkQueueWaitIdle(ctx->queue) != VK_SUCCESS) debug_printf("vkQueueWaitIdle failed\n"); + pipe_resource_reference(&ctx->null_buffer, NULL); + for (int i = 0; i < ARRAY_SIZE(ctx->batches); ++i) vkFreeCommandBuffers(screen->dev, ctx->cmdpool, 1, &ctx->batches[i].cmdbuf); vkDestroyCommandPool(screen->dev, ctx->cmdpool, NULL); @@ -498,9 +500,14 @@ get_render_pass(struct zink_context *ctx) for (int i = 0; i < fb->nr_cbufs; i++) { struct pipe_surface *surf = fb->cbufs[i]; - state.rts[i].format = zink_get_format(screen, surf->format); - state.rts[i].samples = surf->nr_samples > 0 ? surf->nr_samples : - VK_SAMPLE_COUNT_1_BIT; + if (surf) { + state.rts[i].format = zink_get_format(screen, surf->format); + state.rts[i].samples = surf->nr_samples > 0 ? surf->nr_samples : + VK_SAMPLE_COUNT_1_BIT; + } else { + state.rts[i].format = VK_FORMAT_R8_UINT; + state.rts[i].samples = VK_SAMPLE_COUNT_1_BIT; + } } state.num_cbufs = fb->nr_cbufs; @@ -534,6 +541,7 @@ create_framebuffer(struct zink_context *ctx) for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { struct pipe_surface *psurf = ctx->fb_state.cbufs[i]; state.attachments[i] = zink_surface(psurf); + state.has_null_attachments |= !state.attachments[i]; } state.num_attachments = ctx->fb_state.nr_cbufs; @@ -546,14 +554,18 @@ create_framebuffer(struct zink_context *ctx) state.height = ctx->fb_state.height; state.layers = MAX2(ctx->fb_state.layers, 1); - return zink_create_framebuffer(screen, &state); + return zink_create_framebuffer(ctx, screen, &state); } static void -framebuffer_state_buffer_barriers_setup(const struct pipe_framebuffer_state *state, struct zink_batch *batch) +framebuffer_state_buffer_barriers_setup(struct zink_context *ctx, + const struct pipe_framebuffer_state *state, struct zink_batch *batch) { for (int i = 0; i < state->nr_cbufs; i++) { - struct zink_resource *res = zink_resource(state->cbufs[i]->texture); + struct pipe_surface *surf = state->cbufs[i]; + if (!surf) + surf = ctx->framebuffer->null_surface; + struct zink_resource *res = zink_resource(surf->texture); if (res->layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) zink_resource_barrier(batch->cmdbuf, res, res->aspect, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -591,7 +603,7 @@ zink_begin_render_pass(struct zink_context *ctx, struct zink_batch *batch) assert(!batch->rp || batch->rp == ctx->gfx_pipeline_state.render_pass); assert(!batch->fb || batch->fb == ctx->framebuffer); - framebuffer_state_buffer_barriers_setup(fb_state, batch); + framebuffer_state_buffer_barriers_setup(ctx, fb_state, batch); zink_render_pass_reference(screen, &batch->rp, ctx->gfx_pipeline_state.render_pass); zink_framebuffer_reference(screen, &batch->fb, ctx->framebuffer); @@ -661,7 +673,7 @@ zink_set_framebuffer_state(struct pipe_context *pctx, struct zink_batch *batch = zink_batch_no_rp(ctx); - framebuffer_state_buffer_barriers_setup(state, batch); + framebuffer_state_buffer_barriers_setup(ctx, state, batch); } static void diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index fbd6e458da3..a0d4df43c55 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -125,6 +125,7 @@ struct zink_context { bool queries_disabled; struct pipe_resource *dummy_buffer; + struct pipe_resource *null_buffer; /* used to create zink_framebuffer->null_surface */ uint32_t num_so_targets; struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_OUTPUTS]; diff --git a/src/gallium/drivers/zink/zink_framebuffer.c b/src/gallium/drivers/zink/zink_framebuffer.c index 6031ad24a24..c72abd7486c 100644 --- a/src/gallium/drivers/zink/zink_framebuffer.c +++ b/src/gallium/drivers/zink/zink_framebuffer.c @@ -21,6 +21,7 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "zink_context.h" #include "zink_framebuffer.h" #include "zink_render_pass.h" @@ -30,6 +31,31 @@ #include "util/u_memory.h" #include "util/u_string.h" +static struct pipe_surface * +framebuffer_null_surface_init(struct zink_context *ctx, struct zink_framebuffer_state *state) +{ + struct pipe_surface surf_templ = {}; + if (!ctx->null_buffer) { + struct pipe_resource *pres; + struct pipe_resource templ = {}; + templ.width0 = state->width; + templ.height0 = state->height; + templ.depth0 = 1; + templ.format = PIPE_FORMAT_R8_UINT; + templ.target = PIPE_TEXTURE_2D; + templ.bind = PIPE_BIND_RENDER_TARGET; + + pres = ctx->base.screen->resource_create(ctx->base.screen, &templ); + if (!pres) + return NULL; + + ctx->null_buffer = pres; + } + surf_templ.format = PIPE_FORMAT_R8_UINT; + surf_templ.nr_samples = 1; + return ctx->base.create_surface(&ctx->base, ctx->null_buffer, &surf_templ); +} + void zink_destroy_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fbuf) @@ -38,13 +64,15 @@ zink_destroy_framebuffer(struct zink_screen *screen, for (int i = 0; i < ARRAY_SIZE(fbuf->surfaces); ++i) pipe_surface_reference(fbuf->surfaces + i, NULL); + pipe_surface_reference(&fbuf->null_surface, NULL); + zink_render_pass_reference(screen, &fbuf->rp, NULL); FREE(fbuf); } struct zink_framebuffer * -zink_create_framebuffer(struct zink_screen *screen, +zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen, struct zink_framebuffer_state *fb) { struct zink_framebuffer *fbuf = CALLOC_STRUCT(zink_framebuffer); @@ -53,9 +81,14 @@ zink_create_framebuffer(struct zink_screen *screen, pipe_reference_init(&fbuf->reference, 1); - VkImageView attachments[ARRAY_SIZE(fb->attachments)]; + if (fb->has_null_attachments) + fbuf->null_surface = framebuffer_null_surface_init(ctx, fb); + + VkImageView attachments[ARRAY_SIZE(fb->attachments)] = {}; for (int i = 0; i < fb->num_attachments; i++) { struct zink_surface *surf = fb->attachments[i]; + if (!surf) + surf = zink_surface(fbuf->null_surface); pipe_surface_reference(fbuf->surfaces + i, &surf->base); attachments[i] = surf->image_view; } diff --git a/src/gallium/drivers/zink/zink_framebuffer.h b/src/gallium/drivers/zink/zink_framebuffer.h index 63dd3621461..9ab00af8ab7 100644 --- a/src/gallium/drivers/zink/zink_framebuffer.h +++ b/src/gallium/drivers/zink/zink_framebuffer.h @@ -29,6 +29,7 @@ #include "util/u_inlines.h" +struct zink_context; struct zink_screen; struct zink_render_pass; @@ -38,6 +39,7 @@ struct zink_framebuffer_state { uint16_t height, layers; uint8_t num_attachments; struct zink_surface *attachments[PIPE_MAX_COLOR_BUFS + 1]; + bool has_null_attachments; }; struct zink_framebuffer { @@ -46,10 +48,11 @@ struct zink_framebuffer { struct pipe_surface *surfaces[PIPE_MAX_COLOR_BUFS + 1]; struct zink_render_pass *rp; + struct pipe_surface *null_surface; /* for use with unbound attachments */ }; struct zink_framebuffer * -zink_create_framebuffer(struct zink_screen *screen, +zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen, struct zink_framebuffer_state *fb); void -- 2.30.2