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"
36 } tile_alignment
[] = {
47 fdl5_layout(struct fdl_layout
*layout
,
48 enum pipe_format format
, uint32_t nr_samples
,
49 uint32_t width0
, uint32_t height0
, uint32_t depth0
,
50 uint32_t mip_levels
, uint32_t array_size
, bool is_3d
)
52 const struct util_format_description
*format_desc
=
53 util_format_description(format
);
55 assert(nr_samples
> 0);
56 layout
->width0
= width0
;
57 layout
->height0
= height0
;
58 layout
->depth0
= depth0
;
60 layout
->cpp
= util_format_get_blocksize(format
);
61 layout
->cpp
*= nr_samples
;
62 layout
->cpp_shift
= ffs(layout
->cpp
) - 1;
64 layout
->format
= format
;
65 layout
->nr_samples
= nr_samples
;
66 layout
->layer_first
= !is_3d
;
70 uint32_t width
= width0
;
71 uint32_t height
= height0
;
72 uint32_t depth
= depth0
;
73 /* in layer_first layout, the level (slice) contains just one
74 * layer (since in fact the layer contains the slices)
76 uint32_t layers_in_level
= layout
->layer_first
? 1 : array_size
;
78 heightalign
= tile_alignment
[layout
->cpp
].heightalign
;
80 for (uint32_t level
= 0; level
< mip_levels
; level
++) {
81 struct fdl_slice
*slice
= &layout
->slices
[level
];
82 uint32_t tile_mode
= fdl_tile_mode(layout
, level
);
83 uint32_t aligned_height
= height
;
87 pitchalign
= tile_alignment
[layout
->cpp
].pitchalign
;
88 aligned_height
= align(aligned_height
, heightalign
);
92 /* The blits used for mem<->gmem work at a granularity of
93 * 32x32, which can cause faults due to over-fetch on the
94 * last level. The simple solution is to over-allocate a
95 * bit the last level to ensure any over-fetch is harmless.
96 * The pitch is already sufficiently aligned, but height
99 if (level
== mip_levels
- 1)
100 aligned_height
= align(aligned_height
, 32);
103 unsigned pitch_pixels
;
104 if (format_desc
->layout
== UTIL_FORMAT_LAYOUT_ASTC
)
106 util_align_npot(width
, pitchalign
* util_format_get_blockwidth(format
));
108 pitch_pixels
= align(width
, pitchalign
);
110 slice
->offset
= layout
->size
;
111 blocks
= util_format_get_nblocks(format
, pitch_pixels
, aligned_height
);
112 slice
->pitch
= util_format_get_nblocksx(format
, pitch_pixels
) *
115 const int alignment
= is_3d
? 4096 : 1;
117 /* 1d array and 2d array textures must all have the same layer size
118 * for each miplevel on a3xx. 3d textures can have different layer
119 * sizes for high levels, but the hw auto-sizer is buggy (or at least
120 * different than what this code does), so as soon as the layer size
121 * range gets into range, we stop reducing it.
125 (level
> 1 && layout
->slices
[level
- 1].size0
> 0xf000)))
126 slice
->size0
= align(blocks
* layout
->cpp
, alignment
);
127 else if (level
== 0 || layout
->layer_first
|| alignment
== 1)
128 slice
->size0
= align(blocks
* layout
->cpp
, alignment
);
130 slice
->size0
= layout
->slices
[level
- 1].size0
;
132 layout
->size
+= slice
->size0
* depth
* layers_in_level
;
134 width
= u_minify(width
, 1);
135 height
= u_minify(height
, 1);
136 depth
= u_minify(depth
, 1);