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