xref: /aosp_15_r20/external/mesa3d/src/freedreno/fdl/fd6_view.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2016 Red Hat.
3  * Copyright © 2016 Bas Nieuwenhuizen
4  * Copyright © 2021 Valve Corporation
5  * SPDX-License-Identifier: MIT
6  *
7  * Authors:
8  *    Rob Clark <[email protected]>
9  */
10 
11 #include "freedreno_layout.h"
12 #include "fd6_format_table.h"
13 
14 static enum a6xx_tex_type
fdl6_tex_type(enum fdl_view_type type,bool storage)15 fdl6_tex_type(enum fdl_view_type type, bool storage)
16 {
17    STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_1D == (unsigned) A6XX_TEX_1D);
18    STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_2D == (unsigned) A6XX_TEX_2D);
19    STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_CUBE == (unsigned) A6XX_TEX_CUBE);
20    STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_3D == (unsigned) A6XX_TEX_3D);
21    STATIC_ASSERT((unsigned) FDL_VIEW_TYPE_BUFFER == (unsigned) A6XX_TEX_BUFFER);
22 
23    return (storage && type == FDL_VIEW_TYPE_CUBE) ?
24       A6XX_TEX_2D : (enum a6xx_tex_type) type;
25 }
26 
27 void
fdl6_format_swiz(enum pipe_format format,bool has_z24uint_s8uint,unsigned char * format_swiz)28 fdl6_format_swiz(enum pipe_format format, bool has_z24uint_s8uint,
29                  unsigned char *format_swiz)
30 {
31    format_swiz[0] = PIPE_SWIZZLE_X;
32    format_swiz[1] = PIPE_SWIZZLE_Y;
33    format_swiz[2] = PIPE_SWIZZLE_Z;
34    format_swiz[3] = PIPE_SWIZZLE_W;
35 
36    /* Note: Using the swizzle here to do anything other than replace with a
37     * constant or replicate a component breaks border colors, because border
38     * color replacement will happen before this swizzle is applied but it's
39     * supposed to happen after any "hidden" swizzles that are applied by the
40     * driver as part of implementing the API format. There are a few
41     * exceptions, called out below.
42     */
43    switch (format) {
44    case PIPE_FORMAT_G8B8_G8R8_UNORM:
45    case PIPE_FORMAT_B8G8_R8G8_UNORM:
46    case PIPE_FORMAT_G8_B8R8_420_UNORM:
47    case PIPE_FORMAT_G8_B8_R8_420_UNORM:
48       /* These formats are currently only used for Vulkan, and border colors
49        * aren't allowed on these formats in Vulkan because, from the
50        * description of VkImageViewCreateInfo:
51        *
52        *    If the image has a multi-planar format and
53        *    subresourceRange.aspectMask is VK_IMAGE_ASPECT_COLOR_BIT, ... then
54        *    ... the sampler to be used with the image view must enable sampler
55        *    ycbcr conversion.
56        *
57        * combined with this VU on VkSamplerCreateInfo:
58        *
59        *    If sampler ycbcr conversion is enabled, addressModeU,
60        *    addressModeV, and addressModeW must be
61        *    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, ...
62        *
63        * This makes the swizzle safe.
64        */
65       format_swiz[0] = PIPE_SWIZZLE_Z;
66       format_swiz[1] = PIPE_SWIZZLE_X;
67       format_swiz[2] = PIPE_SWIZZLE_Y;
68       break;
69    case PIPE_FORMAT_DXT1_RGB:
70    case PIPE_FORMAT_DXT1_SRGB:
71       /* same hardware format is used for BC1_RGB / BC1_RGBA */
72       format_swiz[3] = PIPE_SWIZZLE_1;
73       break;
74    case PIPE_FORMAT_X24S8_UINT:
75       if (!has_z24uint_s8uint) {
76          /* using FMT6_8_8_8_8_UINT/XYZW so need to swizzle (0,0,1) in the
77           * rest (see "Conversion to RGBA").
78           */
79          format_swiz[1] = PIPE_SWIZZLE_0;
80          format_swiz[2] = PIPE_SWIZZLE_0;
81          format_swiz[3] = PIPE_SWIZZLE_1;
82       } else {
83          /* Using FMT6_Z24_UINT_S8_UINT, which is (d, s, 0, 1), so need to
84           * swizzle away the d. We don't use this if
85           * customBorderColorWithoutFormat is enabled, so we can fix up the
86           * border color, and there's a workaround in freedreno.
87           */
88          format_swiz[0] = PIPE_SWIZZLE_Y;
89          format_swiz[1] = PIPE_SWIZZLE_0;
90       }
91       break;
92 
93    default:
94       /* Our I, L, A, and LA formats use R or RG HW formats except for
95        * A8_UNORM. These aren't supported in Vulkan, and freedreno uses a hack
96        * to get the border colors correct by undoing these swizzles.
97        */
98       if (util_format_is_alpha(format) && format != PIPE_FORMAT_A8_UNORM) {
99          format_swiz[0] = PIPE_SWIZZLE_0;
100          format_swiz[1] = PIPE_SWIZZLE_0;
101          format_swiz[2] = PIPE_SWIZZLE_0;
102          format_swiz[3] = PIPE_SWIZZLE_X;
103       } else if (util_format_is_luminance(format)) {
104          format_swiz[0] = PIPE_SWIZZLE_X;
105          format_swiz[1] = PIPE_SWIZZLE_X;
106          format_swiz[2] = PIPE_SWIZZLE_X;
107          format_swiz[3] = PIPE_SWIZZLE_1;
108       } else if (util_format_is_intensity(format)) {
109          format_swiz[0] = PIPE_SWIZZLE_X;
110          format_swiz[1] = PIPE_SWIZZLE_X;
111          format_swiz[2] = PIPE_SWIZZLE_X;
112          format_swiz[3] = PIPE_SWIZZLE_X;
113       } else if (util_format_is_luminance_alpha(format)) {
114          format_swiz[0] = PIPE_SWIZZLE_X;
115          format_swiz[1] = PIPE_SWIZZLE_X;
116          format_swiz[2] = PIPE_SWIZZLE_X;
117          format_swiz[3] = PIPE_SWIZZLE_Y;
118       } else if (!util_format_has_alpha(format)) {
119          /* for rgbx, force A to 1.  Harmless for R/RG, where we already get 1. */
120          format_swiz[3] = PIPE_SWIZZLE_1;
121       }
122       break;
123    }
124 }
125 
126 static uint32_t
fdl6_texswiz(const struct fdl_view_args * args,bool has_z24uint_s8uint)127 fdl6_texswiz(const struct fdl_view_args *args, bool has_z24uint_s8uint)
128 {
129    unsigned char format_swiz[4];
130    fdl6_format_swiz(args->format, has_z24uint_s8uint, format_swiz);
131 
132    unsigned char swiz[4];
133    util_format_compose_swizzles(format_swiz, args->swiz, swiz);
134 
135    return A6XX_TEX_CONST_0_SWIZ_X(fdl6_swiz(swiz[0])) |
136           A6XX_TEX_CONST_0_SWIZ_Y(fdl6_swiz(swiz[1])) |
137           A6XX_TEX_CONST_0_SWIZ_Z(fdl6_swiz(swiz[2])) |
138           A6XX_TEX_CONST_0_SWIZ_W(fdl6_swiz(swiz[3]));
139 }
140 
141 #define COND(bool, val) ((bool) ? (val) : 0)
142 
143 void
fdl6_view_init(struct fdl6_view * view,const struct fdl_layout ** layouts,const struct fdl_view_args * args,bool has_z24uint_s8uint)144 fdl6_view_init(struct fdl6_view *view, const struct fdl_layout **layouts,
145                const struct fdl_view_args *args, bool has_z24uint_s8uint)
146 {
147    const struct fdl_layout *layout = layouts[0];
148    uint32_t width = u_minify(layout->width0, args->base_miplevel);
149    uint32_t height = u_minify(layout->height0, args->base_miplevel);
150 
151    /* If reinterpreting a compressed format as a size-compatible uncompressed
152     * format, we need width/height in blocks, and vice-versa. In vulkan this
153     * includes single-plane 422 formats which util/format doesn't consider
154     * "compressed" (get_compressed() returns false).
155     */
156    if (util_format_get_blockwidth(layout->format) > 1 &&
157        util_format_get_blockwidth(args->format) == 1) {
158       width = util_format_get_nblocksx(layout->format, width);
159    } else if (util_format_get_blockwidth(layout->format) == 1 &&
160               util_format_get_blockwidth(args->format) > 1) {
161       width *= util_format_get_blockwidth(args->format);
162    }
163 
164    if (util_format_get_blockheight(layout->format) > 1 &&
165        util_format_get_blockheight(args->format) == 1) {
166       height = util_format_get_nblocksy(layout->format, height);
167    } else if (util_format_get_blockheight(layout->format) == 1 &&
168               util_format_get_blockheight(args->format) > 1) {
169       height *= util_format_get_blockheight(args->format);
170    }
171 
172    uint32_t storage_depth = args->layer_count;
173    if (args->type == FDL_VIEW_TYPE_3D) {
174       storage_depth = u_minify(layout->depth0, args->base_miplevel);
175    }
176 
177    uint32_t depth = storage_depth;
178    if (args->type == FDL_VIEW_TYPE_CUBE) {
179       /* Cubes are treated as 2D arrays for storage images, so only divide the
180        * depth by 6 for the texture descriptor.
181        */
182       depth /= 6;
183    }
184 
185    view->offset = fdl_surface_offset(layout, args->base_miplevel, args->base_array_layer);
186    uint64_t base_addr = args->iova + view->offset;
187    uint64_t ubwc_addr = args->iova +
188       fdl_ubwc_offset(layout, args->base_miplevel, args->base_array_layer);
189 
190    uint32_t pitch = fdl_pitch(layout, args->base_miplevel);
191    uint32_t ubwc_pitch = fdl_ubwc_pitch(layout, args->base_miplevel);
192    uint32_t layer_size = fdl_layer_stride(layout, args->base_miplevel);
193 
194    enum a6xx_format texture_format =
195       fd6_texture_format(args->format, layout->tile_mode);
196    enum a3xx_color_swap swap =
197       fd6_texture_swap(args->format, layout->tile_mode);
198    enum a6xx_tile_mode tile_mode = fdl_tile_mode(layout, args->base_miplevel);
199 
200    bool ubwc_enabled = fdl_ubwc_enabled(layout, args->base_miplevel);
201 
202    bool is_d24s8 = (args->format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
203                     args->format == PIPE_FORMAT_Z24X8_UNORM ||
204                     args->format == PIPE_FORMAT_X24S8_UINT);
205 
206    if (args->format == PIPE_FORMAT_X24S8_UINT && has_z24uint_s8uint) {
207       texture_format = FMT6_Z24_UINT_S8_UINT;
208       swap = WZYX;
209    }
210 
211    /* FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 is broken without UBWC on a630.  We
212     * don't need it without UBWC anyway because the purpose of the format is
213     * UBWC-compatibility.
214     */
215    if (texture_format == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 && !ubwc_enabled)
216       texture_format = FMT6_8_8_8_8_UNORM;
217 
218    enum a6xx_format storage_format = texture_format;
219    if (is_d24s8) {
220       if (ubwc_enabled)
221          storage_format = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
222       else
223          storage_format = FMT6_8_8_8_8_UNORM;
224    }
225 
226    view->format = args->format;
227 
228    memset(view->descriptor, 0, sizeof(view->descriptor));
229 
230    view->descriptor[0] =
231       A6XX_TEX_CONST_0_TILE_MODE(tile_mode) |
232       COND(util_format_is_srgb(args->format), A6XX_TEX_CONST_0_SRGB) |
233       A6XX_TEX_CONST_0_FMT(texture_format) |
234       A6XX_TEX_CONST_0_SAMPLES(util_logbase2(layout->nr_samples)) |
235       A6XX_TEX_CONST_0_SWAP(swap) |
236       fdl6_texswiz(args, has_z24uint_s8uint) |
237       A6XX_TEX_CONST_0_MIPLVLS(args->level_count - 1);
238    view->descriptor[1] =
239       A6XX_TEX_CONST_1_WIDTH(width) | A6XX_TEX_CONST_1_HEIGHT(height) |
240       COND(args->ubwc_fc_mutable, A6XX_TEX_CONST_1_MUTABLEEN);
241    view->descriptor[2] =
242       A6XX_TEX_CONST_2_PITCHALIGN(layout->pitchalign - 6) |
243       A6XX_TEX_CONST_2_PITCH(pitch) |
244       A6XX_TEX_CONST_2_TYPE(fdl6_tex_type(args->type, false));
245    view->descriptor[3] = A6XX_TEX_CONST_3_ARRAY_PITCH(layer_size);
246    view->descriptor[4] = base_addr;
247    view->descriptor[5] = (base_addr >> 32) | A6XX_TEX_CONST_5_DEPTH(depth);
248    view->descriptor[6] = A6XX_TEX_CONST_6_MIN_LOD_CLAMP(args->min_lod_clamp - args->base_miplevel);
249 
250    if (layout->tile_all)
251       view->descriptor[3] |= A6XX_TEX_CONST_3_TILE_ALL;
252 
253    if (args->format == PIPE_FORMAT_R8_G8B8_420_UNORM ||
254        args->format == PIPE_FORMAT_G8_B8R8_420_UNORM ||
255        args->format == PIPE_FORMAT_G8_B8_R8_420_UNORM) {
256       /* chroma offset re-uses MIPLVLS bits */
257       assert(args->level_count == 1);
258       if (args->chroma_offsets[0] == FDL_CHROMA_LOCATION_MIDPOINT)
259          view->descriptor[0] |= A6XX_TEX_CONST_0_CHROMA_MIDPOINT_X;
260       if (args->chroma_offsets[1] == FDL_CHROMA_LOCATION_MIDPOINT)
261          view->descriptor[0] |= A6XX_TEX_CONST_0_CHROMA_MIDPOINT_Y;
262 
263       uint64_t base_addr[3];
264 
265       if (ubwc_enabled) {
266          view->descriptor[3] |= A6XX_TEX_CONST_3_FLAG;
267          /* no separate ubwc base, image must have the expected layout */
268          for (uint32_t i = 0; i < 3; i++) {
269             base_addr[i] = args->iova +
270                fdl_ubwc_offset(layouts[i], args->base_miplevel, args->base_array_layer);
271          }
272       } else {
273          for (uint32_t i = 0; i < 3; i++) {
274             base_addr[i] = args->iova +
275                fdl_surface_offset(layouts[i], args->base_miplevel, args->base_array_layer);
276          }
277       }
278 
279       view->descriptor[4] = base_addr[0];
280       view->descriptor[5] |= base_addr[0] >> 32;
281       view->descriptor[6] =
282          A6XX_TEX_CONST_6_PLANE_PITCH(fdl_pitch(layouts[1], args->base_miplevel));
283       view->descriptor[7] = base_addr[1];
284       view->descriptor[8] = base_addr[1] >> 32;
285       view->descriptor[9] = base_addr[2];
286       view->descriptor[10] = base_addr[2] >> 32;
287 
288       assert(args->type != FDL_VIEW_TYPE_3D);
289       return;
290    }
291 
292    if (ubwc_enabled) {
293       uint32_t block_width, block_height;
294       fdl6_get_ubwc_blockwidth(layout, &block_width, &block_height);
295 
296       view->descriptor[3] |= A6XX_TEX_CONST_3_FLAG;
297       view->descriptor[7] = ubwc_addr;
298       view->descriptor[8] = ubwc_addr >> 32;
299       view->descriptor[9] |= A6XX_TEX_CONST_9_FLAG_BUFFER_ARRAY_PITCH(layout->ubwc_layer_size >> 2);
300       view->descriptor[10] |=
301          A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(ubwc_pitch) |
302          A6XX_TEX_CONST_10_FLAG_BUFFER_LOGW(util_logbase2_ceil(DIV_ROUND_UP(width, block_width))) |
303          A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(DIV_ROUND_UP(height, block_height)));
304    }
305 
306    if (args->type == FDL_VIEW_TYPE_3D) {
307       view->descriptor[3] |=
308          A6XX_TEX_CONST_3_MIN_LAYERSZ(layout->slices[layout->mip_levels - 1].size0);
309    }
310 
311    bool samples_average =
312       layout->nr_samples > 1 &&
313       !util_format_is_pure_integer(args->format) &&
314       !util_format_is_depth_or_stencil(args->format);
315 
316    view->pitch = pitch;
317 
318    view->SP_PS_2D_SRC_INFO =
319       A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(storage_format) |
320       A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(tile_mode) |
321       A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(swap) |
322       COND(ubwc_enabled, A6XX_SP_PS_2D_SRC_INFO_FLAGS) |
323       COND(util_format_is_srgb(args->format), A6XX_SP_PS_2D_SRC_INFO_SRGB) |
324       A6XX_SP_PS_2D_SRC_INFO_SAMPLES(util_logbase2(layout->nr_samples)) |
325       COND(samples_average, A6XX_SP_PS_2D_SRC_INFO_SAMPLES_AVERAGE) |
326       A6XX_SP_PS_2D_SRC_INFO_UNK20 |
327       A6XX_SP_PS_2D_SRC_INFO_UNK22 |
328       COND(args->ubwc_fc_mutable, A6XX_SP_PS_2D_SRC_INFO_MUTABLEEN);
329 
330    view->SP_PS_2D_SRC_SIZE =
331       A6XX_SP_PS_2D_SRC_SIZE_WIDTH(width) |
332       A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(height);
333 
334    /* note: these have same encoding for MRT and 2D (except 2D PITCH src) */
335    view->FLAG_BUFFER_PITCH =
336       A6XX_RB_DEPTH_FLAG_BUFFER_PITCH_PITCH(ubwc_pitch) |
337       A6XX_RB_DEPTH_FLAG_BUFFER_PITCH_ARRAY_PITCH(layout->ubwc_layer_size >> 2);
338 
339    const struct util_format_description *format_desc =
340       util_format_description(args->format);
341    if (util_format_has_depth(format_desc)) {
342       view->GRAS_LRZ_DEPTH_VIEW =
343          A6XX_GRAS_LRZ_DEPTH_VIEW_BASE_LAYER(args->base_array_layer) |
344          A6XX_GRAS_LRZ_DEPTH_VIEW_LAYER_COUNT(args->layer_count) |
345          A6XX_GRAS_LRZ_DEPTH_VIEW_BASE_MIP_LEVEL(args->base_miplevel);
346    }
347 
348    view->base_addr = base_addr;
349    view->ubwc_addr = ubwc_addr;
350    view->layer_size = layer_size;
351    view->ubwc_layer_size = layout->ubwc_layer_size;
352 
353    enum a6xx_format color_format =
354       fd6_color_format(args->format, layout->tile_mode);
355 
356    /* Don't set fields that are only used for attachments/blit dest if COLOR
357     * is unsupported.
358     */
359    if (color_format == FMT6_NONE)
360       return;
361 
362    enum a3xx_color_swap color_swap =
363       fd6_color_swap(args->format, layout->tile_mode);
364    enum a6xx_format blit_format = color_format;
365 
366    if (is_d24s8)
367       color_format = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
368 
369    if (color_format == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 && !ubwc_enabled)
370       color_format = FMT6_8_8_8_8_UNORM;
371 
372    /* We don't need FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 / FMT6_8_8_8_8_UNORM
373     * for event blits.  FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 also does not
374     * support fast clears and is slower.
375     */
376    if (is_d24s8 || blit_format == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8)
377       blit_format = FMT6_Z24_UNORM_S8_UINT;
378 
379    memset(view->storage_descriptor, 0, sizeof(view->storage_descriptor));
380 
381    view->storage_descriptor[0] =
382       A6XX_TEX_CONST_0_FMT(storage_format) |
383       COND(util_format_is_srgb(args->format), A6XX_TEX_CONST_0_SRGB) |
384       fdl6_texswiz(args, has_z24uint_s8uint) |
385       A6XX_TEX_CONST_0_TILE_MODE(tile_mode) |
386       A6XX_TEX_CONST_0_SWAP(color_swap);
387    view->storage_descriptor[1] = view->descriptor[1];
388    view->storage_descriptor[2] =
389       A6XX_TEX_CONST_2_PITCH(pitch) |
390       A6XX_TEX_CONST_2_TYPE(fdl6_tex_type(args->type, true));
391    view->storage_descriptor[3] = view->descriptor[3];
392    view->storage_descriptor[4] = base_addr;
393    view->storage_descriptor[5] = (base_addr >> 32) | A6XX_TEX_CONST_5_DEPTH(storage_depth);
394    for (unsigned i = 6; i <= 10; i++)
395       view->storage_descriptor[i] = view->descriptor[i];
396 
397    view->width = width;
398    view->height = height;
399    view->need_y2_align =
400       tile_mode == TILE6_LINEAR && args->base_miplevel != layout->mip_levels - 1;
401 
402    view->ubwc_enabled = ubwc_enabled;
403 
404    view->RB_MRT_BUF_INFO =
405       A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
406       A6XX_RB_MRT_BUF_INFO_COLOR_FORMAT(color_format) |
407       COND(args->chip >= A7XX && ubwc_enabled, A7XX_RB_MRT_BUF_INFO_LOSSLESSCOMPEN) |
408       A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(color_swap) |
409       COND(args->ubwc_fc_mutable, A7XX_RB_MRT_BUF_INFO_MUTABLEEN);
410 
411    view->SP_FS_MRT_REG =
412       A6XX_SP_FS_MRT_REG_COLOR_FORMAT(color_format) |
413       COND(util_format_is_pure_sint(args->format), A6XX_SP_FS_MRT_REG_COLOR_SINT) |
414       COND(util_format_is_pure_uint(args->format), A6XX_SP_FS_MRT_REG_COLOR_UINT);
415 
416    view->RB_2D_DST_INFO =
417       A6XX_RB_2D_DST_INFO_COLOR_FORMAT(color_format) |
418       A6XX_RB_2D_DST_INFO_TILE_MODE(tile_mode) |
419       A6XX_RB_2D_DST_INFO_COLOR_SWAP(color_swap) |
420       COND(ubwc_enabled, A6XX_RB_2D_DST_INFO_FLAGS) |
421       COND(util_format_is_srgb(args->format), A6XX_RB_2D_DST_INFO_SRGB) |
422       COND(args->ubwc_fc_mutable, A6XX_RB_2D_DST_INFO_MUTABLEEN);;
423 
424    view->RB_BLIT_DST_INFO =
425       A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode) |
426       A6XX_RB_BLIT_DST_INFO_SAMPLES(util_logbase2(layout->nr_samples)) |
427       A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(blit_format) |
428       A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(color_swap) |
429       COND(ubwc_enabled, A6XX_RB_BLIT_DST_INFO_FLAGS) |
430       COND(args->ubwc_fc_mutable, A6XX_RB_BLIT_DST_INFO_MUTABLEEN);
431 }
432 
433 void
fdl6_buffer_view_init(uint32_t * descriptor,enum pipe_format format,const uint8_t * swiz,uint64_t iova,uint32_t size)434 fdl6_buffer_view_init(uint32_t *descriptor, enum pipe_format format,
435                       const uint8_t *swiz, uint64_t iova, uint32_t size)
436 {
437    unsigned elem_size = util_format_get_blocksize(format);
438    unsigned elements = size / elem_size;
439    uint64_t base_iova = iova & ~0x3full;
440    unsigned texel_offset = (iova & 0x3f) / elem_size;
441 
442    struct fdl_view_args args = {
443       .format = format,
444       .swiz = {swiz[0], swiz[1], swiz[2], swiz[3]},
445    };
446 
447    memset(descriptor, 0, 4 * FDL6_TEX_CONST_DWORDS);
448 
449    descriptor[0] =
450       A6XX_TEX_CONST_0_TILE_MODE(TILE6_LINEAR) |
451       A6XX_TEX_CONST_0_SWAP(fd6_texture_swap(format, TILE6_LINEAR)) |
452       A6XX_TEX_CONST_0_FMT(fd6_texture_format(format, TILE6_LINEAR)) |
453       A6XX_TEX_CONST_0_MIPLVLS(0) | fdl6_texswiz(&args, false) |
454       COND(util_format_is_srgb(format), A6XX_TEX_CONST_0_SRGB);
455    descriptor[1] = A6XX_TEX_CONST_1_WIDTH(elements & ((1 << 15) - 1)) |
456                    A6XX_TEX_CONST_1_HEIGHT(elements >> 15);
457    descriptor[2] = A6XX_TEX_CONST_2_STRUCTSIZETEXELS(1) |
458                    A6XX_TEX_CONST_2_STARTOFFSETTEXELS(texel_offset) |
459                    A6XX_TEX_CONST_2_TYPE(A6XX_TEX_BUFFER);
460    descriptor[4] = base_iova;
461    descriptor[5] = base_iova >> 32;
462 }
463