turnip: rework format table to support r5g5b5a1_unorm/b5g5r5a1_unorm
[mesa.git] / src / freedreno / vulkan / tu_blit.c
index 36d071cbd655b1410043869653b737011fe6dace..bdd45d0db77fb0542ed29d28b897b52f21c384ec 100644 (file)
@@ -58,38 +58,34 @@ blit_copy_format(VkFormat format)
 }
 
 static uint32_t
-blit_image_info(const struct tu_blit_surf *img, bool src, bool stencil_read)
+blit_image_info(const struct tu_blit_surf *img, struct tu_native_format fmt, bool stencil_read)
 {
-   const struct tu_native_format *fmt = tu6_get_native_format(img->fmt);
-   enum a6xx_format rb = fmt->rb;
-   enum a3xx_color_swap swap = img->tiled ? WZYX : fmt->swap;
-   if (rb == FMT6_10_10_10_2_UNORM_DEST && src)
-      rb = FMT6_10_10_10_2_UNORM;
-   if (rb == FMT6_Z24_UNORM_S8_UINT)
-      rb = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
+   if (fmt.fmt == FMT6_Z24_UNORM_S8_UINT)
+      fmt.fmt = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
 
    if (stencil_read)
-      swap = XYZW;
+      fmt.swap = XYZW;
 
-   return A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb) |
+   return A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(fmt.fmt) |
           A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(img->tile_mode) |
-          A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(swap) |
+          A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(fmt.swap) |
           COND(vk_format_is_srgb(img->fmt), A6XX_SP_PS_2D_SRC_INFO_SRGB) |
           COND(img->ubwc_size, A6XX_SP_PS_2D_SRC_INFO_FLAGS);
 }
 
 static void
