radeonsi: fix surf_pitch for subsampled surface
authorPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Tue, 4 Feb 2020 17:56:59 +0000 (18:56 +0100)
committerPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Thu, 27 Feb 2020 09:01:31 +0000 (10:01 +0100)
gfx9.surf_pitch is supposed to be in blocks (or elements) but addrlib
returns a pitch in pixels.
This cause a mismatch between surface->bpe and surface.u.gfx9.surf_pitch.

For subsampled formats like uyvy (bpe is 2) this breaks in various places:
 - sdma copy
 - video rendering (see issue https://gitlab.freedesktop.org/mesa/mesa/issues/2363)
   when the vl_compositor_gfx_render method is used

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3738>

src/amd/common/ac_surface.c
src/gallium/drivers/radeonsi/si_compute_blit.c

index 8a39f8b02d01860690f91cb46e4e02515eb5ba55..545ef4207567fa9e0f3509781fe93c23ddc750e0 100644 (file)
@@ -1071,6 +1071,11 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
 
        surf->u.gfx9.surf_slice_size = out.sliceSize;
        surf->u.gfx9.surf_pitch = out.pitch;
+       if (!compressed && surf->blk_w > 1 && out.pitch == out.pixelPitch) {
+               /* Adjust surf_pitch to be in elements units,
+                * not in pixels */
+               surf->u.gfx9.surf_pitch /= surf->blk_w;
+       }
        surf->u.gfx9.surf_height = out.height;
        surf->surf_size = out.surfSize;
        surf->surf_alignment = out.baseAlign;
index 73020f9d3b410ed4be671b4685e7e9217391107b..de020bfaf8c2e6a4656e9edc3dbc6017670ec507 100644 (file)
@@ -398,17 +398,17 @@ void si_compute_copy_image(struct si_context *sctx,
        assert(util_format_is_subsampled_422(src_format) ==
               util_format_is_subsampled_422(dst_format));
 
-       if (util_format_is_subsampled_422(src_format))
+       if (util_format_is_subsampled_422(src_format)) {
                src_format = dst_format = PIPE_FORMAT_R32_UINT;
-
-       unsigned x_div = util_format_get_blockwidth(src->format) /
-                        util_format_get_blockwidth(src_format);
-       assert(src_box->x % x_div == 0);
-       assert(width % x_div == 0);
-
-       unsigned data[] = {src_box->x / x_div, src_box->y, src_box->z, 0,
-                          dstx / x_div, dsty, dstz, 0};
-       width /= x_div;
+               /* Interpreting 422 subsampled format (16 bpp) as 32 bpp
+                * should force us to divide src_box->x, dstx and width by 2.
+                * But given that ac_surface allocates this format as 32 bpp
+                * and that surf_size is then modified to pack the values
+                * we must keep the original values to get the correct results.
+                */
+       }
+       unsigned data[] = {src_box->x, src_box->y, src_box->z, 0,
+                          dstx, dsty, dstz, 0};
 
        if (width == 0 || height == 0)
                return;