vc4: Fix incorrect clearing of Z/stencil when cleared separately.
authorEric Anholt <eric@anholt.net>
Fri, 9 Sep 2016 23:26:02 +0000 (16:26 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 14 Sep 2016 05:08:03 +0000 (06:08 +0100)
The clear of Z or stencil will end up clearing the other as well, instead
of masking.  There's no way around this that I know of, so if we are
clearing just one then we need to draw a quad.

Fixes a regression in the job-shuffling code, where the clear values move
to the job and don't just have the last clear's value laying around when
you do glClear(DEPTH) and then glClear(STENCIL) separately
(ext_framebuffer_multisample-clear 4 depth)).

This causes regressions in ext_framebuffer_multisample/multisample-blit
depth and ext_framebuffer_multisample/no-color depth, but these were
formerly false positives due to the reference image also being black.  Now
the reference and test images are both being drawn, and it looks like
there's an incorrect resolve of depth during blitting to an MSAA FBO.

src/gallium/drivers/vc4/vc4_blit.c
src/gallium/drivers/vc4/vc4_context.h
src/gallium/drivers/vc4/vc4_draw.c

index 029170a5dc59303f993886c9c5cfb6bc3ed2c8de..c37354425b6eb98117c59e91907e53d73ad6582e 100644 (file)
@@ -166,18 +166,9 @@ vc4_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info)
         return true;
 }
 
-static bool
-vc4_render_blit(struct pipe_context *ctx, struct pipe_blit_info *info)
+void
+vc4_blitter_save(struct vc4_context *vc4)
 {
-        struct vc4_context *vc4 = vc4_context(ctx);
-
-        if (!util_blitter_is_blit_supported(vc4->blitter, info)) {
-                fprintf(stderr, "blit unsupported %s -> %s\n",
-                    util_format_short_name(info->src.resource->format),
-                    util_format_short_name(info->dst.resource->format));
-                return false;
-        }
-
         util_blitter_save_vertex_buffer_slot(vc4->blitter, vc4->vertexbuf.vb);
         util_blitter_save_vertex_elements(vc4->blitter, vc4->vtx);
         util_blitter_save_vertex_shader(vc4->blitter, vc4->prog.bind_vs);
@@ -195,7 +186,21 @@ vc4_render_blit(struct pipe_context *ctx, struct pipe_blit_info *info)
                         (void **)vc4->fragtex.samplers);
         util_blitter_save_fragment_sampler_views(vc4->blitter,
                         vc4->fragtex.num_textures, vc4->fragtex.textures);
+}
+
+static bool
+vc4_render_blit(struct pipe_context *ctx, struct pipe_blit_info *info)
+{
+        struct vc4_context *vc4 = vc4_context(ctx);
+
+        if (!util_blitter_is_blit_supported(vc4->blitter, info)) {
+                fprintf(stderr, "blit unsupported %s -> %s\n",
+                    util_format_short_name(info->src.resource->format),
+                    util_format_short_name(info->dst.resource->format));
+                return false;
+        }
 
+        vc4_blitter_save(vc4);
         util_blitter_blit(vc4->blitter, info);
 
         return true;
index ce2c6d4e68e1e85b5074b359dceefa2ea508d46c..d02a971a36e54557066626449b9a4476856961b0 100644 (file)
@@ -415,4 +415,5 @@ uint8_t vc4_get_tex_format(enum pipe_format f);
 const uint8_t *vc4_get_format_swizzle(enum pipe_format f);
 void vc4_init_query_functions(struct vc4_context *vc4);
 void vc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info);
+void vc4_blitter_save(struct vc4_context *vc4);
 #endif /* VC4_CONTEXT_H */
index 773caf785ec464a2661efd48cb48b36983d229f4..9770abf242db6a6ba36a53d882702211f5124bc3 100644 (file)
@@ -22,6 +22,7 @@
  * IN THE SOFTWARE.
  */
 
+#include "util/u_blitter.h"
 #include "util/u_prim.h"
 #include "util/u_format.h"
 #include "util/u_pack_color.h"
@@ -468,21 +469,37 @@ vc4_clear(struct pipe_context *pctx, unsigned buffers,
                 vc4_flush(pctx);
         }
 
+        /* 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)) {
+                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) {
                 vc4->clear_color[0] = vc4->clear_color[1] =
                         pack_rgba(vc4->framebuffer.cbufs[0]->format,
                                   color->f);
         }
 
-        if (buffers & PIPE_CLEAR_DEPTH) {
+        if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
                 /* 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.
                  */
                 vc4->clear_depth = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, depth);
-        }
-
-        if (buffers & PIPE_CLEAR_STENCIL)
                 vc4->clear_stencil = stencil;
+        }
 
         vc4->draw_min_x = 0;
         vc4->draw_min_y = 0;