-emit_blit_step(struct tu_cmd_buffer *cmdbuf, const struct tu_blit *blt)
+emit_blit_step(struct tu_cmd_buffer *cmdbuf, struct tu_cs *cs,
+               const struct tu_blit *blt)
 {
-   struct tu_cs *cs = &cmdbuf->cs;
+   struct tu_physical_device *phys_dev = cmdbuf->device->physical_device;
 
-   tu_cs_reserve_space(cmdbuf->device, cs, 66);
+   struct tu_native_format dfmt = tu6_format_color(blt->dst.fmt, blt->dst.tiled);
+   struct tu_native_format sfmt = tu6_format_texture(blt->src.fmt, blt->src.tiled);
 
-   enum a6xx_format fmt = tu6_get_native_format(blt->dst.fmt)->rb;
-   if (fmt == FMT6_Z24_UNORM_S8_UINT)
-      fmt = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
+   if (dfmt.fmt == FMT6_Z24_UNORM_S8_UINT)
+      dfmt.fmt = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
 
-   enum a6xx_2d_ifmt ifmt = tu6_fmt_to_ifmt(fmt);
+   enum a6xx_2d_ifmt ifmt = tu6_fmt_to_ifmt(dfmt.fmt);
 
    if (vk_format_is_srgb(blt->dst.fmt)) {
       assert(ifmt == R2D_UNORM8);
@@ -98,16 +94,17 @@ emit_blit_step(struct tu_cmd_buffer *cmdbuf, const struct tu_blit *blt)
 
    uint32_t blit_cntl = A6XX_RB_2D_BLIT_CNTL_ROTATE(blt->rotation) |
                         COND(blt->type == TU_BLIT_CLEAR, A6XX_RB_2D_BLIT_CNTL_SOLID_COLOR) |
-                        A6XX_RB_2D_BLIT_CNTL_COLOR_FORMAT(fmt) | /* not required? */
-                        COND(fmt == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8, A6XX_RB_2D_BLIT_CNTL_D24S8) |
+                        A6XX_RB_2D_BLIT_CNTL_COLOR_FORMAT(dfmt.fmt) | /* not required? */
+                        COND(dfmt.fmt == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8,
+                             A6XX_RB_2D_BLIT_CNTL_D24S8) |
                         A6XX_RB_2D_BLIT_CNTL_MASK(0xf) |
                         A6XX_RB_2D_BLIT_CNTL_IFMT(ifmt);
 
-   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
-   tu_cs_emit(&cmdbuf->cs, blit_cntl);
+   tu_cs_emit_pkt4(cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
+   tu_cs_emit(cs, blit_cntl);
 
-   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
-   tu_cs_emit(&cmdbuf->cs, blit_cntl);
+   tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
+   tu_cs_emit(cs, blit_cntl);
 
    /*
     * Emit source:
@@ -120,7 +117,7 @@ emit_blit_step(struct tu_cmd_buffer *cmdbuf, const struct tu_blit *blt)
       tu_cs_emit(cs, blt->clear_value[3]);
    } else {
       tu_cs_emit_pkt4(cs, REG_A6XX_SP_PS_2D_SRC_INFO, 10);
-      tu_cs_emit(cs, blit_image_info(&blt->src, true, blt->stencil_read) |
+      tu_cs_emit(cs, blit_image_info(&blt->src, sfmt, blt->stencil_read) |
                      A6XX_SP_PS_2D_SRC_INFO_SAMPLES(tu_msaa_samples(blt->src.samples)) |
                      /* TODO: should disable this bit for integer formats ? */
                      COND(blt->src.samples > 1, A6XX_SP_PS_2D_SRC_INFO_SAMPLES_AVERAGE) |
@@ -152,7 +149,7 @@ emit_blit_step(struct tu_cmd_buffer *cmdbuf, const struct tu_blit *blt)
     * Emit destination:
     */
    tu_cs_emit_pkt4(cs, REG_A6XX_RB_2D_DST_INFO, 9);
-   tu_cs_emit(cs, blit_image_info(&blt->dst, false, false));
+   tu_cs_emit(cs, blit_image_info(&blt->dst, dfmt, false));
    tu_cs_emit_qw(cs, blt->dst.va);
    tu_cs_emit(cs, A6XX_RB_2D_DST_SIZE_PITCH(blt->dst.pitch));
    tu_cs_emit(cs, 0x00000000);
@@ -190,18 +187,18 @@ emit_blit_step(struct tu_cmd_buffer *cmdbuf, const struct tu_blit *blt)
    tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_8C01, 1);
    tu_cs_emit(cs, 0);
 
-   if (fmt == FMT6_10_10_10_2_UNORM_DEST)
-      fmt = FMT6_16_16_16_16_FLOAT;
+   if (dfmt.fmt == FMT6_10_10_10_2_UNORM_DEST)
+      dfmt.fmt = FMT6_16_16_16_16_FLOAT;
 
    tu_cs_emit_pkt4(cs, REG_A6XX_SP_2D_SRC_FORMAT, 1);
    tu_cs_emit(cs, COND(vk_format_is_sint(blt->src.fmt), A6XX_SP_2D_SRC_FORMAT_SINT) |
                   COND(vk_format_is_uint(blt->src.fmt), A6XX_SP_2D_SRC_FORMAT_UINT) |
-                  A6XX_SP_2D_SRC_FORMAT_COLOR_FORMAT(fmt) |
+                  A6XX_SP_2D_SRC_FORMAT_COLOR_FORMAT(dfmt.fmt) |
                   COND(ifmt == R2D_UNORM8_SRGB, A6XX_SP_2D_SRC_FORMAT_SRGB) |
                   A6XX_SP_2D_SRC_FORMAT_MASK(0xf));
 
    tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
-   tu_cs_emit(cs, 0x01000000);
+   tu_cs_emit(cs, phys_dev->magic.RB_UNKNOWN_8E04_blit);
 
    tu_cs_emit_pkt7(cs, CP_BLIT, 1);
    tu_cs_emit(cs, CP_BLIT_0_OP(BLIT_OP_SCALE));
@@ -212,7 +209,8 @@ emit_blit_step(struct tu_cmd_buffer *cmdbuf, const struct tu_blit *blt)
    tu_cs_emit(cs, 0);
 }
 
-void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_blit *blt)
+void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_cs *cs,
+             struct tu_blit *blt)
 {
    switch (blt->type) {
    case TU_BLIT_COPY:
@@ -266,24 +264,27 @@ void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_blit *blt)
       /* unsupported format cleared as UINT32 */
       if (blt->dst.fmt == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)
          blt->dst.fmt = VK_FORMAT_R32_UINT;
-      assert(blt->dst.samples == 1); /* TODO */
+      /* TODO: multisample image clearing also seems not to work with certain
+       * formats. The blob uses a shader-based clear in these cases.
+       */
+      blt->dst.x *= blt->dst.samples;
+      blt->dst.width *= blt->dst.samples;
+      blt->dst.samples = 1;
       blt->src = blt->dst;
       break;
    default:
       assert(blt->dst.samples == 1);
    }
 
