2 * Copyright (C) 2018 Rob Clark <robclark@freedesktop.org>
3 * Copyright © 2018-2019 Google, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * Rob Clark <robclark@freedesktop.org>
30 #include "freedreno_layout.h"
33 fdl5_layout(struct fdl_layout
*layout
,
34 enum pipe_format format
, uint32_t nr_samples
,
35 uint32_t width0
, uint32_t height0
, uint32_t depth0
,
36 uint32_t mip_levels
, uint32_t array_size
, bool is_3d
)
38 assert(nr_samples
> 0);
39 layout
->width0
= width0
;
40 layout
->height0
= height0
;
41 layout
->depth0
= depth0
;
43 layout
->cpp
= util_format_get_blocksize(format
);
44 layout
->cpp
*= nr_samples
;
45 layout
->cpp_shift
= ffs(layout
->cpp
) - 1;
47 layout
->format
= format
;
48 layout
->nr_samples
= nr_samples
;
49 layout
->layer_first
= !is_3d
;
51 uint32_t heightalign
= layout
->cpp
== 1 ? 32 : 16;
52 /* in layer_first layout, the level (slice) contains just one
53 * layer (since in fact the layer contains the slices)
55 uint32_t layers_in_level
= layout
->layer_first
? 1 : array_size
;
57 /* use 128 pixel alignment for cpp=1 and cpp=2 */
58 if (layout
->cpp
< 4 && layout
->tile_mode
)
59 fdl_set_pitchalign(layout
, fdl_cpp_shift(layout
) + 7);
61 fdl_set_pitchalign(layout
, fdl_cpp_shift(layout
) + 6);
63 for (uint32_t level
= 0; level
< mip_levels
; level
++) {
64 struct fdl_slice
*slice
= &layout
->slices
[level
];
65 uint32_t tile_mode
= fdl_tile_mode(layout
, level
);
66 uint32_t pitch
= fdl_pitch(layout
, level
);
67 uint32_t nblocksy
= util_format_get_nblocksy(format
, u_minify(height0
, level
));
70 nblocksy
= align(nblocksy
, heightalign
);
72 /* The blits used for mem<->gmem work at a granularity of
73 * 32x32, which can cause faults due to over-fetch on the
74 * last level. The simple solution is to over-allocate a
75 * bit the last level to ensure any over-fetch is harmless.
76 * The pitch is already sufficiently aligned, but height
79 if (level
== mip_levels
- 1)
80 nblocksy
= align(nblocksy
, 32);
83 slice
->offset
= layout
->size
;
85 const int alignment
= is_3d
? 4096 : 1;
87 /* 1d array and 2d array textures must all have the same layer size
88 * for each miplevel on a3xx. 3d textures can have different layer
89 * sizes for high levels, but the hw auto-sizer is buggy (or at least
90 * different than what this code does), so as soon as the layer size
91 * range gets into range, we stop reducing it.
95 (level
> 1 && layout
->slices
[level
- 1].size0
> 0xf000)))
96 slice
->size0
= align(nblocksy
* pitch
, alignment
);
97 else if (level
== 0 || layout
->layer_first
|| alignment
== 1)
98 slice
->size0
= align(nblocksy
* pitch
, alignment
);
100 slice
->size0
= layout
->slices
[level
- 1].size0
;
102 layout
->size
+= slice
->size0
* u_minify(depth0
, level
) * layers_in_level
;