radeon: Fix 1D tiling layout on SI.
Very similar to Evergreen, but slightly different rules for tile / slice alignment. Fortunately, these map quite naturally onto the previous fixes for linear aligned layout on SI. 2D tiling still needs more work here and possibly in the kernel. Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>main
parent
08cb5c1d02
commit
303ca37e72
|
@ -1000,25 +1000,28 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
|
||||||
* Southern Islands family
|
* Southern Islands family
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
|
static void si_surf_minify(struct radeon_surface *surf,
|
||||||
unsigned level,
|
struct radeon_surface_level *surflevel,
|
||||||
|
unsigned bpe, unsigned level,
|
||||||
uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
|
uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
|
||||||
unsigned offset)
|
unsigned offset)
|
||||||
{
|
{
|
||||||
surf->level[level].npix_x = mip_minify(surf->npix_x, level);
|
surflevel->npix_x = mip_minify(surf->npix_x, level);
|
||||||
surf->level[level].npix_y = mip_minify(surf->npix_y, level);
|
surflevel->npix_y = mip_minify(surf->npix_y, level);
|
||||||
surf->level[level].npix_z = mip_minify(surf->npix_z, level);
|
surflevel->npix_z = mip_minify(surf->npix_z, level);
|
||||||
|
|
||||||
if (level == 0 && surf->last_level > 0) {
|
if (level == 0 && surf->last_level > 0) {
|
||||||
surf->level[level].nblk_x = (next_power_of_two(surf->level[level].npix_x) + surf->blk_w - 1) / surf->blk_w;
|
surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
|
||||||
surf->level[level].nblk_y = (next_power_of_two(surf->level[level].npix_y) + surf->blk_h - 1) / surf->blk_h;
|
surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
|
||||||
surf->level[level].nblk_z = (next_power_of_two(surf->level[level].npix_z) + surf->blk_d - 1) / surf->blk_d;
|
surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
|
||||||
} else {
|
} else {
|
||||||
surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
|
surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
|
||||||
surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
|
surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
|
||||||
surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
|
surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
|
||||||
|
|
||||||
/* XXX: Texture sampling uses unexpectedly large pitches in some cases,
|
/* XXX: Texture sampling uses unexpectedly large pitches in some cases,
|
||||||
* these are just guesses for the rules behind those
|
* these are just guesses for the rules behind those
|
||||||
*/
|
*/
|
||||||
|
@ -1027,17 +1030,16 @@ static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
|
||||||
xalign = MAX2(xalign, slice_align / surf->bpe);
|
xalign = MAX2(xalign, slice_align / surf->bpe);
|
||||||
else
|
else
|
||||||
/* Small rows evenly distributed across slice */
|
/* Small rows evenly distributed across slice */
|
||||||
xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y);
|
xalign = MAX2(xalign, slice_align / surf->bpe / surflevel->nblk_y);
|
||||||
|
|
||||||
surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, xalign);
|
surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
|
||||||
surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, yalign);
|
surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
|
||||||
surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, zalign);
|
|
||||||
|
|
||||||
surf->level[level].offset = offset;
|
surflevel->offset = offset;
|
||||||
surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples;
|
surflevel->pitch_bytes = surflevel->nblk_x * surf->bpe * surf->nsamples;
|
||||||
surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align);
|
surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
|
||||||
|
|
||||||
surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
|
surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
|
static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
|
||||||
|
@ -1059,7 +1061,8 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma
|
||||||
/* build mipmap tree */
|
/* build mipmap tree */
|
||||||
for (i = start_level; i <= surf->last_level; i++) {
|
for (i = start_level; i <= surf->last_level; i++) {
|
||||||
surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
|
surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
|
||||||
si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset);
|
si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign,
|
||||||
|
zalign, slice_align, offset);
|
||||||
/* level0 and first mipmap need to have alignment */
|
/* level0 and first mipmap need to have alignment */
|
||||||
offset = surf->bo_size;
|
offset = surf->bo_size;
|
||||||
if ((i == 0)) {
|
if ((i == 0)) {
|
||||||
|
@ -1069,6 +1072,68 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
|
||||||
|
struct radeon_surface *surf,
|
||||||
|
struct radeon_surface_level *level,
|
||||||
|
unsigned bpe,
|
||||||
|
uint64_t offset, unsigned start_level)
|
||||||
|
{
|
||||||
|
uint32_t xalign, yalign, zalign, slice_align;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
/* compute alignment */
|
||||||
|
xalign = 8;
|
||||||
|
yalign = 8;
|
||||||
|
zalign = 1;
|
||||||
|
slice_align = surf_man->hw_info.group_bytes;
|
||||||
|
if (surf->flags & RADEON_SURF_SCANOUT) {
|
||||||
|
xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!start_level) {
|
||||||
|
unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
|
||||||
|
surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
|
||||||
|
|
||||||
|
if (offset) {
|
||||||
|
offset = ALIGN(offset, alignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build mipmap tree */
|
||||||
|
for (i = start_level; i <= surf->last_level; i++) {
|
||||||
|
level[i].mode = RADEON_SURF_MODE_1D;
|
||||||
|
si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
|
||||||
|
/* level0 and first mipmap need to have alignment */
|
||||||
|
offset = surf->bo_size;
|
||||||
|
if ((i == 0)) {
|
||||||
|
offset = ALIGN(offset, surf->bo_alignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
|
||||||
|
struct radeon_surface *surf)
|
||||||
|
{
|
||||||
|
unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
|
||||||
|
int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
|
||||||
|
/* Old libdrm 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;
|
||||||
|
|
||||||
|
r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (is_depth_stencil) {
|
||||||
|
r = si_surface_init_1d(surf_man, surf, stencil_level, 1,
|
||||||
|
surf->bo_size, 0);
|
||||||
|
surf->stencil_offset = stencil_level[0].offset;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int si_surface_init(struct radeon_surface_manager *surf_man,
|
static int si_surface_init(struct radeon_surface_manager *surf_man,
|
||||||
struct radeon_surface *surf)
|
struct radeon_surface *surf)
|
||||||
{
|
{
|
||||||
|
@ -1115,7 +1180,7 @@ static int si_surface_init(struct radeon_surface_manager *surf_man,
|
||||||
r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
|
r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
|
||||||
break;
|
break;
|
||||||
case RADEON_SURF_MODE_1D:
|
case RADEON_SURF_MODE_1D:
|
||||||
r = eg_surface_init_1d_miptrees(surf_man, surf);
|
r = si_surface_init_1d_miptrees(surf_man, surf);
|
||||||
break;
|
break;
|
||||||
case RADEON_SURF_MODE_2D:
|
case RADEON_SURF_MODE_2D:
|
||||||
r = eg_surface_init_2d_miptrees(surf_man, surf);
|
r = eg_surface_init_2d_miptrees(surf_man, surf);
|
||||||
|
|
Loading…
Reference in New Issue