Mesa (master): vc4: Fix fallback to quad clears of depth in GLX.

Eric Anholt anholt at kemper.freedesktop.org
Fri Oct 7 01:30:46 UTC 2016


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

Author: Eric Anholt <eric at anholt.net>
Date:   Wed Oct  5 14:10:30 2016 -0700

vc4: Fix fallback to quad clears of depth in GLX.

The fix in the vc4-jobs series ended up triggering the fallback path on
GLX apps that use depth but not stencil.

---

 src/gallium/drivers/vc4/vc4_context.c  |  4 ++
 src/gallium/drivers/vc4/vc4_draw.c     | 70 ++++++++++++++++++++++------------
 src/gallium/drivers/vc4/vc4_resource.c |  4 +-
 src/gallium/drivers/vc4/vc4_resource.h | 11 ++++++
 4 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/src/gallium/drivers/vc4/vc4_context.c b/src/gallium/drivers/vc4/vc4_context.c
index b780b13..974df8a 100644
--- a/src/gallium/drivers/vc4/vc4_context.c
+++ b/src/gallium/drivers/vc4/vc4_context.c
@@ -70,6 +70,10 @@ static void
 vc4_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
 {
         struct vc4_context *vc4 = vc4_context(pctx);
+        struct vc4_resource *rsc = vc4_resource(prsc);
+
+        rsc->initialized_buffers = 0;
+
         struct hash_entry *entry = _mesa_hash_table_search(vc4->write_jobs,
                                                            prsc);
         if (!entry)
diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c
index e4d6179..49f9479 100644
--- a/src/gallium/drivers/vc4/vc4_draw.c
+++ b/src/gallium/drivers/vc4/vc4_draw.c
@@ -444,11 +444,21 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
          */
         assert(start_draw_calls_queued == job->draw_calls_queued);
 
-        if (vc4->zsa && vc4->zsa->base.depth.enabled) {
-                job->resolve |= PIPE_CLEAR_DEPTH;
+        if (vc4->zsa && vc4->framebuffer.zsbuf) {
+                struct vc4_resource *rsc =
+                        vc4_resource(vc4->framebuffer.zsbuf->texture);
+
+                if (vc4->zsa->base.depth.enabled) {
+                        job->resolve |= PIPE_CLEAR_DEPTH;
+                        rsc->initialized_buffers = PIPE_CLEAR_DEPTH;
+                }
+
+                if (vc4->zsa->base.stencil[0].enabled) {
+                        job->resolve |= PIPE_CLEAR_STENCIL;
+                        rsc->initialized_buffers |= PIPE_CLEAR_STENCIL;
+                }
         }
-        if (vc4->zsa && vc4->zsa->base.stencil[0].enabled)
-                job->resolve |= PIPE_CLEAR_STENCIL;
+
         job->resolve |= PIPE_CLEAR_COLOR0;
 
         if (vc4_debug & VC4_DEBUG_ALWAYS_FLUSH)
@@ -482,38 +492,50 @@ vc4_clear(struct pipe_context *pctx, unsigned buffers,
                 job = vc4_get_job_for_fbo(vc4);
         }
 
-        /* Clearing ZS will clear both Z and stencil, so if we're trying to
-         * clear just one then we need to draw a quad to do it instead.
-         */
-        if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) != 0 &&
-            (buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL &&
-            util_format_is_depth_and_stencil(vc4->framebuffer.zsbuf->format)) {
-                perf_debug("Partial clear of Z+stencil buffer, drawing a quad "
-                           "instead of fast clearing\n");
-                vc4_blitter_save(vc4);
-                util_blitter_clear(vc4->blitter,
-                                   vc4->framebuffer.width,
-                                   vc4->framebuffer.height,
-                                   1,
-                                   buffers & PIPE_CLEAR_DEPTHSTENCIL,
-                                   NULL, depth, stencil);
-                buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
-                if (!buffers)
-                        return;
-        }
-
         if (buffers & PIPE_CLEAR_COLOR0) {
+                struct vc4_resource *rsc =
+                        vc4_resource(vc4->framebuffer.cbufs[0]->texture);
+
                 job->clear_color[0] = job->clear_color[1] =
                         pack_rgba(vc4->framebuffer.cbufs[0]->format,
                                   color->f);
+                rsc->initialized_buffers |= (buffers & PIPE_CLEAR_COLOR0);
         }
 
         if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+                struct vc4_resource *rsc =
+                        vc4_resource(vc4->framebuffer.zsbuf->texture);
+                unsigned zsclear = buffers & PIPE_CLEAR_DEPTHSTENCIL;
+
+                /* Clearing ZS will clear both Z and stencil, so if we're
+                 * trying to clear just one then we need to draw a quad to do
+                 * it instead.
+                 */
+                if ((zsclear == PIPE_CLEAR_DEPTH ||
+                     zsclear == PIPE_CLEAR_STENCIL) &&
+                    (rsc->initialized_buffers & ~zsclear) &&
+                    util_format_is_depth_and_stencil(vc4->framebuffer.zsbuf->format)) {
+                        perf_debug("Partial clear of Z+stencil buffer, "
+                                   "drawing a quad instead of fast clearing\n");
+                        vc4_blitter_save(vc4);
+                        util_blitter_clear(vc4->blitter,
+                                           vc4->framebuffer.width,
+                                           vc4->framebuffer.height,
+                                           1,
+                                           zsclear,
+                                           NULL, depth, stencil);
+                        buffers &= ~zsclear;
+                        if (!buffers)
+                                return;
+                }
+
                 /* Though the depth buffer is stored with Z in the high 24,
                  * for this field we just need to store it in the low 24.
                  */
                 job->clear_depth = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, depth);
                 job->clear_stencil = stencil;
+
+                rsc->initialized_buffers |= zsclear;
         }
 
         job->draw_min_x = 0;
diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c
index 5f8b6b0..4168079 100644
--- a/src/gallium/drivers/vc4/vc4_resource.c
+++ b/src/gallium/drivers/vc4/vc4_resource.c
@@ -193,8 +193,10 @@ vc4_resource_transfer_map(struct pipe_context *pctx,
                         vc4_flush_jobs_writing_resource(vc4, prsc);
         }
 
-        if (usage & PIPE_TRANSFER_WRITE)
+        if (usage & PIPE_TRANSFER_WRITE) {
                 rsc->writes++;
+                rsc->initialized_buffers = ~0;
+        }
 
         trans = slab_alloc(&vc4->transfer_pool);
         if (!trans)
diff --git a/src/gallium/drivers/vc4/vc4_resource.h b/src/gallium/drivers/vc4/vc4_resource.h
index b275050..27aa4e8 100644
--- a/src/gallium/drivers/vc4/vc4_resource.h
+++ b/src/gallium/drivers/vc4/vc4_resource.h
@@ -71,6 +71,17 @@ struct vc4_resource {
         uint64_t writes;
 
         /**
+         * Bitmask of PIPE_CLEAR_COLOR0, PIPE_CLEAR_DEPTH, PIPE_CLEAR_STENCIL
+         * for which parts of the resource are defined.
+         *
+         * Used for avoiding fallback to quad clears for clearing just depth,
+         * when the stencil contents have never been initialized.  Note that
+         * we're lazy and fields not present in the buffer (DEPTH in a color
+         * buffer) may get marked.
+         */
+        uint32_t initialized_buffers;
+
+        /**
          * Resource containing the non-GL_TEXTURE_BASE_LEVEL-rebased texture
          * contents, or the 4-byte index buffer.
          *




More information about the mesa-commit mailing list