aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichel Dänzer2013-01-17 12:03:42 -0600
committerNikhil Devshatwar2013-05-17 04:51:31 -0500
commit35779fe814b3f84b0fe85e083ef98a546fd94b39 (patch)
tree6e8da3c6b0ec9e36321c51b11da9f20aa03aeaa2
parent0c72cc8e66886b6d85e8d90360d8d5e70eeb2110 (diff)
downloadlibdrm-35779fe814b3f84b0fe85e083ef98a546fd94b39.tar.gz
libdrm-35779fe814b3f84b0fe85e083ef98a546fd94b39.tar.xz
libdrm-35779fe814b3f84b0fe85e083ef98a546fd94b39.zip
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>
-rw-r--r--radeon/radeon_surface.c111
1 files changed, 88 insertions, 23 deletions
diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
index eb587d24..8e93873f 100644
--- a/radeon/radeon_surface.c
+++ b/radeon/radeon_surface.c
@@ -1000,25 +1000,28 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
1000 * Southern Islands family 1000 * Southern Islands family
1001 */ 1001 */
1002 1002
1003static void si_surf_minify_linear_aligned(struct radeon_surface *surf, 1003static void si_surf_minify(struct radeon_surface *surf,
1004 unsigned level, 1004 struct radeon_surface_level *surflevel,
1005 uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align, 1005 unsigned bpe, unsigned level,
1006 unsigned offset) 1006 uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
1007 unsigned offset)
1007{ 1008{
1008 surf->level[level].npix_x = mip_minify(surf->npix_x, level); 1009 surflevel->npix_x = mip_minify(surf->npix_x, level);
1009 surf->level[level].npix_y = mip_minify(surf->npix_y, level); 1010 surflevel->npix_y = mip_minify(surf->npix_y, level);
1010 surf->level[level].npix_z = mip_minify(surf->npix_z, level); 1011 surflevel->npix_z = mip_minify(surf->npix_z, level);
1011 1012
1012 if (level == 0 && surf->last_level > 0) { 1013 if (level == 0 && surf->last_level > 0) {
1013 surf->level[level].nblk_x = (next_power_of_two(surf->level[level].npix_x) + surf->blk_w - 1) / surf->blk_w; 1014 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1014 surf->level[level].nblk_y = (next_power_of_two(surf->level[level].npix_y) + surf->blk_h - 1) / surf->blk_h; 1015 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1015 surf->level[level].nblk_z = (next_power_of_two(surf->level[level].npix_z) + surf->blk_d - 1) / surf->blk_d; 1016 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1016 } else { 1017 } else {
1017 surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w; 1018 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1018 surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h; 1019 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1019 surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d; 1020 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1020 } 1021 }
1021 1022
1023 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1024
1022 /* XXX: Texture sampling uses unexpectedly large pitches in some cases, 1025 /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1023 * these are just guesses for the rules behind those 1026 * these are just guesses for the rules behind those
1024 */ 1027 */
@@ -1027,17 +1030,16 @@ static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
1027 xalign = MAX2(xalign, slice_align / surf->bpe); 1030 xalign = MAX2(xalign, slice_align / surf->bpe);
1028 else 1031 else
1029 /* Small rows evenly distributed across slice */ 1032 /* Small rows evenly distributed across slice */
1030 xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y); 1033 xalign = MAX2(xalign, slice_align / surf->bpe / surflevel->nblk_y);
1031 1034
1032 surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, xalign); 1035 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1033 surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, yalign); 1036 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1034 surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, zalign);
1035 1037
1036 surf->level[level].offset = offset; 1038 surflevel->offset = offset;
1037 surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples; 1039 surflevel->pitch_bytes = surflevel->nblk_x * surf->bpe * surf->nsamples;
1038 surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align); 1040 surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
1039 1041
1040 surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size; 1042 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1041} 1043}
1042 1044
1043static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man, 1045static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
@@ -1059,7 +1061,48 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma
1059 /* build mipmap tree */ 1061 /* build mipmap tree */
1060 for (i = start_level; i <= surf->last_level; i++) { 1062 for (i = start_level; i <= surf->last_level; i++) {
1061 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED; 1063 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1062 si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset); 1064 si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign,
1065 zalign, slice_align, offset);
1066 /* level0 and first mipmap need to have alignment */
1067 offset = surf->bo_size;
1068 if ((i == 0)) {
1069 offset = ALIGN(offset, surf->bo_alignment);
1070 }
1071 }
1072 return 0;
1073}
1074
1075static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1076 struct radeon_surface *surf,
1077 struct radeon_surface_level *level,
1078 unsigned bpe,
1079 uint64_t offset, unsigned start_level)
1080{
1081 uint32_t xalign, yalign, zalign, slice_align;
1082 unsigned i;
1083
1084 /* compute alignment */
1085 xalign = 8;
1086 yalign = 8;
1087 zalign = 1;
1088 slice_align = surf_man->hw_info.group_bytes;
1089 if (surf->flags & RADEON_SURF_SCANOUT) {
1090 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1091 }
1092
1093 if (!start_level) {
1094 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
1095 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1096
1097 if (offset) {
1098 offset = ALIGN(offset, alignment);
1099 }
1100 }
1101
1102 /* build mipmap tree */
1103 for (i = start_level; i <= surf->last_level; i++) {
1104 level[i].mode = RADEON_SURF_MODE_1D;
1105 si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1063 /* level0 and first mipmap need to have alignment */ 1106 /* level0 and first mipmap need to have alignment */
1064 offset = surf->bo_size; 1107 offset = surf->bo_size;
1065 if ((i == 0)) { 1108 if ((i == 0)) {
@@ -1069,6 +1112,28 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma
1069 return 0; 1112 return 0;
1070} 1113}
1071 1114
1115static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1116 struct radeon_surface *surf)
1117{
1118 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
1119 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
1120 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
1121 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
1122 struct radeon_surface_level *stencil_level =
1123 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
1124
1125 r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
1126 if (r)
1127 return r;
1128
1129 if (is_depth_stencil) {
1130 r = si_surface_init_1d(surf_man, surf, stencil_level, 1,
1131 surf->bo_size, 0);
1132 surf->stencil_offset = stencil_level[0].offset;
1133 }
1134 return r;
1135}
1136
1072static int si_surface_init(struct radeon_surface_manager *surf_man, 1137static int si_surface_init(struct radeon_surface_manager *surf_man,
1073 struct radeon_surface *surf) 1138 struct radeon_surface *surf)
1074{ 1139{
@@ -1115,7 +1180,7 @@ static int si_surface_init(struct radeon_surface_manager *surf_man,
1115 r = si_surface_init_linear_aligned(surf_man, surf, 0, 0); 1180 r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
1116 break; 1181 break;
1117 case RADEON_SURF_MODE_1D: 1182 case RADEON_SURF_MODE_1D:
1118 r = eg_surface_init_1d_miptrees(surf_man, surf); 1183 r = si_surface_init_1d_miptrees(surf_man, surf);
1119 break; 1184 break;
1120 case RADEON_SURF_MODE_2D: 1185 case RADEON_SURF_MODE_2D:
1121 r = eg_surface_init_2d_miptrees(surf_man, surf); 1186 r = eg_surface_init_2d_miptrees(surf_man, surf);