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