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