[PATCH libdrm] radeon, evergreen: ensure equal sizes for depth-stencil npot textures
Gert Wollny
gert.wollny at collabora.com
Tue Aug 7 20:37:16 UTC 2018
It seems I did a wrong indication in the subject,
Am Montag, den 06.08.2018, 10:13 +0200 schrieb Gert Wollny:
> On evergreen depth-stencil textures are allocated as two objects, and
> when using the eg_surface_init_1d_miptrees code path the size
> evaluation
> uses the generalized surf_minify function. Here when allocating the
> depth texture the alignment takes the depth bpe value into account,
> and
> uses bpe=1 for the stencil texture. As a result the texture pair may
> consist of textures with two different nblk_x sizes and this seems to
> be a problem with npot textures, i.e. if the so allocated depth
> texture
> is larger than the stencil texture, then the kernel may reject sent
> data
> with an error message like:
>
> evergreen_cs_track_validate_stencil:622 stencil read bo too
> small (layer size 131072, offset 524288, max layer 1, bo size
> 606208)
>
> because apparently the expected layer size is evaluated from the
> depth
> texture size, but the actual bo size is evaluated based on the true
> texture
> size values. If, on the other hand, the stencil texture is larger
> than the
> depth texture, then the data is send with a wrong alignment, and
> certain
> dEQP-GLES31 tests fail.
>
> In order to obtain equal npot texture sizes magnify the depth texture
> alignment
> requirement in these cases by its bpe, so that the relative alignment
> is
> the same for depth and stencil texture.
>
> Fixes on BARTS:
> dEQP-GLES31.functional.stencil_texturing.format
> .depth32f_stencil8_2d
> .depth32f_stencil8_2d_array
> .depth24_stencil8_2d Pass
> .depth24_stencil8_2d_array
> .stencil_index8_2d
> .stencil_index8_2d_array
> .depth32f_stencil8_draw
> .depth24_stencil8_draw
>
> dEQP-GLES31.functional.texture.border_clamp.formats
> .stencil_index8.nearest_size_npot
> .depth24_stencil8_sample_stencil.nearest_size_npot
> .depth32f_stencil8_sample_stencil.nearest_size_npot
>
> dEQP-
> GLES31.functional.texture.border_clamp.per_axis_wrap_mode.texture_2d
> .uint_stencil.nearest.s_clamp_to_edge_t_clamp_to_border_npot
> .uint_stencil.nearest.s_repeat_t_clamp_to_border_npot
> .uint_stencil.nearest.s_mirrored_repeat_t_clamp_to_border_npot
>
> Signed-off-by: Gert Wollny <gert.wollny at collabora.com>
> ---
> Thanks for reviewing and any comments,
> Gert
>
> PS: - I have commit rights for mesa, I'm not sure whether this also
> includes drm.
> - This is a resend, because I first tried with a mail address
> that was not
> subscribed to the list and the mail probably ended up in some
> moderation
> queue (sorry)
>
> radeon/radeon_surface.c | 38 +++++++++++++++++++++++++++-----------
> 1 file changed, 27 insertions(+), 11 deletions(-)
>
> diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
> index 3cafcfcb..0579389c 100644
> --- a/radeon/radeon_surface.c
> +++ b/radeon/radeon_surface.c
> @@ -612,6 +612,7 @@ static int eg_surface_init_1d(struct
> radeon_surface_manager *surf_man,
> struct radeon_surface *surf,
> struct radeon_surface_level *level,
> unsigned bpe,
> + unsigned align_maginify,
> uint64_t offset, unsigned start_level)
> {
> uint32_t xalign, yalign, zalign, tilew;
> @@ -620,7 +621,7 @@ static int eg_surface_init_1d(struct
> radeon_surface_manager *surf_man,
> /* compute alignment */
> tilew = 8;
> xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf-
> >nsamples);
> - xalign = MAX2(tilew, xalign);
> + xalign = MAX2(tilew, xalign * align_maginify);
> yalign = tilew;
> zalign = 1;
> if (surf->flags & RADEON_SURF_SCANOUT) {
> @@ -652,7 +653,8 @@ static int eg_surface_init_1d(struct
> radeon_surface_manager *surf_man,
> static int eg_surface_init_2d(struct radeon_surface_manager
> *surf_man,
> struct radeon_surface *surf,
> struct radeon_surface_level *level,
> - unsigned bpe, unsigned tile_split,
> + unsigned bpe, unsigned align_magnify,
> + unsigned tile_split,
> uint64_t offset, unsigned start_level)
> {
> unsigned tilew, tileh, tileb;
> @@ -691,7 +693,7 @@ static int eg_surface_init_2d(struct
> radeon_surface_manager *surf_man,
> level[i].mode = RADEON_SURF_MODE_2D;
> eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew,
> mtileh, mtileb, offset);
> if (level[i].mode == RADEON_SURF_MODE_1D) {
> - return eg_surface_init_1d(surf_man, surf, level, bpe,
> offset, i);
> + return eg_surface_init_1d(surf_man, surf, level, bpe,
> align_magnify, offset, i);
> }
> /* level0 and first mipmap need to have alignment */
> offset = surf->bo_size;
> @@ -793,16 +795,24 @@ static int eg_surface_init_1d_miptrees(struct
> radeon_surface_manager *surf_man,
> /* Old libdrm_macros.headers didn't have stencil_level in it.
> This prevents crashes. */
> struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
> struct radeon_surface_level *stencil_level =
> - (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf-
> >stencil_level : tmp;
> + (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf-
> >stencil_level : tmp;
>
> - r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe,
> 0, 0);
> + int magnify_align = is_depth_stencil && (surf->npix_x & (surf-
> >npix_x - 1));
> +
> + /* With certain sizes the depth and the stencil texture end up
> being of
> + * different block sizes which later results in wrong rendering
> for npot
> + * textures. Inflate the alignment requirement for the depth
> surface by
> + * its bpe in order to make it allocate a texture that is of the
> same
> + * block size like the stencil texture */
> + r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe,
> + magnify_align ? surf->bpe : 1, 0, 0);
> if (r)
> return r;
>
> if (is_depth_stencil) {
> - r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
> - surf->bo_size, 0);
> - surf->stencil_offset = stencil_level[0].offset;
> + r = eg_surface_init_1d(surf_man, surf, stencil_level, 1, 1,
> + surf->bo_size, 0);
> + surf->stencil_offset = stencil_level[0].offset;
> }
> return r;
> }
> @@ -816,16 +826,22 @@ static int eg_surface_init_2d_miptrees(struct
> radeon_surface_manager *surf_man,
> struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
> struct radeon_surface_level *stencil_level =
> (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf-
> >stencil_level : tmp;
> + int magnify_align = is_depth_stencil && (surf->npix_x & (surf-
> >npix_x - 1));
>
> + /* Inflate the alignment requirement for npot textures to insure
> that
> + * stencil and depth texture have the same block size. Use this
> only in
> + * the 1d code path that uses the non-specific minify. */
> r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
> + magnify_align ? surf->bpe : 1,
> surf->tile_split, 0, 0);
> if (r)
> return r;
>
> if (is_depth_stencil) {
> - r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
> - surf->stencil_tile_split, surf-
> >bo_size, 0);
> - surf->stencil_offset = stencil_level[0].offset;
> + r = eg_surface_init_2d(surf_man, surf, stencil_level, 1, 1,
> + surf->stencil_tile_split, surf-
> >bo_size, 0);
> + surf->stencil_offset = stencil_level[0].offset;
> +
> }
> return r;
> }
More information about the dri-devel
mailing list