radeon: add si tiling support v5
v2: Only writte tile index if flags for it is set v3: Remove useless allow2d scanout flags v4: Split radeon_drm.h update to its own patch v5: update against lastest next tree for radeon Signed-off-by: Jerome Glisse <jglisse@redhat.com> Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>main
parent
309cb649a3
commit
a36cdb858e
|
@ -83,12 +83,14 @@ typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
|
|||
|
||||
struct radeon_hw_info {
|
||||
/* apply to r6, eg */
|
||||
uint32_t group_bytes;
|
||||
uint32_t num_banks;
|
||||
uint32_t num_pipes;
|
||||
uint32_t group_bytes;
|
||||
uint32_t num_banks;
|
||||
uint32_t num_pipes;
|
||||
/* apply to eg */
|
||||
uint32_t row_size;
|
||||
unsigned allow_2d;
|
||||
uint32_t row_size;
|
||||
unsigned allow_2d;
|
||||
/* apply to si */
|
||||
uint32_t tile_mode_array[32];
|
||||
};
|
||||
|
||||
struct radeon_surface_manager {
|
||||
|
@ -1000,12 +1002,403 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
|
|||
/* ===========================================================================
|
||||
* Southern Islands family
|
||||
*/
|
||||
#define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P2 0
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
|
||||
#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
|
||||
#define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
|
||||
#define SI__TILE_SPLIT__64B 0
|
||||
#define SI__TILE_SPLIT__128B 1
|
||||
#define SI__TILE_SPLIT__256B 2
|
||||
#define SI__TILE_SPLIT__512B 3
|
||||
#define SI__TILE_SPLIT__1024B 4
|
||||
#define SI__TILE_SPLIT__2048B 5
|
||||
#define SI__TILE_SPLIT__4096B 6
|
||||
#define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
|
||||
#define SI__BANK_WIDTH__1 0
|
||||
#define SI__BANK_WIDTH__2 1
|
||||
#define SI__BANK_WIDTH__4 2
|
||||
#define SI__BANK_WIDTH__8 3
|
||||
#define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
|
||||
#define SI__BANK_HEIGHT__1 0
|
||||
#define SI__BANK_HEIGHT__2 1
|
||||
#define SI__BANK_HEIGHT__4 2
|
||||
#define SI__BANK_HEIGHT__8 3
|
||||
#define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
|
||||
#define SI__MACRO_TILE_ASPECT__1 0
|
||||
#define SI__MACRO_TILE_ASPECT__2 1
|
||||
#define SI__MACRO_TILE_ASPECT__4 2
|
||||
#define SI__MACRO_TILE_ASPECT__8 3
|
||||
#define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
|
||||
#define SI__NUM_BANKS__2_BANK 0
|
||||
#define SI__NUM_BANKS__4_BANK 1
|
||||
#define SI__NUM_BANKS__8_BANK 2
|
||||
#define SI__NUM_BANKS__16_BANK 3
|
||||
|
||||
|
||||
static void si_gb_tile_mode(uint32_t gb_tile_mode,
|
||||
unsigned *num_pipes,
|
||||
unsigned *num_banks,
|
||||
uint32_t *macro_tile_aspect,
|
||||
uint32_t *bank_w,
|
||||
uint32_t *bank_h,
|
||||
uint32_t *tile_split)
|
||||
{
|
||||
if (num_pipes) {
|
||||
switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P2:
|
||||
default:
|
||||
*num_pipes = 2;
|
||||
break;
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
|
||||
*num_pipes = 4;
|
||||
break;
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
|
||||
case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
|
||||
*num_pipes = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num_banks) {
|
||||
switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
|
||||
default:
|
||||
case SI__NUM_BANKS__2_BANK:
|
||||
*num_banks = 2;
|
||||
break;
|
||||
case SI__NUM_BANKS__4_BANK:
|
||||
*num_banks = 4;
|
||||
break;
|
||||
case SI__NUM_BANKS__8_BANK:
|
||||
*num_banks = 8;
|
||||
break;
|
||||
case SI__NUM_BANKS__16_BANK:
|
||||
*num_banks = 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (macro_tile_aspect) {
|
||||
switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
|
||||
default:
|
||||
case SI__MACRO_TILE_ASPECT__1:
|
||||
*macro_tile_aspect = 1;
|
||||
break;
|
||||
case SI__MACRO_TILE_ASPECT__2:
|
||||
*macro_tile_aspect = 2;
|
||||
break;
|
||||
case SI__MACRO_TILE_ASPECT__4:
|
||||
*macro_tile_aspect = 4;
|
||||
break;
|
||||
case SI__MACRO_TILE_ASPECT__8:
|
||||
*macro_tile_aspect = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bank_w) {
|
||||
switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
|
||||
default:
|
||||
case SI__BANK_WIDTH__1:
|
||||
*bank_w = 1;
|
||||
break;
|
||||
case SI__BANK_WIDTH__2:
|
||||
*bank_w = 2;
|
||||
break;
|
||||
case SI__BANK_WIDTH__4:
|
||||
*bank_w = 4;
|
||||
break;
|
||||
case SI__BANK_WIDTH__8:
|
||||
*bank_w = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bank_h) {
|
||||
switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
|
||||
default:
|
||||
case SI__BANK_HEIGHT__1:
|
||||
*bank_h = 1;
|
||||
break;
|
||||
case SI__BANK_HEIGHT__2:
|
||||
*bank_h = 2;
|
||||
break;
|
||||
case SI__BANK_HEIGHT__4:
|
||||
*bank_h = 4;
|
||||
break;
|
||||
case SI__BANK_HEIGHT__8:
|
||||
*bank_h = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tile_split) {
|
||||
switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
|
||||
default:
|
||||
case SI__TILE_SPLIT__64B:
|
||||
*tile_split = 64;
|
||||
break;
|
||||
case SI__TILE_SPLIT__128B:
|
||||
*tile_split = 128;
|
||||
break;
|
||||
case SI__TILE_SPLIT__256B:
|
||||
*tile_split = 256;
|
||||
break;
|
||||
case SI__TILE_SPLIT__512B:
|
||||
*tile_split = 512;
|
||||
break;
|
||||
case SI__TILE_SPLIT__1024B:
|
||||
*tile_split = 1024;
|
||||
break;
|
||||
case SI__TILE_SPLIT__2048B:
|
||||
*tile_split = 2048;
|
||||
break;
|
||||
case SI__TILE_SPLIT__4096B:
|
||||
*tile_split = 4096;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int si_init_hw_info(struct radeon_surface_manager *surf_man)
|
||||
{
|
||||
uint32_t tiling_config;
|
||||
drmVersionPtr version;
|
||||
int r;
|
||||
|
||||
r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
|
||||
&tiling_config);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
surf_man->hw_info.allow_2d = 0;
|
||||
version = drmGetVersion(surf_man->fd);
|
||||
if (version && version->version_minor >= 33) {
|
||||
if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
|
||||
surf_man->hw_info.allow_2d = 1;
|
||||
}
|
||||
}
|
||||
drmFreeVersion(version);
|
||||
|
||||
switch (tiling_config & 0xf) {
|
||||
case 0:
|
||||
surf_man->hw_info.num_pipes = 1;
|
||||
break;
|
||||
case 1:
|
||||
surf_man->hw_info.num_pipes = 2;
|
||||
break;
|
||||
case 2:
|
||||
surf_man->hw_info.num_pipes = 4;
|
||||
break;
|
||||
case 3:
|
||||
surf_man->hw_info.num_pipes = 8;
|
||||
break;
|
||||
default:
|
||||
surf_man->hw_info.num_pipes = 8;
|
||||
surf_man->hw_info.allow_2d = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((tiling_config & 0xf0) >> 4) {
|
||||
case 0:
|
||||
surf_man->hw_info.num_banks = 4;
|
||||
break;
|
||||
case 1:
|
||||
surf_man->hw_info.num_banks = 8;
|
||||
break;
|
||||
case 2:
|
||||
surf_man->hw_info.num_banks = 16;
|
||||
break;
|
||||
default:
|
||||
surf_man->hw_info.num_banks = 8;
|
||||
surf_man->hw_info.allow_2d = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((tiling_config & 0xf00) >> 8) {
|
||||
case 0:
|
||||
surf_man->hw_info.group_bytes = 256;
|
||||
break;
|
||||
case 1:
|
||||
surf_man->hw_info.group_bytes = 512;
|
||||
break;
|
||||
default:
|
||||
surf_man->hw_info.group_bytes = 256;
|
||||
surf_man->hw_info.allow_2d = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((tiling_config & 0xf000) >> 12) {
|
||||
case 0:
|
||||
surf_man->hw_info.row_size = 1024;
|
||||
break;
|
||||
case 1:
|
||||
surf_man->hw_info.row_size = 2048;
|
||||
break;
|
||||
case 2:
|
||||
surf_man->hw_info.row_size = 4096;
|
||||
break;
|
||||
default:
|
||||
surf_man->hw_info.row_size = 4096;
|
||||
surf_man->hw_info.allow_2d = 0;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si_surface_sanity(struct radeon_surface_manager *surf_man,
|
||||
struct radeon_surface *surf,
|
||||
unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
|
||||
{
|
||||
uint32_t gb_tile_mode;
|
||||
|
||||
/* check surface dimension */
|
||||
if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check mipmap last_level */
|
||||
if (surf->last_level > 15) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* force 1d on kernel that can't do 2d */
|
||||
if (mode > RADEON_SURF_MODE_1D &&
|
||||
(!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
|
||||
if (surf->nsamples > 1) {
|
||||
fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
|
||||
return -EFAULT;
|
||||
}
|
||||
mode = RADEON_SURF_MODE_1D;
|
||||
surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
|
||||
surf->flags |= RADEON_SURF_SET(mode, MODE);
|
||||
}
|
||||
|
||||
if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!surf->tile_split) {
|
||||
/* default value */
|
||||
surf->mtilea = 1;
|
||||
surf->bankw = 1;
|
||||
surf->bankw = 1;
|
||||
surf->tile_split = 64;
|
||||
surf->stencil_tile_split = 64;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case RADEON_SURF_MODE_2D:
|
||||
if (surf->flags & RADEON_SURF_SBUFFER) {
|
||||
switch (surf->nsamples) {
|
||||
case 1:
|
||||
*stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
|
||||
break;
|
||||
case 2:
|
||||
*stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
|
||||
break;
|
||||
case 4:
|
||||
*stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
|
||||
break;
|
||||
case 8:
|
||||
*stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
/* retrieve tiling mode value */
|
||||
gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
|
||||
si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
|
||||
}
|
||||
if (surf->flags & RADEON_SURF_ZBUFFER) {
|
||||
switch (surf->nsamples) {
|
||||
case 1:
|
||||
*tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
|
||||
break;
|
||||
case 2:
|
||||
*tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
|
||||
break;
|
||||
case 4:
|
||||
*tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
|
||||
break;
|
||||
case 8:
|
||||
*tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (surf->flags & RADEON_SURF_SCANOUT) {
|
||||
switch (surf->bpe) {
|
||||
case 2:
|
||||
*tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
|
||||
break;
|
||||
case 4:
|
||||
*tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
switch (surf->bpe) {
|
||||
case 1:
|
||||
*tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
|
||||
break;
|
||||
case 2:
|
||||
*tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
|
||||
break;
|
||||
case 4:
|
||||
*tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
|
||||
break;
|
||||
case 8:
|
||||
case 16:
|
||||
*tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* retrieve tiling mode value */
|
||||
gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
|
||||
si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
|
||||
break;
|
||||
case RADEON_SURF_MODE_1D:
|
||||
if (surf->flags & RADEON_SURF_SBUFFER) {
|
||||
*stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
|
||||
}
|
||||
if (surf->flags & RADEON_SURF_ZBUFFER) {
|
||||
*tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
|
||||
} else if (surf->flags & RADEON_SURF_SCANOUT) {
|
||||
*tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
|
||||
} else {
|
||||
*tile_mode = SI_TILE_MODE_COLOR_1D;
|
||||
}
|
||||
break;
|
||||
case RADEON_SURF_MODE_LINEAR_ALIGNED:
|
||||
default:
|
||||
*tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void si_surf_minify(struct radeon_surface *surf,
|
||||
struct radeon_surface_level *surflevel,
|
||||
unsigned bpe, unsigned level,
|
||||
uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
|
||||
unsigned offset)
|
||||
struct radeon_surface_level *surflevel,
|
||||
unsigned bpe, unsigned level,
|
||||
uint32_t xalign, uint32_t yalign, uint32_t zalign,
|
||||
uint32_t slice_align, unsigned offset)
|
||||
{
|
||||
surflevel->npix_x = mip_minify(surf->npix_x, level);
|
||||
surflevel->npix_y = mip_minify(surf->npix_y, level);
|
||||
|
@ -1043,8 +1436,52 @@ static void si_surf_minify(struct radeon_surface *surf,
|
|||
surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
|
||||
}
|
||||
|
||||
static void si_surf_minify_2d(struct radeon_surface *surf,
|
||||
struct radeon_surface_level *surflevel,
|
||||
unsigned bpe, unsigned level, unsigned slice_pt,
|
||||
uint32_t xalign, uint32_t yalign, uint32_t zalign,
|
||||
unsigned mtileb, unsigned offset)
|
||||
{
|
||||
unsigned mtile_pr, mtile_ps;
|
||||
|
||||
surflevel->npix_x = mip_minify(surf->npix_x, level);
|
||||
surflevel->npix_y = mip_minify(surf->npix_y, level);
|
||||
surflevel->npix_z = mip_minify(surf->npix_z, level);
|
||||
|
||||
if (level == 0 && surf->last_level > 0) {
|
||||
surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
|
||||
surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
|
||||
surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
|
||||
} else {
|
||||
surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
|
||||
surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
|
||||
surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
|
||||
}
|
||||
|
||||
if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
|
||||
if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
|
||||
surflevel->mode = RADEON_SURF_MODE_1D;
|
||||
return;
|
||||
}
|
||||
}
|
||||
surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
|
||||
surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
|
||||
surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
|
||||
|
||||
/* macro tile per row */
|
||||
mtile_pr = surflevel->nblk_x / xalign;
|
||||
/* macro tile per slice */
|
||||
mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
|
||||
surflevel->offset = offset;
|
||||
surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
|
||||
surflevel->slice_size = mtile_ps * mtileb * slice_pt;
|
||||
|
||||
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,
|
||||
struct radeon_surface *surf,
|
||||
unsigned tile_mode,
|
||||
uint64_t offset, unsigned start_level)
|
||||
{
|
||||
uint32_t xalign, yalign, zalign, slice_align;
|
||||
|
@ -1062,13 +1499,15 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma
|
|||
/* build mipmap tree */
|
||||
for (i = start_level; i <= surf->last_level; i++) {
|
||||
surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
|
||||
si_surf_minify(surf, surf->level+i, surf->bpe, 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 */
|
||||
offset = surf->bo_size;
|
||||
if ((i == 0)) {
|
||||
offset = ALIGN(offset, surf->bo_alignment);
|
||||
}
|
||||
if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
|
||||
surf->tiling_index[i] = tile_mode;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1076,7 +1515,7 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma
|
|||
static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
|
||||
struct radeon_surface *surf,
|
||||
struct radeon_surface_level *level,
|
||||
unsigned bpe,
|
||||
unsigned bpe, unsigned tile_mode,
|
||||
uint64_t offset, unsigned start_level)
|
||||
{
|
||||
uint32_t xalign, yalign, zalign, slice_align;
|
||||
|
@ -1092,11 +1531,10 @@ static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
|
|||
}
|
||||
|
||||
if (!start_level) {
|
||||
unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
|
||||
surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
|
||||
surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
|
||||
|
||||
if (offset) {
|
||||
offset = ALIGN(offset, alignment);
|
||||
offset = ALIGN(offset, surf->bo_alignment);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1109,28 +1547,140 @@ static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
|
|||
if ((i == 0)) {
|
||||
offset = ALIGN(offset, surf->bo_alignment);
|
||||
}
|
||||
if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
|
||||
if (surf->level == level) {
|
||||
surf->tiling_index[i] = tile_mode;
|
||||
/* it's ok because stencil is done after */
|
||||
surf->stencil_tiling_index[i] = tile_mode;
|
||||
} else {
|
||||
surf->stencil_tiling_index[i] = tile_mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
|
||||
struct radeon_surface *surf)
|
||||
struct radeon_surface *surf,
|
||||
unsigned tile_mode, unsigned stencil_tile_mode)
|
||||
{
|
||||
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;
|
||||
int r;
|
||||
|
||||
r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
|
||||
if (r)
|
||||
r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 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;
|
||||
if (surf->flags & RADEON_SURF_SBUFFER) {
|
||||
r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
|
||||
surf->stencil_offset = surf->stencil_level[0].offset;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
|
||||
struct radeon_surface *surf,
|
||||
struct radeon_surface_level *level,
|
||||
unsigned bpe, unsigned tile_mode,
|
||||
unsigned num_pipes, unsigned num_banks,
|
||||
unsigned tile_split,
|
||||
uint64_t offset,
|
||||
unsigned start_level)
|
||||
{
|
||||
unsigned tilew, tileh, tileb;
|
||||
unsigned mtilew, mtileh, mtileb;
|
||||
unsigned slice_pt;
|
||||
unsigned i;
|
||||
|
||||
/* compute tile values */
|
||||
tilew = 8;
|
||||
tileh = 8;
|
||||
tileb = tilew * tileh * bpe * surf->nsamples;
|
||||
/* slices per tile */
|
||||
slice_pt = 1;
|
||||
if (tileb > tile_split) {
|
||||
slice_pt = tileb / tile_split;
|
||||
}
|
||||
tileb = tileb / slice_pt;
|
||||
|
||||
/* macro tile width & height */
|
||||
mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
|
||||
mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
|
||||
|
||||
/* macro tile bytes */
|
||||
mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
|
||||
|
||||
if (!start_level) {
|
||||
unsigned alignment = MAX2(256, mtileb);
|
||||
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_2D;
|
||||
si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, offset);
|
||||
if (level[i].mode == RADEON_SURF_MODE_1D) {
|
||||
switch (tile_mode) {
|
||||
case SI_TILE_MODE_COLOR_2D_8BPP:
|
||||
case SI_TILE_MODE_COLOR_2D_16BPP:
|
||||
case SI_TILE_MODE_COLOR_2D_32BPP:
|
||||
case SI_TILE_MODE_COLOR_2D_64BPP:
|
||||
tile_mode = SI_TILE_MODE_COLOR_1D;
|
||||
break;
|
||||
case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
|
||||
case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
|
||||
tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
|
||||
break;
|
||||
case SI_TILE_MODE_DEPTH_STENCIL_2D:
|
||||
tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
|
||||
}
|
||||
/* level0 and first mipmap need to have alignment */
|
||||
offset = surf->bo_size;
|
||||
if ((i == 0)) {
|
||||
offset = ALIGN(offset, surf->bo_alignment);
|
||||
}
|
||||
if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
|
||||
if (surf->level == level) {
|
||||
surf->tiling_index[i] = tile_mode;
|
||||
/* it's ok because stencil is done after */
|
||||
surf->stencil_tiling_index[i] = tile_mode;
|
||||
} else {
|
||||
surf->stencil_tiling_index[i] = tile_mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
|
||||
struct radeon_surface *surf,
|
||||
unsigned tile_mode, unsigned stencil_tile_mode)
|
||||
{
|
||||
unsigned num_pipes, num_banks;
|
||||
uint32_t gb_tile_mode;
|
||||
int r;
|
||||
|
||||
/* retrieve tiling mode value */
|
||||
gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
|
||||
si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
|
||||
|
||||
r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (surf->flags & RADEON_SURF_SBUFFER) {
|
||||
r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0);
|
||||
surf->stencil_offset = surf->stencil_level[0].offset;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -1138,7 +1688,7 @@ static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
|
|||
static int si_surface_init(struct radeon_surface_manager *surf_man,
|
||||
struct radeon_surface *surf)
|
||||
{
|
||||
unsigned mode;
|
||||
unsigned mode, tile_mode, stencil_tile_mode;
|
||||
int r;
|
||||
|
||||
/* MSAA surfaces support the 2D mode only. */
|
||||
|
@ -1150,12 +1700,6 @@ static int si_surface_init(struct radeon_surface_manager *surf_man,
|
|||
/* tiling mode */
|
||||
mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
|
||||
|
||||
/* those are already handled by the kernel tile mode array but we still
|
||||
* need value that won't be rejected by kernel set tiling function
|
||||
*/
|
||||
surf->tile_split = 0;
|
||||
surf->stencil_tile_split = 0;
|
||||
|
||||
if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
|
||||
/* zbuffer only support 1D or 2D tiled surface */
|
||||
switch (mode) {
|
||||
|
@ -1170,7 +1714,7 @@ static int si_surface_init(struct radeon_surface_manager *surf_man,
|
|||
}
|
||||
}
|
||||
|
||||
r = eg_surface_sanity(surf_man, surf, mode);
|
||||
r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
@ -1184,13 +1728,13 @@ static int si_surface_init(struct radeon_surface_manager *surf_man,
|
|||
r = r6_surface_init_linear(surf_man, surf, 0, 0);
|
||||
break;
|
||||
case RADEON_SURF_MODE_LINEAR_ALIGNED:
|
||||
r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
|
||||
r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
|
||||
break;
|
||||
case RADEON_SURF_MODE_1D:
|
||||
r = si_surface_init_1d_miptrees(surf_man, surf);
|
||||
r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
|
||||
break;
|
||||
case RADEON_SURF_MODE_2D:
|
||||
r = eg_surface_init_2d_miptrees(surf_man, surf);
|
||||
r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -1198,6 +1742,28 @@ static int si_surface_init(struct radeon_surface_manager *surf_man,
|
|||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* depending on surface
|
||||
*/
|
||||
static int si_surface_best(struct radeon_surface_manager *surf_man,
|
||||
struct radeon_surface *surf)
|
||||
{
|
||||
unsigned mode, tile_mode, stencil_tile_mode;
|
||||
|
||||
/* tiling mode */
|
||||
mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
|
||||
|
||||
if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
|
||||
!(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
|
||||
/* depth/stencil force 1d tiling for old mesa */
|
||||
surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
|
||||
surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
|
||||
}
|
||||
|
||||
return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
|
||||
}
|
||||
|
||||
|
||||
/* ===========================================================================
|
||||
* public API
|
||||
*/
|
||||
|
@ -1223,16 +1789,18 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd)
|
|||
}
|
||||
surf_man->surface_init = &r6_surface_init;
|
||||
surf_man->surface_best = &r6_surface_best;
|
||||
} else {
|
||||
} else if (surf_man->family <= CHIP_ARUBA) {
|
||||
if (eg_init_hw_info(surf_man)) {
|
||||
goto out_err;
|
||||
}
|
||||
if (surf_man->family <= CHIP_ARUBA) {
|
||||
surf_man->surface_init = &eg_surface_init;
|
||||
} else {
|
||||
surf_man->surface_init = &si_surface_init;
|
||||
}
|
||||
surf_man->surface_init = &eg_surface_init;
|
||||
surf_man->surface_best = &eg_surface_best;
|
||||
} else {
|
||||
if (si_init_hw_info(surf_man)) {
|
||||
goto out_err;
|
||||
}
|
||||
surf_man->surface_init = &si_surface_init;
|
||||
surf_man->surface_best = &si_surface_best;
|
||||
}
|
||||
|
||||
return surf_man;
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#define RADEON_SURF_ZBUFFER (1 << 17)
|
||||
#define RADEON_SURF_SBUFFER (1 << 18)
|
||||
#define RADEON_SURF_HAS_SBUFFER_MIPTREE (1 << 19)
|
||||
#define RADEON_SURF_HAS_TILE_MODE_INDEX (1 << 20)
|
||||
|
||||
#define RADEON_SURF_GET(v, field) (((v) >> RADEON_SURF_ ## field ## _SHIFT) & RADEON_SURF_ ## field ## _MASK)
|
||||
#define RADEON_SURF_SET(v, field) (((v) & RADEON_SURF_ ## field ## _MASK) << RADEON_SURF_ ## field ## _SHIFT)
|
||||
|
@ -76,6 +77,34 @@ struct radeon_surface_level {
|
|||
uint32_t mode;
|
||||
};
|
||||
|
||||
enum si_tiling_mode {
|
||||
SI_TILING_AUTO = 0,
|
||||
|
||||
SI_TILING_COLOR_1D,
|
||||
SI_TILING_COLOR_1D_SCANOUT,
|
||||
SI_TILING_COLOR_2D_8BPP,
|
||||
SI_TILING_COLOR_2D_16BPP,
|
||||
SI_TILING_COLOR_2D_32BPP,
|
||||
SI_TILING_COLOR_2D_64BPP,
|
||||
SI_TILING_COLOR_2D_SCANOUT_16BPP,
|
||||
SI_TILING_COLOR_2D_SCANOUT_32BPP,
|
||||
SI_TILING_COLOR_LINEAR,
|
||||
|
||||
SI_TILING_STENCIL_1D,
|
||||
SI_TILING_STENCIL_2D,
|
||||
SI_TILING_STENCIL_2D_2AA,
|
||||
SI_TILING_STENCIL_2D_4AA,
|
||||
SI_TILING_STENCIL_2D_8AA,
|
||||
|
||||
SI_TILING_DEPTH_1D,
|
||||
SI_TILING_DEPTH_2D,
|
||||
SI_TILING_DEPTH_2D_2AA,
|
||||
SI_TILING_DEPTH_2D_4AA,
|
||||
SI_TILING_DEPTH_2D_8AA,
|
||||
|
||||
SI_TILING_LAST_MODE,
|
||||
};
|
||||
|
||||
struct radeon_surface {
|
||||
uint32_t npix_x;
|
||||
uint32_t npix_y;
|
||||
|
@ -104,6 +133,8 @@ struct radeon_surface {
|
|||
uint64_t stencil_offset;
|
||||
struct radeon_surface_level level[RADEON_SURF_MAX_LEVEL];
|
||||
struct radeon_surface_level stencil_level[RADEON_SURF_MAX_LEVEL];
|
||||
uint32_t tiling_index[RADEON_SURF_MAX_LEVEL];
|
||||
uint32_t stencil_tiling_index[RADEON_SURF_MAX_LEVEL];
|
||||
};
|
||||
|
||||
struct radeon_surface_manager *radeon_surface_manager_new(int fd);
|
||||
|
|
Loading…
Reference in New Issue