xref: /aosp_15_r20/external/mesa3d/src/freedreno/fdl/fd5_layout.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2018 Rob Clark <[email protected]>
3  * Copyright © 2018-2019 Google, Inc.
4  * SPDX-License-Identifier: MIT
5  *
6  * Authors:
7  *    Rob Clark <[email protected]>
8  */
9 
10 #include <stdio.h>
11 
12 #include "freedreno_layout.h"
13 
14 void
fdl5_layout(struct fdl_layout * layout,enum pipe_format format,uint32_t nr_samples,uint32_t width0,uint32_t height0,uint32_t depth0,uint32_t mip_levels,uint32_t array_size,bool is_3d)15 fdl5_layout(struct fdl_layout *layout, enum pipe_format format,
16             uint32_t nr_samples, uint32_t width0, uint32_t height0,
17             uint32_t depth0, uint32_t mip_levels, uint32_t array_size,
18             bool is_3d)
19 {
20    assert(nr_samples > 0);
21    layout->width0 = width0;
22    layout->height0 = height0;
23    layout->depth0 = depth0;
24 
25    layout->cpp = util_format_get_blocksize(format);
26    layout->cpp *= nr_samples;
27    layout->cpp_shift = ffs(layout->cpp) - 1;
28 
29    layout->format = format;
30    layout->nr_samples = nr_samples;
31    layout->layer_first = !is_3d;
32 
33    uint32_t heightalign = layout->cpp == 1 ? 32 : 16;
34    /* in layer_first layout, the level (slice) contains just one
35     * layer (since in fact the layer contains the slices)
36     */
37    uint32_t layers_in_level = layout->layer_first ? 1 : array_size;
38 
39    /* use 128 pixel alignment for cpp=1 and cpp=2 */
40    if (layout->cpp < 4 && layout->tile_mode)
41       fdl_set_pitchalign(layout, fdl_cpp_shift(layout) + 7);
42    else
43       fdl_set_pitchalign(layout, fdl_cpp_shift(layout) + 6);
44 
45    for (uint32_t level = 0; level < mip_levels; level++) {
46       uint32_t depth = u_minify(depth0, level);
47       struct fdl_slice *slice = &layout->slices[level];
48       uint32_t tile_mode = fdl_tile_mode(layout, level);
49       uint32_t pitch = fdl_pitch(layout, level);
50       uint32_t nblocksy =
51          util_format_get_nblocksy(format, u_minify(height0, level));
52 
53       if (tile_mode) {
54          nblocksy = align(nblocksy, heightalign);
55       } else {
56          /* The blits used for mem<->gmem work at a granularity of
57           * 32x32, which can cause faults due to over-fetch on the
58           * last level.  The simple solution is to over-allocate a
59           * bit the last level to ensure any over-fetch is harmless.
60           * The pitch is already sufficiently aligned, but height
61           * may not be:
62           */
63          if (level == mip_levels - 1)
64             nblocksy = align(nblocksy, 32);
65       }
66 
67       slice->offset = layout->size;
68 
69       /* 1d array and 2d array textures must all have the same layer size
70        * for each miplevel on a3xx. 3d textures can have different layer
71        * sizes for high levels, but the hw auto-sizer is buggy (or at least
72        * different than what this code does), so as soon as the layer size
73        * range gets into range, we stop reducing it.
74        */
75       if (is_3d) {
76          if (level <= 1 || layout->slices[level - 1].size0 > 0xf000) {
77             slice->size0 = align(nblocksy * pitch, 4096);
78          } else {
79             slice->size0 = layout->slices[level - 1].size0;
80          }
81       } else {
82          slice->size0 = nblocksy * pitch;
83       }
84 
85       layout->size += slice->size0 * depth * layers_in_level;
86    }
87 
88    if (layout->layer_first) {
89       layout->layer_size = align64(layout->size, 4096);
90       layout->size = layout->layer_size * array_size;
91    }
92 }
93