1 /* 2 * Copyright 2006 VMware, Inc. 3 * Copyright 2006 Intel Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 /** 27 * \file brw_tex_layout.cpp 28 * 29 * Code to lay out images in a mipmap tree. 30 * 31 * \author Keith Whitwell <keithw (at) vmware.com> 32 * \author Michel Dnzer <daenzer (at) vmware.com> 33 */ 34 35 #include "intel_mipmap_tree.h" 36 #include "brw_context.h" 37 #include "main/macros.h" 38 #include "main/glformats.h" 39 40 #define FILE_DEBUG_FLAG DEBUG_MIPTREE 41 42 static unsigned int 43 tr_mode_horizontal_texture_alignment(const struct intel_mipmap_tree *mt) 44 { 45 unsigned ret_align, divisor, multiplier_ys; 46 47 /* Values in below tables specifiy the horizontal alignment requirement 48 * in elements for TRMODE_YF surface. An element is defined as a pixel in 49 * uncompressed surface formats, and as a compression block in compressed 50 * surface formats. For MSFMT_DEPTH_STENCIL type multisampled surfaces, an 51 * element is a sample. 52 */ 53 const unsigned align_1d_yf[] = {4096, 2048, 1024, 512, 256}; 54 const unsigned align_2d_yf[] = {64, 64, 32, 32, 16}; 55 const unsigned align_3d_yf[] = {16, 8, 8, 8, 4}; 56 57 assert(mt->tr_mode != INTEL_MIPTREE_TRMODE_NONE); 58 59 /* Alignment computations below assume a power of 2 cpp. */ 60 assert (mt->cpp >= 1 && mt->cpp <= 16 && _mesa_is_pow_two(mt->cpp)); 61 /* Compute array index. */ 62 const int i = ffs(mt->cpp) - 1; 63 64 switch(mt->target) { 65 case GL_TEXTURE_1D: 66 case GL_TEXTURE_1D_ARRAY: 67 ret_align = align_1d_yf[i]; 68 multiplier_ys = 16; 69 break; 70 case GL_TEXTURE_2D: 71 case GL_TEXTURE_RECTANGLE: 72 case GL_TEXTURE_2D_ARRAY: 73 case GL_TEXTURE_CUBE_MAP: 74 case GL_TEXTURE_CUBE_MAP_ARRAY: 75 case GL_TEXTURE_2D_MULTISAMPLE: 76 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 77 ret_align = align_2d_yf[i]; 78 multiplier_ys = 4; 79 break; 80 case GL_TEXTURE_3D: 81 ret_align = align_3d_yf[i]; 82 multiplier_ys = 4; 83 break; 84 default: 85 unreachable("not reached"); 86 } 87 88 if (mt->tr_mode == INTEL_MIPTREE_TRMODE_YS) 89 ret_align *= multiplier_ys; 90 91 assert(_mesa_is_pow_two(mt->num_samples)); 92 93 switch (mt->num_samples) { 94 case 2: 95 case 4: 96 divisor = 2; 97 break; 98 case 8: 99 case 16: 100 divisor = 4; 101 break; 102 default: 103 divisor = 1; 104 break; 105 } 106 return ret_align / divisor; 107 } 108 109 110 static unsigned int 111 intel_horizontal_texture_alignment_unit(struct brw_context *brw, 112 struct intel_mipmap_tree *mt, 113 uint32_t layout_flags) 114 { 115 if (layout_flags & MIPTREE_LAYOUT_FORCE_HALIGN16) 116 return 16; 117 118 /** 119 * +----------------------------------------------------------------------+ 120 * | | alignment unit width ("i") | 121 * | Surface Property |-----------------------------| 122 * | | 915 | 965 | ILK | SNB | IVB | 123 * +----------------------------------------------------------------------+ 124 * | YUV 4:2:2 format | 8 | 4 | 4 | 4 | 4 | 125 * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | 126 * | FXT1 compressed format | 8 | 8 | 8 | 8 | 8 | 127 * | Depth Buffer (16-bit) | 4 | 4 | 4 | 4 | 8 | 128 * | Depth Buffer (other) | 4 | 4 | 4 | 4 | 4 | 129 * | Separate Stencil Buffer | N/A | N/A | 8 | 8 | 8 | 130 * | All Others | 4 | 4 | 4 | 4 | 4 | 131 * +----------------------------------------------------------------------+ 132 * 133 * On IVB+, non-special cases can be overridden by setting the SURFACE_STATE 134 * "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8. 135 */ 136 137 if (brw->gen >= 7 && mt->format == MESA_FORMAT_Z_UNORM16) 138 return 8; 139 140 return 4; 141 } 142 143 static unsigned int 144 tr_mode_vertical_texture_alignment(const struct intel_mipmap_tree *mt) 145 { 146 unsigned ret_align, divisor, multiplier_ys; 147 148 /* Vertical alignment tables for TRMODE_YF */ 149 const unsigned align_2d_yf[] = {64, 32, 32, 16, 16}; 150 const unsigned align_3d_yf[] = {16, 16, 16, 8, 8}; 151 152 assert(mt->tr_mode != INTEL_MIPTREE_TRMODE_NONE); 153 154 /* Alignment computations below assume a power of 2 cpp. */ 155 assert (mt->cpp >= 1 && mt->cpp <= 16 && _mesa_is_pow_two(mt->cpp)) ; 156 /* Compute array index. */ 157 const int i = ffs(mt->cpp) - 1; 158 159 switch(mt->target) { 160 case GL_TEXTURE_2D: 161 case GL_TEXTURE_RECTANGLE: 162 case GL_TEXTURE_2D_ARRAY: 163 case GL_TEXTURE_CUBE_MAP: 164 case GL_TEXTURE_CUBE_MAP_ARRAY: 165 case GL_TEXTURE_2D_MULTISAMPLE: 166 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 167 ret_align = align_2d_yf[i]; 168 multiplier_ys = 4; 169 break; 170 case GL_TEXTURE_3D: 171 ret_align = align_3d_yf[i]; 172 multiplier_ys = 2; 173 break; 174 case GL_TEXTURE_1D: 175 case GL_TEXTURE_1D_ARRAY: 176 default: 177 unreachable("Unexpected miptree target"); 178 } 179 180 if (mt->tr_mode == INTEL_MIPTREE_TRMODE_YS) 181 ret_align *= multiplier_ys; 182 183 assert(_mesa_is_pow_two(mt->num_samples)); 184 185 switch (mt->num_samples) { 186 case 4: 187 case 8: 188 divisor = 2; 189 break; 190 case 16: 191 divisor = 4; 192 break; 193 default: 194 divisor = 1; 195 break; 196 } 197 return ret_align / divisor; 198 } 199 200 static unsigned int 201 intel_vertical_texture_alignment_unit(struct brw_context *brw, 202 const struct intel_mipmap_tree *mt) 203 { 204 /** 205 * +----------------------------------------------------------------------+ 206 * | | alignment unit height ("j") | 207 * | Surface Property |-----------------------------| 208 * | | 915 | 965 | ILK | SNB | IVB | 209 * +----------------------------------------------------------------------+ 210 * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | 211 * | FXT1 compressed format | 4 | 4 | 4 | 4 | 4 | 212 * | Depth Buffer | 2 | 2 | 2 | 4 | 4 | 213 * | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 | 214 * | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 | 215 * | All Others | 2 | 2 | 2 | * | * | 216 * +----------------------------------------------------------------------+ 217 * 218 * Where "*" means either VALIGN_2 or VALIGN_4 depending on the setting of 219 * the SURFACE_STATE "Surface Vertical Alignment" field. 220 */ 221 222 /* Broadwell only supports VALIGN of 4, 8, and 16. The BSpec says 4 223 * should always be used, except for stencil buffers, which should be 8. 224 */ 225 if (brw->gen >= 8) 226 return 4; 227 228 if (mt->num_samples > 1) 229 return 4; 230 231 GLenum base_format = _mesa_get_format_base_format(mt->format); 232 233 if (brw->gen >= 6 && 234 (base_format == GL_DEPTH_COMPONENT || 235 base_format == GL_DEPTH_STENCIL)) { 236 return 4; 237 } 238 239 if (brw->gen == 7) { 240 /* On Gen7, we prefer a vertical alignment of 4 when possible, because 241 * that allows Y tiled render targets. 242 * 243 * From the Ivy Bridge PRM, Vol4 Part1 2.12.2.1 (SURFACE_STATE for most 244 * messages), on p64, under the heading "Surface Vertical Alignment": 245 * 246 * Value of 1 [VALIGN_4] is not supported for format YCRCB_NORMAL 247 * (0x182), YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY 248 * (0x190) 249 * 250 * VALIGN_4 is not supported for surface format R32G32B32_FLOAT. 251 */ 252 if (base_format == GL_YCBCR_MESA || mt->format == MESA_FORMAT_RGB_FLOAT32) 253 return 2; 254 255 return 4; 256 } 257 258 return 2; 259 } 260 261 static void 262 gen9_miptree_layout_1d(struct intel_mipmap_tree *mt) 263 { 264 unsigned x = 0; 265 unsigned width = mt->physical_width0; 266 unsigned depth = mt->physical_depth0; /* number of array layers. */ 267 268 /* When this layout is used the horizontal alignment is fixed at 64 and the 269 * hardware ignores the value given in the surface state 270 */ 271 const unsigned int halign = 64; 272 273 mt->total_height = mt->physical_height0; 274 mt->total_width = 0; 275 276 for (unsigned level = mt->first_level; level <= mt->last_level; level++) { 277 unsigned img_width; 278 279 intel_miptree_set_level_info(mt, level, x, 0, depth); 280 281 img_width = ALIGN(width, halign); 282 283 mt->total_width = MAX2(mt->total_width, x + img_width); 284 285 x += img_width; 286 287 width = minify(width, 1); 288 } 289 } 290 291 static void 292 brw_miptree_layout_2d(struct intel_mipmap_tree *mt) 293 { 294 unsigned x = 0; 295 unsigned y = 0; 296 unsigned width = mt->physical_width0; 297 unsigned height = mt->physical_height0; 298 unsigned depth = mt->physical_depth0; /* number of array layers. */ 299 unsigned int bw, bh; 300 301 _mesa_get_format_block_size(mt->format, &bw, &bh); 302 303 mt->total_width = mt->physical_width0; 304 305 if (mt->compressed) 306 mt->total_width = ALIGN_NPOT(mt->total_width, bw); 307 308 /* May need to adjust width to accommodate the placement of 309 * the 2nd mipmap. This occurs when the alignment 310 * constraints of mipmap placement push the right edge of the 311 * 2nd mipmap out past the width of its parent. 312 */ 313 if (mt->first_level != mt->last_level) { 314 unsigned mip1_width; 315 316 if (mt->compressed) { 317 mip1_width = ALIGN_NPOT(minify(mt->physical_width0, 1), mt->halign) + 318 ALIGN_NPOT(minify(mt->physical_width0, 2), bw); 319 } else { 320 mip1_width = ALIGN_NPOT(minify(mt->physical_width0, 1), mt->halign) + 321 minify(mt->physical_width0, 2); 322 } 323 324 if (mip1_width > mt->total_width) { 325 mt->total_width = mip1_width; 326 } 327 } 328 329 mt->total_width /= bw; 330 mt->total_height = 0; 331 332 for (unsigned level = mt->first_level; level <= mt->last_level; level++) { 333 unsigned img_height; 334 335 intel_miptree_set_level_info(mt, level, x, y, depth); 336 337 img_height = ALIGN_NPOT(height, mt->valign); 338 if (mt->compressed) 339 img_height /= bh; 340 341 if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) { 342 /* Compact arrays with separated miplevels */ 343 img_height *= depth; 344 } 345 346 /* Because the images are packed better, the final offset 347 * might not be the maximal one: 348 */ 349 mt->total_height = MAX2(mt->total_height, y + img_height); 350 351 /* Layout_below: step right after second mipmap. 352 */ 353 if (level == mt->first_level + 1) { 354 x += ALIGN_NPOT(width, mt->halign) / bw; 355 } else { 356 y += img_height; 357 } 358 359 width = minify(width, 1); 360 height = minify(height, 1); 361 362 if (mt->target == GL_TEXTURE_3D) 363 depth = minify(depth, 1); 364 } 365 } 366 367 unsigned 368 brw_miptree_get_horizontal_slice_pitch(const struct brw_context *brw, 369 const struct intel_mipmap_tree *mt, 370 unsigned level) 371 { 372 if ((brw->gen < 9 && mt->target == GL_TEXTURE_3D) || 373 (brw->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP)) { 374 return ALIGN_NPOT(minify(mt->physical_width0, level), mt->halign); 375 } else { 376 return 0; 377 } 378 } 379 380 unsigned 381 brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw, 382 const struct intel_mipmap_tree *mt, 383 unsigned level) 384 { 385 if (brw->gen >= 9) { 386 /* ALL_SLICES_AT_EACH_LOD isn't supported on Gen8+ but this code will 387 * effectively end up with a packed qpitch anyway whenever 388 * mt->first_level == mt->last_level. 389 */ 390 assert(mt->array_layout != ALL_SLICES_AT_EACH_LOD); 391 392 /* On Gen9 we can pick whatever qpitch we like as long as it's aligned 393 * to the vertical alignment so we don't need to add any extra rows. 394 */ 395 unsigned qpitch = mt->total_height; 396 397 /* If the surface might be used as a stencil buffer or HiZ buffer then 398 * it needs to be a multiple of 8. 399 */ 400 const GLenum base_format = _mesa_get_format_base_format(mt->format); 401 if (_mesa_is_depth_or_stencil_format(base_format)) 402 qpitch = ALIGN(qpitch, 8); 403 404 /* 3D textures need to be aligned to the tile height. At this point we 405 * don't know which tiling will be used so let's just align it to 32 406 */ 407 if (mt->target == GL_TEXTURE_3D) 408 qpitch = ALIGN(qpitch, 32); 409 410 return qpitch; 411 412 } else if (mt->target == GL_TEXTURE_3D || 413 (brw->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP) || 414 mt->array_layout == ALL_SLICES_AT_EACH_LOD) { 415 return ALIGN_NPOT(minify(mt->physical_height0, level), mt->valign); 416 417 } else { 418 const unsigned h0 = ALIGN_NPOT(mt->physical_height0, mt->valign); 419 const unsigned h1 = ALIGN_NPOT(minify(mt->physical_height0, 1), mt->valign); 420 421 return h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->valign; 422 } 423 } 424 425 static void 426 align_cube(struct intel_mipmap_tree *mt) 427 { 428 /* The 965's sampler lays cachelines out according to how accesses 429 * in the texture surfaces run, so they may be "vertical" through 430 * memory. As a result, the docs say in Surface Padding Requirements: 431 * Sampling Engine Surfaces that two extra rows of padding are required. 432 */ 433 if (mt->target == GL_TEXTURE_CUBE_MAP) 434 mt->total_height += 2; 435 } 436 437 bool 438 gen9_use_linear_1d_layout(const struct brw_context *brw, 439 const struct intel_mipmap_tree *mt) 440 { 441 /* On Gen9+ the mipmap levels of a 1D surface are all laid out in a 442 * horizontal line. This isn't done for depth/stencil buffers however 443 * because those will be using a tiled layout 444 */ 445 if (brw->gen >= 9 && 446 (mt->target == GL_TEXTURE_1D || 447 mt->target == GL_TEXTURE_1D_ARRAY)) { 448 GLenum base_format = _mesa_get_format_base_format(mt->format); 449 450 if (base_format != GL_DEPTH_COMPONENT && 451 base_format != GL_DEPTH_STENCIL && 452 base_format != GL_STENCIL_INDEX) 453 return true; 454 } 455 456 return false; 457 } 458 459 static void 460 brw_miptree_layout_texture_array(struct brw_context *brw, 461 struct intel_mipmap_tree *mt) 462 { 463 unsigned height = mt->physical_height0; 464 bool layout_1d = gen9_use_linear_1d_layout(brw, mt); 465 int physical_qpitch; 466 467 if (layout_1d) 468 gen9_miptree_layout_1d(mt); 469 else 470 brw_miptree_layout_2d(mt); 471 472 if (layout_1d) { 473 physical_qpitch = 1; 474 /* When using the horizontal layout the qpitch specifies the distance in 475 * pixels between array slices. The total_width is forced to be a 476 * multiple of the horizontal alignment in brw_miptree_layout_1d (in 477 * this case it's always 64). The vertical alignment is ignored. 478 */ 479 mt->qpitch = mt->total_width; 480 } else { 481 mt->qpitch = brw_miptree_get_vertical_slice_pitch(brw, mt, 0); 482 /* Unlike previous generations the qpitch is a multiple of the 483 * compressed block size on Gen9 so physical_qpitch matches mt->qpitch. 484 */ 485 physical_qpitch = (mt->compressed && brw->gen < 9 ? mt->qpitch / 4 : 486 mt->qpitch); 487 } 488 489 for (unsigned level = mt->first_level; level <= mt->last_level; level++) { 490 unsigned img_height; 491 img_height = ALIGN_NPOT(height, mt->valign); 492 if (mt->compressed) 493 img_height /= mt->valign; 494 495 for (unsigned q = 0; q < mt->level[level].depth; q++) { 496 if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) { 497 intel_miptree_set_image_offset(mt, level, q, 0, q * img_height); 498 } else { 499 intel_miptree_set_image_offset(mt, level, q, 0, q * physical_qpitch); 500 } 501 } 502 height = minify(height, 1); 503 } 504 if (mt->array_layout == ALL_LOD_IN_EACH_SLICE) 505 mt->total_height = physical_qpitch * mt->physical_depth0; 506 507 align_cube(mt); 508 } 509 510 static void 511 brw_miptree_layout_texture_3d(struct brw_context *brw, 512 struct intel_mipmap_tree *mt) 513 { 514 mt->total_width = 0; 515 mt->total_height = 0; 516 517 unsigned ysum = 0; 518 unsigned bh, bw; 519 520 _mesa_get_format_block_size(mt->format, &bw, &bh); 521 522 for (unsigned level = mt->first_level; level <= mt->last_level; level++) { 523 unsigned WL = MAX2(mt->physical_width0 >> level, 1); 524 unsigned HL = MAX2(mt->physical_height0 >> level, 1); 525 unsigned DL = MAX2(mt->physical_depth0 >> level, 1); 526 unsigned wL = ALIGN_NPOT(WL, mt->halign); 527 unsigned hL = ALIGN_NPOT(HL, mt->valign); 528 529 if (mt->target == GL_TEXTURE_CUBE_MAP) 530 DL = 6; 531 532 intel_miptree_set_level_info(mt, level, 0, 0, DL); 533 534 for (unsigned q = 0; q < DL; q++) { 535 unsigned x = (q % (1 << level)) * wL; 536 unsigned y = ysum + (q >> level) * hL; 537 538 intel_miptree_set_image_offset(mt, level, q, x / bw, y / bh); 539 mt->total_width = MAX2(mt->total_width, (x + wL) / bw); 540 mt->total_height = MAX2(mt->total_height, (y + hL) / bh); 541 } 542 543 ysum += ALIGN(DL, 1 << level) / (1 << level) * hL; 544 } 545 546 align_cube(mt); 547 } 548 549 /** 550 * \brief Helper function for intel_miptree_create(). 551 */ 552 static uint32_t 553 brw_miptree_choose_tiling(struct brw_context *brw, 554 const struct intel_mipmap_tree *mt, 555 uint32_t layout_flags) 556 { 557 if (mt->format == MESA_FORMAT_S_UINT8) { 558 /* The stencil buffer is W tiled. However, we request from the kernel a 559 * non-tiled buffer because the GTT is incapable of W fencing. 560 */ 561 return I915_TILING_NONE; 562 } 563 564 /* Do not support changing the tiling for miptrees with pre-allocated BOs. */ 565 assert((layout_flags & MIPTREE_LAYOUT_FOR_BO) == 0); 566 567 /* Some usages may want only one type of tiling, like depth miptrees (Y 568 * tiled), or temporary BOs for uploading data once (linear). 569 */ 570 switch (layout_flags & MIPTREE_LAYOUT_TILING_ANY) { 571 case MIPTREE_LAYOUT_TILING_ANY: 572 break; 573 case MIPTREE_LAYOUT_TILING_Y: 574 return I915_TILING_Y; 575 case MIPTREE_LAYOUT_TILING_NONE: 576 return I915_TILING_NONE; 577 } 578 579 if (mt->num_samples > 1) { 580 /* From p82 of the Sandy Bridge PRM, dw3[1] of SURFACE_STATE ("Tiled 581 * Surface"): 582 * 583 * [DevSNB+]: For multi-sample render targets, this field must be 584 * 1. MSRTs can only be tiled. 585 * 586 * Our usual reason for preferring X tiling (fast blits using the 587 * blitting engine) doesn't apply to MSAA, since we'll generally be 588 * downsampling or upsampling when blitting between the MSAA buffer 589 * and another buffer, and the blitting engine doesn't support that. 590 * So use Y tiling, since it makes better use of the cache. 591 */ 592 return I915_TILING_Y; 593 } 594 595 GLenum base_format = _mesa_get_format_base_format(mt->format); 596 if (base_format == GL_DEPTH_COMPONENT || 597 base_format == GL_DEPTH_STENCIL_EXT) 598 return I915_TILING_Y; 599 600 /* 1D textures (and 1D array textures) don't get any benefit from tiling, 601 * in fact it leads to a less efficient use of memory space and bandwidth 602 * due to tile alignment. 603 */ 604 if (mt->logical_height0 == 1) 605 return I915_TILING_NONE; 606 607 int minimum_pitch = mt->total_width * mt->cpp; 608 609 /* If the width is much smaller than a tile, don't bother tiling. */ 610 if (minimum_pitch < 64) 611 return I915_TILING_NONE; 612 613 if (ALIGN(minimum_pitch, 512) >= 32768) { 614 perf_debug("%dx%d miptree too large to blit, falling back to untiled", 615 mt->total_width, mt->total_height); 616 return I915_TILING_NONE; 617 } 618 619 /* Pre-gen6 doesn't have BLORP to handle Y-tiling, so use X-tiling. */ 620 if (brw->gen < 6) 621 return I915_TILING_X; 622 623 /* From the Sandybridge PRM, Volume 1, Part 2, page 32: 624 * "NOTE: 128BPE Format Color Buffer ( render target ) MUST be either TileX 625 * or Linear." 626 * 128 bits per pixel translates to 16 bytes per pixel. This is necessary 627 * all the way back to 965, but is permitted on Gen7+. 628 */ 629 if (brw->gen < 7 && mt->cpp >= 16) 630 return I915_TILING_X; 631 632 /* From the Ivy Bridge PRM, Vol4 Part1 2.12.2.1 (SURFACE_STATE for most 633 * messages), on p64, under the heading "Surface Vertical Alignment": 634 * 635 * This field must be set to VALIGN_4 for all tiled Y Render Target 636 * surfaces. 637 * 638 * So if the surface is renderable and uses a vertical alignment of 2, 639 * force it to be X tiled. This is somewhat conservative (it's possible 640 * that the client won't ever render to this surface), but it's difficult 641 * to know that ahead of time. And besides, since we use a vertical 642 * alignment of 4 as often as we can, this shouldn't happen very often. 643 */ 644 if (brw->gen == 7 && mt->valign == 2 && 645 brw->format_supported_as_render_target[mt->format]) { 646 return I915_TILING_X; 647 } 648 649 return I915_TILING_Y | I915_TILING_X; 650 } 651 652 static void 653 intel_miptree_set_total_width_height(struct brw_context *brw, 654 struct intel_mipmap_tree *mt) 655 { 656 switch (mt->target) { 657 case GL_TEXTURE_CUBE_MAP: 658 if (brw->gen == 4) { 659 /* Gen4 stores cube maps as 3D textures. */ 660 assert(mt->physical_depth0 == 6); 661 brw_miptree_layout_texture_3d(brw, mt); 662 } else { 663 /* All other hardware stores cube maps as 2D arrays. */ 664 brw_miptree_layout_texture_array(brw, mt); 665 } 666 break; 667 668 case GL_TEXTURE_3D: 669 if (brw->gen >= 9) 670 brw_miptree_layout_texture_array(brw, mt); 671 else 672 brw_miptree_layout_texture_3d(brw, mt); 673 break; 674 675 case GL_TEXTURE_1D_ARRAY: 676 case GL_TEXTURE_2D_ARRAY: 677 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 678 case GL_TEXTURE_CUBE_MAP_ARRAY: 679 brw_miptree_layout_texture_array(brw, mt); 680 break; 681 682 default: 683 switch (mt->msaa_layout) { 684 case INTEL_MSAA_LAYOUT_UMS: 685 case INTEL_MSAA_LAYOUT_CMS: 686 brw_miptree_layout_texture_array(brw, mt); 687 break; 688 case INTEL_MSAA_LAYOUT_NONE: 689 case INTEL_MSAA_LAYOUT_IMS: 690 if (gen9_use_linear_1d_layout(brw, mt)) 691 gen9_miptree_layout_1d(mt); 692 else 693 brw_miptree_layout_2d(mt); 694 break; 695 } 696 break; 697 } 698 699 DBG("%s: %dx%dx%d\n", __func__, 700 mt->total_width, mt->total_height, mt->cpp); 701 } 702 703 static void 704 intel_miptree_set_alignment(struct brw_context *brw, 705 struct intel_mipmap_tree *mt, 706 uint32_t layout_flags) 707 { 708 /** 709 * From the "Alignment Unit Size" section of various specs, namely: 710 * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 711 * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. 712 * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 713 * - BSpec (for Ivybridge and slight variations in separate stencil) 714 */ 715 bool gen6_hiz_or_stencil = false; 716 717 if (brw->gen == 6 && mt->array_layout == ALL_SLICES_AT_EACH_LOD) { 718 const GLenum base_format = _mesa_get_format_base_format(mt->format); 719 gen6_hiz_or_stencil = _mesa_is_depth_or_stencil_format(base_format); 720 } 721 722 if (gen6_hiz_or_stencil) { 723 /* On gen6, we use ALL_SLICES_AT_EACH_LOD for stencil/hiz because the 724 * hardware doesn't support multiple mip levels on stencil/hiz. 725 * 726 * PRM Vol 2, Part 1, 7.5.3 Hierarchical Depth Buffer: 727 * "The hierarchical depth buffer does not support the LOD field" 728 * 729 * PRM Vol 2, Part 1, 7.5.4.1 Separate Stencil Buffer: 730 * "The stencil depth buffer does not support the LOD field" 731 */ 732 if (mt->format == MESA_FORMAT_S_UINT8) { 733 /* Stencil uses W tiling, so we force W tiling alignment for the 734 * ALL_SLICES_AT_EACH_LOD miptree layout. 735 */ 736 mt->halign = 64; 737 mt->valign = 64; 738 assert((layout_flags & MIPTREE_LAYOUT_FORCE_HALIGN16) == 0); 739 } else { 740 /* Depth uses Y tiling, so we force need Y tiling alignment for the 741 * ALL_SLICES_AT_EACH_LOD miptree layout. 742 */ 743 mt->halign = 128 / mt->cpp; 744 mt->valign = 32; 745 } 746 } else if (mt->compressed) { 747 /* The hardware alignment requirements for compressed textures 748 * happen to match the block boundaries. 749 */ 750 _mesa_get_format_block_size(mt->format, &mt->halign, &mt->valign); 751 752 /* On Gen9+ we can pick our own alignment for compressed textures but it 753 * has to be a multiple of the block size. The minimum alignment we can 754 * pick is 4 so we effectively have to align to 4 times the block 755 * size 756 */ 757 if (brw->gen >= 9) { 758 mt->halign *= 4; 759 mt->valign *= 4; 760 } 761 } else if (mt->format == MESA_FORMAT_S_UINT8) { 762 mt->halign = 8; 763 mt->valign = brw->gen >= 7 ? 8 : 4; 764 } else if (brw->gen >= 9 && mt->tr_mode != INTEL_MIPTREE_TRMODE_NONE) { 765 mt->halign = tr_mode_horizontal_texture_alignment(mt); 766 mt->valign = tr_mode_vertical_texture_alignment(mt); 767 } else { 768 mt->halign = 769 intel_horizontal_texture_alignment_unit(brw, mt, layout_flags); 770 mt->valign = intel_vertical_texture_alignment_unit(brw, mt); 771 } 772 } 773 774 void 775 brw_miptree_layout(struct brw_context *brw, 776 struct intel_mipmap_tree *mt, 777 uint32_t layout_flags) 778 { 779 mt->tr_mode = INTEL_MIPTREE_TRMODE_NONE; 780 781 intel_miptree_set_alignment(brw, mt, layout_flags); 782 intel_miptree_set_total_width_height(brw, mt); 783 784 if (!mt->total_width || !mt->total_height) { 785 intel_miptree_release(&mt); 786 return; 787 } 788 789 /* On Gen9+ the alignment values are expressed in multiples of the block 790 * size 791 */ 792 if (brw->gen >= 9) { 793 unsigned int i, j; 794 _mesa_get_format_block_size(mt->format, &i, &j); 795 mt->halign /= i; 796 mt->valign /= j; 797 } 798 799 if ((layout_flags & MIPTREE_LAYOUT_FOR_BO) == 0) 800 mt->tiling = brw_miptree_choose_tiling(brw, mt, layout_flags); 801 } 802 803