panfrost: Fix AFBC header_size and slice size calculation
authorBoris Brezillon <boris.brezillon@collabora.com>
Wed, 16 Dec 2020 09:06:44 +0000 (10:06 +0100)
committerBoris Brezillon <boris.brezillon@collabora.com>
Mon, 4 Jan 2021 16:05:42 +0000 (17:05 +0100)
3D AFBC textures have their AFBC headers grouped together at the
beginning of the buffer which means the header_size should be multiplied
by the depth. 2D arrays have their AFBC headers placed at the beginning
of each slice, meaning that the slice size should take them into account.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8125>

src/gallium/drivers/panfrost/pan_resource.c

index e1a8c01..96c552f 100644 (file)
@@ -350,6 +350,7 @@ panfrost_setup_layout(struct panfrost_device *dev,
         bool tiled = pres->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
         bool linear = pres->layout.modifier == DRM_FORMAT_MOD_LINEAR;
         bool should_align = renderable || tiled || afbc;
+        bool is_3d = res->target == PIPE_TEXTURE_3D;
 
         unsigned offset = 0;
         unsigned tile_h = 1, tile_w = 1, tile_shift = 0;
@@ -396,19 +397,29 @@ panfrost_setup_layout(struct panfrost_device *dev,
                 slice->row_stride = stride * (tile_h >> tile_shift);
 
                 unsigned slice_one_size = slice->line_stride * effective_height;
-                unsigned slice_full_size =
-                        slice_one_size * effective_depth * nr_samples;
-
-                slice->surface_stride = slice_one_size;
 
                 /* Compute AFBC sizes if necessary */
                 if (afbc) {
                         slice->afbc.header_size =
                                 panfrost_afbc_header_size(width, height);
 
-                        offset += slice->afbc.header_size;
+                        /* 3D AFBC resources have all headers placed at the
+                         * beginning instead of having them split per depth
+                         * level
+                         */
+                        if (is_3d)
+                                slice->afbc.header_size *= effective_depth;
+                        else
+                                slice_one_size += slice->afbc.header_size;
                 }
 
+                unsigned slice_full_size =
+                        slice_one_size * effective_depth * nr_samples;
+
+                slice->surface_stride = slice_one_size;
+
+                /* Compute AFBC sizes if necessary */
+
                 offset += slice_full_size;
 
                 /* Add a checksum region if necessary */