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); }