panfrost: Decouple Gallium clear from FBD clear
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Tue, 26 Feb 2019 23:51:34 +0000 (23:51 +0000)
committerAlyssa Rosenzweig <alyssa@rosenzweig.io>
Mon, 4 Mar 2019 04:58:55 +0000 (04:58 +0000)
The operations of gallium->clear() and the hardware callbacks are
fundamentally independent. This routine decouples them by routing shared
information via panfrost_job, allowing the hardware half to be deferred
to the fragment job generation.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
src/gallium/drivers/panfrost/pan_context.c
src/gallium/drivers/panfrost/pan_job.h

index 257482f900668662e93f4fe84bdec0a7cb49b8b7..d05863d35a041e7c3d13a96c434816597ac186f0 100644 (file)
@@ -412,42 +412,31 @@ normalised_float_to_u8(float f)
 }
 
 static void
-panfrost_clear_sfbd(struct panfrost_context *ctx,
-                bool clear_color,
-                bool clear_depth,
-                bool clear_stencil,
-                uint32_t packed_color,
-                double depth, unsigned stencil
-                )
+panfrost_clear_sfbd(struct panfrost_job *job)
 {
+        struct panfrost_context *ctx = job->ctx;
         struct mali_single_framebuffer *sfbd = &ctx->fragment_sfbd;
 
-        if (clear_color) {
-                sfbd->clear_color_1 = packed_color;
-                sfbd->clear_color_2 = packed_color;
-                sfbd->clear_color_3 = packed_color;
-                sfbd->clear_color_4 = packed_color;
+        if (job->clear & PIPE_CLEAR_COLOR) {
+                sfbd->clear_color_1 = job->clear_color;
+                sfbd->clear_color_2 = job->clear_color;
+                sfbd->clear_color_3 = job->clear_color;
+                sfbd->clear_color_4 = job->clear_color;
         }
 
-        if (clear_depth) {
-                sfbd->clear_depth_1 = depth;
-                sfbd->clear_depth_2 = depth;
-                sfbd->clear_depth_3 = depth;
-                sfbd->clear_depth_4 = depth;
-        }
-
-        if (clear_stencil) {
-                sfbd->clear_stencil = stencil;
-        }
+        if (job->clear & PIPE_CLEAR_DEPTH) {
+                sfbd->clear_depth_1 = job->clear_depth;
+                sfbd->clear_depth_2 = job->clear_depth;
+                sfbd->clear_depth_3 = job->clear_depth;
+                sfbd->clear_depth_4 = job->clear_depth;
 
-        /* Setup buffers */
-
-        if (clear_depth) {
                 sfbd->depth_buffer = ctx->depth_stencil_buffer.gpu;
                 sfbd->depth_buffer_enable = MALI_DEPTH_STENCIL_ENABLE;
         }
 
-        if (clear_stencil) {
+        if (job->clear & PIPE_CLEAR_STENCIL) {
+                sfbd->clear_stencil = job->clear_stencil;
+
                 sfbd->stencil_buffer = ctx->depth_stencil_buffer.gpu;
                 sfbd->stencil_buffer_enable = MALI_DEPTH_STENCIL_ENABLE;
         }
@@ -456,14 +445,14 @@ panfrost_clear_sfbd(struct panfrost_context *ctx,
         /* XXX: What do these flags mean? */
         int clear_flags = 0x101100;
 
-        if (clear_color && clear_depth && clear_stencil) {
+        if (!(job->clear & ~(PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) {
                 /* On a tiler like this, it's fastest to clear all three buffers at once */
 
                 clear_flags |= MALI_CLEAR_FAST;
         } else {
                 clear_flags |= MALI_CLEAR_SLOW;
 
-                if (clear_stencil)
+                if (job->clear & PIPE_CLEAR_STENCIL)
                         clear_flags |= MALI_CLEAR_SLOW_STENCIL;
         }
 
@@ -471,36 +460,30 @@ panfrost_clear_sfbd(struct panfrost_context *ctx,
 }
 
 static void
-panfrost_clear_mfbd(struct panfrost_context *ctx,
-                bool clear_color,
-                bool clear_depth,
-                bool clear_stencil,
-                uint32_t packed_color,
-                double depth, unsigned stencil
-                )
+panfrost_clear_mfbd(struct panfrost_job *job)
 {
+        struct panfrost_context *ctx = job->ctx;
         struct bifrost_render_target *buffer_color = &ctx->fragment_rts[0];
         struct bifrost_framebuffer *buffer_ds = &ctx->fragment_mfbd;
 
-        if (clear_color) {
-                buffer_color->clear_color_1 = packed_color;
-                buffer_color->clear_color_2 = packed_color;
-                buffer_color->clear_color_3 = packed_color;
-                buffer_color->clear_color_4 = packed_color;
+        if (job->clear & PIPE_CLEAR_COLOR) {
+                buffer_color->clear_color_1 = job->clear_color;
+                buffer_color->clear_color_2 = job->clear_color;
+                buffer_color->clear_color_3 = job->clear_color;
+                buffer_color->clear_color_4 = job->clear_color;
         }
 
-        if (clear_depth) {
-                buffer_ds->clear_depth = depth;
+        if (job->clear & PIPE_CLEAR_DEPTH) {
+                buffer_ds->clear_depth = job->clear_depth;
         }
 
-        if (clear_stencil) {
-                buffer_ds->clear_stencil = stencil;
+        if (job->clear & PIPE_CLEAR_STENCIL) {
+                buffer_ds->clear_stencil = job->clear_stencil;
         }
 
-        if (clear_depth || clear_stencil) {
+        if (job->clear & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
                 /* Setup combined 24/8 depth/stencil */
                 ctx->fragment_mfbd.unk3 |= MALI_MFBD_EXTRA;
-                //ctx->fragment_extra.unk = /*0x405*/0x404;
                 ctx->fragment_extra.unk = 0x405;
                 ctx->fragment_extra.ds_linear.depth = ctx->depth_stencil_buffer.gpu;
                 ctx->fragment_extra.ds_linear.depth_stride = ctx->pipe_framebuffer.width * 4;
@@ -515,40 +498,32 @@ panfrost_clear(
         double depth, unsigned stencil)
 {
         struct panfrost_context *ctx = pan_context(pipe);
+        struct panfrost_job *job = panfrost_get_job_for_fbo(ctx);
 
-        if (!color) {
-                printf("Warning: clear color null?\n");
-                return;
-        }
-
-        /* Save settings for FBO switch */
-        ctx->last_clear.buffers = buffers;
-        ctx->last_clear.color = color;
-        ctx->last_clear.depth = depth;
-        ctx->last_clear.depth = depth;
+        if (buffers & PIPE_CLEAR_COLOR) {
+                /* Alpha clear only meaningful without alpha channel, TODO less ad hoc */
+                bool has_alpha = util_format_has_alpha(ctx->pipe_framebuffer.cbufs[0]->format);
+                float clear_alpha = has_alpha ? color->f[3] : 1.0f;
 
-        bool clear_color = buffers & PIPE_CLEAR_COLOR;
-        bool clear_depth = buffers & PIPE_CLEAR_DEPTH;
-        bool clear_stencil = buffers & PIPE_CLEAR_STENCIL;
+                uint32_t packed_color =
+                        (normalised_float_to_u8(clear_alpha) << 24) |
+                        (normalised_float_to_u8(color->f[2]) << 16) |
+                        (normalised_float_to_u8(color->f[1]) <<  8) |
+                        (normalised_float_to_u8(color->f[0]) <<  0);
 
-        /* Remember that we've done something */
-        ctx->frame_cleared = true;
+                job->clear_color = packed_color;
 
-        /* Alpha clear only meaningful without alpha channel */
-        bool has_alpha = ctx->pipe_framebuffer.nr_cbufs && util_format_has_alpha(ctx->pipe_framebuffer.cbufs[0]->format);
-        float clear_alpha = has_alpha ? color->f[3] : 1.0f;
+        }
 
-        uint32_t packed_color =
-                (normalised_float_to_u8(clear_alpha) << 24) |
-                (normalised_float_to_u8(color->f[2]) << 16) |
-                (normalised_float_to_u8(color->f[1]) <<  8) |
-                (normalised_float_to_u8(color->f[0]) <<  0);
+        if (buffers & PIPE_CLEAR_DEPTH) {
+                job->clear_depth = depth;
+        }
 
-        if (require_sfbd) {
-                panfrost_clear_sfbd(ctx, clear_color, clear_depth, clear_stencil, packed_color, depth, stencil);
-        } else {
-                panfrost_clear_mfbd(ctx, clear_color, clear_depth, clear_stencil, packed_color, depth, stencil);
+        if (buffers & PIPE_CLEAR_STENCIL) {
+                job->clear_stencil = stencil;
         }
+
+        job->clear |= buffers;
 }
 
 static mali_ptr
@@ -977,7 +952,17 @@ panfrost_set_value_job(struct panfrost_context *ctx)
 mali_ptr
 panfrost_fragment_job(struct panfrost_context *ctx)
 {
-        /* Update fragment FBD */
+        struct panfrost_job *job = panfrost_get_job_for_fbo(ctx);
+
+        /* Actualize the clear late; TODO: Fix order dependency between clear
+         * and afbc */
+
+        if (require_sfbd) {
+                panfrost_clear_sfbd(job);
+        } else {
+                panfrost_clear_mfbd(job);
+        }
+
         panfrost_set_fragment_afbc(ctx);
 
         if (ctx->pipe_framebuffer.nr_cbufs == 1) {
index 2e6062112b37361bc33ebd83f601738b707a4ba2..0eb729a5b69b10dc460c03ad15931d78a4599998 100644 (file)
@@ -39,6 +39,14 @@ struct panfrost_job_key {
 struct panfrost_job {
         struct panfrost_context *ctx;
         struct panfrost_job_key key;
+
+        /* Buffers cleared (PIPE_CLEAR_* bitmask) */
+        unsigned clear;
+
+        /* Packed clear values */
+        uint32_t clear_color;
+        float clear_depth;
+        unsigned clear_stencil;
 };
 
 /* Functions for managing the above */