• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Alyssa Rosenzweig
3  * SPDX-License-Identifier: MIT
4  *
5  */
6 
7 #pragma once
8 
9 #include "util/format/u_format.h"
10 #include "util/macros.h"
11 #include "util/u_math.h"
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 #define AIL_CACHELINE      0x80
18 #define AIL_PAGESIZE       0x4000
19 #define AIL_MAX_MIP_LEVELS 16
20 
21 enum ail_tiling {
22    /**
23     * Strided linear (raster order). Only allowed for 1D or 2D, without
24     * mipmapping, multisampling, block-compression, or arrays.
25     */
26    AIL_TILING_LINEAR,
27 
28    /**
29     * Twiddled (Morton order). Always allowed.
30     */
31    AIL_TILING_TWIDDLED,
32 
33    /**
34     * Twiddled (Morton order) with compression.
35     */
36    AIL_TILING_TWIDDLED_COMPRESSED,
37 };
38 
39 /*
40  * Represents the dimensions of a single tile. Used to describe tiled layouts.
41  * Width and height are in units of elements, not pixels, to model compressed
42  * textures corrects.
43  *
44  * Invariant: width_el and height_el are powers of two.
45  */
46 struct ail_tile {
47    unsigned width_el, height_el;
48 };
49 
50 /*
51  * An AGX image layout.
52  */
53 struct ail_layout {
54    /** Width, height, and depth in pixels at level 0 */
55    uint32_t width_px, height_px, depth_px;
56 
57    /** Number of samples per pixel. 1 if multisampling is disabled. */
58    uint8_t sample_count_sa;
59 
60    /** Number of miplevels. 1 if no mipmapping is used. */
61    uint8_t levels;
62 
63    /** Should this image be mipmapped along the Z-axis in addition to the X- and
64     * Y-axes? This should be set for API-level 3D images, but not 2D arrays or
65     * cubes.
66     */
67    bool mipmapped_z;
68 
69    /** Tiling mode used */
70    enum ail_tiling tiling;
71 
72    /** Texture format */
73    enum pipe_format format;
74 
75    /**
76     * If tiling is LINEAR, the number of bytes between adjacent rows of
77     * elements. Otherwise, this field is zero.
78     */
79    uint32_t linear_stride_B;
80 
81    /**
82     * Stride between layers of an array texture, including a cube map. Layer i
83     * begins at offset (i * layer_stride_B) from the beginning of the texture.
84     *
85     * If depth_px = 1, the value of this field is UNDEFINED.
86     */
87    uint64_t layer_stride_B;
88 
89    /**
90     * Whether the layer stride is aligned to the page size or not. The hardware
91     * needs this flag to compute the implicit layer stride.
92     */
93    bool page_aligned_layers;
94 
95    /**
96     * Offsets of mip levels within a layer.
97     */
98    uint64_t level_offsets_B[AIL_MAX_MIP_LEVELS];
99 
100    /**
101     * For the compressed buffer, offsets of mip levels within a layer.
102     */
103    uint64_t level_offsets_compressed_B[AIL_MAX_MIP_LEVELS];
104 
105    /**
106     * If tiling is TWIDDLED, the tile size used for each mip level within a
107     * layer. Calculating tile sizes is the sole responsibility of
108     * ail_initialized_twiddled.
109     */
110    struct ail_tile tilesize_el[AIL_MAX_MIP_LEVELS];
111 
112    /**
113     * If tiling is TWIDDLED, the stride in elements used for each mip level
114     * within a layer. Calculating level strides is the sole responsibility of
115     * ail_initialized_twiddled. This is necessary because compressed pixel
116     * formats may add extra stride padding.
117     */
118    uint32_t stride_el[AIL_MAX_MIP_LEVELS];
119 
120    /* Offset of the start of the compression metadata buffer */
121    uint32_t metadata_offset_B;
122 
123    /* Stride between subsequent layers in the compression metadata buffer */
124    uint64_t compression_layer_stride_B;
125 
126    /* Size of entire texture */
127    uint64_t size_B;
128 
129    /* Must the layout support writeable images? If false, the layout MUST NOT be
130     * used as a writeable image (either PBE or image atomics).
131     */
132    bool writeable_image;
133 
134    /* Must the layout support rendering? If false, the layout MUST NOT be used
135     * for rendering, either PBE or ZLS.
136     */
137    bool renderable;
138 };
139 
140 static inline uint32_t
ail_get_linear_stride_B(struct ail_layout * layout,ASSERTED uint8_t level)141 ail_get_linear_stride_B(struct ail_layout *layout, ASSERTED uint8_t level)
142 {
143    assert(layout->tiling == AIL_TILING_LINEAR && "Invalid usage");
144    assert(level == 0 && "Strided linear mipmapped textures are unsupported");
145 
146    return layout->linear_stride_B;
147 }
148 
149 /*
150  * For WSI purposes, we need to associate a stride with all layouts. In the
151  * hardware, only strided linear images have an associated stride, there is no
152  * natural stride associated with twiddled images. However, various clients
153  * assert that the stride is valid for the image if it were linear (even if it
154  * is in fact not linear). In those cases, by convention we use the minimum
155  * valid such stride.
156  */
157 static inline uint32_t
ail_get_wsi_stride_B(struct ail_layout * layout,unsigned level)158 ail_get_wsi_stride_B(struct ail_layout *layout, unsigned level)
159 {
160    assert(level == 0 && "Mipmaps cannot be shared as WSI");
161 
162    if (layout->tiling == AIL_TILING_LINEAR)
163       return ail_get_linear_stride_B(layout, level);
164    else
165       return util_format_get_stride(layout->format, layout->width_px);
166 }
167 
168 static inline uint32_t
ail_get_layer_offset_B(struct ail_layout * layout,unsigned z_px)169 ail_get_layer_offset_B(struct ail_layout *layout, unsigned z_px)
170 {
171    return z_px * layout->layer_stride_B;
172 }
173 
174 static inline uint32_t
ail_get_level_offset_B(struct ail_layout * layout,unsigned level)175 ail_get_level_offset_B(struct ail_layout *layout, unsigned level)
176 {
177    return layout->level_offsets_B[level];
178 }
179 
180 static inline uint32_t
ail_get_layer_level_B(struct ail_layout * layout,unsigned z_px,unsigned level)181 ail_get_layer_level_B(struct ail_layout *layout, unsigned z_px, unsigned level)
182 {
183    return ail_get_layer_offset_B(layout, z_px) +
184           ail_get_level_offset_B(layout, level);
185 }
186 
187 static inline uint32_t
ail_get_linear_pixel_B(struct ail_layout * layout,ASSERTED unsigned level,uint32_t x_px,uint32_t y_px,uint32_t z_px)188 ail_get_linear_pixel_B(struct ail_layout *layout, ASSERTED unsigned level,
189                        uint32_t x_px, uint32_t y_px, uint32_t z_px)
190 {
191    assert(level == 0 && "Strided linear mipmapped textures are unsupported");
192    assert(util_format_get_blockwidth(layout->format) == 1 &&
193           "Strided linear block formats unsupported");
194    assert(util_format_get_blockheight(layout->format) == 1 &&
195           "Strided linear block formats unsupported");
196    assert(layout->sample_count_sa == 1 &&
197           "Strided linear multisampling unsupported");
198 
199    return ail_get_layer_offset_B(layout, z_px) +
200           (y_px * ail_get_linear_stride_B(layout, level)) +
201           (x_px * util_format_get_blocksize(layout->format));
202 }
203 
204 static inline unsigned
ail_effective_width_sa(unsigned width_px,unsigned sample_count_sa)205 ail_effective_width_sa(unsigned width_px, unsigned sample_count_sa)
206 {
207    return width_px * (sample_count_sa == 4 ? 2 : 1);
208 }
209 
210 static inline unsigned
ail_effective_height_sa(unsigned height_px,unsigned sample_count_sa)211 ail_effective_height_sa(unsigned height_px, unsigned sample_count_sa)
212 {
213    return height_px * (sample_count_sa >= 2 ? 2 : 1);
214 }
215 
216 static inline bool
ail_can_compress(unsigned w_px,unsigned h_px,unsigned sample_count_sa)217 ail_can_compress(unsigned w_px, unsigned h_px, unsigned sample_count_sa)
218 {
219    assert(sample_count_sa == 1 || sample_count_sa == 2 || sample_count_sa == 4);
220 
221    /* Small textures cannot be compressed */
222    return ail_effective_width_sa(w_px, sample_count_sa) >= 16 &&
223           ail_effective_height_sa(h_px, sample_count_sa) >= 16;
224 }
225 
226 static inline bool
ail_is_compressed(struct ail_layout * layout)227 ail_is_compressed(struct ail_layout *layout)
228 {
229    return layout->tiling == AIL_TILING_TWIDDLED_COMPRESSED;
230 }
231 
232 /*
233  * Even when the base mip level is compressed, high levels of the miptree
234  * (smaller than 16 pixels on either axis) are not compressed as it would be
235  * pointless. This queries this case.
236  */
237 static inline bool
ail_is_level_compressed(struct ail_layout * layout,unsigned level)238 ail_is_level_compressed(struct ail_layout *layout, unsigned level)
239 {
240    unsigned width_sa = ALIGN(
241       ail_effective_width_sa(layout->width_px, layout->sample_count_sa), 16);
242 
243    unsigned height_sa = ALIGN(
244       ail_effective_height_sa(layout->height_px, layout->sample_count_sa), 16);
245 
246    return ail_is_compressed(layout) &&
247           u_minify(MAX2(width_sa, height_sa), level) >= 16;
248 }
249 
250 static inline bool
ail_is_level_twiddled_uncompressed(struct ail_layout * layout,unsigned level)251 ail_is_level_twiddled_uncompressed(struct ail_layout *layout, unsigned level)
252 {
253    switch (layout->tiling) {
254    case AIL_TILING_TWIDDLED:
255       return true;
256    case AIL_TILING_TWIDDLED_COMPRESSED:
257       return !ail_is_level_compressed(layout, level);
258    default:
259       return false;
260    }
261 }
262 
263 void ail_make_miptree(struct ail_layout *layout);
264 
265 void ail_detile(void *_tiled, void *_linear, struct ail_layout *tiled_layout,
266                 unsigned level, unsigned linear_pitch_B, unsigned sx_px,
267                 unsigned sy_px, unsigned width_px, unsigned height_px);
268 
269 void ail_tile(void *_tiled, void *_linear, struct ail_layout *tiled_layout,
270               unsigned level, unsigned linear_pitch_B, unsigned sx_px,
271               unsigned sy_px, unsigned width_px, unsigned height_px);
272 
273 #ifdef __cplusplus
274 } /* extern C */
275 #endif
276