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