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: 115b61e51f
("ac/surface: don't oversize surf_size")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26947>
This commit is contained in:

committed by
Marge Bot

parent
810c1f7747
commit
4e76c4ecb4
@@ -1883,12 +1883,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;
|
||||
|
@@ -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 {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
/* 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[4] |= S_008F20_PITCH(epitch);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user