• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <robclark@freedesktop.org>
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, layout->is_mutable);
196    enum a3xx_color_swap swap =
197       fd6_texture_swap(args->format, layout->tile_mode, layout->is_mutable);
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    bool is_mutable = layout->is_mutable && tile_mode == TILE6_3;
231 
232    view->descriptor[0] =
233       A6XX_TEX_CONST_0_TILE_MODE(tile_mode) |
234       COND(util_format_is_srgb(args->format), A6XX_TEX_CONST_0_SRGB) |
235       A6XX_TEX_CONST_0_FMT(texture_format) |
236       A6XX_TEX_CONST_0_SAMPLES(util_logbase2(layout->nr_samples)) |
237       A6XX_TEX_CONST_0_SWAP(swap) |
238       fdl6_texswiz(args, has_z24uint_s8uint) |
239       A6XX_TEX_CONST_0_MIPLVLS(args->level_count - 1);
240    view->descriptor[1] =
241       A6XX_TEX_CONST_1_WIDTH(width) | A6XX_TEX_CONST_1_HEIGHT(height) |
242       COND(is_mutable, A6XX_TEX_CONST_1_MUTABLEEN);
243    view->descriptor[2] =
244       A6XX_TEX_CONST_2_PITCHALIGN(layout->pitchalign - 6) |
245       A6XX_TEX_CONST_2_PITCH(pitch) |
246       A6XX_TEX_CONST_2_TYPE(fdl6_tex_type(args->type, false));
247    view->descriptor[3] = A6XX_TEX_CONST_3_ARRAY_PITCH(layer_size);
248    view->descriptor[4] = base_addr;
249    view->descriptor[5] = (base_addr >> 32) | A6XX_TEX_CONST_5_DEPTH(depth);
250    view->descriptor[6] = A6XX_TEX_CONST_6_MIN_LOD_CLAMP(args->min_lod_clamp - args->base_miplevel);
251 
252    if (layout->tile_all)
253       view->descriptor[3] |= A6XX_TEX_CONST_3_TILE_ALL;
254 
255    if (args->format == PIPE_FORMAT_R8_G8B8_420_UNORM ||
256        args->format == PIPE_FORMAT_G8_B8R8_420_UNORM ||
257        args->format == PIPE_FORMAT_G8_B8_R8_420_UNORM) {
258       /* chroma offset re-uses MIPLVLS bits */
259       assert(args->level_count == 1);
260       if (args->chroma_offsets[0] == FDL_CHROMA_LOCATION_MIDPOINT)
261          view->descriptor[0] |= A6XX_TEX_CONST_0_CHROMA_MIDPOINT_X;
262       if (args->chroma_offsets[1] == FDL_CHROMA_LOCATION_MIDPOINT)
263          view->descriptor[0] |= A6XX_TEX_CONST_0_CHROMA_MIDPOINT_Y;
264 
265       uint64_t base_addr[3];
266 
267       if (ubwc_enabled) {
268          view->descriptor[3] |= A6XX_TEX_CONST_3_FLAG;
269          /* no separate ubwc base, image must have the expected layout */
270          for (uint32_t i = 0; i < 3; i++) {
271             base_addr[i] = args->iova +
272                fdl_ubwc_offset(layouts[i], args->base_miplevel, args->base_array_layer);
273          }
274       } else {
275          for (uint32_t i = 0; i < 3; i++) {
276             base_addr[i] = args->iova +
277                fdl_surface_offset(layouts[i], args->base_miplevel, args->base_array_layer);
278          }
279       }
280 
281       view->descriptor[4] = base_addr[0];
282       view->descriptor[5] |= base_addr[0] >> 32;
283       view->descriptor[6] =
284          A6XX_TEX_CONST_6_PLANE_PITCH(fdl_pitch(layouts[1], args->base_miplevel));
285       view->descriptor[7] = base_addr[1];
286       view->descriptor[8] = base_addr[1] >> 32;
287       view->descriptor[9] = base_addr[2];
288       view->descriptor[10] = base_addr[2] >> 32;
289 
290       assert(args->type != FDL_VIEW_TYPE_3D);
291       return;
292    }
293 
294    if (ubwc_enabled) {
295       uint32_t block_width, block_height;
296       fdl6_get_ubwc_blockwidth(layout, &block_width, &block_height);
297 
298       view->descriptor[3] |= A6XX_TEX_CONST_3_FLAG;
299       view->descriptor[7] = ubwc_addr;
300       view->descriptor[8] = ubwc_addr >> 32;
301       view->descriptor[9] |= A6XX_TEX_CONST_9_FLAG_BUFFER_ARRAY_PITCH(layout->ubwc_layer_size >> 2);
302       view->descriptor[10] |=
303          A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(ubwc_pitch) |
304          A6XX_TEX_CONST_10_FLAG_BUFFER_LOGW(util_logbase2_ceil(DIV_ROUND_UP(width, block_width))) |
305          A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(DIV_ROUND_UP(height, block_height)));
306    }
307 
308    if (args->type == FDL_VIEW_TYPE_3D) {
309       view->descriptor[3] |=
310          A6XX_TEX_CONST_3_MIN_LAYERSZ(layout->slices[layout->mip_levels - 1].size0);
311    }
312 
313    bool samples_average =
314       layout->nr_samples > 1 &&
315       !util_format_is_pure_integer(args->format) &&
316       !util_format_is_depth_or_stencil(args->format);
317 
318    view->pitch = pitch;
319 
320    view->SP_PS_2D_SRC_INFO =
321       A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(storage_format) |
322       A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(tile_mode) |
323       A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(swap) |
324       COND(ubwc_enabled, A6XX_SP_PS_2D_SRC_INFO_FLAGS) |
325       COND(util_format_is_srgb(args->format), A6XX_SP_PS_2D_SRC_INFO_SRGB) |
326       A6XX_SP_PS_2D_SRC_INFO_SAMPLES(util_logbase2(layout->nr_samples)) |
327       COND(samples_average, A6XX_SP_PS_2D_SRC_INFO_SAMPLES_AVERAGE) |
328       A6XX_SP_PS_2D_SRC_INFO_UNK20 |
329       A6XX_SP_PS_2D_SRC_INFO_UNK22 |
330       COND(is_mutable, A6XX_SP_PS_2D_SRC_INFO_MUTABLEEN);
331 
332    view->SP_PS_2D_SRC_SIZE =
333       A6XX_SP_PS_2D_SRC_SIZE_WIDTH(width) |
334       A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(height);
335 
336    /* note: these have same encoding for MRT and 2D (except 2D PITCH src) */
337    view->FLAG_BUFFER_PITCH =
338       A6XX_RB_DEPTH_FLAG_BUFFER_PITCH_PITCH(ubwc_pitch) |
339       A6XX_RB_DEPTH_FLAG_BUFFER_PITCH_ARRAY_PITCH(layout->ubwc_layer_size >> 2);
340 
341    const struct util_format_description *format_desc =
342       util_format_description(args->format);
343    if (util_format_has_depth(format_desc)) {
344       view->GRAS_LRZ_DEPTH_VIEW =
345          A6XX_GRAS_LRZ_DEPTH_VIEW_BASE_LAYER(args->base_array_layer) |
346          A6XX_GRAS_LRZ_DEPTH_VIEW_LAYER_COUNT(args->layer_count) |
347          A6XX_GRAS_LRZ_DEPTH_VIEW_BASE_MIP_LEVEL(args->base_miplevel);
348    }
349 
350    view->base_addr = base_addr;
351    view->ubwc_addr = ubwc_addr;
352    view->layer_size = layer_size;
353    view->ubwc_layer_size = layout->ubwc_layer_size;
354 
355    enum a6xx_format color_format =
356       fd6_color_format(args->format, layout->tile_mode);
357 
358    /* Don't set fields that are only used for attachments/blit dest if COLOR
359     * is unsupported.
360     */
361    if (color_format == FMT6_NONE)
362       return;
363 
364    enum a3xx_color_swap color_swap =
365       fd6_color_swap(args->format, layout->tile_mode, layout->is_mutable);
366    enum a6xx_format blit_format = color_format;
367 
368    if (is_d24s8)
369       color_format = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
370 
371    if (color_format == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 && !ubwc_enabled)
372       color_format = FMT6_8_8_8_8_UNORM;
373 
374    /* We don't need FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 / FMT6_8_8_8_8_UNORM
375     * for event blits.  FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 also does not
376     * support fast clears and is slower.
377     */
378    if (is_d24s8 || blit_format == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8)
379       blit_format = FMT6_Z24_UNORM_S8_UINT;
380 
381    memset(view->storage_descriptor, 0, sizeof(view->storage_descriptor));
382 
383    view->storage_descriptor[0] =
384       A6XX_TEX_CONST_0_FMT(storage_format) |
385       COND(util_format_is_srgb(args->format), A6XX_TEX_CONST_0_SRGB) |
386       fdl6_texswiz(args, has_z24uint_s8uint) |
387       A6XX_TEX_CONST_0_TILE_MODE(tile_mode) |
388       A6XX_TEX_CONST_0_SWAP(color_swap);
389    view->storage_descriptor[1] = view->descriptor[1];
390    view->storage_descriptor[2] =
391       A6XX_TEX_CONST_2_PITCH(pitch) |
392       A6XX_TEX_CONST_2_TYPE(fdl6_tex_type(args->type, true));
393    view->storage_descriptor[3] = view->descriptor[3];
394    view->storage_descriptor[4] = base_addr;
395    view->storage_descriptor[5] = (base_addr >> 32) | A6XX_TEX_CONST_5_DEPTH(storage_depth);
396    for (unsigned i = 6; i <= 10; i++)
397       view->storage_descriptor[i] = view->descriptor[i];
398 
399    view->width = width;
400    view->height = height;
401    view->need_y2_align =
402       tile_mode == TILE6_LINEAR && args->base_miplevel != layout->mip_levels - 1;
403 
404    view->ubwc_enabled = ubwc_enabled;
405 
406    view->RB_MRT_BUF_INFO =
407       A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
408       A6XX_RB_MRT_BUF_INFO_COLOR_FORMAT(color_format) |
409       COND(args->chip >= A7XX && ubwc_enabled, A7XX_RB_MRT_BUF_INFO_LOSSLESSCOMPEN) |
410       A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(color_swap) |
411       COND(is_mutable, A7XX_RB_MRT_BUF_INFO_MUTABLEEN);
412 
413    view->SP_FS_MRT_REG =
414       A6XX_SP_FS_MRT_REG_COLOR_FORMAT(color_format) |
415       COND(util_format_is_pure_sint(args->format), A6XX_SP_FS_MRT_REG_COLOR_SINT) |
416       COND(util_format_is_pure_uint(args->format), A6XX_SP_FS_MRT_REG_COLOR_UINT);
417 
418    view->RB_2D_DST_INFO =
419       A6XX_RB_2D_DST_INFO_COLOR_FORMAT(color_format) |
420       A6XX_RB_2D_DST_INFO_TILE_MODE(tile_mode) |
421       A6XX_RB_2D_DST_INFO_COLOR_SWAP(color_swap) |
422       COND(ubwc_enabled, A6XX_RB_2D_DST_INFO_FLAGS) |
423       COND(util_format_is_srgb(args->format), A6XX_RB_2D_DST_INFO_SRGB) |
424       COND(is_mutable, A6XX_RB_2D_DST_INFO_MUTABLEEN);;
425 
426    view->RB_BLIT_DST_INFO =
427       A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode) |
428       A6XX_RB_BLIT_DST_INFO_SAMPLES(util_logbase2(layout->nr_samples)) |
429       A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(blit_format) |
430       A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(color_swap) |
431       COND(ubwc_enabled, A6XX_RB_BLIT_DST_INFO_FLAGS) |
432       COND(is_mutable, A6XX_RB_BLIT_DST_INFO_MUTABLEEN);
433 }
434 
435 void
fdl6_buffer_view_init(uint32_t * descriptor,enum pipe_format format,const uint8_t * swiz,uint64_t iova,uint32_t size)436 fdl6_buffer_view_init(uint32_t *descriptor, enum pipe_format format,
437                       const uint8_t *swiz, uint64_t iova, uint32_t size)
438 {
439    unsigned elem_size = util_format_get_blocksize(format);
440    unsigned elements = size / elem_size;
441    uint64_t base_iova = iova & ~0x3full;
442    unsigned texel_offset = (iova & 0x3f) / elem_size;
443 
444    struct fdl_view_args args = {
445       .format = format,
446       .swiz = {swiz[0], swiz[1], swiz[2], swiz[3]},
447    };
448 
449    memset(descriptor, 0, 4 * FDL6_TEX_CONST_DWORDS);
450 
451    descriptor[0] =
452       A6XX_TEX_CONST_0_TILE_MODE(TILE6_LINEAR) |
453       A6XX_TEX_CONST_0_SWAP(fd6_texture_swap(format, TILE6_LINEAR, false)) |
454       A6XX_TEX_CONST_0_FMT(fd6_texture_format(format, TILE6_LINEAR, false)) |
455       A6XX_TEX_CONST_0_MIPLVLS(0) | fdl6_texswiz(&args, false) |
456       COND(util_format_is_srgb(format), A6XX_TEX_CONST_0_SRGB);
457    descriptor[1] = A6XX_TEX_CONST_1_WIDTH(elements & ((1 << 15) - 1)) |
458                    A6XX_TEX_CONST_1_HEIGHT(elements >> 15);
459    descriptor[2] = A6XX_TEX_CONST_2_STRUCTSIZETEXELS(1) |
460                    A6XX_TEX_CONST_2_STARTOFFSETTEXELS(texel_offset) |
461                    A6XX_TEX_CONST_2_TYPE(A6XX_TEX_BUFFER);
462    descriptor[4] = base_iova;
463    descriptor[5] = base_iova >> 32;
464 }
465