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