-   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 18);
-
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, LRZ_FLUSH, false);
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, PC_CCU_INVALIDATE_COLOR, false);
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, PC_CCU_INVALIDATE_DEPTH, false);
+   tu6_emit_event_write(cmdbuf, cs, LRZ_FLUSH, false);
+   tu6_emit_event_write(cmdbuf, cs, PC_CCU_FLUSH_COLOR_TS, true);
+   tu6_emit_event_write(cmdbuf, cs, PC_CCU_FLUSH_DEPTH_TS, true);
+   tu6_emit_event_write(cmdbuf, cs, PC_CCU_INVALIDATE_COLOR, false);
+   tu6_emit_event_write(cmdbuf, cs, PC_CCU_INVALIDATE_DEPTH, false);
 
    /* buffer copy setup */
-   tu_cs_emit_pkt7(&cmdbuf->cs, CP_SET_MARKER, 1);
-   tu_cs_emit(&cmdbuf->cs, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
+   tu_cs_emit_pkt7(cs, CP_SET_MARKER, 1);
+   tu_cs_emit(cs, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
 
    for (unsigned layer = 0; layer < blt->layers; layer++) {
       if (blt->buffer) {
@@ -303,7 +304,7 @@ void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_blit *blt)
 
             line_blt.src.width = line_blt.dst.width = tmp;
 
-            emit_blit_step(cmdbuf, &line_blt);
+            emit_blit_step(cmdbuf, cs, &line_blt);
 
             src_va += tmp * blocksize;
             dst_va += tmp * blocksize;
@@ -324,7 +325,7 @@ void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_blit *blt)
             line_blt.src.x = blt->src.x + (src_va & 63) / vk_format_get_blocksize(blt->src.fmt);
             line_blt.src.va = src_va & ~63;
 
-            emit_blit_step(cmdbuf, &line_blt);
+            emit_blit_step(cmdbuf, cs, &line_blt);
 
             line_blt.dst.y++;
             src_va += blt->src.pitch;
@@ -344,13 +345,13 @@ void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_blit *blt)
             line_blt.dst.x = blt->dst.x + (dst_va & 63) / vk_format_get_blocksize(blt->dst.fmt);
             line_blt.dst.va = dst_va & ~63;
 
-            emit_blit_step(cmdbuf, &line_blt);
+            emit_blit_step(cmdbuf, cs, &line_blt);
 
             line_blt.src.y++;
             dst_va += blt->dst.pitch;
          }
       } else {
-         emit_blit_step(cmdbuf, blt);
+         emit_blit_step(cmdbuf, cs, blt);
       }
       blt->dst.va += blt->dst.layer_size;
       blt->src.va += blt->src.layer_size;
@@ -358,10 +359,8 @@ void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_blit *blt)
       blt->src.ubwc_va += blt->src.ubwc_size;
    }
 
-   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 17);
-
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
-   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_INVALIDATE, false);
+   tu6_emit_event_write(cmdbuf, cs, PC_CCU_FLUSH_COLOR_TS, true);
+   tu6_emit_event_write(cmdbuf, cs, PC_CCU_FLUSH_DEPTH_TS, true);
+   tu6_emit_event_write(cmdbuf, cs, CACHE_FLUSH_TS, true);
+   tu6_emit_event_write(cmdbuf, cs, CACHE_INVALIDATE, false);
 }