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@vmware.com>
32 * \author Michel Dänzer <daenzer@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
tr_mode_horizontal_texture_alignment(const struct intel_mipmap_tree * mt)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
intel_horizontal_texture_alignment_unit(struct brw_context * brw,struct intel_mipmap_tree * mt,uint32_t layout_flags)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
tr_mode_vertical_texture_alignment(const struct intel_mipmap_tree * mt)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
intel_vertical_texture_alignment_unit(struct brw_context * brw,const struct intel_mipmap_tree * mt)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
gen9_miptree_layout_1d(struct intel_mipmap_tree * mt)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
brw_miptree_layout_2d(struct intel_mipmap_tree * mt)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
brw_miptree_get_horizontal_slice_pitch(const struct brw_context * brw,const struct intel_mipmap_tree * mt,unsigned level)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
brw_miptree_get_vertical_slice_pitch(const struct brw_context * brw,const struct intel_mipmap_tree * mt,unsigned level)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
align_cube(struct intel_mipmap_tree * mt)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
gen9_use_linear_1d_layout(const struct brw_context * brw,const struct intel_mipmap_tree * mt)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
brw_miptree_layout_texture_array(struct brw_context * brw,struct intel_mipmap_tree * mt)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
brw_miptree_layout_texture_3d(struct brw_context * brw,struct intel_mipmap_tree * mt)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
brw_miptree_choose_tiling(struct brw_context * brw,const struct intel_mipmap_tree * mt,uint32_t layout_flags)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
intel_miptree_set_total_width_height(struct brw_context * brw,struct intel_mipmap_tree * mt)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
intel_miptree_set_alignment(struct brw_context * brw,struct intel_mipmap_tree * mt,uint32_t layout_flags)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
brw_miptree_layout(struct brw_context * brw,struct intel_mipmap_tree * mt,uint32_t layout_flags)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