freedreno/a6xx: Clear sysmem with CP_BLIT
authorKristian H. Kristensen <hoegsberg@google.com>
Fri, 20 Sep 2019 00:13:34 +0000 (17:13 -0700)
committerKristian H. Kristensen <hoegsberg@google.com>
Fri, 8 Nov 2019 00:36:28 +0000 (16:36 -0800)
Signed-off-by: Kristian H. Kristensen <hoegsberg@google.com>
Acked-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Rob Clark <robdclark@gmail.com>
src/freedreno/registers/a6xx.xml
src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
src/gallium/drivers/freedreno/a6xx/fd6_blitter.h
src/gallium/drivers/freedreno/a6xx/fd6_format.h
src/gallium/drivers/freedreno/a6xx/fd6_gmem.c

index 858f2f3c94c814a775690fe074e6345ee061d8af..4763c47b7d1e0c12243b33eab9b5b11d31b028c7 100644 (file)
@@ -963,6 +963,7 @@ to upconvert to 32b float internally?
        <value value="0x4"  name="R2D_FLOAT32"/>
        <value value="0x3"  name="R2D_FLOAT16"/>
        <value value="0x1"  name="R2D_UNORM8_SRGB"/>
+       <value value="0x0"  name="R2D_RAW"/>
 </enum>
 
 <domain name="A6XX" width="32">
@@ -2009,6 +2010,9 @@ to upconvert to 32b float internally?
                <bitfield name="SOLID_COLOR" pos="7" type="boolean"/>
                <bitfield name="COLOR_FORMAT" low="8" high="15" type="a6xx_color_fmt"/>
                <bitfield name="SCISSOR" pos="16" type="boolean"/>
+
+               <bitfield name="UNK" low="17" high="18" type="uint"/>
+
                <!-- required when blitting D24S8/D24X8 -->
                <bitfield name="D24S8" pos="19" type="boolean"/>
                <!-- some sort of channel mask, disabled channels are set to zero ? -->
index 67924a8185faa8dafdb11e20ee94f5fa34a49c9a..79541e5cb544304816aab01fbe729f215f1f91d0 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include "util/u_dump.h"
+#include "util/half_float.h"
 
 #include "freedreno_blitter.h"
 #include "freedreno_fence.h"
@@ -341,8 +342,8 @@ emit_blit_buffer(struct fd_context *ctx, struct fd_ringbuffer *ring,
 }
 
 static void
-emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring,
-               const struct pipe_blit_info *info)
+emit_blit_or_clear_texture(struct fd_context *ctx, struct fd_ringbuffer *ring,
+               const struct pipe_blit_info *info, union pipe_color_union *color)
 {
        const struct pipe_box *sbox = &info->src.box;
        const struct pipe_box *dbox = &info->dst.box;
@@ -393,7 +394,7 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring,
                nelements = blocksize;
        } else {
                debug_assert(!util_format_is_compressed(info->dst.format));
-               nelements = 1;
+               nelements = (dst->base.nr_samples ? dst->base.nr_samples : 1);
        }
 
        spitch = DIV_ROUND_UP(sslice->pitch, blockwidth) * src->cpp;
@@ -417,6 +418,68 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring,
 
        uint32_t blit_cntl = blit_control(dfmt);
 
+       if (color) {
+               blit_cntl |= A6XX_RB_2D_BLIT_CNTL_SOLID_COLOR;
+
+               switch (info->dst.format) {
+               case PIPE_FORMAT_Z24X8_UNORM:
+               case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+               case PIPE_FORMAT_X24S8_UINT: {
+                       uint32_t depth_unorm24 = color->f[0] * ((1u << 24) - 1);
+                       uint8_t stencil = color->ui[1];
+                       color->ui[0] = depth_unorm24 & 0xff;
+                       color->ui[1] = (depth_unorm24 >> 8) & 0xff;
+                       color->ui[2] = (depth_unorm24 >> 16) & 0xff;
+                       color->ui[3] = stencil;
+
+                       dfmt = RB6_Z24_UNORM_S8_UINT;
+                       break;
+               }
+               case PIPE_FORMAT_B5G6R5_UNORM:
+               case PIPE_FORMAT_B5G5R5A1_UNORM:
+               case PIPE_FORMAT_B5G5R5X1_UNORM:
+               case PIPE_FORMAT_B4G4R4A4_UNORM:
+                       color->ui[0] = float_to_ubyte(color->f[0]);
+                       color->ui[1] = float_to_ubyte(color->f[1]);
+                       color->ui[2] = float_to_ubyte(color->f[2]);
+                       color->ui[3] = float_to_ubyte(color->f[3]);
+                       break;
+               default:
+                       break;
+               }
+
+               OUT_PKT4(ring, REG_A6XX_RB_2D_SRC_SOLID_C0, 4);
+
+               switch (fd6_ifmt(dfmt)) {
+               case R2D_UNORM8:
+               case R2D_UNORM8_SRGB:
+                       OUT_RING(ring, float_to_ubyte(color->f[0]));
+                       OUT_RING(ring, float_to_ubyte(color->f[1]));
+                       OUT_RING(ring, float_to_ubyte(color->f[2]));
+                       OUT_RING(ring, float_to_ubyte(color->f[3]));
+                       break;
+               case R2D_FLOAT16:
+                       OUT_RING(ring, _mesa_float_to_half(color->f[0]));
+                       OUT_RING(ring, _mesa_float_to_half(color->f[1]));
+                       OUT_RING(ring, _mesa_float_to_half(color->f[2]));
+                       OUT_RING(ring, _mesa_float_to_half(color->f[3]));
+                       sfmt = RB6_R16G16B16A16_FLOAT;
+                       break;
+
+               case R2D_FLOAT32:
+               case R2D_INT32:
+               case R2D_INT16:
+               case R2D_INT8:
+               case R2D_RAW:
+               default:
+                       OUT_RING(ring, color->ui[0]);
+                       OUT_RING(ring, color->ui[1]);
+                       OUT_RING(ring, color->ui[2]);
+                       OUT_RING(ring, color->ui[3]);
+                       break;
+               }
+       }
+
        if (dtile != stile)
                blit_cntl |= 0x20000000;
 
