Mesa (master): zink: handle empty attachments

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jul 14 16:53:44 UTC 2020


Module: Mesa
Branch: master
Commit: 1ee598cfed3de5d220900efcd93f158da324cb10
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1ee598cfed3de5d220900efcd93f158da324cb10

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Fri May 29 16:23:49 2020 -0400

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 <erik.faye-lund at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5686>

---

 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



More information about the mesa-commit mailing list