Module: Mesa
Branch: staging/23.3
Commit: 7979ca07ec81c8b1e45647cab235235565851b2d
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=7979ca07ec81c8b1e45647cab235235565851b2d

Author: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-pra...@amd.com>
Date:   Wed Jan  3 14:42:52 2024 +0100

radeonsi: compute epitch when modifying surf_pitch

In the linear case with no mipmaps addrlib sets epitch to surf_pitch - 1
so lets do the same thing here.

The change in si_descriptors.c looks like it's papering over a bug but I
couldn't find any other changes that wouldn't break at least one use case.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10375
Fixes: 115b61e51f6 ("ac/surface: don't oversize surf_size")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26947>
(cherry picked from commit 4e76c4ecb462ec6bc1b114b93161c7c732f3a65b)

---

 .pick_status.json                             |  2 +-
 src/amd/common/ac_surface.c                   | 12 ++++++----
 src/gallium/drivers/radeonsi/si_descriptors.c | 34 ++++++++++++++++++++-------
 3 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/.pick_status.json b/.pick_status.json
index 0ef1979e2b1..9acfcbde276 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -54,7 +54,7 @@
         "description": "radeonsi: compute epitch when modifying surf_pitch",
         "nominated": true,
         "nomination_type": 1,
-        "resolution": 0,
+        "resolution": 1,
         "main_sha": null,
         "because_sha": "115b61e51f619df0b8d920b8ee572b56e7be575f",
         "notes": null
diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c
index 337bb85d383..875e2aeb89d 100644
--- a/src/amd/common/ac_surface.c
+++ b/src/amd/common/ac_surface.c
@@ -1869,12 +1869,16 @@ static int gfx9_compute_miptree(struct ac_addrlib 
*addrlib, const struct radeon_
       util_next_power_of_two(LINEAR_PITCH_ALIGNMENT / surf->bpe);
 
    if (!compressed && surf->blk_w > 1 && out.pitch == out.pixelPitch &&
-       surf->u.gfx9.swizzle_mode == ADDR_SW_LINEAR) {
-      /* Adjust surf_pitch to be in elements units not in pixels */
+       surf->u.gfx9.swizzle_mode == ADDR_SW_LINEAR &&
+       in->numMipLevels == 1) {
+      /* Divide surf_pitch (= pitch in pixels) by blk_w to get a
+       * pitch in elements instead because that's what the hardware needs
+       * in resource descriptors.
+       * See the comment in si_descriptors.c.
+       */
       surf->u.gfx9.surf_pitch = align(surf->u.gfx9.surf_pitch / surf->blk_w,
                                       linear_alignment);
-      surf->u.gfx9.epitch =
-         MAX2(surf->u.gfx9.epitch, surf->u.gfx9.surf_pitch * surf->blk_w - 1);
+      surf->u.gfx9.epitch = surf->u.gfx9.surf_pitch - 1;
        /* Adjust surf_slice_size and surf_size to reflect the change made to 
surf_pitch. */
       surf->u.gfx9.surf_slice_size = (uint64_t)surf->u.gfx9.surf_pitch * 
out.height * surf->bpe;
       surf->surf_size = surf->u.gfx9.surf_slice_size * in->numSlices;
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c 
b/src/gallium/drivers/radeonsi/si_descriptors.c
index a47bc4ecafe..9db3b242709 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -382,17 +382,33 @@ void si_set_mutable_tex_desc_fields(struct si_screen 
*sscreen, struct si_texture
          state[3] |= 
S_008F1C_SW_MODE(tex->surface.u.gfx9.zs.stencil_swizzle_mode);
          state[4] |= S_008F20_PITCH(tex->surface.u.gfx9.zs.stencil_epitch);
       } else {
+         state[3] |= S_008F1C_SW_MODE(tex->surface.u.gfx9.swizzle_mode);
+
+         uint32_t hw_format = G_008F14_DATA_FORMAT(state[1]);
          uint16_t epitch = tex->surface.u.gfx9.epitch;
-         if (tex->buffer.b.b.format == PIPE_FORMAT_R8G8_R8B8_UNORM &&
-             block_width == 1) {
-            /* epitch is patched in ac_surface for sdma/vcn blocks to get
-             * a value expressed in elements unit.
-             * But here the texture is used with block_width == 1 so we
-             * need epitch in pixel units.
-             */
-            epitch = (epitch + 1) / tex->surface.blk_w - 1;
+
+         /* epitch is surf_pitch - 1 and are in elements unit.
+          * For some reason I don't understand, when a packed YUV format
+          * like UYUV is used, we have to double epitch (making it a pixel
+          * pitch instead of an element pitch). Note that it's only done
+          * when sampling the texture using its native format; we don't
+          * need to do this when sampling it as UINT32 (as done by
+          * SI_IMAGE_ACCESS_BLOCK_FORMAT_AS_UINT).
+          * This looks broken, so it's possible that surf_pitch / epitch
+          * are computed incorrectly, but that's the only way I found
+          * to get these use cases to work properly:
+          *   - yuyv dmabuf import (#6131)
+          *   - jpeg vaapi decode
+          *   - yuyv texture sampling (!26947)
+          *   - jpeg vaapi get image (#10375)
+          */
+         if ((tex->buffer.b.b.format == PIPE_FORMAT_R8G8_R8B8_UNORM ||
+             tex->buffer.b.b.format == PIPE_FORMAT_G8R8_B8R8_UNORM) &&
+             (hw_format == V_008F14_IMG_DATA_FORMAT_GB_GR ||
+                hw_format == V_008F14_IMG_DATA_FORMAT_BG_RG)) {
+            epitch = (epitch + 1) * 2 - 1;
          }
-         state[3] |= S_008F1C_SW_MODE(tex->surface.u.gfx9.swizzle_mode);
+
          state[4] |= S_008F20_PITCH(epitch);
       }
 

Reply via email to