zink: add a dynamic render version of clear_texture hook
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Thu, 2 Mar 2023 17:12:32 +0000 (12:12 -0500)
committerMarge Bot <emma+marge@anholt.net>
Mon, 20 Mar 2023 02:26:20 +0000 (02:26 +0000)
this avoids the (sizable) overhead of going through the previous path
with set_frame_buffer state et al, instead just firing off a quick
begin+end rendering with a clear

it's also easily reorderable

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21906>

src/gallium/drivers/zink/zink_clear.c
src/gallium/drivers/zink/zink_clear.h
src/gallium/drivers/zink/zink_context.c

index 8d67577..39ac5c4 100644 (file)
@@ -437,6 +437,87 @@ set_clear_fb(struct pipe_context *pctx, struct pipe_surface *psurf, struct pipe_
 }
 
 void
+zink_clear_texture_dynamic(struct pipe_context *pctx,
+                           struct pipe_resource *pres,
+                           unsigned level,
+                           const struct pipe_box *box,
+                           const void *data)
+{
+   struct zink_context *ctx = zink_context(pctx);
+   struct zink_resource *res = zink_resource(pres);
+
+   bool full_clear = 0 <= box->x && u_minify(pres->width0, level) >= box->x + box->width &&
+                     0 <= box->y && u_minify(pres->height0, level) >= box->y + box->height &&
+                     0 <= box->z && u_minify(pres->target == PIPE_TEXTURE_3D ? pres->depth0 : pres->array_size, level) >= box->z + box->depth;
+
+   struct pipe_surface *surf = create_clear_surface(pctx, pres, level, box);
+
+   VkRenderingAttachmentInfo att = {0};
+   att.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
+   att.imageView = zink_csurface(surf)->image_view;
+   att.imageLayout = res->aspect & VK_IMAGE_ASPECT_COLOR_BIT ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+   att.loadOp = full_clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
+   att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+
+   VkRenderingInfo info = {0};
+   info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
+   info.renderArea.offset.x = box->x;
+   info.renderArea.offset.y = box->y;
+   info.renderArea.extent.width = box->width;
+   info.renderArea.extent.height = box->height;
+   info.layerCount = MAX2(box->depth, 1);
+
+   union pipe_color_union color;
+   float depth = 0.0;
+   uint8_t stencil = 0;
+   if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
+      util_format_unpack_rgba(pres->format, color.ui, data, 1);
+   } else {
+      if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
+         util_format_unpack_z_float(pres->format, &depth, data, 1);
+
+      if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT)
+         util_format_unpack_s_8uint(pres->format, &stencil, data, 1);
+   }
+
+   zink_blit_barriers(ctx, NULL, res, full_clear);
+   VkCommandBuffer cmdbuf = zink_get_cmdbuf(ctx, NULL, res);
+   if (cmdbuf == ctx->batch.state->cmdbuf && ctx->batch.in_rp)
+      zink_batch_no_rp(ctx);
+
+   if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
+      memcpy(&att.clearValue, &color, sizeof(float) * 4);
+      info.colorAttachmentCount = 1;
+      info.pColorAttachments = &att;
+   } else {
+      att.clearValue.depthStencil.depth = depth;
+      att.clearValue.depthStencil.stencil = stencil;
+      if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
+         info.pDepthAttachment = &att;
+      if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT)
+         info.pStencilAttachment = &att;
+   }
+   VKCTX(CmdBeginRendering)(cmdbuf, &info);
+   if (!full_clear) {
+      VkClearRect rect;
+      rect.rect = info.renderArea;
+      rect.baseArrayLayer = box->z;
+      rect.layerCount = box->depth;
+
+      VkClearAttachment clear_att;
+      clear_att.aspectMask = res->aspect;
+      clear_att.colorAttachment = 0;
+      clear_att.clearValue = att.clearValue;
+
+      VKCTX(CmdClearAttachments)(cmdbuf, 1, &clear_att, 1, &rect);
+   }
+   VKCTX(CmdEndRendering)(cmdbuf);
+   zink_batch_reference_resource_rw(&ctx->batch, res, true);
+   /* this will never destroy the surface */
+   pipe_surface_reference(&surf, NULL);
+}
+
+void
 zink_clear_texture(struct pipe_context *pctx,
                    struct pipe_resource *pres,
                    unsigned level,
index b1f4b18..eb17f15 100644 (file)
@@ -40,6 +40,12 @@ zink_clear_texture(struct pipe_context *ctx,
                    const struct pipe_box *box,
                    const void *data);
 void
+zink_clear_texture_dynamic(struct pipe_context *ctx,
+                           struct pipe_resource *p_res,
+                           unsigned level,
+                           const struct pipe_box *box,
+                           const void *data);
+void
 zink_clear_buffer(struct pipe_context *pctx,
                   struct pipe_resource *pres,
                   unsigned offset,
index b59bd10..552b8ef 100644 (file)
@@ -5316,7 +5316,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
    ctx->gfx_pipeline_state.sample_mask = UINT32_MAX;
 
    ctx->base.clear = zink_clear;
-   ctx->base.clear_texture = zink_clear_texture;
+   ctx->base.clear_texture = screen->info.have_KHR_dynamic_rendering ? zink_clear_texture_dynamic : zink_clear_texture;
    ctx->base.clear_buffer = zink_clear_buffer;
    ctx->base.clear_render_target = zink_clear_render_target;
    ctx->base.clear_depth_stencil = zink_clear_depth_stencil;