1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 * SPDX-License-Identifier: MIT
5 *
6 * based in part on anv driver which is:
7 * Copyright © 2015 Intel Corporation
8 */
9
10 #include "tu_image.h"
11
12 #include "fdl/fd6_format_table.h"
13 #include "common/freedreno_lrz.h"
14
15 #include "util/u_debug.h"
16 #include "util/format/u_format.h"
17 #include "vulkan/vulkan_android.h"
18 #include "vk_android.h"
19 #include "vk_debug_utils.h"
20 #include "vk_util.h"
21 #include "drm-uapi/drm_fourcc.h"
22 #include "vulkan/vulkan_core.h"
23
24 #include "tu_buffer.h"
25 #include "tu_cs.h"
26 #include "tu_descriptor_set.h"
27 #include "tu_device.h"
28 #include "tu_formats.h"
29 #include "tu_lrz.h"
30 #include "tu_rmv.h"
31 #include "tu_wsi.h"
32
33 uint32_t
tu6_plane_count(VkFormat format)34 tu6_plane_count(VkFormat format)
35 {
36 switch (format) {
37 case VK_FORMAT_D32_SFLOAT_S8_UINT:
38 /* We do not support interleaved depth/stencil. Instead, we decompose to
39 * a depth plane and a stencil plane.
40 */
41 return 2;
42 default:
43 return vk_format_get_plane_count(format);
44 }
45 }
46
47 enum pipe_format
tu6_plane_format(VkFormat format,uint32_t plane)48 tu6_plane_format(VkFormat format, uint32_t plane)
49 {
50 switch (format) {
51 case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
52 return plane ? PIPE_FORMAT_R8G8_UNORM : PIPE_FORMAT_Y8_UNORM;
53 case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
54 return PIPE_FORMAT_R8_UNORM;
55 case VK_FORMAT_D32_SFLOAT_S8_UINT:
56 return plane ? PIPE_FORMAT_S8_UINT : PIPE_FORMAT_Z32_FLOAT;
57 default:
58 return vk_format_to_pipe_format(format);
59 }
60 }
61
62 uint32_t
tu6_plane_index(VkFormat format,VkImageAspectFlags aspect_mask)63 tu6_plane_index(VkFormat format, VkImageAspectFlags aspect_mask)
64 {
65 switch (aspect_mask) {
66 default:
67 assert(aspect_mask != VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT);
68 return 0;
69 case VK_IMAGE_ASPECT_PLANE_1_BIT:
70 case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:
71 return 1;
72 case VK_IMAGE_ASPECT_PLANE_2_BIT:
73 case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:
74 return 2;
75 case VK_IMAGE_ASPECT_STENCIL_BIT:
76 return format == VK_FORMAT_D32_SFLOAT_S8_UINT;
77 }
78 }
79
80 enum pipe_format
tu_format_for_aspect(enum pipe_format format,VkImageAspectFlags aspect_mask)81 tu_format_for_aspect(enum pipe_format format, VkImageAspectFlags aspect_mask)
82 {
83 switch (format) {
84 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
85 /* VK_IMAGE_ASPECT_COLOR_BIT is used internally for blits (despite we
86 * also incorrectly advertise VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT for
87 * depth formats). Return PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8 in
88 * this case.
89 *
90 * Otherwise, return the appropriate pipe format and let fdl6_view_init
91 * take care of the rest.
92 */
93 if (aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT)
94 return PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
95 if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
96 if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
97 return PIPE_FORMAT_Z24_UNORM_S8_UINT;
98 else
99 return PIPE_FORMAT_X24S8_UINT;
100 } else {
101 return PIPE_FORMAT_Z24X8_UNORM;
102 }
103 case PIPE_FORMAT_Z24X8_UNORM:
104 if (aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT)
105 return PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
106 return PIPE_FORMAT_Z24X8_UNORM;
107 default:
108 return format;
109 }
110 }
111
112 static bool
tu_is_r8g8(enum pipe_format format)113 tu_is_r8g8(enum pipe_format format)
114 {
115 return (util_format_get_blocksize(format) == 2) &&
116 (util_format_get_nr_components(format) == 2);
117 }
118
119 static bool
tu_is_r8g8_compatible(enum pipe_format format)120 tu_is_r8g8_compatible(enum pipe_format format)
121 {
122 return (util_format_get_blocksize(format) == 2) &&
123 !util_format_is_depth_or_stencil(format);
124 }
125
126 uint64_t
tu_layer_address(const struct fdl6_view * iview,uint32_t layer)127 tu_layer_address(const struct fdl6_view *iview, uint32_t layer)
128 {
129 return iview->base_addr + iview->layer_size * layer;
130 }
131
132 void
tu_cs_image_ref(struct tu_cs * cs,const struct fdl6_view * iview,uint32_t layer)133 tu_cs_image_ref(struct tu_cs *cs, const struct fdl6_view *iview, uint32_t layer)
134 {
135 tu_cs_emit(cs, A6XX_RB_MRT_PITCH(0, iview->pitch).value);
136 tu_cs_emit(cs, iview->layer_size >> 6);
137 tu_cs_emit_qw(cs, tu_layer_address(iview, layer));
138 }
139
140 void
tu_cs_image_stencil_ref(struct tu_cs * cs,const struct tu_image_view * iview,uint32_t layer)141 tu_cs_image_stencil_ref(struct tu_cs *cs, const struct tu_image_view *iview, uint32_t layer)
142 {
143 tu_cs_emit(cs, A6XX_RB_STENCIL_BUFFER_PITCH(iview->stencil_pitch).value);
144 tu_cs_emit(cs, iview->stencil_layer_size >> 6);
145 tu_cs_emit_qw(cs, iview->stencil_base_addr + iview->stencil_layer_size * layer);
146 }
147
148 void
tu_cs_image_depth_ref(struct tu_cs * cs,const struct tu_image_view * iview,uint32_t layer)149 tu_cs_image_depth_ref(struct tu_cs *cs, const struct tu_image_view *iview, uint32_t layer)
150 {
151 tu_cs_emit(cs, A6XX_RB_DEPTH_BUFFER_PITCH(iview->depth_pitch).value);
152 tu_cs_emit(cs, iview->depth_layer_size >> 6);
153 tu_cs_emit_qw(cs, iview->depth_base_addr + iview->depth_layer_size * layer);
154 }
155
156 template <chip CHIP>
157 void
tu_cs_image_ref_2d(struct tu_cs * cs,const struct fdl6_view * iview,uint32_t layer,bool src)158 tu_cs_image_ref_2d(struct tu_cs *cs, const struct fdl6_view *iview, uint32_t layer, bool src)
159 {
160 tu_cs_emit_qw(cs, iview->base_addr + iview->layer_size * layer);
161 /* SP_PS_2D_SRC_PITCH has shifted pitch field */
162 if (src)
163 tu_cs_emit(cs, SP_PS_2D_SRC_PITCH(CHIP, .pitch = iview->pitch).value);
164 else
165 tu_cs_emit(cs, A6XX_RB_2D_DST_PITCH(iview->pitch).value);
166 }
167 TU_GENX(tu_cs_image_ref_2d);
168
169 void
tu_cs_image_flag_ref(struct tu_cs * cs,const struct fdl6_view * iview,uint32_t layer)170 tu_cs_image_flag_ref(struct tu_cs *cs, const struct fdl6_view *iview, uint32_t layer)
171 {
172 tu_cs_emit_qw(cs, iview->ubwc_addr + iview->ubwc_layer_size * layer);
173 tu_cs_emit(cs, iview->FLAG_BUFFER_PITCH);
174 }
175
176 static void
tu_image_view_init(struct tu_device * device,struct tu_image_view * iview,const VkImageViewCreateInfo * pCreateInfo,bool has_z24uint_s8uint)177 tu_image_view_init(struct tu_device *device,
178 struct tu_image_view *iview,
179 const VkImageViewCreateInfo *pCreateInfo,
180 bool has_z24uint_s8uint)
181 {
182 VK_FROM_HANDLE(tu_image, image, pCreateInfo->image);
183 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
184 VkFormat vk_format =
185 vk_select_android_external_format(pCreateInfo->pNext, pCreateInfo->format);
186
187 /* With AHB, the app may be using an external format but not necessarily
188 * chain the VkExternalFormatANDROID. In this case, just take the format
189 * from the image.
190 */
191 if ((vk_format == VK_FORMAT_UNDEFINED) &&
192 (image->vk.external_handle_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID))
193 vk_format = image->vk.format;
194
195 VkImageAspectFlags aspect_mask = pCreateInfo->subresourceRange.aspectMask;
196
197 const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion =
198 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
199 const struct vk_ycbcr_conversion *conversion = ycbcr_conversion ?
200 vk_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL;
201
202 vk_image_view_init(&device->vk, &iview->vk, false, pCreateInfo);
203
204 iview->image = image;
205
206 const struct fdl_layout *layouts[3];
207
208 layouts[0] = &image->layout[tu6_plane_index(image->vk.format, aspect_mask)];
209
210 enum pipe_format format;
211 if (aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT)
212 format = tu6_plane_format(vk_format, tu6_plane_index(vk_format, aspect_mask));
213 else
214 format = vk_format_to_pipe_format(vk_format);
215
216 if (image->vk.format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM &&
217 aspect_mask == VK_IMAGE_ASPECT_PLANE_0_BIT) {
218 if (vk_format == VK_FORMAT_R8_UNORM) {
219 /* The 0'th plane of this format has a different UBWC compression. */
220 format = PIPE_FORMAT_Y8_UNORM;
221 } else {
222 /* If the user wants to reinterpret this plane, then they should've
223 * set MUTABLE_FORMAT_BIT which should disable UBWC and tiling.
224 */
225 assert(!layouts[0]->ubwc);
226 }
227 }
228
229 if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT &&
230 (vk_format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM ||
231 vk_format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM)) {
232 layouts[1] = &image->layout[1];
233 layouts[2] = &image->layout[2];
234 }
235
236 vk_component_mapping_to_pipe_swizzle(pCreateInfo->components,
237 iview->swizzle);
238
239 struct fdl_view_args args = {};
240 args.chip = device->physical_device->info->chip;
241 args.iova = image->iova;
242 args.base_array_layer = range->baseArrayLayer;
243 args.base_miplevel = range->baseMipLevel;
244 args.layer_count = vk_image_subresource_layer_count(&image->vk, range);
245 args.level_count = vk_image_subresource_level_count(&image->vk, range);
246 args.min_lod_clamp = iview->vk.min_lod;
247 args.format = tu_format_for_aspect(format, aspect_mask);
248 args.ubwc_fc_mutable = image->ubwc_fc_mutable;
249 vk_component_mapping_to_pipe_swizzle(pCreateInfo->components, args.swiz);
250 if (conversion) {
251 unsigned char conversion_swiz[4], create_swiz[4];
252 memcpy(create_swiz, args.swiz, sizeof(create_swiz));
253
254 VkComponentMapping component = {
255 .r = conversion->state.mapping[0],
256 .g = conversion->state.mapping[1],
257 .b = conversion->state.mapping[2],
258 .a = conversion->state.mapping[3]
259 };
260 vk_component_mapping_to_pipe_swizzle(component, conversion_swiz);
261 util_format_compose_swizzles(create_swiz, conversion_swiz, args.swiz);
262 }
263
264 switch (pCreateInfo->viewType) {
265 case VK_IMAGE_VIEW_TYPE_1D:
266 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
267 args.type = FDL_VIEW_TYPE_1D;
268 break;
269 case VK_IMAGE_VIEW_TYPE_2D:
270 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
271 args.type = FDL_VIEW_TYPE_2D;
272 break;
273 case VK_IMAGE_VIEW_TYPE_CUBE:
274 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
275 args.type = FDL_VIEW_TYPE_CUBE;
276 break;
277 case VK_IMAGE_VIEW_TYPE_3D:
278 args.type = FDL_VIEW_TYPE_3D;
279 break;
280 default:
281 unreachable("unknown view type");
282 }
283
284 STATIC_ASSERT((unsigned)VK_CHROMA_LOCATION_COSITED_EVEN == (unsigned)FDL_CHROMA_LOCATION_COSITED_EVEN);
285 STATIC_ASSERT((unsigned)VK_CHROMA_LOCATION_MIDPOINT == (unsigned)FDL_CHROMA_LOCATION_MIDPOINT);
286 if (conversion) {
287 args.chroma_offsets[0] = (enum fdl_chroma_location) conversion->state.chroma_offsets[0];
288 args.chroma_offsets[1] = (enum fdl_chroma_location) conversion->state.chroma_offsets[1];
289 }
290
291 fdl6_view_init(&iview->view, layouts, &args, has_z24uint_s8uint);
292
293 if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
294 struct fdl_layout *layout = &image->layout[0];
295 iview->depth_base_addr = image->iova +
296 fdl_surface_offset(layout, range->baseMipLevel, range->baseArrayLayer);
297 iview->depth_layer_size = fdl_layer_stride(layout, range->baseMipLevel);
298 iview->depth_pitch = fdl_pitch(layout, range->baseMipLevel);
299
300 layout = &image->layout[1];
301 iview->stencil_base_addr = image->iova +
302 fdl_surface_offset(layout, range->baseMipLevel, range->baseArrayLayer);
303 iview->stencil_layer_size = fdl_layer_stride(layout, range->baseMipLevel);
304 iview->stencil_pitch = fdl_pitch(layout, range->baseMipLevel);
305 }
306 }
307
308 bool
tiling_possible(VkFormat format)309 tiling_possible(VkFormat format)
310 {
311 if (format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM ||
312 format == VK_FORMAT_G8B8G8R8_422_UNORM ||
313 format == VK_FORMAT_B8G8R8G8_422_UNORM)
314 return false;
315
316 return true;
317 }
318
319 /* Checks if we should advertise UBWC support for the given usage.
320 *
321 * Used by both vkCreateImage and vkGetPhysicalDeviceFormatProperties2, so the
322 * logical tu_device may be NULL.
323 */
324 bool
ubwc_possible(struct tu_device * device,VkFormat format,VkImageType type,VkImageUsageFlags usage,VkImageUsageFlags stencil_usage,const struct fd_dev_info * info,VkSampleCountFlagBits samples,bool use_z24uint_s8uint)325 ubwc_possible(struct tu_device *device,
326 VkFormat format,
327 VkImageType type,
328 VkImageUsageFlags usage,
329 VkImageUsageFlags stencil_usage,
330 const struct fd_dev_info *info,
331 VkSampleCountFlagBits samples,
332 bool use_z24uint_s8uint)
333 {
334 /* no UBWC with compressed formats, E5B9G9R9, S8_UINT
335 * (S8_UINT because separate stencil doesn't have UBWC-enable bit)
336 */
337 if (vk_format_is_compressed(format) ||
338 format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 ||
339 format == VK_FORMAT_S8_UINT)
340 return false;
341
342 /* In copy_format, we treat snorm as unorm to avoid clamping. But snorm
343 * and unorm are UBWC incompatible for special values such as all 0's or
344 * all 1's prior to a740. Disable UBWC for snorm.
345 */
346 if (vk_format_is_snorm(format) &&
347 !info->a7xx.ubwc_unorm_snorm_int_compatible)
348 return false;
349
350 if (!info->a6xx.has_8bpp_ubwc &&
351 vk_format_get_blocksizebits(format) == 8 &&
352 vk_format_get_plane_count(format) == 1)
353 return false;
354
355 if (type == VK_IMAGE_TYPE_3D) {
356 if (device) {
357 perf_debug(device,
358 "Disabling UBWC for %s 3D image, but it should be "
359 "possible to support.",
360 util_format_name(vk_format_to_pipe_format(format)));
361 }
362 return false;
363 }
364
365 /* Disable UBWC for storage images when not supported.
366 *
367 * Prior to a7xx, storage images must be readonly or writeonly to use UBWC.
368 * Freedreno can determine when this isn't the case and decompress the
369 * image on-the-fly, but we don't know which image a binding corresponds to
370 * and we can't change the descriptor so we can't do this.
371 */
372 if (((usage | stencil_usage) & VK_IMAGE_USAGE_STORAGE_BIT) &&
373 !info->a7xx.supports_ibo_ubwc) {
374 return false;
375 }
376
377 /* A690 seem to have broken UBWC for depth/stencil, it requires
378 * depth flushing where we cannot realistically place it, like between
379 * ordinary draw calls writing read/depth. WSL blob seem to use ubwc
380 * sometimes for depth/stencil.
381 */
382 if (info->a6xx.broken_ds_ubwc_quirk &&
383 vk_format_is_depth_or_stencil(format))
384 return false;
385
386 /* Disable UBWC for D24S8 on A630 in some cases
387 *
388 * VK_IMAGE_ASPECT_STENCIL_BIT image view requires to be able to sample
389 * from the stencil component as UINT, however no format allows this
390 * on a630 (the special FMT6_Z24_UINT_S8_UINT format is missing)
391 *
392 * It must be sampled as FMT6_8_8_8_8_UINT, which is not UBWC-compatible
393 *
394 * If we wish to get the border colors correct without knowing the format
395 * when creating the sampler, we also have to use the A630 workaround.
396 */
397 if (!use_z24uint_s8uint &&
398 format == VK_FORMAT_D24_UNORM_S8_UINT &&
399 (stencil_usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)))
400 return false;
401
402 if (!info->a6xx.has_z24uint_s8uint &&
403 (format == VK_FORMAT_D24_UNORM_S8_UINT ||
404 format == VK_FORMAT_X8_D24_UNORM_PACK32) &&
405 samples > VK_SAMPLE_COUNT_1_BIT) {
406 return false;
407 }
408
409 return true;
410 }
411
412 /* R8G8 have a different block width/height and height alignment from other
413 * formats that would normally be compatible (like R16), and so if we are
414 * trying to, for example, sample R16 as R8G8 we need to demote to linear.
415 */
416 static bool
format_list_reinterprets_r8g8_r16(enum pipe_format format,const VkImageFormatListCreateInfo * fmt_list)417 format_list_reinterprets_r8g8_r16(enum pipe_format format, const VkImageFormatListCreateInfo *fmt_list)
418 {
419 /* Check if it's actually a 2-cpp color format. */
420 if (!tu_is_r8g8_compatible(format))
421 return false;
422
423 /* If there's no format list, then the app may reinterpret to any compatible
424 * format.
425 */
426 if (!fmt_list || !fmt_list->viewFormatCount)
427 return true;
428
429 bool has_r8g8 = false;
430 bool has_non_r8g8 = false;
431 for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
432 enum pipe_format format =
433 vk_format_to_pipe_format(fmt_list->pViewFormats[i]);
434 if (tu_is_r8g8(format))
435 has_r8g8 = true;
436 else
437 has_non_r8g8 = true;
438 }
439 return has_r8g8 && has_non_r8g8;
440 }
441
442 static bool
format_list_has_swaps(const VkImageFormatListCreateInfo * fmt_list)443 format_list_has_swaps(const VkImageFormatListCreateInfo *fmt_list)
444 {
445 /* If there's no format list, then the app may reinterpret to any compatible
446 * format, and presumably one would have the swap set.
447 */
448 if (!fmt_list || !fmt_list->viewFormatCount)
449 return true;
450
451 for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
452 enum pipe_format format =
453 vk_format_to_pipe_format(fmt_list->pViewFormats[i]);
454
455 if (tu6_format_texture(format, TILE6_LINEAR).swap)
456 return true;
457 }
458 return false;
459 }
460
461 template <chip CHIP>
462 VkResult
tu_image_update_layout(struct tu_device * device,struct tu_image * image,uint64_t modifier,const VkSubresourceLayout * plane_layouts)463 tu_image_update_layout(struct tu_device *device, struct tu_image *image,
464 uint64_t modifier, const VkSubresourceLayout *plane_layouts)
465 {
466 enum a6xx_tile_mode tile_mode = TILE6_3;
467 image->vk.drm_format_mod = modifier;
468
469 if (modifier == DRM_FORMAT_MOD_LINEAR) {
470 image->force_linear_tile = true;
471 }
472
473 if (image->force_linear_tile) {
474 tile_mode = TILE6_LINEAR;
475 image->ubwc_enabled = false;
476 }
477
478 /* Whether a view of the image with an R8G8 format could be made. */
479 bool has_r8g8 = tu_is_r8g8(vk_format_to_pipe_format(image->vk.format));
480
481 /* With AHB, we could be asked to create an image with VK_IMAGE_TILING_LINEAR
482 * but gralloc doesn't know this. So if we are explicitly told that it is
483 * UBWC, then override how the image was created.
484 */
485 if (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) {
486 assert(!image->force_linear_tile);
487 image->ubwc_enabled = true;
488 }
489
490 /* Non-UBWC tiled R8G8 is probably buggy since media formats are always
491 * either linear or UBWC. There is no simple test to reproduce the bug.
492 * However it was observed in the wild leading to an unrecoverable hang
493 * on a650/a660.
494 */
495 if (has_r8g8 && tile_mode == TILE6_3 && !image->ubwc_enabled) {
496 tile_mode = TILE6_LINEAR;
497 }
498
499 for (uint32_t i = 0; i < tu6_plane_count(image->vk.format); i++) {
500 struct fdl_layout *layout = &image->layout[i];
501 enum pipe_format format = tu6_plane_format(image->vk.format, i);
502 uint32_t width0 = vk_format_get_plane_width(image->vk.format, i, image->vk.extent.width);
503 uint32_t height0 = vk_format_get_plane_height(image->vk.format, i, image->vk.extent.height);
504
505 if (i == 1 && image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT)
506 /* no UBWC for separate stencil */
507 image->ubwc_enabled = false;
508
509 struct fdl_explicit_layout plane_layout;
510
511 if (plane_layouts) {
512 /* only expect simple 2D images for now */
513 if (image->vk.mip_levels != 1 ||
514 image->vk.array_layers != 1 ||
515 image->vk.extent.depth != 1)
516 return vk_error(device, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
517
518 plane_layout.offset = plane_layouts[i].offset;
519 plane_layout.pitch = plane_layouts[i].rowPitch;
520 /* note: use plane_layouts[0].arrayPitch to support array formats */
521 }
522
523 layout->tile_mode = tile_mode;
524 layout->ubwc = image->ubwc_enabled;
525
526 if (!fdl6_layout(layout, format,
527 image->vk.samples,
528 width0, height0,
529 image->vk.extent.depth,
530 image->vk.mip_levels,
531 image->vk.array_layers,
532 image->vk.image_type == VK_IMAGE_TYPE_3D,
533 plane_layouts ? &plane_layout : NULL)) {
534 assert(plane_layouts); /* can only fail with explicit layout */
535 return vk_error(device, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
536 }
537
538 if (TU_DEBUG(LAYOUT))
539 fdl_dump_layout(layout);
540
541 /* fdl6_layout can't take explicit offset without explicit pitch
542 * add offset manually for extra layouts for planes
543 */
544 if (!plane_layouts && i > 0) {
545 uint32_t offset = ALIGN_POT(image->total_size, 4096);
546 for (int i = 0; i < image->vk.mip_levels; i++) {
547 layout->slices[i].offset += offset;
548 layout->ubwc_slices[i].offset += offset;
549 }
550 layout->size += offset;
551 }
552
553 image->total_size = MAX2(image->total_size, layout->size);
554 }
555
556 const struct util_format_description *desc = util_format_description(image->layout[0].format);
557 if (util_format_has_depth(desc) && device->use_lrz) {
558 /* Depth plane is the first one */
559 struct fdl_layout *layout = &image->layout[0];
560 unsigned width = layout->width0;
561 unsigned height = layout->height0;
562
563 /* LRZ buffer is super-sampled */
564 switch (layout->nr_samples) {
565 case 4:
566 width *= 2;
567 FALLTHROUGH;
568 case 2:
569 height *= 2;
570 break;
571 default:
572 break;
573 }
574
575 unsigned lrz_pitch = align(DIV_ROUND_UP(width, 8), 32);
576 unsigned lrz_height = align(DIV_ROUND_UP(height, 8), 16);
577
578 image->lrz_height = lrz_height;
579 image->lrz_pitch = lrz_pitch;
580 image->lrz_offset = image->total_size;
581 unsigned lrz_size = lrz_pitch * lrz_height * sizeof(uint16_t);
582
583 unsigned nblocksx = DIV_ROUND_UP(DIV_ROUND_UP(width, 8), 16);
584 unsigned nblocksy = DIV_ROUND_UP(DIV_ROUND_UP(height, 8), 4);
585
586 /* Fast-clear buffer is 1bit/block */
587 unsigned lrz_fc_size = DIV_ROUND_UP(nblocksx * nblocksy, 8);
588
589 /* Fast-clear buffer cannot be larger than 512 bytes on A6XX and 1024 bytes on A7XX (HW limitation) */
590 image->has_lrz_fc =
591 device->physical_device->info->a6xx.enable_lrz_fast_clear &&
592 lrz_fc_size <= fd_lrzfc_layout<CHIP>::FC_SIZE &&
593 !TU_DEBUG(NOLRZFC);
594
595 if (image->has_lrz_fc || device->physical_device->info->a6xx.has_lrz_dir_tracking) {
596 image->lrz_fc_offset = image->total_size + lrz_size;
597 lrz_size += sizeof(fd_lrzfc_layout<CHIP>);
598 }
599
600 image->total_size += lrz_size;
601 } else {
602 image->lrz_height = 0;
603 }
604
605 return VK_SUCCESS;
606 }
607 TU_GENX(tu_image_update_layout);
608
609 static VkResult
tu_image_init(struct tu_device * device,struct tu_image * image,const VkImageCreateInfo * pCreateInfo)610 tu_image_init(struct tu_device *device, struct tu_image *image,
611 const VkImageCreateInfo *pCreateInfo)
612 {
613 image->ubwc_enabled = true;
614
615 /* use linear tiling if requested */
616 if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) {
617 image->force_linear_tile = true;
618 }
619
620 /* Force linear tiling for formats with "fake" optimalTilingFeatures */
621 if (!tiling_possible(image->vk.format)) {
622 image->force_linear_tile = true;
623 }
624
625 /* No sense in tiling a 1D image, you'd just waste space and cache locality. */
626 if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D) {
627 image->force_linear_tile = true;
628 }
629
630 /* Fragment density maps are sampled on the CPU and we don't support
631 * sampling tiled images on the CPU or UBWC at the moment.
632 */
633 if (pCreateInfo->usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT) {
634 image->force_linear_tile = true;
635 }
636
637 if (image->force_linear_tile ||
638 !ubwc_possible(device, image->vk.format, pCreateInfo->imageType,
639 pCreateInfo->usage, image->vk.stencil_usage,
640 device->physical_device->info, pCreateInfo->samples,
641 device->use_z24uint_s8uint))
642 image->ubwc_enabled = false;
643
644 bool fmt_list_has_swaps = false;
645 /* Mutable images can be reinterpreted as any other compatible format.
646 * This is a problem with UBWC (compression for different formats is different),
647 * but also tiling ("swap" affects how tiled formats are stored in memory)
648 * Depth and stencil formats cannot be reintepreted as another format, and
649 * cannot be linear with sysmem rendering, so don't fall back for those.
650 *
651 * TODO:
652 * - if the fmt_list contains only formats which are swapped, but compatible
653 * with each other (B8G8R8A8_UNORM and B8G8R8A8_UINT for example), then
654 * tiling is still possible
655 * - figure out which UBWC compressions are compatible to keep it enabled
656 */
657 if ((pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
658 !vk_format_is_depth_or_stencil(image->vk.format)) {
659 const VkImageFormatListCreateInfo *fmt_list =
660 vk_find_struct_const(pCreateInfo->pNext, IMAGE_FORMAT_LIST_CREATE_INFO);
661 fmt_list_has_swaps = format_list_has_swaps(fmt_list);
662 if (!tu6_mutable_format_list_ubwc_compatible(device->physical_device->info,
663 fmt_list)) {
664 bool mutable_ubwc_fc = device->physical_device->info->a7xx.ubwc_all_formats_compatible;
665 if (image->ubwc_enabled && !mutable_ubwc_fc) {
666 if (fmt_list && fmt_list->viewFormatCount == 2) {
667 perf_debug(
668 device,
669 "Disabling UBWC on %dx%d %s resource due to mutable formats "
670 "(fmt list %s, %s)",
671 image->vk.extent.width, image->vk.extent.height,
672 util_format_name(vk_format_to_pipe_format(image->vk.format)),
673 util_format_name(vk_format_to_pipe_format(fmt_list->pViewFormats[0])),
674 util_format_name(vk_format_to_pipe_format(fmt_list->pViewFormats[1])));
675 } else {
676 perf_debug(
677 device,
678 "Disabling UBWC on %dx%d %s resource due to mutable formats "
679 "(fmt list %s)",
680 image->vk.extent.width, image->vk.extent.height,
681 util_format_name(vk_format_to_pipe_format(image->vk.format)),
682 fmt_list ? "present" : "missing");
683 }
684 image->ubwc_enabled = false;
685 }
686
687 bool r8g8_r16 = format_list_reinterprets_r8g8_r16(vk_format_to_pipe_format(image->vk.format), fmt_list);
688
689 /* A750+ TODO: Correctly handle swaps when copying mutable images.
690 * We should be able to support UBWC for mutable images with swaps.
691 */
692 if ((r8g8_r16 && !mutable_ubwc_fc) || fmt_list_has_swaps) {
693 image->ubwc_enabled = false;
694 image->force_linear_tile = true;
695 }
696
697 image->ubwc_fc_mutable = image->ubwc_enabled && mutable_ubwc_fc;
698 }
699 }
700
701 if (TU_DEBUG(NOUBWC)) {
702 image->ubwc_enabled = false;
703 }
704
705 return VK_SUCCESS;
706 }
707
708 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * alloc,VkImage * pImage)709 tu_CreateImage(VkDevice _device,
710 const VkImageCreateInfo *pCreateInfo,
711 const VkAllocationCallbacks *alloc,
712 VkImage *pImage)
713 {
714 uint64_t modifier = DRM_FORMAT_MOD_INVALID;
715 const VkSubresourceLayout *plane_layouts = NULL;
716 VkResult result;
717
718 VK_FROM_HANDLE(tu_device, device, _device);
719
720 #ifdef TU_USE_WSI_PLATFORM
721 /* Ignore swapchain creation info on Android. Since we don't have an
722 * implementation in Mesa, we're guaranteed to access an Android object
723 * incorrectly.
724 */
725 const VkImageSwapchainCreateInfoKHR *swapchain_info =
726 vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
727 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
728 return wsi_common_create_swapchain_image(device->physical_device->vk.wsi_device,
729 pCreateInfo,
730 swapchain_info->swapchain,
731 pImage);
732 }
733 #endif
734
735 struct tu_image *image = (struct tu_image *)
736 vk_image_create(&device->vk, pCreateInfo, alloc, sizeof(*image));
737
738 if (!image)
739 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
740
741 if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
742 const VkImageDrmFormatModifierListCreateInfoEXT *mod_info =
743 vk_find_struct_const(pCreateInfo->pNext,
744 IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
745 const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_explicit_info =
746 vk_find_struct_const(pCreateInfo->pNext,
747 IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
748
749 assert(mod_info || drm_explicit_info);
750
751 if (mod_info) {
752 modifier = DRM_FORMAT_MOD_LINEAR;
753 for (unsigned i = 0; i < mod_info->drmFormatModifierCount; i++) {
754 if (mod_info->pDrmFormatModifiers[i] == DRM_FORMAT_MOD_QCOM_COMPRESSED)
755 modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
756 }
757 } else {
758 modifier = drm_explicit_info->drmFormatModifier;
759 assert(modifier == DRM_FORMAT_MOD_LINEAR ||
760 modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED);
761 plane_layouts = drm_explicit_info->pPlaneLayouts;
762 }
763 } else {
764 const struct wsi_image_create_info *wsi_info =
765 vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
766 if (wsi_info && wsi_info->scanout)
767 modifier = DRM_FORMAT_MOD_LINEAR;
768 }
769
770 /* This section is removed by the optimizer for non-ANDROID builds */
771 VkImageDrmFormatModifierExplicitCreateInfoEXT eci;
772 VkSubresourceLayout a_plane_layouts[TU_MAX_PLANE_COUNT];
773 if (vk_image_is_android_native_buffer(&image->vk)) {
774 result = vk_android_get_anb_layout(
775 pCreateInfo, &eci, a_plane_layouts, TU_MAX_PLANE_COUNT);
776 if (result != VK_SUCCESS)
777 goto fail;
778
779 plane_layouts = a_plane_layouts;
780 modifier = eci.drmFormatModifier;
781 }
782
783 result = tu_image_init(device, image, pCreateInfo);
784 if (result != VK_SUCCESS)
785 goto fail;
786
787 /* This section is removed by the optimizer for non-ANDROID builds */
788 if (vk_image_is_android_hardware_buffer(&image->vk)) {
789 /* At this time, an AHB handle is not yet provided.
790 * Image layout will be filled up during vkBindImageMemory2
791 */
792 *pImage = tu_image_to_handle(image);
793 return VK_SUCCESS;
794 }
795
796 result = TU_CALLX(device, tu_image_update_layout)(device, image, modifier,
797 plane_layouts);
798 if (result != VK_SUCCESS)
799 goto fail;
800
801 /* This section is removed by the optimizer for non-ANDROID builds */
802 if (vk_image_is_android_native_buffer(&image->vk)) {
803 result = vk_android_import_anb(&device->vk, pCreateInfo, alloc,
804 &image->vk);
805 if (result != VK_SUCCESS)
806 goto fail;
807 }
808
809 TU_RMV(image_create, device, image);
810
811 #ifdef HAVE_PERFETTO
812 tu_perfetto_log_create_image(device, image);
813 #endif
814
815 *pImage = tu_image_to_handle(image);
816
817 return VK_SUCCESS;
818 fail:
819 vk_image_destroy(&device->vk, alloc, &image->vk);
820 return result;
821 }
822
823 VKAPI_ATTR void VKAPI_CALL
tu_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)824 tu_DestroyImage(VkDevice _device,
825 VkImage _image,
826 const VkAllocationCallbacks *pAllocator)
827 {
828 VK_FROM_HANDLE(tu_device, device, _device);
829 VK_FROM_HANDLE(tu_image, image, _image);
830 struct tu_instance *instance = device->physical_device->instance;
831
832 if (!image)
833 return;
834
835 TU_RMV(image_destroy, device, image);
836
837 #ifdef HAVE_PERFETTO
838 tu_perfetto_log_destroy_image(device, image);
839 #endif
840
841 if (image->iova)
842 vk_address_binding_report(&instance->vk, &image->vk.base,
843 image->iova, image->total_size,
844 VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT);
845
846 vk_image_destroy(&device->vk, pAllocator, &image->vk);
847 }
848
849 VKAPI_ATTR VkResult VKAPI_CALL
tu_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)850 tu_BindImageMemory2(VkDevice _device,
851 uint32_t bindInfoCount,
852 const VkBindImageMemoryInfo *pBindInfos)
853 {
854 VK_FROM_HANDLE(tu_device, device, _device);
855 struct tu_instance *instance = device->physical_device->instance;
856
857 for (uint32_t i = 0; i < bindInfoCount; ++i) {
858 VK_FROM_HANDLE(tu_image, image, pBindInfos[i].image);
859 VK_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
860
861 /* Ignore this struct on Android, we cannot access swapchain structures there. */
862 #ifdef TU_USE_WSI_PLATFORM
863 const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
864 vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
865
866 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
867 VkImage _wsi_image = wsi_common_get_image(swapchain_info->swapchain,
868 swapchain_info->imageIndex);
869 VK_FROM_HANDLE(tu_image, wsi_img, _wsi_image);
870
871 image->bo = wsi_img->bo;
872 image->map = NULL;
873 image->iova = wsi_img->iova;
874
875 TU_RMV(image_bind, device, image);
876
877 vk_address_binding_report(&instance->vk, &image->vk.base,
878 image->iova, image->total_size,
879 VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
880
881 continue;
882 }
883 #endif
884
885 const VkBindMemoryStatusKHR *status =
886 vk_find_struct_const(pBindInfos[i].pNext, BIND_MEMORY_STATUS_KHR);
887 if (status)
888 *status->pResult = VK_SUCCESS;
889
890 if (mem) {
891 VkResult result;
892 if (vk_image_is_android_hardware_buffer(&image->vk)) {
893 VkImageDrmFormatModifierExplicitCreateInfoEXT eci;
894 VkSubresourceLayout a_plane_layouts[TU_MAX_PLANE_COUNT];
895 result = vk_android_get_ahb_layout(mem->vk.ahardware_buffer,
896 &eci, a_plane_layouts,
897 TU_MAX_PLANE_COUNT);
898 if (result != VK_SUCCESS) {
899 if (status)
900 *status->pResult = result;
901 return result;
902 }
903
904 result = TU_CALLX(device, tu_image_update_layout)(device, image,
905 eci.drmFormatModifier, a_plane_layouts);
906 if (result != VK_SUCCESS) {
907 if (status)
908 *status->pResult = result;
909 return result;
910 }
911 }
912 image->bo = mem->bo;
913 image->iova = mem->bo->iova + pBindInfos[i].memoryOffset;
914
915 if (image->vk.usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT) {
916 if (!mem->bo->map) {
917 result = tu_bo_map(device, mem->bo, NULL);
918 if (result != VK_SUCCESS) {
919 if (status)
920 *status->pResult = result;
921 return result;
922 }
923 }
924
925 image->map = (char *)mem->bo->map + pBindInfos[i].memoryOffset;
926 } else {
927 image->map = NULL;
928 }
929 #ifdef HAVE_PERFETTO
930 tu_perfetto_log_bind_image(device, image);
931 #endif
932 } else {
933 image->bo = NULL;
934 image->map = NULL;
935 image->iova = 0;
936 }
937
938 TU_RMV(image_bind, device, image);
939
940 vk_address_binding_report(&instance->vk, &image->vk.base,
941 image->iova, image->total_size,
942 VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
943 }
944
945 return VK_SUCCESS;
946 }
947
948 static void
tu_get_image_memory_requirements(struct tu_device * dev,struct tu_image * image,VkMemoryRequirements2 * pMemoryRequirements)949 tu_get_image_memory_requirements(struct tu_device *dev, struct tu_image *image,
950 VkMemoryRequirements2 *pMemoryRequirements)
951 {
952 pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
953 .size = image->total_size,
954 .alignment = image->layout[0].base_align,
955 .memoryTypeBits = (1 << dev->physical_device->memory.type_count) - 1,
956 };
957
958 vk_foreach_struct(ext, pMemoryRequirements->pNext) {
959 switch (ext->sType) {
960 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
961 VkMemoryDedicatedRequirements *req =
962 (VkMemoryDedicatedRequirements *) ext;
963 req->requiresDedicatedAllocation =
964 image->vk.external_handle_types != 0;
965 req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
966 break;
967 }
968 default:
969 break;
970 }
971 }
972 }
973
974 VKAPI_ATTR void VKAPI_CALL
tu_GetImageMemoryRequirements2(VkDevice _device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)975 tu_GetImageMemoryRequirements2(VkDevice _device,
976 const VkImageMemoryRequirementsInfo2 *pInfo,
977 VkMemoryRequirements2 *pMemoryRequirements)
978 {
979 VK_FROM_HANDLE(tu_device, device, _device);
980 VK_FROM_HANDLE(tu_image, image, pInfo->image);
981
982 tu_get_image_memory_requirements(device, image, pMemoryRequirements);
983 }
984
985 VKAPI_ATTR void VKAPI_CALL
tu_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)986 tu_GetImageSparseMemoryRequirements2(
987 VkDevice device,
988 const VkImageSparseMemoryRequirementsInfo2 *pInfo,
989 uint32_t *pSparseMemoryRequirementCount,
990 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
991 {
992 tu_stub();
993 }
994
995 VKAPI_ATTR void VKAPI_CALL
tu_GetDeviceImageMemoryRequirements(VkDevice _device,const VkDeviceImageMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)996 tu_GetDeviceImageMemoryRequirements(
997 VkDevice _device,
998 const VkDeviceImageMemoryRequirements *pInfo,
999 VkMemoryRequirements2 *pMemoryRequirements)
1000 {
1001 VK_FROM_HANDLE(tu_device, device, _device);
1002
1003 struct tu_image image = {0};
1004
1005 vk_image_init(&device->vk, &image.vk, pInfo->pCreateInfo);
1006 tu_image_init(device, &image, pInfo->pCreateInfo);
1007 TU_CALLX(device, tu_image_update_layout)(device, &image, DRM_FORMAT_MOD_INVALID, NULL);
1008
1009 tu_get_image_memory_requirements(device, &image, pMemoryRequirements);
1010 }
1011
1012 VKAPI_ATTR void VKAPI_CALL
tu_GetDeviceImageSparseMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1013 tu_GetDeviceImageSparseMemoryRequirements(
1014 VkDevice device,
1015 const VkDeviceImageMemoryRequirements *pInfo,
1016 uint32_t *pSparseMemoryRequirementCount,
1017 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1018 {
1019 tu_stub();
1020 }
1021
1022 static void
tu_get_image_subresource_layout(struct tu_image * image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)1023 tu_get_image_subresource_layout(struct tu_image *image,
1024 const VkImageSubresource2KHR *pSubresource,
1025 VkSubresourceLayout2KHR *pLayout)
1026 {
1027 struct fdl_layout *layout =
1028 &image->layout[tu6_plane_index(image->vk.format,
1029 pSubresource->imageSubresource.aspectMask)];
1030 const struct fdl_slice *slice = layout->slices +
1031 pSubresource->imageSubresource.mipLevel;
1032
1033 pLayout->subresourceLayout.offset =
1034 fdl_surface_offset(layout, pSubresource->imageSubresource.mipLevel,
1035 pSubresource->imageSubresource.arrayLayer);
1036 pLayout->subresourceLayout.rowPitch =
1037 fdl_pitch(layout, pSubresource->imageSubresource.mipLevel);
1038 pLayout->subresourceLayout.arrayPitch =
1039 fdl_layer_stride(layout, pSubresource->imageSubresource.mipLevel);
1040 pLayout->subresourceLayout.depthPitch = slice->size0;
1041 pLayout->subresourceLayout.size = slice->size0 * layout->depth0;
1042
1043 if (fdl_ubwc_enabled(layout, pSubresource->imageSubresource.mipLevel)) {
1044 /* UBWC starts at offset 0 */
1045 pLayout->subresourceLayout.offset = 0;
1046 /* UBWC scanout won't match what the kernel wants if we have levels/layers */
1047 assert(image->vk.mip_levels == 1 && image->vk.array_layers == 1);
1048 }
1049 }
1050
1051 VKAPI_ATTR void VKAPI_CALL
tu_GetImageSubresourceLayout2KHR(VkDevice _device,VkImage _image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)1052 tu_GetImageSubresourceLayout2KHR(VkDevice _device,
1053 VkImage _image,
1054 const VkImageSubresource2KHR *pSubresource,
1055 VkSubresourceLayout2KHR *pLayout)
1056 {
1057 VK_FROM_HANDLE(tu_image, image, _image);
1058
1059 tu_get_image_subresource_layout(image, pSubresource, pLayout);
1060 }
1061
1062 VKAPI_ATTR void VKAPI_CALL
tu_GetDeviceImageSubresourceLayoutKHR(VkDevice _device,const VkDeviceImageSubresourceInfoKHR * pInfo,VkSubresourceLayout2KHR * pLayout)1063 tu_GetDeviceImageSubresourceLayoutKHR(VkDevice _device,
1064 const VkDeviceImageSubresourceInfoKHR *pInfo,
1065 VkSubresourceLayout2KHR *pLayout)
1066 {
1067 VK_FROM_HANDLE(tu_device, device, _device);
1068
1069 struct tu_image image = {0};
1070
1071 vk_image_init(&device->vk, &image.vk, pInfo->pCreateInfo);
1072 tu_image_init(device, &image, pInfo->pCreateInfo);
1073 TU_CALLX(device, tu_image_update_layout)(device, &image, DRM_FORMAT_MOD_INVALID, NULL);
1074
1075 tu_get_image_subresource_layout(&image, pInfo->pSubresource, pLayout);
1076 }
1077
1078 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)1079 tu_CreateImageView(VkDevice _device,
1080 const VkImageViewCreateInfo *pCreateInfo,
1081 const VkAllocationCallbacks *pAllocator,
1082 VkImageView *pView)
1083 {
1084 VK_FROM_HANDLE(tu_device, device, _device);
1085 struct tu_image_view *view;
1086
1087 view = (struct tu_image_view *) vk_object_alloc(
1088 &device->vk, pAllocator, sizeof(*view), VK_OBJECT_TYPE_IMAGE_VIEW);
1089 if (view == NULL)
1090 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1091
1092 tu_image_view_init(device, view, pCreateInfo, device->use_z24uint_s8uint);
1093
1094 *pView = tu_image_view_to_handle(view);
1095
1096 return VK_SUCCESS;
1097 }
1098
1099 VKAPI_ATTR void VKAPI_CALL
tu_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)1100 tu_DestroyImageView(VkDevice _device,
1101 VkImageView _iview,
1102 const VkAllocationCallbacks *pAllocator)
1103 {
1104 VK_FROM_HANDLE(tu_device, device, _device);
1105 VK_FROM_HANDLE(tu_image_view, iview, _iview);
1106
1107 if (!iview)
1108 return;
1109
1110 vk_object_free(&device->vk, pAllocator, iview);
1111 }
1112
1113 /* Impelements the operations described in "Fragment Density Map Operations."
1114 */
1115 void
tu_fragment_density_map_sample(const struct tu_image_view * fdm,uint32_t x,uint32_t y,uint32_t width,uint32_t height,uint32_t layers,struct tu_frag_area * areas)1116 tu_fragment_density_map_sample(const struct tu_image_view *fdm,
1117 uint32_t x, uint32_t y,
1118 uint32_t width, uint32_t height,
1119 uint32_t layers,
1120 struct tu_frag_area *areas)
1121 {
1122 assert(fdm->image->layout[0].tile_mode == TILE6_LINEAR);
1123
1124 uint32_t fdm_shift_x = util_logbase2_ceil(DIV_ROUND_UP(width, fdm->vk.extent.width));
1125 uint32_t fdm_shift_y = util_logbase2_ceil(DIV_ROUND_UP(height, fdm->vk.extent.height));
1126
1127 fdm_shift_x = CLAMP(fdm_shift_x, MIN_FDM_TEXEL_SIZE_LOG2, MAX_FDM_TEXEL_SIZE_LOG2);
1128 fdm_shift_y = CLAMP(fdm_shift_y, MIN_FDM_TEXEL_SIZE_LOG2, MAX_FDM_TEXEL_SIZE_LOG2);
1129
1130 uint32_t i = x >> fdm_shift_x;
1131 uint32_t j = y >> fdm_shift_y;
1132
1133 unsigned cpp = fdm->image->layout[0].cpp;
1134 unsigned pitch = fdm->view.pitch;
1135
1136 void *pixel = (char *)fdm->image->map + fdm->view.offset + cpp * i + pitch * j;
1137 for (unsigned i = 0; i < layers; i++) {
1138 float density_src[4], density[4];
1139 util_format_unpack_rgba(fdm->view.format, density_src, pixel, 1);
1140 pipe_swizzle_4f(density, density_src, fdm->swizzle);
1141 areas[i].width = 1.0f / density[0];
1142 areas[i].height = 1.0f / density[1];
1143
1144 pixel = (char *)pixel + fdm->view.layer_size;
1145 }
1146 }
1147