@@ -452,6 +515,9 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring,
 
                enum a3xx_msaa_samples samples = fd_msaa_samples(src->base.nr_samples);
 
+               if (sfmt == RB6_R10G10B10A2_UNORM)
+                       sfmt = RB6_R10G10B10A2_FLOAT16;
+
                OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 10);
                OUT_RING(ring, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(sfmt) |
                                A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(stile) |
@@ -526,6 +592,9 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring,
                OUT_PKT4(ring, REG_A6XX_RB_UNKNOWN_8C01, 1);
                OUT_RING(ring, 0);
 
+               if (dfmt == RB6_R10G10B10A2_UNORM)
+                       sfmt = RB6_R16G16B16A16_FLOAT;
+
                OUT_PKT4(ring, REG_A6XX_SP_2D_SRC_FORMAT, 1);
                OUT_RING(ring, A6XX_SP_2D_SRC_FORMAT_COLOR_FORMAT(sfmt) |
                                COND(util_format_is_pure_sint(info->src.format),
@@ -554,6 +623,30 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring,
        }
 }
 
+void
+fd6_clear_surface(struct fd_context *ctx,
+               struct fd_ringbuffer *ring, struct pipe_surface *psurf,
+               uint32_t width, uint32_t height, union pipe_color_union *color)
+{
+       struct pipe_blit_info info = {};
+
+       info.dst.resource = psurf->texture;
+       info.dst.level = psurf->u.tex.level;
+       info.dst.box.x = 0;
+       info.dst.box.y = 0;
+       info.dst.box.z = psurf->u.tex.first_layer;
+       info.dst.box.width = width;
+       info.dst.box.height = height;
+       info.dst.box.depth = psurf->u.tex.last_layer + 1 - psurf->u.tex.first_layer;
+       info.dst.format = psurf->format;
+       info.src = info.dst;
+       info.mask = util_format_get_mask(psurf->format);
+       info.filter = PIPE_TEX_FILTER_NEAREST;
+       info.scissor_enable = 0;
+
+       emit_blit_or_clear_texture(ctx, ring, &info, color);
+}
+
 static bool handle_rgba_blit(struct fd_context *ctx, const struct pipe_blit_info *info);
 
 /**
@@ -683,7 +776,7 @@ handle_rgba_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
                /* I don't *think* we need to handle blits between buffer <-> !buffer */
                debug_assert(info->src.resource->target != PIPE_BUFFER);
                debug_assert(info->dst.resource->target != PIPE_BUFFER);
-               emit_blit_texture(ctx, batch->draw, info);
+               emit_blit_or_clear_texture(ctx, batch->draw, info, NULL);
        }
 
        fd6_event_write(batch, batch->draw, 0x1d, true);
index c1609b5793602887d56c3f5c58e55398daaff015..b75013c6d04d36e6024ff81e2052e4b12e3322f4 100644 (file)
@@ -35,4 +35,9 @@
 void fd6_blitter_init(struct pipe_context *pctx);
 unsigned fd6_tile_mode(const struct pipe_resource *tmpl);
 
+void
+fd6_clear_surface(struct fd_context *ctx,
+               struct fd_ringbuffer *ring, struct pipe_surface *psurf,
+               uint32_t width, uint32_t height, union pipe_color_union *color);
+
 #endif /* FD6_BLIT_H_ */
