Mesa (master): zink: handle clears with scissor regions

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jan 15 16:46:10 UTC 2021


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

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Thu Aug 13 13:44:56 2020 -0400

zink: handle clears with scissor regions

this just sets the info struct members as needed

Reviewed-by: Adam Jackson <ajax at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8512>

---

 src/gallium/drivers/zink/zink_clear.c | 127 ++++++++++++++++++++++++++++++----
 1 file changed, 114 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_clear.c b/src/gallium/drivers/zink/zink_clear.c
index e8dbe01e334..de834b612e8 100644
--- a/src/gallium/drivers/zink/zink_clear.c
+++ b/src/gallium/drivers/zink/zink_clear.c
@@ -23,8 +23,26 @@
 
 #include "zink_context.h"
 #include "zink_resource.h"
+#include "util/format/u_format.h"
 #include "util/u_framebuffer.h"
+#include "util/format_srgb.h"
+#include "util/u_rect.h"
 
+static inline bool
+check_3d_layers(struct pipe_surface *psurf)
+{
+   /* SPEC PROBLEM:
+    * though the vk spec doesn't seem to explicitly address this, currently drivers
+    * are claiming that all 3D images have a single "3D" layer regardless of layercount,
+    * so we can never clear them if we aren't trying to clear only layer 0
+    */
+   if (psurf->u.tex.first_layer)
+      return false;
+      
+   if (psurf->u.tex.last_layer - psurf->u.tex.first_layer > 0)
+      return false;
+   return true;
+}
 
 static void
 clear_in_rp(struct pipe_context *pctx,
@@ -72,11 +90,16 @@ clear_in_rp(struct pipe_context *pctx,
       ++num_attachments;
    }
 
-   VkClearRect cr;
-   cr.rect.offset.x = 0;
-   cr.rect.offset.y = 0;
-   cr.rect.extent.width = fb->width;
-   cr.rect.extent.height = fb->height;
+   VkClearRect cr = {};
+   if (scissor_state) {
+      cr.rect.offset.x = scissor_state->minx;
+      cr.rect.offset.y = scissor_state->miny;
+      cr.rect.extent.width = MIN2(fb->width, scissor_state->maxx - scissor_state->minx);
+      cr.rect.extent.height = MIN2(fb->height, scissor_state->maxy - scissor_state->miny);
+   } else {
+      cr.rect.extent.width = fb->width;
+      cr.rect.extent.height = fb->height;
+   }
    cr.baseArrayLayer = 0;
    cr.layerCount = util_framebuffer_get_num_layers(fb);
    vkCmdClearAttachments(batch->cmdbuf, num_attachments, attachments, 1, &cr);
@@ -90,16 +113,94 @@ zink_clear(struct pipe_context *pctx,
            double depth, unsigned stencil)
 {
    struct zink_context *ctx = zink_context(pctx);
+   struct pipe_framebuffer_state *fb = &ctx->fb_state;
+   struct zink_batch *batch = zink_curr_batch(ctx);
 
-   /* FIXME: this is very inefficient; if no renderpass has been started yet,
-    * we should record the clear if it's full-screen, and apply it as we
-    * start the render-pass. Otherwise we can do a partial out-of-renderpass
-    * clear.
-    */
-   zink_batch_rp(ctx);
-   assert(zink_curr_batch(ctx)->in_rp);
-   if (zink_curr_batch(ctx)->in_rp || ctx->render_condition_active) {
+   if (scissor_state) {
+      bool need_rp = false;
+      struct u_rect intersect = {0, fb->width, 0, fb->height};
+      struct u_rect scissor = {scissor_state->minx, scissor_state->maxx, scissor_state->miny, scissor_state->maxy};
+      if (!u_rect_test_intersection(&scissor, &intersect))
+         need_rp = true;
+      else {
+          u_rect_find_intersection(&scissor, &intersect);
+          if (intersect.x0 != 0 || intersect.y0 != 0 ||
+              intersect.x1 != fb->width || intersect.y1 != fb->height)
+             need_rp = true;
+      }
+      if (need_rp)
+         /* FIXME: this is very inefficient; if no renderpass has been started yet,
+          * we should record the clear if it's full-screen, and apply it as we
+          * start the render-pass. Otherwise we can do a partial out-of-renderpass
+          * clear.
+          */
+         batch = zink_batch_rp(ctx);
+   }
+
+   if (batch->in_rp || ctx->render_condition_active) {
       clear_in_rp(pctx, buffers, scissor_state, pcolor, depth, stencil);
       return;
    }
+
+   VkImageSubresourceRange range = {};
+   range.levelCount = 1;
+   if (buffers & PIPE_CLEAR_COLOR) {
+      range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+      for (unsigned i = 0; i < fb->nr_cbufs; i++) {
+         if (!(buffers & (PIPE_CLEAR_COLOR0 << i)) || !fb->cbufs[i])
+            continue;
+          VkClearColorValue color;
+          struct pipe_surface *psurf = fb->cbufs[i];
+
+          if (psurf->texture->target == PIPE_TEXTURE_3D && !check_3d_layers(psurf)) {
+             clear_in_rp(pctx, buffers, scissor_state, pcolor, depth, stencil);
+             return;
+          }
+
+          struct zink_resource *res = zink_resource(psurf->texture);
+          if (res->layout != VK_IMAGE_LAYOUT_GENERAL && res->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
+             zink_resource_barrier(batch->cmdbuf, res, range.aspectMask, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+          if (psurf->format != res->base.format &&
+              !util_format_is_srgb(psurf->format) && util_format_is_srgb(res->base.format)) {
+             /* if SRGB mode is disabled for the fb with a backing srgb image then we have to
+              * convert this to srgb color
+              */
+             color.float32[0] = util_format_srgb_to_linear_float(pcolor->f[0]);
+             color.float32[1] = util_format_srgb_to_linear_float(pcolor->f[1]);
+             color.float32[2] = util_format_srgb_to_linear_float(pcolor->f[2]);
+          } else {
+             color.float32[0] = pcolor->f[0];
+             color.float32[1] = pcolor->f[1];
+             color.float32[2] = pcolor->f[2];
+          }
+          color.float32[3] = pcolor->f[3];
+          range.baseMipLevel = psurf->u.tex.level;
+          range.baseArrayLayer = psurf->u.tex.first_layer;
+          range.layerCount = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;
+
+          vkCmdClearColorImage(batch->cmdbuf, res->image, res->layout, &color, 1, &range);
+      }
+   }
+
+   range.aspectMask = 0;
+   if (buffers & PIPE_CLEAR_DEPTHSTENCIL && fb->zsbuf) {
+      if (fb->zsbuf->texture->target == PIPE_TEXTURE_3D && !check_3d_layers(fb->zsbuf)) {
+         clear_in_rp(pctx, buffers, scissor_state, pcolor, depth, stencil);
+         return;
+      }
+
+      if (buffers & PIPE_CLEAR_DEPTH)
+         range.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
+      if (buffers & PIPE_CLEAR_STENCIL)
+         range.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+      VkClearDepthStencilValue zs_value = {depth, stencil};
+      range.baseMipLevel = fb->zsbuf->u.tex.level;
+      range.baseArrayLayer = fb->zsbuf->u.tex.first_layer;
+      range.layerCount = fb->zsbuf->u.tex.last_layer - fb->zsbuf->u.tex.first_layer + 1;
+
+      struct zink_resource *res = zink_resource(fb->zsbuf->texture);
+      if (res->layout != VK_IMAGE_LAYOUT_GENERAL && res->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
+         zink_resource_barrier(batch->cmdbuf, res, range.aspectMask, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+      vkCmdClearDepthStencilImage(batch->cmdbuf, res->image, res->layout, &zs_value, 1, &range);
+   }
 }



More information about the mesa-commit mailing list