• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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