index 388de5b48c07c8e00e88fa09d820d0ad0653bb45..3c1e0a0e5d4cbaa84acbf0a355d64968c7860a1b 100644 (file)
@@ -102,21 +102,20 @@ fd6_ifmt(enum a6xx_color_fmt fmt)
        case RB6_R16_FLOAT:
        case RB6_R16G16_FLOAT:
        case RB6_R16G16B16A16_FLOAT:
+       case RB6_R11G11B10_FLOAT:
                return R2D_FLOAT16;
 
+       case RB6_R10G10B10A2_UNORM:
        case RB6_R4G4B4A4_UNORM:
        case RB6_R5G5B5A1_UNORM:
        case RB6_R5G6B5_UNORM:
-       case RB6_R10G10B10A2_UNORM:
        case RB6_R10G10B10A2_UINT:
-       case RB6_R11G11B10_FLOAT:
        case RB6_X8Z24_UNORM:
-               // ???
-               return 0;
+       case RB6_Z24_UNORM_S8_UINT:
+               return R2D_RAW;
        default:
                unreachable("bad format");
                return 0;
        }
 }
-
 #endif /* FD6_UTIL_H_ */
index d9fabcbaa23ea7ad066dec92a54694501eae1f73..5799e6b0d3f0cda5d3de6d210c6c793c07db2343 100644 (file)
@@ -37,6 +37,7 @@
 #include "freedreno_state.h"
 #include "freedreno_resource.h"
 
+#include "fd6_blitter.h"
 #include "fd6_gmem.h"
 #include "fd6_context.h"
 #include "fd6_draw.h"
@@ -1445,6 +1446,58 @@ fd6_emit_tile_fini(struct fd_batch *batch)
        }
 }
 
+static void
+emit_sysmem_clears(struct fd_batch *batch, struct fd_ringbuffer *ring)
+{
+       struct fd_context *ctx = batch->ctx;
+       struct pipe_framebuffer_state *pfb = &batch->framebuffer;
+
+       uint32_t buffers = batch->fast_cleared;
+
+       if (buffers & PIPE_CLEAR_COLOR) {
+               for (int i = 0; i < pfb->nr_cbufs; i++) {
+                       union pipe_color_union *color = &batch->clear_color[i];
+
+                       if (!pfb->cbufs[i])
+                               continue;
+
+                       if (!(buffers & (PIPE_CLEAR_COLOR0 << i)))
+                               continue;
+
+                       fd6_clear_surface(ctx, ring,
+                                       pfb->cbufs[i], pfb->width, pfb->height, color);
+               }
+       }
+       if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
+               union pipe_color_union value = {};
+
+               const bool has_depth = pfb->zsbuf;
+               struct pipe_resource *separate_stencil =
+                       has_depth && fd_resource(pfb->zsbuf->texture)->stencil ?
+                       &fd_resource(pfb->zsbuf->texture)->stencil->base : NULL;
+
+               if ((has_depth && (buffers & PIPE_CLEAR_DEPTH)) ||
+                               (!separate_stencil && (buffers & PIPE_CLEAR_STENCIL))) {
+                       value.f[0] = batch->clear_depth;
+                       value.ui[1] = batch->clear_stencil;
+                       fd6_clear_surface(ctx, ring,
+                                       pfb->zsbuf, pfb->width, pfb->height, &value);
+               }
+
+               if (separate_stencil && (buffers & PIPE_CLEAR_STENCIL)) {
+                       value.ui[0] = batch->clear_stencil;
+
+                       struct pipe_surface stencil_surf = *pfb->zsbuf;
+                       stencil_surf.texture = separate_stencil;
+
+                       fd6_clear_surface(ctx, ring,
+                                       &stencil_surf, pfb->width, pfb->height, &value);
+               }
+       }
+
+       fd6_event_write(batch, ring, 0x1d, true);
+}
+
 static void
 fd6_emit_sysmem_prep(struct fd_batch *batch)
 {
@@ -1453,6 +1506,14 @@ fd6_emit_sysmem_prep(struct fd_batch *batch)
 
        fd6_emit_restore(batch, ring);
 
+       set_scissor(ring, 0, 0, pfb->width - 1, pfb->height - 1);
+
+       set_window_offset(ring, 0, 0);
+
+       set_bin_size(ring, 0, 0, 0xc00000); /* 0xc00000 = BYPASS? */
+
+       emit_sysmem_clears(batch, ring);
+
        fd6_emit_lrz_flush(ring);
 
        emit_marker6(ring, 7);
@@ -1474,12 +1535,6 @@ fd6_emit_sysmem_prep(struct fd_batch *batch)
        OUT_PKT4(ring, REG_A6XX_VPC_SO_OVERRIDE, 1);
        OUT_RING(ring, 0);
 
-       set_scissor(ring, 0, 0, pfb->width - 1, pfb->height - 1);
-
-       set_window_offset(ring, 0, 0);
-
-       set_bin_size(ring, 0, 0, 0xc00000); /* 0xc00000 = BYPASS? */
-
        OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
        OUT_RING(ring, 0x1);