gallium/u_transfer_helper: Add support for separate Z24/S8 as well.
authorKenneth Graunke <kenneth@whitecape.org>
Mon, 30 Jul 2018 22:20:00 +0000 (15:20 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 15 Oct 2018 06:36:28 +0000 (23:36 -0700)
u_transfer_helper already had code to handle treating packed Z32_S8
as separate Z32_FLOAT and S8_UINT resources, since some drivers can't
handle that interleaved format natively.

Other hardware needs depth and stencil as separate resources for all
formats.  For example, V3D3 needs this for 24-bit depth as well.

This patch adds a new flag to lower all depth/stencils formats, and
implements support for Z24_UNORM_S8_UINT.  (S8_UINT_Z24_UNORM is left
as an exercise to the reader, preferably someone who has access to a
machine that uses that format.)

Reviewed-by: Eric Anholt <eric@anholt.net>
src/gallium/auxiliary/util/u_transfer_helper.c
src/gallium/auxiliary/util/u_transfer_helper.h
src/gallium/drivers/freedreno/freedreno_resource.c
src/gallium/drivers/v3d/v3d_resource.c
src/gallium/drivers/vc4/vc4_resource.c

index df67f8288523a4cc183682d010d7f2024cb417db..14c4d56392d041370be692ca98600122c2e2ece8 100644 (file)
@@ -33,7 +33,8 @@
 
 struct u_transfer_helper {
    const struct u_transfer_vtbl *vtbl;
-   bool separate_z32s8;
+   bool separate_z32s8; /**< separate z32 and s8 */
+   bool separate_stencil; /**< separate stencil for all formats */
    bool fake_rgtc;
    bool msaa_map;
 };
@@ -88,11 +89,12 @@ u_transfer_helper_resource_create(struct pipe_screen *pscreen,
    enum pipe_format format = templ->format;
    struct pipe_resource *prsc;
 
-   if ((format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) && helper->separate_z32s8) {
+   if ((helper->separate_stencil && util_format_is_depth_and_stencil(format)) ||
+       (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && helper->separate_z32s8)) {
       struct pipe_resource t = *templ;
       struct pipe_resource *stencil;
 
-      t.format = PIPE_FORMAT_Z32_FLOAT;
+      t.format = util_format_get_depth_only(format);
 
       prsc = helper->vtbl->resource_create(pscreen, &t);
       if (!prsc)
@@ -266,22 +268,37 @@ u_transfer_helper_transfer_map(struct pipe_context *pctx,
    if (!trans->ptr)
       goto fail;
 
-   if (prsc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
+   if (util_format_is_depth_and_stencil(prsc->format)) {
       struct pipe_resource *stencil = helper->vtbl->get_stencil(prsc);
       trans->ptr2 = helper->vtbl->transfer_map(pctx, stencil, level,
                                                usage, box, &trans->trans2);
 
       if (needs_pack(usage)) {
-         util_format_z32_float_s8x24_uint_pack_z_float(trans->staging,
-                                                       ptrans->stride,
-                                                       trans->ptr,
-                                                       trans->trans->stride,
-                                                       width, height);
-         util_format_z32_float_s8x24_uint_pack_s_8uint(trans->staging,
-                                                       ptrans->stride,
-                                                       trans->ptr2,
-                                                       trans->trans2->stride,
-                                                       width, height);
+         switch (prsc->format) {
+         case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+            util_format_z32_float_s8x24_uint_pack_z_float(trans->staging,
+                                                          ptrans->stride,
+                                                          trans->ptr,
+                                                          trans->trans->stride,
+                                                          width, height);
+            util_format_z32_float_s8x24_uint_pack_s_8uint(trans->staging,
+                                                          ptrans->stride,
+                                                          trans->ptr2,
+                                                          trans->trans2->stride,
+                                                          width, height);
+            break;
+         case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+            util_format_z24_unorm_s8_uint_pack_separate(trans->staging,
+                                                        ptrans->stride,
+                                                        trans->ptr,
+                                                        trans->trans->stride,
+                                                        trans->ptr2,
+                                                        trans->trans2->stride,
+                                                        width, height);
+            break;
+         default:
+            unreachable("Unexpected format");
+         }
       }
    } else if (needs_pack(usage) &&
               util_format_description(prsc->format)->layout == UTIL_FORMAT_LAYOUT_RGTC) {
@@ -395,6 +412,22 @@ flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans,
                                                       ptrans->stride,
                                                       width, height);
       break;
+   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+      /* just do a strided 32-bit copy for depth; s8 can become garbage x8 */
+      util_format_z32_unorm_unpack_z_32unorm(dst, trans->trans->stride,
+                                             src, ptrans->stride,
+                                             width, height);
+      /* fallthru */
+   case PIPE_FORMAT_X24S8_UINT:
+      dst = (uint8_t *)trans->ptr2 +
+            (box->y * trans->trans2->stride) +
+            (box->x * util_format_get_blocksize(PIPE_FORMAT_S8_UINT));
+
+      util_format_z24_unorm_s8_uint_unpack_s_8uint(dst, trans->trans2->stride,
+                                                   src, ptrans->stride,
+                                                   width, height);
+      break;
+
    case PIPE_FORMAT_RGTC1_UNORM:
    case PIPE_FORMAT_RGTC1_SNORM:
    case PIPE_FORMAT_LATC1_UNORM:
@@ -487,6 +520,7 @@ u_transfer_helper_transfer_unmap(struct pipe_context *pctx,
 struct u_transfer_helper *
 u_transfer_helper_create(const struct u_transfer_vtbl *vtbl,
                          bool separate_z32s8,
+                         bool separate_stencil,
                          bool fake_rgtc,
                          bool msaa_map)
 {
@@ -494,6 +528,7 @@ u_transfer_helper_create(const struct u_transfer_vtbl *vtbl,
 
    helper->vtbl = vtbl;
    helper->separate_z32s8 = separate_z32s8;
+   helper->separate_stencil = separate_stencil;
    helper->fake_rgtc = fake_rgtc;
    helper->msaa_map = msaa_map;
 
index b13a1ec06c1073098606eb6d1c8e626cc949b4de..9e5f889f9d82f99ad9999a7953247e0d130a20d9 100644 (file)
@@ -33,7 +33,7 @@ extern "C" {
 
 /* A helper to implement various "lowering" for transfers:
  *
- *  - exposing separate z32 and s8 as z32x24s8
+ *  - exposing separate depth and stencil resources as packed depth-stencil
  *  - fake RGTC support for GLES class hardware which needs it to expose GL3+
  *  - MSAA resolves
  *
@@ -79,16 +79,16 @@ struct u_transfer_vtbl {
     */
 
    /**
-    * Must be implemented if separate_z32s8 or fake_rgtc is used.  The
+    * Must be implemented if separate stencil or fake_rgtc is used.  The
     * internal_format is the format the resource was created with.  In
-    * the case of separate_z32s8 or fake_rgtc, prsc->format is set back
-    * to the state tracker visible format (Z32_FLOAT_S8X24_UINT or
+    * the case of separate stencil or fake_rgtc, prsc->format is set back
+    * to the state tracker visible format (e.g. Z32_FLOAT_S8X24_UINT or
     * PIPE_FORMAT_{RTGC,LATC}* after the resource is created.
     */
    enum pipe_format (*get_internal_format)(struct pipe_resource *prsc);
 
    /**
-    * Must be implemented if separate_z32s8 is used.  Used to set/get
+    * Must be implemented if separate stencil is lowered.  Used to set/get
     * the separate s8 stencil buffer.
     *
     * These two do not get/put references to the pipe_resource.  The
@@ -123,6 +123,7 @@ struct u_transfer_helper;
 
 struct u_transfer_helper * u_transfer_helper_create(const struct u_transfer_vtbl *vtbl,
                                                     bool separate_z32s8,
+                                                    bool separate_stencil,
                                                     bool fake_rgtc,
                                                     bool msaa_map);
 
index 8fbc78193038db356650a5bd12d8a68641c43cbe..c82be3e203261db56f84207907bd6ec318cac62b 100644 (file)
@@ -1183,7 +1183,7 @@ fd_resource_screen_init(struct pipe_screen *pscreen)
        pscreen->resource_destroy = u_transfer_helper_resource_destroy;
 
        pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl,
-                       true, fake_rgtc, true);
+                       true, false, fake_rgtc, true);
 
        if (!screen->setup_slices)
                screen->setup_slices = fd_setup_slices;
index 8bf6a97c3940b429e99b0505bf7fc3cea36b47ec..dd0db8cfd89fb54943acfa194ca2643b888e584c 100644 (file)
@@ -909,7 +909,8 @@ v3d_resource_screen_init(struct pipe_screen *pscreen)
         pscreen->resource_get_handle = v3d_resource_get_handle;
         pscreen->resource_destroy = u_transfer_helper_resource_destroy;
         pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl,
-                                                            true, true, true);
+                                                            true, false,
+                                                            true, true);
 }
 
 void
index e169303f4a37c17eef0061b0e977914ebb1cb42d..94784bbdc0a2fda1a83e9cd337cc7a551668477e 100644 (file)
@@ -1129,7 +1129,8 @@ vc4_resource_screen_init(struct pipe_screen *pscreen)
         pscreen->resource_get_handle = vc4_resource_get_handle;
         pscreen->resource_destroy = vc4_resource_destroy;
         pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl,
-                                                            false, false, true);
+                                                            false, false,
+                                                            false, true);
 
         /* Test if the kernel has GET_TILING; it will return -EINVAL if the
          * ioctl does not exist, but -ENOENT if we pass an impossible handle.