• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       /* Depth plane is the first one */
577       struct fdl_layout *layout = &image->layout[0];
578       unsigned width = layout->width0;
579       unsigned height = layout->height0;
580 
581       /* LRZ buffer is super-sampled */
582       switch (layout->nr_samples) {
583       case 4:
584          width *= 2;
585          FALLTHROUGH;
586       case 2:
587          height *= 2;
588          break;
589       default:
590          break;
591       }
592 
593       unsigned lrz_pitch  = align(DIV_ROUND_UP(width, 8), 32);
594       unsigned lrz_height = align(DIV_ROUND_UP(height, 8), 32);
595 
596       image->lrz_height = lrz_height;
597       image->lrz_pitch = lrz_pitch;
598       image->lrz_offset = image->total_size;
599       unsigned lrz_size = lrz_pitch * lrz_height * sizeof(uint16_t);
600 
601       unsigned nblocksx = DIV_ROUND_UP(DIV_ROUND_UP(width, 8), 16);
602       unsigned nblocksy = DIV_ROUND_UP(DIV_ROUND_UP(height, 8), 4);
603 
604       /* Fast-clear buffer is 1bit/block */
605       unsigned lrz_fc_size = DIV_ROUND_UP(nblocksx * nblocksy, 8);
606 
607       /* Fast-clear buffer cannot be larger than 512 bytes on A6XX and 1024 bytes on A7XX (HW limitation) */
608       image->has_lrz_fc =
609          device->physical_device->info->a6xx.enable_lrz_fast_clear &&
610          lrz_fc_size <= fd_lrzfc_layout<CHIP>::FC_SIZE &&
611          !TU_DEBUG(NOLRZFC);
612 
613       if (image->has_lrz_fc || device->physical_device->info->a6xx.has_lrz_dir_tracking) {
614          image->lrz_fc_offset = image->total_size + lrz_size;
615          lrz_size += sizeof(fd_lrzfc_layout<CHIP>);
616       }
617 
618       image->total_size += lrz_size;
619    } else {
620       image->lrz_height = 0;
621    }
622 
623    return VK_SUCCESS;
624 }
625 TU_GENX(tu_image_update_layout);
626 
627 /* Return true if all formats in the format list can support UBWC.
628  */
629 static bool
format_list_ubwc_possible(struct tu_device * dev,const VkImageFormatListCreateInfo * fmt_list,const VkImageCreateInfo * create_info)630 format_list_ubwc_possible(struct tu_device *dev,
631                           const VkImageFormatListCreateInfo *fmt_list,
632                           const VkImageCreateInfo *create_info)
633 {
634    /* If there is no format list, we may have to assume that a
635     * UBWC-incompatible format may be used.
636     * TODO: limit based on compatiblity class
637     */
638    if (!fmt_list || !fmt_list->viewFormatCount)
639       return false;
640 
641    for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
642       if (!ubwc_possible(dev, fmt_list->pViewFormats[i],
643                          create_info->imageType, create_info->usage,
644                          create_info->usage, dev->physical_device->info,
645                          create_info->samples, create_info->mipLevels,
646                          dev->use_z24uint_s8uint))
647          return false;
648    }
649 
650    return true;
651 }
652 
653 static VkResult
tu_image_init(struct tu_device * device,struct tu_image * image,const VkImageCreateInfo * pCreateInfo)654 tu_image_init(struct tu_device *device, struct tu_image *image,
655               const VkImageCreateInfo *pCreateInfo)
656 {
657    image->ubwc_enabled = true;
658 
659    /* use linear tiling if requested */
660    if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) {
661       image->force_linear_tile = true;
662    }
663 
664    /* Force linear tiling for formats with "fake" optimalTilingFeatures */
665    if (!tiling_possible(image->vk.format)) {
666       image->force_linear_tile = true;
667    }
668 
669    /* No sense in tiling a 1D image, you'd just waste space and cache locality. */
670    if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D) {
671       image->force_linear_tile = true;
672    }
673 
674    /* Fragment density maps are sampled on the CPU and we don't support
675     * sampling tiled images on the CPU or UBWC at the moment.
676     */
677    if (pCreateInfo->usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT) {
678       image->force_linear_tile = true;
679    }
680 
681    /* Force linear tiling for HIC usage with swapped formats. Because tiled
682     * images are stored without the swap, we would have to apply the swap when
683     * copying on the CPU, which for some formats is tricky.
684     *
685     * TODO: should we add a fast path for BGRA8 and allow tiling for it?
686     */
687    if ((pCreateInfo->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) &&
688        fd6_color_swap(vk_format_to_pipe_format(image->vk.format),
689                                                TILE6_LINEAR, false) != WZYX)
690       image->force_linear_tile = true;
691 
692    /* Some kind of HW limitation. */
693    if (pCreateInfo->usage &
694           VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR &&
695        image->vk.extent.width < 16) {
696       image->force_linear_tile = true;
697    }
698 
699    if (image->force_linear_tile ||
700        !ubwc_possible(device, image->vk.format, pCreateInfo->imageType,
701                       pCreateInfo->usage, image->vk.stencil_usage,
702                       device->physical_device->info, pCreateInfo->samples,
703                       pCreateInfo->mipLevels, device->use_z24uint_s8uint))
704       image->ubwc_enabled = false;
705 
706    /* Mutable images can be reinterpreted as any other compatible format.
707     * This is a problem with UBWC (compression for different formats is different),
708     * but also tiling ("swap" affects how tiled formats are stored in memory)
709     * Depth and stencil formats cannot be reintepreted as another format, and
710     * cannot be linear with sysmem rendering, so don't fall back for those.
711     *
712     * TODO:
713     * - if the fmt_list contains only formats which are swapped, but compatible
714     *   with each other (B8G8R8A8_UNORM and B8G8R8A8_UINT for example), then
715     *   tiling is still possible
716     */
717    if ((pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
718        !vk_format_is_depth_or_stencil(image->vk.format)) {
719       const VkImageFormatListCreateInfo *fmt_list =
720          vk_find_struct_const(pCreateInfo->pNext, IMAGE_FORMAT_LIST_CREATE_INFO);
721       if (!tu6_mutable_format_list_ubwc_compatible(device->physical_device->info,
722                                                    fmt_list)) {
723          bool mutable_ubwc_fc = device->physical_device->info->a7xx.ubwc_all_formats_compatible;
724 
725          /* NV12 uses a special compression scheme for the Y channel which
726           * doesn't support reinterpretation. We have to fall back to linear
727           * always.
728           */
729          if (pCreateInfo->format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) {
730             if (image->ubwc_enabled) {
731                perf_debug(
732                   device,
733                   "Disabling UBWC and tiling on %dx%d %s resource due to mutable formats "
734                   "(fmt list %s)",
735                   image->vk.extent.width, image->vk.extent.height,
736                   util_format_name(vk_format_to_pipe_format(image->vk.format)),
737                   fmt_list ? "present" : "missing");
738             }
739             image->ubwc_enabled = false;
740             image->force_linear_tile = true;
741          } else if (!mutable_ubwc_fc) {
742             if (image->ubwc_enabled) {
743                if (fmt_list && fmt_list->viewFormatCount == 2) {
744                   perf_debug(
745                      device,
746                      "Disabling UBWC on %dx%d %s resource due to mutable formats "
747                      "(fmt list %s, %s)",
748                      image->vk.extent.width, image->vk.extent.height,
749                      util_format_name(vk_format_to_pipe_format(image->vk.format)),
750                      util_format_name(vk_format_to_pipe_format(fmt_list->pViewFormats[0])),
751                      util_format_name(vk_format_to_pipe_format(fmt_list->pViewFormats[1])));
752                } else {
753                   perf_debug(
754                      device,
755                      "Disabling UBWC on %dx%d %s resource due to mutable formats "
756                      "(fmt list %s)",
757                      image->vk.extent.width, image->vk.extent.height,
758                      util_format_name(vk_format_to_pipe_format(image->vk.format)),
759                      fmt_list ? "present" : "missing");
760                }
761                image->ubwc_enabled = false;
762             }
763 
764             bool r8g8_r16 = format_list_reinterprets_r8g8_r16(vk_format_to_pipe_format(image->vk.format), fmt_list);
765             bool fmt_list_has_swaps = format_list_has_swaps(fmt_list);
766 
767             if (r8g8_r16 || fmt_list_has_swaps) {
768                image->ubwc_enabled = false;
769                image->force_linear_tile = true;
770             }
771          } else {
772             image->is_mutable = true;
773             if (!format_list_ubwc_possible(device, fmt_list, pCreateInfo))
774                image->ubwc_enabled = false;
775          }
776       }
777    }
778 
779    if (TU_DEBUG(NOUBWC)) {
780       image->ubwc_enabled = false;
781    }
782 
783    return VK_SUCCESS;
784 }
785 
786 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * alloc,VkImage * pImage)787 tu_CreateImage(VkDevice _device,
788                const VkImageCreateInfo *pCreateInfo,
789                const VkAllocationCallbacks *alloc,
790                VkImage *pImage)
791 {
792    uint64_t modifier = DRM_FORMAT_MOD_INVALID;
793    const VkSubresourceLayout *plane_layouts = NULL;
794    VkResult result;
795 
796    VK_FROM_HANDLE(tu_device, device, _device);
797 
798 #ifdef TU_USE_WSI_PLATFORM
799    /* Ignore swapchain creation info on Android. Since we don't have an
800     * implementation in Mesa, we're guaranteed to access an Android object
801     * incorrectly.
802     */
803    const VkImageSwapchainCreateInfoKHR *swapchain_info =
804       vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
805    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
806       return wsi_common_create_swapchain_image(device->physical_device->vk.wsi_device,
807                                                pCreateInfo,
808                                                swapchain_info->swapchain,
809                                                pImage);
810    }
811 #endif
812 
813    struct tu_image *image = (struct tu_image *)
814       vk_image_create(&device->vk, pCreateInfo, alloc, sizeof(*image));
815 
816    if (!image)
817       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
818 
819    if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
820       const VkImageDrmFormatModifierListCreateInfoEXT *mod_info =
821          vk_find_struct_const(pCreateInfo->pNext,
822                               IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
823       const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_explicit_info =
824          vk_find_struct_const(pCreateInfo->pNext,
825                               IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
826 
827       assert(mod_info || drm_explicit_info);
828 
829       if (mod_info) {
830          modifier = DRM_FORMAT_MOD_LINEAR;
831          for (unsigned i = 0; i < mod_info->drmFormatModifierCount; i++) {
832             if (mod_info->pDrmFormatModifiers[i] == DRM_FORMAT_MOD_QCOM_COMPRESSED)
833                modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
834          }
835       } else {
836          modifier = drm_explicit_info->drmFormatModifier;
837          assert(modifier == DRM_FORMAT_MOD_LINEAR ||
838                 modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED);
839          plane_layouts = drm_explicit_info->pPlaneLayouts;
840       }
841    } else {
842       const struct wsi_image_create_info *wsi_info =
843          vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
844       if (wsi_info && wsi_info->scanout)
845          modifier = DRM_FORMAT_MOD_LINEAR;
846    }
847 
848    /* This section is removed by the optimizer for non-ANDROID builds */
849    VkImageDrmFormatModifierExplicitCreateInfoEXT eci;
850    VkSubresourceLayout a_plane_layouts[TU_MAX_PLANE_COUNT];
851    if (vk_image_is_android_native_buffer(&image->vk)) {
852       result = vk_android_get_anb_layout(
853          pCreateInfo, &eci, a_plane_layouts, TU_MAX_PLANE_COUNT);
854       if (result != VK_SUCCESS)
855          goto fail;
856 
857       plane_layouts = a_plane_layouts;
858       modifier = eci.drmFormatModifier;
859    }
860 
861    result = tu_image_init(device, image, pCreateInfo);
862    if (result != VK_SUCCESS)
863       goto fail;
864 
865    /* This section is removed by the optimizer for non-ANDROID builds */
866    if (vk_image_is_android_hardware_buffer(&image->vk)) {
867       /* At this time, an AHB handle is not yet provided.
868        * Image layout will be filled up during vkBindImageMemory2
869        */
870       *pImage = tu_image_to_handle(image);
871       return VK_SUCCESS;
872    }
873 
874    result = TU_CALLX(device, tu_image_update_layout)(device, image, modifier,
875                                                     plane_layouts);
876    if (result != VK_SUCCESS)
877       goto fail;
878 
879    /* This section is removed by the optimizer for non-ANDROID builds */
880    if (vk_image_is_android_native_buffer(&image->vk)) {
881       result = vk_android_import_anb(&device->vk, pCreateInfo, alloc,
882                                      &image->vk);
883       if (result != VK_SUCCESS)
884          goto fail;
885    }
886 
887    TU_RMV(image_create, device, image);
888 
889 #ifdef HAVE_PERFETTO
890    tu_perfetto_log_create_image(device, image);
891 #endif
892 
893    *pImage = tu_image_to_handle(image);
894 
895    return VK_SUCCESS;
896 fail:
897    vk_image_destroy(&device->vk, alloc, &image->vk);
898    return result;
899 }
900 
901 VKAPI_ATTR void VKAPI_CALL
tu_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)902 tu_DestroyImage(VkDevice _device,
903                 VkImage _image,
904                 const VkAllocationCallbacks *pAllocator)
905 {
906    VK_FROM_HANDLE(tu_device, device, _device);
907    VK_FROM_HANDLE(tu_image, image, _image);
908    struct tu_instance *instance = device->physical_device->instance;
909 
910    if (!image)
911       return;
912 
913    TU_RMV(image_destroy, device, image);
914 
915 #ifdef HAVE_PERFETTO
916    tu_perfetto_log_destroy_image(device, image);
917 #endif
918 
919    if (image->iova)
920       vk_address_binding_report(&instance->vk, &image->vk.base,
921                                 image->iova, image->total_size,
922                                 VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT);
923 
924    vk_image_destroy(&device->vk, pAllocator, &image->vk);
925 }
926 
927 VKAPI_ATTR VkResult VKAPI_CALL
tu_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)928 tu_BindImageMemory2(VkDevice _device,
929                     uint32_t bindInfoCount,
930                     const VkBindImageMemoryInfo *pBindInfos)
931 {
932    VK_FROM_HANDLE(tu_device, device, _device);
933    struct tu_instance *instance = device->physical_device->instance;
934 
935    for (uint32_t i = 0; i < bindInfoCount; ++i) {
936       VK_FROM_HANDLE(tu_image, image, pBindInfos[i].image);
937       VK_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
938 
939       /* Ignore this struct on Android, we cannot access swapchain structures there. */
940 #ifdef TU_USE_WSI_PLATFORM
941       const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
942          vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
943 
944       if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
945          VkImage _wsi_image = wsi_common_get_image(swapchain_info->swapchain,
946                                                    swapchain_info->imageIndex);
947          VK_FROM_HANDLE(tu_image, wsi_img, _wsi_image);
948 
949          image->bo = wsi_img->bo;
950          image->map = NULL;
951          image->iova = wsi_img->iova;
952 
953          TU_RMV(image_bind, device, image);
954 
955          vk_address_binding_report(&instance->vk, &image->vk.base,
956                                    image->iova, image->total_size,
957                                    VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
958 
959          continue;
960       }
961 #endif
962 
963       const VkBindMemoryStatusKHR *status =
964          vk_find_struct_const(pBindInfos[i].pNext, BIND_MEMORY_STATUS_KHR);
965       if (status)
966          *status->pResult = VK_SUCCESS;
967 
968       if (mem) {
969          VkResult result;
970          if (vk_image_is_android_hardware_buffer(&image->vk)) {
971             VkImageDrmFormatModifierExplicitCreateInfoEXT eci;
972             VkSubresourceLayout a_plane_layouts[TU_MAX_PLANE_COUNT];
973             result = vk_android_get_ahb_layout(mem->vk.ahardware_buffer,
974                                             &eci, a_plane_layouts,
975                                             TU_MAX_PLANE_COUNT);
976             if (result != VK_SUCCESS) {
977                if (status)
978                   *status->pResult = result;
979                return result;
980             }
981 
982             result = TU_CALLX(device, tu_image_update_layout)(device, image,
983                                                               eci.drmFormatModifier, a_plane_layouts);
984             if (result != VK_SUCCESS) {
985                if (status)
986                   *status->pResult = result;
987                return result;
988             }
989          }
990          image->bo = mem->bo;
991          image->bo_offset = pBindInfos[i].memoryOffset;
992          image->iova = mem->bo->iova + pBindInfos[i].memoryOffset;
993 
994          if (image->vk.usage & (VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT |
995                                 VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT)) {
996             if (!mem->bo->map) {
997                result = tu_bo_map(device, mem->bo, NULL);
998                if (result != VK_SUCCESS) {
999                   if (status)
1000                      *status->pResult = result;
1001                   return result;
1002                }
1003             }
1004 
1005             image->map = (char *)mem->bo->map + pBindInfos[i].memoryOffset;
1006          } else {
1007             image->map = NULL;
1008          }
1009 #ifdef HAVE_PERFETTO
1010          tu_perfetto_log_bind_image(device, image);
1011 #endif
1012       } else {
1013          image->bo = NULL;
1014          image->map = NULL;
1015          image->iova = 0;
1016       }
1017 
1018       TU_RMV(image_bind, device, image);
1019 
1020       vk_address_binding_report(&instance->vk, &image->vk.base,
1021                                 image->iova, image->total_size,
1022                                 VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
1023    }
1024 
1025    return VK_SUCCESS;
1026 }
1027 
1028 static void
tu_get_image_memory_requirements(struct tu_device * dev,struct tu_image * image,VkMemoryRequirements2 * pMemoryRequirements)1029 tu_get_image_memory_requirements(struct tu_device *dev, struct tu_image *image,
1030                                  VkMemoryRequirements2 *pMemoryRequirements)
1031 {
1032    pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
1033       .size = image->total_size,
1034       .alignment = image->layout[0].base_align,
1035       .memoryTypeBits = (1 << dev->physical_device->memory.type_count) - 1,
1036    };
1037 
1038    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
1039       switch (ext->sType) {
1040       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1041          VkMemoryDedicatedRequirements *req =
1042             (VkMemoryDedicatedRequirements *) ext;
1043          req->requiresDedicatedAllocation =
1044             image->vk.external_handle_types != 0;
1045          req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
1046          break;
1047       }
1048       default:
1049          break;
1050       }
1051    }
1052 }
1053 
1054 VKAPI_ATTR void VKAPI_CALL
tu_GetImageMemoryRequirements2(VkDevice _device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1055 tu_GetImageMemoryRequirements2(VkDevice _device,
1056                                const VkImageMemoryRequirementsInfo2 *pInfo,
1057                                VkMemoryRequirements2 *pMemoryRequirements)
1058 {
1059    VK_FROM_HANDLE(tu_device, device, _device);
1060    VK_FROM_HANDLE(tu_image, image, pInfo->image);
1061 
1062    tu_get_image_memory_requirements(device, image, pMemoryRequirements);
1063 }
1064 
1065 VKAPI_ATTR void VKAPI_CALL
tu_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1066 tu_GetImageSparseMemoryRequirements2(
1067    VkDevice device,
1068    const VkImageSparseMemoryRequirementsInfo2 *pInfo,
1069    uint32_t *pSparseMemoryRequirementCount,
1070    VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1071 {
1072    tu_stub();
1073 }
1074 
1075 VKAPI_ATTR void VKAPI_CALL
tu_GetDeviceImageMemoryRequirements(VkDevice _device,const VkDeviceImageMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1076 tu_GetDeviceImageMemoryRequirements(
1077    VkDevice _device,
1078    const VkDeviceImageMemoryRequirements *pInfo,
1079    VkMemoryRequirements2 *pMemoryRequirements)
1080 {
1081    VK_FROM_HANDLE(tu_device, device, _device);
1082 
1083    struct tu_image image = {0};
1084 
1085    vk_image_init(&device->vk, &image.vk, pInfo->pCreateInfo);
1086    tu_image_init(device, &image, pInfo->pCreateInfo);
1087    TU_CALLX(device, tu_image_update_layout)(device, &image, DRM_FORMAT_MOD_INVALID, NULL);
1088 
1089    tu_get_image_memory_requirements(device, &image, pMemoryRequirements);
1090 }
1091 
1092 VKAPI_ATTR void VKAPI_CALL
tu_GetDeviceImageSparseMemoryRequirements(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1093 tu_GetDeviceImageSparseMemoryRequirements(
1094     VkDevice device,
1095     const VkDeviceImageMemoryRequirements *pInfo,
1096     uint32_t *pSparseMemoryRequirementCount,
1097     VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1098 {
1099    tu_stub();
1100 }
1101 
1102 static void
tu_get_image_subresource_layout(struct tu_image * image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)1103 tu_get_image_subresource_layout(struct tu_image *image,
1104                                 const VkImageSubresource2KHR *pSubresource,
1105                                 VkSubresourceLayout2KHR *pLayout)
1106 {
1107    struct fdl_layout *layout =
1108       &image->layout[tu6_plane_index(image->vk.format,
1109                                      pSubresource->imageSubresource.aspectMask)];
1110    const struct fdl_slice *slice = layout->slices +
1111       pSubresource->imageSubresource.mipLevel;
1112 
1113    pLayout->subresourceLayout.offset =
1114       fdl_surface_offset(layout, pSubresource->imageSubresource.mipLevel,
1115                          pSubresource->imageSubresource.arrayLayer);
1116    pLayout->subresourceLayout.rowPitch =
1117       fdl_pitch(layout, pSubresource->imageSubresource.mipLevel);
1118    pLayout->subresourceLayout.arrayPitch =
1119       fdl_layer_stride(layout, pSubresource->imageSubresource.mipLevel);
1120    pLayout->subresourceLayout.depthPitch = slice->size0;
1121    pLayout->subresourceLayout.size = slice->size0 * layout->depth0;
1122 
1123    VkSubresourceHostMemcpySizeEXT *memcpy_size =
1124       vk_find_struct(pLayout, SUBRESOURCE_HOST_MEMCPY_SIZE_EXT);
1125    if (memcpy_size) {
1126       memcpy_size->size = slice->size0;
1127    }
1128 
1129    if (fdl_ubwc_enabled(layout, pSubresource->imageSubresource.mipLevel)) {
1130       /* UBWC starts at offset 0 */
1131       pLayout->subresourceLayout.offset = 0;
1132       /* UBWC scanout won't match what the kernel wants if we have levels/layers */
1133       assert(image->vk.mip_levels == 1 && image->vk.array_layers == 1);
1134    }
1135 }
1136 
1137 VKAPI_ATTR void VKAPI_CALL
tu_GetImageSubresourceLayout2KHR(VkDevice _device,VkImage _image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)1138 tu_GetImageSubresourceLayout2KHR(VkDevice _device,
1139                                  VkImage _image,
1140                                  const VkImageSubresource2KHR *pSubresource,
1141                                  VkSubresourceLayout2KHR *pLayout)
1142 {
1143    VK_FROM_HANDLE(tu_image, image, _image);
1144 
1145    tu_get_image_subresource_layout(image, pSubresource, pLayout);
1146 }
1147 
1148 VKAPI_ATTR void VKAPI_CALL
tu_GetDeviceImageSubresourceLayoutKHR(VkDevice _device,const VkDeviceImageSubresourceInfoKHR * pInfo,VkSubresourceLayout2KHR * pLayout)1149 tu_GetDeviceImageSubresourceLayoutKHR(VkDevice _device,
1150                                       const VkDeviceImageSubresourceInfoKHR *pInfo,
1151                                       VkSubresourceLayout2KHR *pLayout)
1152 {
1153    VK_FROM_HANDLE(tu_device, device, _device);
1154 
1155    struct tu_image image = {0};
1156 
1157    vk_image_init(&device->vk, &image.vk, pInfo->pCreateInfo);
1158    tu_image_init(device, &image, pInfo->pCreateInfo);
1159    TU_CALLX(device, tu_image_update_layout)(device, &image, DRM_FORMAT_MOD_INVALID, NULL);
1160 
1161    tu_get_image_subresource_layout(&image, pInfo->pSubresource, pLayout);
1162 }
1163 
1164 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)1165 tu_CreateImageView(VkDevice _device,
1166                    const VkImageViewCreateInfo *pCreateInfo,
1167                    const VkAllocationCallbacks *pAllocator,
1168                    VkImageView *pView)
1169 {
1170    VK_FROM_HANDLE(tu_device, device, _device);
1171    struct tu_image_view *view;
1172 
1173    view = (struct tu_image_view *) vk_object_alloc(
1174       &device->vk, pAllocator, sizeof(*view), VK_OBJECT_TYPE_IMAGE_VIEW);
1175    if (view == NULL)
1176       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1177 
1178    tu_image_view_init(device, view, pCreateInfo, device->use_z24uint_s8uint);
1179 
1180    *pView = tu_image_view_to_handle(view);
1181 
1182    return VK_SUCCESS;
1183 }
1184 
1185 VKAPI_ATTR void VKAPI_CALL
tu_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)1186 tu_DestroyImageView(VkDevice _device,
1187                     VkImageView _iview,
1188                     const VkAllocationCallbacks *pAllocator)
1189 {
1190    VK_FROM_HANDLE(tu_device, device, _device);
1191    VK_FROM_HANDLE(tu_image_view, iview, _iview);
1192 
1193    if (!iview)
1194       return;
1195 
1196    vk_object_free(&device->vk, pAllocator, iview);
1197 }
1198 
1199 /* Impelements the operations described in "Fragment Density Map Operations."
1200  */
1201 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)1202 tu_fragment_density_map_sample(const struct tu_image_view *fdm,
1203                                uint32_t x, uint32_t y,
1204                                uint32_t width, uint32_t height,
1205                                uint32_t layers,
1206                                struct tu_frag_area *areas)
1207 {
1208    assert(fdm->image->layout[0].tile_mode == TILE6_LINEAR);
1209 
1210    uint32_t fdm_shift_x = util_logbase2_ceil(DIV_ROUND_UP(width, fdm->vk.extent.width));
1211    uint32_t fdm_shift_y = util_logbase2_ceil(DIV_ROUND_UP(height, fdm->vk.extent.height));
1212 
1213    fdm_shift_x = CLAMP(fdm_shift_x, MIN_FDM_TEXEL_SIZE_LOG2, MAX_FDM_TEXEL_SIZE_LOG2);
1214    fdm_shift_y = CLAMP(fdm_shift_y, MIN_FDM_TEXEL_SIZE_LOG2, MAX_FDM_TEXEL_SIZE_LOG2);
1215 
1216    uint32_t i = x >> fdm_shift_x;
1217    uint32_t j = y >> fdm_shift_y;
1218 
1219    unsigned cpp = fdm->image->layout[0].cpp;
1220    unsigned pitch = fdm->view.pitch;
1221 
1222    void *pixel = (char *)fdm->image->map + fdm->view.offset + cpp * i + pitch * j;
1223    for (unsigned i = 0; i < layers; i++) {
1224       float density_src[4], density[4];
1225       util_format_unpack_rgba(fdm->view.format, density_src, pixel, 1);
1226       pipe_swizzle_4f(density, density_src, fdm->swizzle);
1227       areas[i].width = 1.0f / density[0];
1228       areas[i].height = 1.0f / density[1];
1229 
1230       pixel = (char *)pixel + fdm->view.layer_size;
1231    }
1232 }
1233