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