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