xref: /aosp_15_r20/external/mesa3d/src/intel/vulkan/anv_image.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2015 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/mman.h>
30 #include "drm-uapi/drm_fourcc.h"
31 
32 #include "anv_private.h"
33 #include "common/intel_aux_map.h"
34 #include "util/u_debug.h"
35 #include "vk_util.h"
36 #include "util/u_math.h"
37 
38 #include "vk_format.h"
39 
40 #define ANV_OFFSET_IMPLICIT UINT64_MAX
41 
42 static const enum isl_surf_dim
43 vk_to_isl_surf_dim[] = {
44    [VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D,
45    [VK_IMAGE_TYPE_2D] = ISL_SURF_DIM_2D,
46    [VK_IMAGE_TYPE_3D] = ISL_SURF_DIM_3D,
47 };
48 
49 static uint64_t MUST_CHECK UNUSED
memory_range_end(struct anv_image_memory_range memory_range)50 memory_range_end(struct anv_image_memory_range memory_range)
51 {
52    assert(anv_is_aligned(memory_range.offset, memory_range.alignment));
53    return memory_range.offset + memory_range.size;
54 }
55 
56 /**
57  * Get binding for VkImagePlaneMemoryRequirementsInfo,
58  * VkBindImagePlaneMemoryInfo and VkDeviceImageMemoryRequirements.
59  */
60 struct anv_image_binding *
anv_image_aspect_to_binding(struct anv_image * image,VkImageAspectFlags aspect)61 anv_image_aspect_to_binding(struct anv_image *image,
62                             VkImageAspectFlags aspect)
63 {
64    uint32_t plane = 0;
65 
66    assert(image->disjoint);
67 
68    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
69       /* Spec requires special aspects for modifier images. */
70       assert(aspect == VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT ||
71              aspect == VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT ||
72              aspect == VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT ||
73              aspect == VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT);
74 
75       /* We don't advertise DISJOINT for modifiers with aux, and therefore we
76        * don't handle queries of the modifier's "aux plane" here.
77        */
78       assert(!isl_drm_modifier_has_aux(image->vk.drm_format_mod));
79 
80       switch(aspect) {
81          case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT: plane = 0; break;
82          case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT: plane = 1; break;
83          case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT: plane = 2; break;
84          case VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT: plane = 3; break;
85       }
86    } else {
87       plane = anv_image_aspect_to_plane(image, aspect);
88    }
89 
90    return &image->bindings[ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane];
91 }
92 
93 /**
94  * Extend the memory binding's range by appending a new memory range with `size`
95  * and `alignment` at `offset`. Return the appended range.
96  *
97  * Offset is ignored if ANV_OFFSET_IMPLICIT.
98  *
99  * The given binding must not be ANV_IMAGE_MEMORY_BINDING_MAIN. The function
100  * converts to MAIN as needed.
101  */
102 static VkResult MUST_CHECK
image_binding_grow(const struct anv_device * device,struct anv_image * image,enum anv_image_memory_binding binding,uint64_t offset,uint64_t size,uint32_t alignment,struct anv_image_memory_range * out_range)103 image_binding_grow(const struct anv_device *device,
104                    struct anv_image *image,
105                    enum anv_image_memory_binding binding,
106                    uint64_t offset,
107                    uint64_t size,
108                    uint32_t alignment,
109                    struct anv_image_memory_range *out_range)
110 {
111    /* We overwrite 'offset' but need to remember if it was implicit. */
112    const bool has_implicit_offset = (offset == ANV_OFFSET_IMPLICIT);
113 
114    assert(size > 0);
115    assert(util_is_power_of_two_or_zero(alignment));
116 
117    switch (binding) {
118    case ANV_IMAGE_MEMORY_BINDING_MAIN:
119       /* The caller must not pre-translate BINDING_PLANE_i to BINDING_MAIN. */
120       unreachable("ANV_IMAGE_MEMORY_BINDING_MAIN");
121    case ANV_IMAGE_MEMORY_BINDING_PLANE_0:
122    case ANV_IMAGE_MEMORY_BINDING_PLANE_1:
123    case ANV_IMAGE_MEMORY_BINDING_PLANE_2:
124       if (!image->disjoint)
125          binding = ANV_IMAGE_MEMORY_BINDING_MAIN;
126       break;
127    case ANV_IMAGE_MEMORY_BINDING_PRIVATE:
128       assert(offset == ANV_OFFSET_IMPLICIT);
129       break;
130    case ANV_IMAGE_MEMORY_BINDING_END:
131       unreachable("ANV_IMAGE_MEMORY_BINDING_END");
132    }
133 
134    struct anv_image_memory_range *container =
135       &image->bindings[binding].memory_range;
136 
137    if (has_implicit_offset) {
138       offset = align64(container->offset + container->size, alignment);
139    } else {
140       /* Offset must be validated because it comes from
141        * VkImageDrmFormatModifierExplicitCreateInfoEXT.
142        */
143       if (unlikely(!anv_is_aligned(offset, alignment))) {
144          return vk_errorf(device,
145                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
146                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
147                           "pPlaneLayouts[]::offset is misaligned");
148       }
149    }
150 
151    /* Surfaces can be added out of memory-order. Track the end of each memory
152     * plane to update the binding size properly.
153     */
154    uint64_t memory_range_end;
155    if (__builtin_add_overflow(offset, size, &memory_range_end)) {
156       if (has_implicit_offset) {
157          assert(!"overflow");
158          return vk_errorf(device, VK_ERROR_UNKNOWN,
159                           "internal error: overflow in %s", __func__);
160       } else {
161          return vk_errorf(device,
162                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
163                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
164                           "pPlaneLayouts[]::offset is too large");
165       }
166    }
167 
168    container->size = MAX2(container->size, memory_range_end);
169    container->alignment = MAX2(container->alignment, alignment);
170 
171    *out_range = (struct anv_image_memory_range) {
172       .binding = binding,
173       .alignment = alignment,
174       .size = size,
175       .offset = offset,
176    };
177 
178    return VK_SUCCESS;
179 }
180 
181 /**
182  * Adjust range 'a' to contain range 'b'.
183  *
184  * For simplicity's sake, the offset of 'a' must be 0 and remains 0.
185  * If 'a' and 'b' target different bindings, then no merge occurs.
186  */
187 static void
memory_range_merge(struct anv_image_memory_range * a,const struct anv_image_memory_range b)188 memory_range_merge(struct anv_image_memory_range *a,
189                    const struct anv_image_memory_range b)
190 {
191    if (b.size == 0)
192       return;
193 
194    if (a->binding != b.binding)
195       return;
196 
197    assert(a->offset == 0);
198    assert(anv_is_aligned(a->offset, a->alignment));
199    assert(anv_is_aligned(b.offset, b.alignment));
200 
201    a->alignment = MAX2(a->alignment, b.alignment);
202    a->size = MAX2(a->size, b.offset + b.size);
203 }
204 
205 isl_surf_usage_flags_t
anv_image_choose_isl_surf_usage(struct anv_physical_device * device,VkImageCreateFlags vk_create_flags,VkImageUsageFlags vk_usage,isl_surf_usage_flags_t isl_extra_usage,VkImageAspectFlagBits aspect,VkImageCompressionFlagsEXT comp_flags)206 anv_image_choose_isl_surf_usage(struct anv_physical_device *device,
207                                 VkImageCreateFlags vk_create_flags,
208                                 VkImageUsageFlags vk_usage,
209                                 isl_surf_usage_flags_t isl_extra_usage,
210                                 VkImageAspectFlagBits aspect,
211                                 VkImageCompressionFlagsEXT comp_flags)
212 {
213    isl_surf_usage_flags_t isl_usage = isl_extra_usage;
214 
215    /* On platform like MTL, we choose to allocate additional CCS memory at the
216     * back of the VkDeviceMemory objects since different images can share the
217     * AUX-TT PTE because the HW doesn't care about the image format in the
218     * PTE. That means we can always ignore the AUX-TT alignment requirement
219     * from an ISL point of view.
220     */
221    if (device->alloc_aux_tt_mem)
222       isl_usage |= ISL_SURF_USAGE_NO_AUX_TT_ALIGNMENT_BIT;
223 
224    if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
225       isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
226 
227    if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
228       isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
229 
230    if (vk_usage & VK_IMAGE_USAGE_STORAGE_BIT)
231       isl_usage |= ISL_SURF_USAGE_STORAGE_BIT;
232 
233    if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
234       isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
235 
236    if (vk_usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)
237       isl_usage |= ISL_SURF_USAGE_CPB_BIT;
238 
239    /* TODO: consider whether compression with sparse is workable. */
240    if (vk_create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)
241       isl_usage |= ISL_SURF_USAGE_SPARSE_BIT |
242                    ISL_SURF_USAGE_DISABLE_AUX_BIT;
243 
244    if (vk_usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR ||
245        vk_usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR ||
246        vk_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR ||
247        vk_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR)
248       isl_usage |= ISL_SURF_USAGE_VIDEO_DECODE_BIT;
249 
250    if (vk_create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
251       isl_usage |= ISL_SURF_USAGE_CUBE_BIT;
252 
253    if (vk_create_flags & (VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT |
254                           VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT))
255       isl_usage |= ISL_SURF_USAGE_2D_3D_COMPATIBLE_BIT;
256 
257    if (vk_create_flags & VK_IMAGE_CREATE_PROTECTED_BIT)
258       isl_usage |= ISL_SURF_USAGE_PROTECTED_BIT;
259 
260    /* Even if we're only using it for transfer operations, clears to depth and
261     * stencil images happen as depth and stencil so they need the right ISL
262     * usage bits or else things will fall apart.
263     */
264    switch (aspect) {
265    case VK_IMAGE_ASPECT_DEPTH_BIT:
266       isl_usage |= ISL_SURF_USAGE_DEPTH_BIT;
267       break;
268    case VK_IMAGE_ASPECT_STENCIL_BIT:
269       isl_usage |= ISL_SURF_USAGE_STENCIL_BIT;
270       break;
271    case VK_IMAGE_ASPECT_COLOR_BIT:
272    case VK_IMAGE_ASPECT_PLANE_0_BIT:
273    case VK_IMAGE_ASPECT_PLANE_1_BIT:
274    case VK_IMAGE_ASPECT_PLANE_2_BIT:
275       break;
276    default:
277       unreachable("bad VkImageAspect");
278    }
279 
280    if (vk_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
281       /* blorp implements transfers by sampling from the source image. */
282       isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
283    }
284 
285    if (vk_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT &&
286        aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
287       /* blorp implements transfers by rendering into the destination image.
288        * Only request this with color images, as we deal with depth/stencil
289        * formats differently. */
290       isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
291    }
292 
293    if (comp_flags & VK_IMAGE_COMPRESSION_DISABLED_EXT)
294       isl_usage |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
295 
296    return isl_usage;
297 }
298 
299 static isl_tiling_flags_t
choose_isl_tiling_flags(const struct intel_device_info * devinfo,const struct anv_image_create_info * anv_info,const struct isl_drm_modifier_info * isl_mod_info,bool legacy_scanout)300 choose_isl_tiling_flags(const struct intel_device_info *devinfo,
301                         const struct anv_image_create_info *anv_info,
302                         const struct isl_drm_modifier_info *isl_mod_info,
303                         bool legacy_scanout)
304 {
305    const VkImageCreateInfo *base_info = anv_info->vk_info;
306    isl_tiling_flags_t flags = 0;
307 
308    assert((isl_mod_info != NULL) ==
309           (base_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT));
310 
311    switch (base_info->tiling) {
312    default:
313       unreachable("bad VkImageTiling");
314    case VK_IMAGE_TILING_OPTIMAL:
315       flags = ISL_TILING_ANY_MASK;
316       break;
317    case VK_IMAGE_TILING_LINEAR:
318       flags = ISL_TILING_LINEAR_BIT;
319       break;
320    case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
321       flags = 1 << isl_mod_info->tiling;
322    }
323 
324    if (anv_info->isl_tiling_flags) {
325       assert(isl_mod_info == NULL);
326       flags &= anv_info->isl_tiling_flags;
327    }
328 
329    if (legacy_scanout) {
330       isl_tiling_flags_t legacy_mask = ISL_TILING_LINEAR_BIT;
331       if (devinfo->has_tiling_uapi)
332          legacy_mask |= ISL_TILING_X_BIT;
333       flags &= legacy_mask;
334    }
335 
336    assert(flags);
337 
338    return flags;
339 }
340 
341 /**
342  * Add the surface to the binding at the given offset.
343  *
344  * \see image_binding_grow()
345  */
346 static VkResult MUST_CHECK
add_surface(struct anv_device * device,struct anv_image * image,struct anv_surface * surf,enum anv_image_memory_binding binding,uint64_t offset)347 add_surface(struct anv_device *device,
348             struct anv_image *image,
349             struct anv_surface *surf,
350             enum anv_image_memory_binding binding,
351             uint64_t offset)
352 {
353    /* isl surface must be initialized */
354    assert(surf->isl.size_B > 0);
355 
356    return image_binding_grow(device, image, binding, offset,
357                              surf->isl.size_B,
358                              surf->isl.alignment_B,
359                              &surf->memory_range);
360 }
361 
362 static bool
can_fast_clear_with_non_zero_color(const struct intel_device_info * devinfo,const struct anv_image * image,uint32_t plane,const VkImageFormatListCreateInfo * fmt_list)363 can_fast_clear_with_non_zero_color(const struct intel_device_info *devinfo,
364                                    const struct anv_image *image,
365                                    uint32_t plane,
366                                    const VkImageFormatListCreateInfo *fmt_list)
367 {
368    /* If we don't have an AUX surface where fast clears apply, we can return
369     * early.
370     */
371    if (!isl_aux_usage_has_fast_clears(image->planes[plane].aux_usage))
372       return false;
373 
374    /* On TGL (< C0), if a block of fragment shader outputs match the surface's
375     * clear color, the HW may convert them to fast-clears (see HSD 1607794140).
376     * This can lead to rendering corruptions if not handled properly. We
377     * restrict the clear color to zero to avoid issues that can occur with:
378     *     - Texture view rendering (including blorp_copy calls)
379     *     - Images with multiple levels or array layers
380     */
381    if (image->planes[plane].aux_usage == ISL_AUX_USAGE_FCV_CCS_E)
382       return false;
383 
384    /* Turning on non zero fast clears for CCS_E introduces a performance
385     * regression for games such as F1 22 and RDR2 by introducing additional
386     * partial resolves. Let's turn non zero fast clears back off till we can
387     * fix performance.
388     */
389    if (image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E &&
390        devinfo->ver >= 12)
391       return false;
392 
393    /* Non mutable image, we can fast clear with any color supported by HW.
394     */
395    if (!(image->vk.create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
396       return true;
397 
398    /* Mutable image with no format list, we have to assume all formats */
399    if (!fmt_list || fmt_list->viewFormatCount == 0)
400       return false;
401 
402    enum isl_format img_format = image->planes[plane].primary_surface.isl.format;
403 
404    /* Check bit compatibility for clear color components */
405    for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
406       if (fmt_list->pViewFormats[i] == VK_FORMAT_UNDEFINED)
407          continue;
408 
409       struct anv_format_plane view_format_plane =
410          anv_get_format_plane(devinfo, fmt_list->pViewFormats[i],
411                               plane, image->vk.tiling);
412 
413       enum isl_format view_format = view_format_plane.isl_format;
414 
415       if (!isl_formats_have_same_bits_per_channel(img_format, view_format))
416          return false;
417    }
418 
419    return true;
420 }
421 
422 /**
423  * Return true if the storage image could be used with atomics.
424  *
425  * If the image was created with an explicit format, we check it for typed
426  * atomic support.  If MUTABLE_FORMAT_BIT is set, then we check the optional
427  * format list, seeing if /any/ of the formats support typed atomics.  If no
428  * list is supplied, we fall back to using the bpb, as the application could
429  * make an image view with a format that does use atomics.
430  */
431 static bool
storage_image_format_supports_atomic(const struct intel_device_info * devinfo,VkImageCreateFlags create_flags,enum isl_format format,VkImageTiling vk_tiling,const VkImageFormatListCreateInfo * fmt_list)432 storage_image_format_supports_atomic(const struct intel_device_info *devinfo,
433                                      VkImageCreateFlags create_flags,
434                                      enum isl_format format,
435                                      VkImageTiling vk_tiling,
436                                      const VkImageFormatListCreateInfo *fmt_list)
437 {
438    if (isl_format_supports_typed_atomics(devinfo, format))
439       return true;
440 
441    if (!(create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
442       return false;
443 
444    if (fmt_list) {
445       for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
446          if (fmt_list->pViewFormats[i] == VK_FORMAT_UNDEFINED)
447             continue;
448 
449          enum isl_format view_format =
450             anv_get_isl_format(devinfo, fmt_list->pViewFormats[i],
451                                VK_IMAGE_ASPECT_COLOR_BIT, vk_tiling);
452 
453          if (isl_format_supports_typed_atomics(devinfo, view_format))
454             return true;
455       }
456 
457       return false;
458    }
459 
460    /* No explicit format list.  Any 16/32/64bpp format could be used with atomics. */
461    unsigned bpb = isl_format_get_layout(format)->bpb;
462    return bpb == 16 || bpb == 32 || bpb == 64;
463 }
464 
465 static bool
formats_ccs_e_compatible(const struct intel_device_info * devinfo,VkImageCreateFlags create_flags,enum isl_format format,VkImageTiling vk_tiling,const VkImageFormatListCreateInfo * fmt_list)466 formats_ccs_e_compatible(const struct intel_device_info *devinfo,
467                          VkImageCreateFlags create_flags,
468                          enum isl_format format, VkImageTiling vk_tiling,
469                          const VkImageFormatListCreateInfo *fmt_list)
470 {
471    if (!anv_format_supports_ccs_e(devinfo, format))
472       return false;
473 
474    /* For images created without MUTABLE_FORMAT_BIT set, we know that they will
475     * always be used with the original format. In particular, they will always
476     * be used with a format that supports color compression.
477     */
478    if (!(create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
479       return true;
480 
481    if (!fmt_list || fmt_list->viewFormatCount == 0)
482       return false;
483 
484    for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
485       if (fmt_list->pViewFormats[i] == VK_FORMAT_UNDEFINED)
486          continue;
487 
488       enum isl_format view_format =
489          anv_get_isl_format(devinfo, fmt_list->pViewFormats[i],
490                             VK_IMAGE_ASPECT_COLOR_BIT, vk_tiling);
491 
492       if (!isl_formats_are_ccs_e_compatible(devinfo, format, view_format))
493          return false;
494    }
495 
496    return true;
497 }
498 
499 bool
anv_format_supports_ccs_e(const struct intel_device_info * devinfo,const enum isl_format format)500 anv_format_supports_ccs_e(const struct intel_device_info *devinfo,
501                           const enum isl_format format)
502 {
503    /* CCS_E for YCRCB_NORMAL and YCRCB_SWAP_UV is not currently supported by
504     * ANV so leave it disabled for now.
505     */
506    if (isl_format_is_yuv(format))
507       return false;
508 
509    return isl_format_supports_ccs_e(devinfo, format);
510 }
511 
512 bool
anv_formats_ccs_e_compatible(const struct intel_device_info * devinfo,VkImageCreateFlags create_flags,VkFormat vk_format,VkImageTiling vk_tiling,VkImageUsageFlags vk_usage,const VkImageFormatListCreateInfo * fmt_list)513 anv_formats_ccs_e_compatible(const struct intel_device_info *devinfo,
514                              VkImageCreateFlags create_flags,
515                              VkFormat vk_format, VkImageTiling vk_tiling,
516                              VkImageUsageFlags vk_usage,
517                              const VkImageFormatListCreateInfo *fmt_list)
518 {
519    u_foreach_bit(b, vk_format_aspects(vk_format)) {
520       VkImageAspectFlagBits aspect = 1 << b;
521       enum isl_format format =
522          anv_get_isl_format(devinfo, vk_format, aspect, vk_tiling);
523 
524       if (!formats_ccs_e_compatible(devinfo, create_flags, format, vk_tiling,
525                                     fmt_list))
526          return false;
527 
528       if (vk_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
529          if (devinfo->verx10 < 125)
530             return false;
531 
532          /* Disable compression when surface can be potentially used for
533           * atomic operation.
534           */
535          if (storage_image_format_supports_atomic(devinfo, create_flags,
536                                                   format, vk_tiling,
537                                                   fmt_list))
538             return false;
539       }
540    }
541 
542    return true;
543 }
544 
545 /**
546  * For color images that have an auxiliary surface, request allocation for an
547  * additional buffer that mainly stores fast-clear values. Use of this buffer
548  * allows us to access the image's subresources while being aware of their
549  * fast-clear values in non-trivial cases (e.g., outside of a render pass in
550  * which a fast clear has occurred).
551  *
552  * In order to avoid having multiple clear colors for a single plane of an
553  * image (hence a single RENDER_SURFACE_STATE), we only allow fast-clears on
554  * the first slice (level 0, layer 0).  At the time of our testing (Jan 17,
555  * 2018), there were no known applications which would benefit from fast-
556  * clearing more than just the first slice.
557  *
558  * The fast clear portion of the image is laid out in the following order:
559  *
560  *  * 1 or 4 dwords (depending on hardware generation) for the clear color
561  *  * 1 dword for the anv_fast_clear_type of the clear color
562  *  * On gfx9+, 1 dword per level and layer of the image (3D levels count
563  *    multiple layers) in level-major order for compression state.
564  *
565  * For the purpose of discoverability, the algorithm used to manage
566  * compression and fast-clears is described here:
567  *
568  *  * On a transition from UNDEFINED or PREINITIALIZED to a defined layout,
569  *    all of the values in the fast clear portion of the image are initialized
570  *    to default values.
571  *
572  *  * On fast-clear, the clear value is written into surface state and also
573  *    into the buffer and the fast clear type is set appropriately.  Both
574  *    setting the fast-clear value in the buffer and setting the fast-clear
575  *    type happen from the GPU using MI commands.
576  *
577  *  * Whenever a render or blorp operation is performed with CCS_E, we call
578  *    genX(cmd_buffer_mark_image_written) to set the compression state to
579  *    true (which is represented by UINT32_MAX).
580  *
581  *  * On pipeline barrier transitions, the worst-case transition is computed
582  *    from the image layouts.  The command streamer inspects the fast clear
583  *    type and compression state dwords and constructs a predicate.  The
584  *    worst-case resolve is performed with the given predicate and the fast
585  *    clear and compression state is set accordingly.
586  *
587  * See anv_layout_to_aux_usage and anv_layout_to_fast_clear_type functions for
588  * details on exactly what is allowed in what layouts.
589  *
590  * On gfx7-9, we do not have a concept of indirect clear colors in hardware.
591  * In order to deal with this, we have to do some clear color management.
592  *
593  *  * For LOAD_OP_LOAD at the top of a renderpass, we have to copy the clear
594  *    value from the buffer into the surface state with MI commands.
595  *
596  *  * For any blorp operations, we pass the address to the clear value into
597  *    blorp and it knows to copy the clear color.
598  */
599 static VkResult MUST_CHECK
add_aux_state_tracking_buffer(struct anv_device * device,struct anv_image * image,uint64_t state_offset,uint32_t plane)600 add_aux_state_tracking_buffer(struct anv_device *device,
601                               struct anv_image *image,
602                               uint64_t state_offset,
603                               uint32_t plane)
604 {
605    assert(image && device);
606    /* Xe2+ platforms don't use aux tracking buffers. We shouldn't get here. */
607    assert(device->info->ver < 20);
608    assert(image->planes[plane].aux_usage != ISL_AUX_USAGE_NONE &&
609           image->vk.aspects & (VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV |
610                                VK_IMAGE_ASPECT_DEPTH_BIT));
611 
612    unsigned clear_color_state_size;
613    if (device->info->ver >= 11) {
614       /* When importing an image from another source with a drm modifier that
615        * supports clear color, the clear color values are in a 32-byte struct
616        * defined in drm_fourcc.h. The fast clear type and compression state
617        * are not defined in these drm_fourcc.h, so there won't be memory
618        * allocated for these extra meta data by the source.
619        *
620        * We use the last 2 dwords of the clear color struct's memory to store
621        * the fast clear type and the first compression state, so the driver
622        * doesn't assume the extra size or need another allocation later.
623        *
624        * So far, the 2 stolen dwords are either not used in the clear color
625        * struct or for features not enabled. There should be no side effect to
626        * the hardware and destinations of images exported by this driver.
627        *
628        * Images with multiple levels or layers are not supported by drm
629        * modifiers, so we don't have to apply the above approach or face a
630        * bigger shortage from multiple compression states. We just apply the
631        * approach to all cases to keep the design unified.
632        *
633        * As a result, the state starts 8 bytes lower than where it should be.
634        */
635       assert(device->isl_dev.ss.clear_color_state_size >= 32);
636       clear_color_state_size = device->isl_dev.ss.clear_color_state_size - 8;
637    } else {
638       clear_color_state_size = device->isl_dev.ss.clear_value_size;
639    }
640 
641    /* Clear color and fast clear type */
642    unsigned state_size = clear_color_state_size + 4;
643 
644    /* We only need to track compression on CCS_E surfaces. */
645    if (isl_aux_usage_has_ccs_e(image->planes[plane].aux_usage)) {
646       if (image->vk.image_type == VK_IMAGE_TYPE_3D) {
647          for (uint32_t l = 0; l < image->vk.mip_levels; l++)
648             state_size += u_minify(image->vk.extent.depth, l) * 4;
649       } else {
650          state_size += image->vk.mip_levels * image->vk.array_layers * 4;
651       }
652    }
653 
654    enum anv_image_memory_binding binding =
655       ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane;
656 
657    /* If an auxiliary surface is used for an externally-shareable image,
658     * we have to hide this from the memory of the image since other
659     * processes with access to the memory may not be aware of it or of
660     * its current state. So put that auxiliary data into a separate
661     * buffer (ANV_IMAGE_MEMORY_BINDING_PRIVATE).
662     *
663     * But when the image is created with a drm modifier that supports
664     * clear color, it will be exported along with main surface.
665     */
666    if (anv_image_is_externally_shared(image)
667        && !isl_drm_modifier_get_info(image->vk.drm_format_mod)->supports_clear_color) {
668       binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
669    }
670 
671    /* The indirect clear color BO requires 64B-alignment on gfx11+. */
672    return image_binding_grow(device, image, binding,
673                              state_offset, state_size, 64,
674                              &image->planes[plane].fast_clear_memory_range);
675 }
676 
677 static VkResult MUST_CHECK
add_compression_control_buffer(struct anv_device * device,struct anv_image * image,uint32_t plane,uint32_t binding,uint64_t offset)678 add_compression_control_buffer(struct anv_device *device,
679                                struct anv_image *image,
680                                uint32_t plane,
681                                uint32_t binding,
682                                uint64_t offset)
683 {
684    assert(device->info->has_aux_map);
685 
686    return image_binding_grow(device, image, binding, offset,
687                              image->planes[plane].primary_surface.isl.size_B /
688                              INTEL_AUX_MAP_MAIN_SIZE_SCALEDOWN,
689                              INTEL_AUX_MAP_META_ALIGNMENT_B,
690                              &image->planes[plane].compr_ctrl_memory_range);
691 }
692 
693 static bool
want_hiz_wt_for_image(const struct intel_device_info * devinfo,const struct anv_image * image)694 want_hiz_wt_for_image(const struct intel_device_info *devinfo,
695                       const struct anv_image *image)
696 {
697    /* Gen12 only supports single-sampled while Gen20+ supports
698     * multi-sampled images.
699     */
700    if (devinfo->ver < 20 && image->vk.samples > 1)
701       return false;
702 
703    if ((image->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
704                            VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) == 0)
705       return false;
706 
707    /* If this image has the maximum number of samples supported by
708     * running platform and will be used as a texture, put the HiZ surface
709     * in write-through mode so that we can sample from it.
710     *
711     * TODO: This is a heuristic trade-off; we haven't tuned it at all.
712     */
713    return true;
714 }
715 
716 /**
717  * The return code indicates whether creation of the VkImage should continue
718  * or fail, not whether the creation of the aux surface succeeded.  If the aux
719  * surface is not required (for example, by neither hardware nor DRM format
720  * modifier), then this may return VK_SUCCESS when creation of the aux surface
721  * fails.
722  *
723  * @param offset See add_surface()
724  */
725 static VkResult
add_aux_surface_if_supported(struct anv_device * device,struct anv_image * image,uint32_t plane,struct anv_format_plane plane_format,const VkImageFormatListCreateInfo * fmt_list,uint64_t offset,uint32_t stride,uint64_t aux_state_offset)726 add_aux_surface_if_supported(struct anv_device *device,
727                              struct anv_image *image,
728                              uint32_t plane,
729                              struct anv_format_plane plane_format,
730                              const VkImageFormatListCreateInfo *fmt_list,
731                              uint64_t offset,
732                              uint32_t stride,
733                              uint64_t aux_state_offset)
734 {
735    VkImageAspectFlags aspect = plane_format.aspect;
736    VkResult result;
737    bool ok;
738 
739    /* The aux surface must not be already added. */
740    assert(!anv_surface_is_valid(&image->planes[plane].aux_surface));
741 
742    if (image->planes[plane].primary_surface.isl.usage &
743        ISL_SURF_USAGE_DISABLE_AUX_BIT)
744       return VK_SUCCESS;
745 
746    uint32_t binding;
747    if (image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID ||
748        isl_drm_modifier_has_aux(image->vk.drm_format_mod)) {
749       binding = ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane;
750    } else {
751       binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
752    }
753 
754    if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
755       /* We don't advertise that depth buffers could be used as storage
756        * images.
757        */
758        assert(!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT));
759 
760       ok = isl_surf_get_hiz_surf(&device->isl_dev,
761                                  &image->planes[plane].primary_surface.isl,
762                                  &image->planes[plane].aux_surface.isl);
763       if (!ok)
764          return VK_SUCCESS;
765 
766       if (!isl_surf_supports_ccs(&device->isl_dev,
767                                  &image->planes[plane].primary_surface.isl,
768                                  &image->planes[plane].aux_surface.isl)) {
769          image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ;
770       } else if (want_hiz_wt_for_image(device->info, image)) {
771          assert(device->info->ver >= 12);
772          image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ_CCS_WT;
773       } else {
774          assert(device->info->ver >= 12);
775          image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ_CCS;
776       }
777 
778       result = add_surface(device, image, &image->planes[plane].aux_surface,
779                            binding, ANV_OFFSET_IMPLICIT);
780       if (result != VK_SUCCESS)
781          return result;
782 
783       if (anv_image_plane_uses_aux_map(device, image, plane)) {
784          result = add_compression_control_buffer(device, image, plane,
785                                                  binding,
786                                                  ANV_OFFSET_IMPLICIT);
787          if (result != VK_SUCCESS)
788             return result;
789       }
790 
791       if (device->info->ver == 12 &&
792           image->planes[plane].aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT) {
793          return add_aux_state_tracking_buffer(device, image, aux_state_offset,
794                                               plane);
795       }
796    } else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
797       if (!isl_surf_supports_ccs(&device->isl_dev,
798                                  &image->planes[plane].primary_surface.isl,
799                                  NULL))
800          return VK_SUCCESS;
801 
802       image->planes[plane].aux_usage = ISL_AUX_USAGE_STC_CCS;
803 
804       if (device->info->has_aux_map) {
805          result = add_compression_control_buffer(device, image, plane,
806                                                  binding,
807                                                  ANV_OFFSET_IMPLICIT);
808          if (result != VK_SUCCESS)
809             return result;
810       }
811    } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->vk.samples == 1) {
812 
813       if (device->info->has_flat_ccs || device->info->has_aux_map) {
814          ok = isl_surf_supports_ccs(&device->isl_dev,
815                                     &image->planes[plane].primary_surface.isl,
816                                     NULL);
817       } else {
818          ok = isl_surf_get_ccs_surf(&device->isl_dev,
819                                     &image->planes[plane].primary_surface.isl,
820                                     &image->planes[plane].aux_surface.isl,
821                                     stride);
822       }
823       if (!ok)
824          return VK_SUCCESS;
825 
826       /* Choose aux usage. */
827       if (device->info->verx10 == 125 && !device->physical->disable_fcv) {
828          /* FCV is enabled via 3DSTATE_3D_MODE. We'd expect plain CCS_E to
829           * perform better because it allows for non-zero fast clear colors,
830           * but we've run into regressions in several benchmarks (F1 22 and
831           * RDR2) when trying to enable it. When non-zero clear colors are
832           * enabled, we've observed many partial resolves. We haven't yet
833           * root-caused what layout transitions are causing these resolves,
834           * so in the meantime, we choose to reduce our clear color support.
835           * With only zero clear colors being supported, we might as well
836           * turn on FCV.
837           */
838          image->planes[plane].aux_usage = ISL_AUX_USAGE_FCV_CCS_E;
839       } else if (intel_needs_workaround(device->info, 1607794140)) {
840          /* FCV is permanently enabled on this hardware. */
841          assert(device->info->verx10 == 120);
842          image->planes[plane].aux_usage = ISL_AUX_USAGE_FCV_CCS_E;
843       } else if (device->info->ver >= 12) {
844          /* Support for CCS_E was already checked for in anv_image_init(). */
845          image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_E;
846       } else if (anv_formats_ccs_e_compatible(device->info,
847                                               image->vk.create_flags,
848                                               image->vk.format,
849                                               image->vk.tiling,
850                                               image->vk.usage, fmt_list)) {
851          image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_E;
852       } else {
853          image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_D;
854       }
855 
856       if (device->info->has_flat_ccs) {
857          result = VK_SUCCESS;
858       } else if (device->info->has_aux_map) {
859          result = add_compression_control_buffer(device, image, plane,
860                                                  binding, offset);
861       } else {
862          result = add_surface(device, image,
863                               &image->planes[plane].aux_surface, binding,
864                               offset);
865       }
866       if (result != VK_SUCCESS)
867          return result;
868 
869       if (device->info->ver <= 12)
870          return add_aux_state_tracking_buffer(device, image, aux_state_offset,
871                                               plane);
872    } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->vk.samples > 1) {
873       assert(!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT));
874       ok = isl_surf_get_mcs_surf(&device->isl_dev,
875                                  &image->planes[plane].primary_surface.isl,
876                                  &image->planes[plane].aux_surface.isl);
877       if (!ok)
878          return VK_SUCCESS;
879 
880       image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
881 
882       result = add_surface(device, image, &image->planes[plane].aux_surface,
883                            binding, ANV_OFFSET_IMPLICIT);
884       if (result != VK_SUCCESS)
885          return result;
886 
887       if (device->info->ver <= 12)
888          return add_aux_state_tracking_buffer(device, image, aux_state_offset,
889                                               plane);
890    }
891 
892    return VK_SUCCESS;
893 }
894 
895 static VkResult
add_video_buffers(struct anv_device * device,struct anv_image * image,const struct VkVideoProfileListInfoKHR * profile_list)896 add_video_buffers(struct anv_device *device,
897                   struct anv_image *image,
898                   const struct VkVideoProfileListInfoKHR *profile_list)
899 {
900    ASSERTED bool ok;
901    unsigned size = 0;
902 
903    for (unsigned i = 0; i < profile_list->profileCount; i++) {
904       if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
905          unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, ANV_MB_WIDTH);
906          unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, ANV_MB_HEIGHT);
907          size = w_mb * h_mb * 128;
908       }
909       else if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR ||
910                profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) {
911          unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, 32);
912          unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, 32);
913          size = ALIGN(w_mb * h_mb, 2) << 6;
914       }
915    }
916 
917    if (size == 0)
918       return VK_SUCCESS;
919 
920    ok = image_binding_grow(device, image, ANV_IMAGE_MEMORY_BINDING_PRIVATE,
921                            ANV_OFFSET_IMPLICIT, size, 65536, &image->vid_dmv_top_surface);
922    return ok;
923 }
924 
925 /**
926  * Initialize the anv_image::*_surface selected by \a aspect. Then update the
927  * image's memory requirements (that is, the image's size and alignment).
928  *
929  * @param offset See add_surface()
930  */
931 static VkResult
add_primary_surface(struct anv_device * device,struct anv_image * image,uint32_t plane,struct anv_format_plane plane_format,uint64_t offset,uint32_t stride,isl_tiling_flags_t isl_tiling_flags,isl_surf_usage_flags_t isl_usage)932 add_primary_surface(struct anv_device *device,
933                     struct anv_image *image,
934                     uint32_t plane,
935                     struct anv_format_plane plane_format,
936                     uint64_t offset,
937                     uint32_t stride,
938                     isl_tiling_flags_t isl_tiling_flags,
939                     isl_surf_usage_flags_t isl_usage)
940 {
941    struct anv_surface *anv_surf = &image->planes[plane].primary_surface;
942    bool ok;
943 
944    uint32_t width = image->vk.extent.width;
945    uint32_t height = image->vk.extent.height;
946    const struct vk_format_ycbcr_info *ycbcr_info =
947       vk_format_get_ycbcr_info(image->vk.format);
948    if (ycbcr_info) {
949       assert(plane < ycbcr_info->n_planes);
950       width /= ycbcr_info->planes[plane].denominator_scales[0];
951       height /= ycbcr_info->planes[plane].denominator_scales[1];
952    }
953 
954    ok = isl_surf_init(&device->isl_dev, &anv_surf->isl,
955       .dim = vk_to_isl_surf_dim[image->vk.image_type],
956       .format = plane_format.isl_format,
957       .width = width,
958       .height = height,
959       .depth = image->vk.extent.depth,
960       .levels = image->vk.mip_levels,
961       .array_len = image->vk.array_layers,
962       .samples = image->vk.samples,
963       .min_alignment_B = 0,
964       .row_pitch_B = stride,
965       .usage = isl_usage,
966       .tiling_flags = isl_tiling_flags);
967 
968    if (!ok) {
969       /* TODO: Should return
970        * VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT in come cases.
971        */
972       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
973    }
974 
975    image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
976 
977    return add_surface(device, image, anv_surf,
978                       ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane, offset);
979 }
980 
981 #ifndef NDEBUG
982 static bool MUST_CHECK
memory_range_is_aligned(struct anv_image_memory_range memory_range)983 memory_range_is_aligned(struct anv_image_memory_range memory_range)
984 {
985    return anv_is_aligned(memory_range.offset, memory_range.alignment);
986 }
987 
988 static bool MUST_CHECK
memory_ranges_equal(struct anv_image_memory_range a,struct anv_image_memory_range b)989 memory_ranges_equal(struct anv_image_memory_range a,
990                     struct anv_image_memory_range b)
991 {
992    return a.binding == b.binding &&
993           a.alignment == b.alignment &&
994           a.size == b.size &&
995           a.offset == b.offset;
996 }
997 #endif
998 
999 struct check_memory_range_params {
1000    struct anv_image_memory_range *accum_ranges;
1001    const struct anv_surface *test_surface;
1002    const struct anv_image_memory_range *test_range;
1003    enum anv_image_memory_binding expect_binding;
1004 };
1005 
1006 #define check_memory_range(...) \
1007    check_memory_range_s(&(struct check_memory_range_params) { __VA_ARGS__ })
1008 
1009 static void UNUSED
check_memory_range_s(const struct check_memory_range_params * p)1010 check_memory_range_s(const struct check_memory_range_params *p)
1011 {
1012    assert((p->test_surface == NULL) != (p->test_range == NULL));
1013 
1014    const struct anv_image_memory_range *test_range =
1015       p->test_range ?: &p->test_surface->memory_range;
1016 
1017    struct anv_image_memory_range *accum_range =
1018       &p->accum_ranges[p->expect_binding];
1019 
1020    assert(test_range->binding == p->expect_binding);
1021    assert(test_range->offset >= memory_range_end(*accum_range));
1022    assert(memory_range_is_aligned(*test_range));
1023 
1024    if (p->test_surface) {
1025       assert(anv_surface_is_valid(p->test_surface));
1026       assert(p->test_surface->memory_range.alignment ==
1027              p->test_surface->isl.alignment_B);
1028    }
1029 
1030    memory_range_merge(accum_range, *test_range);
1031 }
1032 
1033 /**
1034  * Validate the image's memory bindings *after* all its surfaces and memory
1035  * ranges are final.
1036  *
1037  * For simplicity's sake, we do not validate free-form layout of the image's
1038  * memory bindings. We validate the layout described in the comments of struct
1039  * anv_image.
1040  */
1041 static void
check_memory_bindings(const struct anv_device * device,const struct anv_image * image)1042 check_memory_bindings(const struct anv_device *device,
1043                      const struct anv_image *image)
1044 {
1045 #if MESA_DEBUG
1046    /* As we inspect each part of the image, we merge the part's memory range
1047     * into these accumulation ranges.
1048     */
1049    struct anv_image_memory_range accum_ranges[ANV_IMAGE_MEMORY_BINDING_END];
1050    for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; ++i) {
1051       accum_ranges[i] = (struct anv_image_memory_range) {
1052          .binding = i,
1053       };
1054    }
1055 
1056    for (uint32_t p = 0; p < image->n_planes; ++p) {
1057       const struct anv_image_plane *plane = &image->planes[p];
1058 
1059       /* The binding that must contain the plane's primary surface. */
1060       const enum anv_image_memory_binding primary_binding = image->disjoint
1061          ? ANV_IMAGE_MEMORY_BINDING_PLANE_0 + p
1062          : ANV_IMAGE_MEMORY_BINDING_MAIN;
1063 
1064       /* Aliasing is incompatible with the private binding because it does not
1065        * live in a VkDeviceMemory.  The exception is either swapchain images or
1066        * that the private binding is for a video motion vector buffer.
1067        */
1068       assert(!(image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT) ||
1069              image->from_wsi ||
1070              (plane->primary_surface.isl.usage & ISL_SURF_USAGE_VIDEO_DECODE_BIT) ||
1071              image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].memory_range.size == 0);
1072 
1073       /* Check primary surface */
1074       check_memory_range(accum_ranges,
1075                          .test_surface = &plane->primary_surface,
1076                          .expect_binding = primary_binding);
1077 
1078       /* Check aux_surface */
1079       const struct anv_image_memory_range *aux_mem_range =
1080          anv_image_get_aux_memory_range(image, p);
1081       if (aux_mem_range->size > 0) {
1082          enum anv_image_memory_binding binding = primary_binding;
1083 
1084          /* If an auxiliary surface is used for an externally-shareable image,
1085           * we have to hide this from the memory of the image since other
1086           * processes with access to the memory may not be aware of it or of
1087           * its current state. So put that auxiliary data into a separate
1088           * buffer (ANV_IMAGE_MEMORY_BINDING_PRIVATE).
1089           */
1090          if (anv_image_is_externally_shared(image) &&
1091              !isl_drm_modifier_has_aux(image->vk.drm_format_mod)) {
1092             binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
1093          }
1094 
1095          /* Display hardware requires that the aux surface start at
1096           * a higher address than the primary surface. The 3D hardware
1097           * doesn't care, but we enforce the display requirement in case
1098           * the image is sent to display.
1099           */
1100          check_memory_range(accum_ranges,
1101                             .test_range = aux_mem_range,
1102                             .expect_binding = binding);
1103       }
1104 
1105       /* Check fast clear state */
1106       if (plane->fast_clear_memory_range.size > 0) {
1107          enum anv_image_memory_binding binding = primary_binding;
1108 
1109          /* If an auxiliary surface is used for an externally-shareable image,
1110           * we have to hide this from the memory of the image since other
1111           * processes with access to the memory may not be aware of it or of
1112           * its current state. So put that auxiliary data into a separate
1113           * buffer (ANV_IMAGE_MEMORY_BINDING_PRIVATE).
1114           *
1115           * But when the image is created with a drm modifier that supports
1116           * clear color, it will be exported along with main surface.
1117           */
1118          if (anv_image_is_externally_shared(image)
1119              && !isl_drm_modifier_get_info(image->vk.drm_format_mod)->supports_clear_color) {
1120             binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
1121          }
1122 
1123          /* The indirect clear color BO requires 64B-alignment on gfx11+. */
1124          assert(plane->fast_clear_memory_range.alignment == 64);
1125          check_memory_range(accum_ranges,
1126                             .test_range = &plane->fast_clear_memory_range,
1127                             .expect_binding = binding);
1128       }
1129    }
1130 #endif
1131 }
1132 
1133 /**
1134  * Check that the fully-initialized anv_image is compatible with its DRM format
1135  * modifier.
1136  *
1137  * Checking compatibility at the end of image creation is prudent, not
1138  * superfluous, because usage of modifiers triggers numerous special cases
1139  * throughout queries and image creation, and because
1140  * vkGetPhysicalDeviceImageFormatProperties2 has difficulty detecting all
1141  * incompatibilities.
1142  *
1143  * Return VK_ERROR_UNKNOWN if the incompatibility is difficult to detect in
1144  * vkGetPhysicalDeviceImageFormatProperties2.  Otherwise, assert fail.
1145  *
1146  * Ideally, if vkGetPhysicalDeviceImageFormatProperties2() succeeds with a given
1147  * modifier, then vkCreateImage() produces an image that is compatible with the
1148  * modifier. However, it is difficult to reconcile the two functions to agree
1149  * due to their complexity. For example, isl_surf_get_ccs_surf() may
1150  * unexpectedly fail in vkCreateImage(), eliminating the image's aux surface
1151  * even when the modifier requires one. (Maybe we should reconcile the two
1152  * functions despite the difficulty).
1153  */
1154 static VkResult MUST_CHECK
check_drm_format_mod(const struct anv_device * device,const struct anv_image * image)1155 check_drm_format_mod(const struct anv_device *device,
1156                      const struct anv_image *image)
1157 {
1158    /* Image must have a modifier if and only if it has modifier tiling. */
1159    assert((image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID) ==
1160           (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT));
1161 
1162    if (image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID)
1163       return VK_SUCCESS;
1164 
1165    const struct isl_drm_modifier_info *isl_mod_info =
1166       isl_drm_modifier_get_info(image->vk.drm_format_mod);
1167 
1168    /* Driver must support the modifier. */
1169    assert(isl_drm_modifier_get_score(device->info, isl_mod_info->modifier));
1170 
1171    /* Enforced by us, not the Vulkan spec. */
1172    assert(image->vk.image_type == VK_IMAGE_TYPE_2D);
1173    assert(!(image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT));
1174    assert(!(image->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT));
1175    assert(image->vk.mip_levels == 1);
1176    assert(image->vk.array_layers == 1);
1177    assert(image->vk.samples == 1);
1178 
1179    for (int i = 0; i < image->n_planes; ++i) {
1180       const struct anv_image_plane *plane = &image->planes[i];
1181       ASSERTED const struct isl_format_layout *isl_layout =
1182          isl_format_get_layout(plane->primary_surface.isl.format);
1183 
1184       /* Enforced by us, not the Vulkan spec. */
1185       assert(isl_layout->txc == ISL_TXC_NONE);
1186       assert(isl_layout->colorspace == ISL_COLORSPACE_LINEAR ||
1187              isl_layout->colorspace == ISL_COLORSPACE_SRGB);
1188 
1189       if (isl_drm_modifier_has_aux(isl_mod_info->modifier)) {
1190          /* Reject DISJOINT for consistency with the GL driver. */
1191          assert(!image->disjoint);
1192 
1193          /* The modifier's required aux usage mandates the image's aux usage.
1194           * The inverse, however, does not hold; if the modifier has no aux
1195           * usage, then we may enable a private aux surface.
1196           */
1197          if ((isl_mod_info->supports_media_compression &&
1198               plane->aux_usage != ISL_AUX_USAGE_MC) ||
1199              (isl_mod_info->supports_render_compression &&
1200               !isl_aux_usage_has_ccs_e(plane->aux_usage))) {
1201             return vk_errorf(device, VK_ERROR_UNKNOWN,
1202                              "image with modifier unexpectedly has wrong aux "
1203                              "usage");
1204          }
1205       }
1206    }
1207 
1208    return VK_SUCCESS;
1209 }
1210 
1211 /**
1212  * Use when the app does not provide
1213  * VkImageDrmFormatModifierExplicitCreateInfoEXT.
1214  */
1215 static VkResult MUST_CHECK
add_all_surfaces_implicit_layout(struct anv_device * device,struct anv_image * image,const VkImageFormatListCreateInfo * format_list_info,uint32_t stride,isl_tiling_flags_t isl_tiling_flags,isl_surf_usage_flags_t isl_extra_usage_flags)1216 add_all_surfaces_implicit_layout(
1217    struct anv_device *device,
1218    struct anv_image *image,
1219    const VkImageFormatListCreateInfo *format_list_info,
1220    uint32_t stride,
1221    isl_tiling_flags_t isl_tiling_flags,
1222    isl_surf_usage_flags_t isl_extra_usage_flags)
1223 {
1224    const struct intel_device_info *devinfo = device->info;
1225    VkResult result;
1226 
1227    const struct vk_format_ycbcr_info *ycbcr_info =
1228       vk_format_get_ycbcr_info(image->vk.format);
1229    if (ycbcr_info)
1230       assert(ycbcr_info->n_planes == image->n_planes);
1231 
1232    unsigned num_aspects = 0;
1233    VkImageAspectFlagBits aspects[3];
1234    u_foreach_bit(b, image->vk.aspects) {
1235       assert(num_aspects < 3);
1236       aspects[num_aspects++] = 1 << b;
1237    }
1238    assert(num_aspects == image->n_planes);
1239 
1240    /* The Android hardware buffer YV12 format has the planes ordered as Y-Cr-Cb,
1241     * while Vulkan expects VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM to be in Y-Cb-Cr.
1242     * Adjust the order we add the ISL surfaces accordingly so the implicit
1243     * offset gets calculated correctly.
1244     */
1245    if (image->from_ahb && image->vk.format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) {
1246       assert(num_aspects == 3);
1247       assert(aspects[1] == VK_IMAGE_ASPECT_PLANE_1_BIT);
1248       assert(aspects[2] == VK_IMAGE_ASPECT_PLANE_2_BIT);
1249       aspects[1] = VK_IMAGE_ASPECT_PLANE_2_BIT;
1250       aspects[2] = VK_IMAGE_ASPECT_PLANE_1_BIT;
1251    }
1252 
1253    for (unsigned i = 0; i < num_aspects; i++) {
1254       VkImageAspectFlagBits aspect = aspects[i];
1255       const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1256       const  struct anv_format_plane plane_format =
1257          anv_get_format_plane(devinfo, image->vk.format, plane, image->vk.tiling);
1258 
1259       enum isl_format isl_fmt = plane_format.isl_format;
1260       assert(isl_fmt != ISL_FORMAT_UNSUPPORTED);
1261 
1262       uint32_t plane_stride = stride * isl_format_get_layout(isl_fmt)->bpb / 8;
1263       if (ycbcr_info)
1264          plane_stride /= ycbcr_info->planes[plane].denominator_scales[0];
1265 
1266       VkImageUsageFlags vk_usage = vk_image_usage(&image->vk, aspect);
1267       isl_surf_usage_flags_t isl_usage =
1268          anv_image_choose_isl_surf_usage(device->physical,
1269                                          image->vk.create_flags, vk_usage,
1270                                          isl_extra_usage_flags, aspect,
1271                                          image->vk.compr_flags);
1272 
1273       result = add_primary_surface(device, image, plane, plane_format,
1274                                    ANV_OFFSET_IMPLICIT, plane_stride,
1275                                    isl_tiling_flags, isl_usage);
1276       if (result != VK_SUCCESS)
1277          return result;
1278 
1279       result = add_aux_surface_if_supported(device, image, plane, plane_format,
1280                                             format_list_info,
1281                                             ANV_OFFSET_IMPLICIT, plane_stride,
1282                                             ANV_OFFSET_IMPLICIT);
1283       if (result != VK_SUCCESS)
1284          return result;
1285    }
1286 
1287    return VK_SUCCESS;
1288 }
1289 
1290 /**
1291  * Use when the app provides VkImageDrmFormatModifierExplicitCreateInfoEXT.
1292  */
1293 static VkResult
add_all_surfaces_explicit_layout(struct anv_device * device,struct anv_image * image,const VkImageFormatListCreateInfo * format_list_info,const VkImageDrmFormatModifierExplicitCreateInfoEXT * drm_info,isl_tiling_flags_t isl_tiling_flags,isl_surf_usage_flags_t isl_extra_usage_flags)1294 add_all_surfaces_explicit_layout(
1295    struct anv_device *device,
1296    struct anv_image *image,
1297    const VkImageFormatListCreateInfo *format_list_info,
1298    const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_info,
1299    isl_tiling_flags_t isl_tiling_flags,
1300    isl_surf_usage_flags_t isl_extra_usage_flags)
1301 {
1302    const struct intel_device_info *devinfo = device->info;
1303    const uint32_t mod_plane_count = drm_info->drmFormatModifierPlaneCount;
1304    const bool mod_has_aux =
1305       isl_drm_modifier_has_aux(drm_info->drmFormatModifier);
1306    VkResult result;
1307 
1308    /* Currently there is no way to properly map memory planes to format planes
1309     * and aux planes due to the lack of defined ABI for external multi-planar
1310     * images.
1311     */
1312    if (image->n_planes == 1)
1313       assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT);
1314    else
1315       assert(!(image->vk.aspects & ~VK_IMAGE_ASPECT_PLANES_BITS_ANV));
1316 
1317    if (mod_has_aux) {
1318       assert(image->n_planes == 1);
1319 
1320       /* About valid usage in the Vulkan spec:
1321        *
1322        * Unlike vanilla vkCreateImage, which produces undefined behavior on user
1323        * error, here the spec requires the implementation to return
1324        * VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT if the app provides
1325        * a bad plane layout. However, the spec does require
1326        * drmFormatModifierPlaneCount to be valid.
1327        *
1328        * Most validation of plane layout occurs in add_surface().
1329        */
1330       uint32_t n_mod_planes =
1331          isl_drm_modifier_get_plane_count(devinfo,
1332                                           drm_info->drmFormatModifier,
1333                                           image->n_planes);
1334       assert(n_mod_planes == mod_plane_count);
1335    } else {
1336       assert(image->n_planes == mod_plane_count);
1337    }
1338 
1339    /* Reject special values in the app-provided plane layouts. */
1340    for (uint32_t i = 0; i < mod_plane_count; ++i) {
1341       if (drm_info->pPlaneLayouts[i].rowPitch == 0) {
1342          return vk_errorf(device,
1343                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
1344                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
1345                           "pPlaneLayouts[%u]::rowPitch is 0", i);
1346       }
1347 
1348       if (drm_info->pPlaneLayouts[i].offset == ANV_OFFSET_IMPLICIT) {
1349          return vk_errorf(device,
1350                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
1351                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
1352                           "pPlaneLayouts[%u]::offset is %" PRIu64,
1353                           i, ANV_OFFSET_IMPLICIT);
1354       }
1355    }
1356 
1357    u_foreach_bit(b, image->vk.aspects) {
1358       const VkImageAspectFlagBits aspect = 1 << b;
1359       const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1360       const struct anv_format_plane format_plane =
1361          anv_get_format_plane(devinfo, image->vk.format, plane, image->vk.tiling);
1362       const VkSubresourceLayout *primary_layout = &drm_info->pPlaneLayouts[plane];
1363 
1364       result = add_primary_surface(device, image, plane,
1365                                    format_plane,
1366                                    primary_layout->offset,
1367                                    primary_layout->rowPitch,
1368                                    isl_tiling_flags,
1369                                    isl_extra_usage_flags);
1370       if (result != VK_SUCCESS)
1371          return result;
1372 
1373       if (mod_has_aux) {
1374          const VkSubresourceLayout flat_ccs_layout = {
1375             .offset = ANV_OFFSET_IMPLICIT,
1376          };
1377 
1378          const VkSubresourceLayout *aux_layout;
1379 
1380          uint64_t aux_state_offset = ANV_OFFSET_IMPLICIT;
1381 
1382          /* We already asserted on image->n_planes == 1 when mod_has_aux is
1383           * true above, so the indexes of aux and clear color are just hard-
1384           * coded without ambiguity.
1385           */
1386          if (devinfo->has_flat_ccs) {
1387             aux_layout = &flat_ccs_layout;
1388             if (isl_drm_modifier_get_info(
1389                   drm_info->drmFormatModifier)->supports_clear_color) {
1390                aux_state_offset = drm_info->pPlaneLayouts[1].offset;
1391             }
1392          } else {
1393             aux_layout = &drm_info->pPlaneLayouts[1];
1394             if (isl_drm_modifier_get_info(
1395                   drm_info->drmFormatModifier)->supports_clear_color) {
1396                aux_state_offset = drm_info->pPlaneLayouts[2].offset;
1397             }
1398          }
1399 
1400          result = add_aux_surface_if_supported(device, image, plane,
1401                                                format_plane,
1402                                                format_list_info,
1403                                                aux_layout->offset,
1404                                                aux_layout->rowPitch,
1405                                                aux_state_offset);
1406          if (result != VK_SUCCESS)
1407             return result;
1408 
1409          assert(isl_aux_usage_has_ccs(image->planes[plane].aux_usage));
1410       }
1411    }
1412 
1413    return VK_SUCCESS;
1414 }
1415 
1416 static const struct isl_drm_modifier_info *
choose_drm_format_mod(const struct anv_physical_device * device,uint32_t modifier_count,const uint64_t * modifiers)1417 choose_drm_format_mod(const struct anv_physical_device *device,
1418                       uint32_t modifier_count, const uint64_t *modifiers)
1419 {
1420    uint64_t best_mod = UINT64_MAX;
1421    uint32_t best_score = 0;
1422 
1423    for (uint32_t i = 0; i < modifier_count; ++i) {
1424       uint32_t score = isl_drm_modifier_get_score(&device->info, modifiers[i]);
1425       if (score > best_score) {
1426          best_mod = modifiers[i];
1427          best_score = score;
1428       }
1429    }
1430 
1431    if (best_score > 0)
1432       return isl_drm_modifier_get_info(best_mod);
1433    else
1434       return NULL;
1435 }
1436 
1437 static VkImageUsageFlags
anv_image_create_usage(const VkImageCreateInfo * pCreateInfo,VkImageUsageFlags usage)1438 anv_image_create_usage(const VkImageCreateInfo *pCreateInfo,
1439                        VkImageUsageFlags usage)
1440 {
1441    /* Add TRANSFER_SRC usage for multisample attachment images. This is
1442     * because we might internally use the TRANSFER_SRC layout on them for
1443     * blorp operations associated with resolving those into other attachments
1444     * at the end of a subpass.
1445     *
1446     * Without this additional usage, we compute an incorrect AUX state in
1447     * anv_layout_to_aux_state().
1448     */
1449    if (pCreateInfo->samples > VK_SAMPLE_COUNT_1_BIT &&
1450        (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1451                  VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)))
1452       usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1453    return usage;
1454 }
1455 
1456 static VkResult MUST_CHECK
alloc_private_binding(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * create_info)1457 alloc_private_binding(struct anv_device *device,
1458                       struct anv_image *image,
1459                       const VkImageCreateInfo *create_info)
1460 {
1461    struct anv_image_binding *binding =
1462       &image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE];
1463 
1464    if (binding->memory_range.size == 0)
1465       return VK_SUCCESS;
1466 
1467    const VkImageSwapchainCreateInfoKHR *swapchain_info =
1468       vk_find_struct_const(create_info->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1469 
1470    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1471       /* The image will be bound to swapchain memory. */
1472       return VK_SUCCESS;
1473    }
1474 
1475    VkResult result = anv_device_alloc_bo(device, "image-binding-private",
1476                                          binding->memory_range.size, 0, 0,
1477                                          &binding->address.bo);
1478    if (result == VK_SUCCESS) {
1479       pthread_mutex_lock(&device->mutex);
1480       list_addtail(&image->link, &device->image_private_objects);
1481       pthread_mutex_unlock(&device->mutex);
1482    }
1483 
1484    return result;
1485 }
1486 
1487 static void
anv_image_finish_sparse_bindings(struct anv_image * image)1488 anv_image_finish_sparse_bindings(struct anv_image *image)
1489 {
1490    struct anv_device *device =
1491       container_of(image->vk.base.device, struct anv_device, vk);
1492 
1493    assert(anv_image_is_sparse(image));
1494 
1495    for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; i++) {
1496       struct anv_image_binding *b = &image->bindings[i];
1497 
1498       if (b->sparse_data.size != 0) {
1499          assert(b->memory_range.size == b->sparse_data.size);
1500          assert(b->address.offset == b->sparse_data.address);
1501          anv_free_sparse_bindings(device, &b->sparse_data);
1502       }
1503    }
1504 }
1505 
1506 static VkResult MUST_CHECK
anv_image_init_sparse_bindings(struct anv_image * image,const struct anv_image_create_info * create_info)1507 anv_image_init_sparse_bindings(struct anv_image *image,
1508                                const struct anv_image_create_info *create_info)
1509 {
1510    struct anv_device *device =
1511       container_of(image->vk.base.device, struct anv_device, vk);
1512    VkResult result;
1513 
1514    assert(anv_image_is_sparse(image));
1515 
1516    enum anv_bo_alloc_flags alloc_flags = 0;
1517    uint64_t explicit_address = 0;
1518    if (image->vk.create_flags & VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT) {
1519       alloc_flags |= ANV_BO_ALLOC_FIXED_ADDRESS;
1520 
1521       const VkOpaqueCaptureDescriptorDataCreateInfoEXT *opaque_info =
1522          vk_find_struct_const(create_info->vk_info->pNext,
1523                               OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT);
1524       if (opaque_info)
1525          explicit_address = *((const uint64_t *)opaque_info->opaqueCaptureDescriptorData);
1526    }
1527 
1528    for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; i++) {
1529       struct anv_image_binding *b = &image->bindings[i];
1530 
1531       if (b->memory_range.size != 0) {
1532          assert(b->sparse_data.size == 0);
1533 
1534          /* From the spec, Custom Sparse Image Block Shapes section:
1535           *   "... the size in bytes of the custom sparse image block shape
1536           *    will be reported in VkMemoryRequirements::alignment."
1537           *
1538           * ISL should have set this for us, so just assert it here.
1539           */
1540          assert(b->memory_range.alignment == ANV_SPARSE_BLOCK_SIZE);
1541          assert(b->memory_range.size % ANV_SPARSE_BLOCK_SIZE == 0);
1542 
1543          result = anv_init_sparse_bindings(device,
1544                                            b->memory_range.size,
1545                                            &b->sparse_data,
1546                                            alloc_flags,
1547                                            explicit_address,
1548                                            &b->address);
1549          if (result != VK_SUCCESS) {
1550             anv_image_finish_sparse_bindings(image);
1551             return result;
1552          }
1553       }
1554    }
1555 
1556    return VK_SUCCESS;
1557 }
1558 
1559 VkResult
anv_image_init(struct anv_device * device,struct anv_image * image,const struct anv_image_create_info * create_info)1560 anv_image_init(struct anv_device *device, struct anv_image *image,
1561                const struct anv_image_create_info *create_info)
1562 {
1563    const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
1564    const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_explicit_info = NULL;
1565    const struct isl_drm_modifier_info *isl_mod_info = NULL;
1566    VkResult r;
1567 
1568    vk_image_init(&device->vk, &image->vk, pCreateInfo);
1569 
1570    image->vk.usage = anv_image_create_usage(pCreateInfo, image->vk.usage);
1571    image->vk.stencil_usage =
1572       anv_image_create_usage(pCreateInfo, image->vk.stencil_usage);
1573 
1574    isl_surf_usage_flags_t isl_extra_usage_flags =
1575       create_info->isl_extra_usage_flags;
1576    if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1577       assert(!image->vk.wsi_legacy_scanout);
1578       mod_explicit_info =
1579          vk_find_struct_const(pCreateInfo->pNext,
1580                               IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
1581       if (mod_explicit_info) {
1582          isl_mod_info = isl_drm_modifier_get_info(mod_explicit_info->drmFormatModifier);
1583       } else {
1584          const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list_info =
1585             vk_find_struct_const(pCreateInfo->pNext,
1586                                  IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
1587          isl_mod_info = choose_drm_format_mod(device->physical,
1588                                               mod_list_info->drmFormatModifierCount,
1589                                               mod_list_info->pDrmFormatModifiers);
1590       }
1591 
1592       assert(isl_mod_info);
1593       assert(image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID);
1594       image->vk.drm_format_mod = isl_mod_info->modifier;
1595 
1596       if (isl_drm_modifier_needs_display_layout(image->vk.drm_format_mod))
1597          isl_extra_usage_flags |= ISL_SURF_USAGE_DISPLAY_BIT;
1598 
1599       /* Disable compression on gen12+ if the selected/requested modifier
1600        * doesn't support it. Prior to that we can use a private binding for
1601        * the aux surface and it should be transparent to users.
1602        */
1603       if (device->info->ver >= 12 &&
1604           !isl_drm_modifier_has_aux(image->vk.drm_format_mod)) {
1605          isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1606       }
1607    }
1608 
1609    for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; ++i) {
1610       image->bindings[i] = (struct anv_image_binding) {
1611          .memory_range = { .binding = i },
1612       };
1613    }
1614 
1615    /* In case of AHardwareBuffer import, we don't know the layout yet */
1616    if (image->vk.external_handle_types &
1617        VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
1618       image->from_ahb = true;
1619 #if DETECT_OS_ANDROID
1620       image->vk.ahb_format = anv_ahb_format_for_vk_format(image->vk.format);
1621 #endif
1622       return VK_SUCCESS;
1623    }
1624 
1625    image->n_planes = anv_get_format_planes(image->vk.format);
1626 
1627 #ifdef VK_USE_PLATFORM_ANDROID_KHR
1628    /* In the case of gralloc-backed swap chain image, we don't know the
1629     * layout yet.
1630     */
1631    if (vk_find_struct_const(pCreateInfo->pNext,
1632                             IMAGE_SWAPCHAIN_CREATE_INFO_KHR) != NULL)
1633       return VK_SUCCESS;
1634 #endif
1635 
1636    image->from_wsi =
1637       vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA) != NULL;
1638 
1639    /* The Vulkan 1.2.165 glossary says:
1640     *
1641     *    A disjoint image consists of multiple disjoint planes, and is created
1642     *    with the VK_IMAGE_CREATE_DISJOINT_BIT bit set.
1643     */
1644    image->disjoint = image->n_planes > 1 &&
1645                      (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
1646 
1647    if (anv_is_format_emulated(device->physical, pCreateInfo->format)) {
1648       assert(image->n_planes == 1 &&
1649              vk_format_is_compressed(image->vk.format));
1650       assert(!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT));
1651 
1652       image->emu_plane_format =
1653          anv_get_emulation_format(device->physical, image->vk.format);
1654 
1655       /* for fetching the raw copmressed data and storing the decompressed
1656        * data
1657        */
1658       image->vk.create_flags |=
1659          VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
1660          VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
1661       if (image->vk.image_type == VK_IMAGE_TYPE_3D)
1662          image->vk.create_flags |= VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT;
1663       image->vk.usage |=
1664          VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
1665 
1666       /* TODO: enable compression on emulation plane */
1667       isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1668    }
1669 
1670    /* Disable aux if image supports export without modifiers. */
1671    if (image->vk.external_handle_types != 0 &&
1672        image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
1673       isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1674 
1675    if (device->queue_count > 1) {
1676       /* Notify ISL that the app may access this image from different engines.
1677        * Note that parallel access to the surface will occur regardless of the
1678        * sharing mode.
1679        */
1680       isl_extra_usage_flags |= ISL_SURF_USAGE_MULTI_ENGINE_PAR_BIT;
1681 
1682       /* If the resource is created with the CONCURRENT sharing mode, we can't
1683        * support compression because we aren't allowed barriers in order to
1684        * construct the main surface data with FULL_RESOLVE/PARTIAL_RESOLVE.
1685        */
1686       if (image->vk.sharing_mode == VK_SHARING_MODE_CONCURRENT)
1687          isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1688    }
1689 
1690    /* Aux is pointless if it will never be used as an attachment. */
1691    if (vk_format_is_depth_or_stencil(image->vk.format) &&
1692        !(image->vk.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
1693       isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1694 
1695    /* TODO: Adjust blorp for multi-LOD HiZ surface on Gen9. */
1696    if (vk_format_has_depth(image->vk.format) &&
1697        image->vk.mip_levels > 1 && device->info->ver == 9) {
1698       anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Enable multi-LOD HiZ");
1699       isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1700    }
1701 
1702    /* Mark WSI images with the right surf usage. */
1703    if (image->from_wsi)
1704       isl_extra_usage_flags |= ISL_SURF_USAGE_DISPLAY_BIT;
1705 
1706    const isl_tiling_flags_t isl_tiling_flags =
1707       choose_isl_tiling_flags(device->info, create_info, isl_mod_info,
1708                               image->vk.wsi_legacy_scanout);
1709 
1710    const VkImageFormatListCreateInfo *fmt_list =
1711       vk_find_struct_const(pCreateInfo->pNext,
1712                            IMAGE_FORMAT_LIST_CREATE_INFO);
1713 
1714    if ((image->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) &&
1715        image->vk.samples == 1) {
1716       if (image->n_planes != 1) {
1717          /* Multiplanar images seem to hit a sampler bug with CCS and R16G16
1718           * format. (Putting the clear state a page/4096bytes further fixes
1719           * the issue).
1720           */
1721          isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1722       }
1723 
1724       if ((image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT) &&
1725           !image->from_wsi) {
1726          /* The image may alias a plane of a multiplanar image. Above we ban
1727           * CCS on multiplanar images.
1728           *
1729           * We must also reject aliasing of any image that uses
1730           * ANV_IMAGE_MEMORY_BINDING_PRIVATE. Since we're already rejecting
1731           * all aliasing here, there's no need to further analyze if the image
1732           * needs a private binding.
1733           */
1734          isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1735       }
1736 
1737       if (device->info->ver >= 12 &&
1738           !anv_formats_ccs_e_compatible(device->info, image->vk.create_flags,
1739                                         image->vk.format, image->vk.tiling,
1740                                         image->vk.usage, fmt_list)) {
1741          /* CCS_E is the only aux-mode supported for single sampled color
1742           * surfaces on gfx12+. If we can't support it, we should configure
1743           * the main surface without aux support.
1744           */
1745          isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1746       }
1747    }
1748 
1749    if (mod_explicit_info) {
1750       r = add_all_surfaces_explicit_layout(device, image, fmt_list,
1751                                            mod_explicit_info, isl_tiling_flags,
1752                                            isl_extra_usage_flags);
1753    } else {
1754       r = add_all_surfaces_implicit_layout(device, image, fmt_list, create_info->stride,
1755                                            isl_tiling_flags,
1756                                            isl_extra_usage_flags);
1757    }
1758 
1759    if (r != VK_SUCCESS)
1760       goto fail;
1761 
1762    if (image->emu_plane_format != VK_FORMAT_UNDEFINED) {
1763       const struct intel_device_info *devinfo = device->info;
1764       const uint32_t plane = image->n_planes;
1765       const struct anv_format_plane plane_format = anv_get_format_plane(
1766             devinfo, image->emu_plane_format, 0, image->vk.tiling);
1767 
1768       isl_surf_usage_flags_t isl_usage = anv_image_choose_isl_surf_usage(
1769          device->physical, image->vk.create_flags, image->vk.usage,
1770          isl_extra_usage_flags, VK_IMAGE_ASPECT_COLOR_BIT,
1771          image->vk.compr_flags);
1772 
1773       r = add_primary_surface(device, image, plane, plane_format,
1774                               ANV_OFFSET_IMPLICIT, 0,
1775                               isl_tiling_flags, isl_usage);
1776       if (r != VK_SUCCESS)
1777          goto fail;
1778    }
1779 
1780    const VkVideoProfileListInfoKHR *video_profile =
1781       vk_find_struct_const(pCreateInfo->pNext,
1782                            VIDEO_PROFILE_LIST_INFO_KHR);
1783    if (video_profile) {
1784       r = add_video_buffers(device, image, video_profile);
1785       if (r != VK_SUCCESS)
1786          goto fail;
1787    }
1788 
1789    if (!create_info->no_private_binding_alloc) {
1790       r = alloc_private_binding(device, image, pCreateInfo);
1791       if (r != VK_SUCCESS)
1792          goto fail;
1793    }
1794 
1795    check_memory_bindings(device, image);
1796 
1797    r = check_drm_format_mod(device, image);
1798    if (r != VK_SUCCESS)
1799       goto fail;
1800 
1801    /* Once we have all the bindings, determine whether we can do non 0 fast
1802     * clears for each plane.
1803     */
1804    for (uint32_t p = 0; p < image->n_planes; p++) {
1805       image->planes[p].can_non_zero_fast_clear =
1806          can_fast_clear_with_non_zero_color(device->info, image, p, fmt_list);
1807    }
1808 
1809    if (anv_image_is_sparse(image)) {
1810       r = anv_image_init_sparse_bindings(image, create_info);
1811       if (r != VK_SUCCESS)
1812          goto fail;
1813    }
1814 
1815    return VK_SUCCESS;
1816 
1817 fail:
1818    vk_image_finish(&image->vk);
1819    return r;
1820 }
1821 
1822 void
anv_image_finish(struct anv_image * image)1823 anv_image_finish(struct anv_image *image)
1824 {
1825    struct anv_device *device =
1826       container_of(image->vk.base.device, struct anv_device, vk);
1827 
1828    if (anv_image_is_sparse(image))
1829       anv_image_finish_sparse_bindings(image);
1830 
1831    /* Unmap a CCS so that if the bound region of the image is rebound to
1832     * another image, the AUX tables will be cleared to allow for a new
1833     * mapping.
1834     */
1835    for (int p = 0; p < image->n_planes; ++p) {
1836       if (image->planes[p].aux_tt.mapped) {
1837          intel_aux_map_del_mapping(device->aux_map_ctx,
1838                                    image->planes[p].aux_tt.addr,
1839                                    image->planes[p].aux_tt.size);
1840       }
1841    }
1842 
1843    if (image->from_gralloc) {
1844       assert(!image->disjoint);
1845       assert(image->n_planes == 1);
1846       assert(image->planes[0].primary_surface.memory_range.binding ==
1847              ANV_IMAGE_MEMORY_BINDING_MAIN);
1848       assert(image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo != NULL);
1849       anv_device_release_bo(device, image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo);
1850    }
1851 
1852    struct anv_bo *private_bo = image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].address.bo;
1853    if (private_bo) {
1854       pthread_mutex_lock(&device->mutex);
1855       list_del(&image->link);
1856       pthread_mutex_unlock(&device->mutex);
1857       anv_device_release_bo(device, private_bo);
1858    }
1859 
1860    vk_image_finish(&image->vk);
1861 }
1862 
1863 static struct anv_image *
anv_swapchain_get_image(VkSwapchainKHR swapchain,uint32_t index)1864 anv_swapchain_get_image(VkSwapchainKHR swapchain,
1865                         uint32_t index)
1866 {
1867    VkImage image = wsi_common_get_image(swapchain, index);
1868    return anv_image_from_handle(image);
1869 }
1870 
1871 static VkResult
anv_image_init_from_create_info(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * pCreateInfo,bool no_private_binding_alloc)1872 anv_image_init_from_create_info(struct anv_device *device,
1873                                 struct anv_image *image,
1874                                 const VkImageCreateInfo *pCreateInfo,
1875                                 bool no_private_binding_alloc)
1876 {
1877    if (pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {
1878       VkResult result =
1879          anv_sparse_image_check_support(device->physical,
1880                                         pCreateInfo->flags,
1881                                         pCreateInfo->tiling,
1882                                         pCreateInfo->samples,
1883                                         pCreateInfo->imageType,
1884                                         pCreateInfo->format);
1885       if (result != VK_SUCCESS)
1886          return result;
1887    }
1888 
1889    const VkNativeBufferANDROID *gralloc_info =
1890       vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
1891    if (gralloc_info)
1892       return anv_image_init_from_gralloc(device, image, pCreateInfo,
1893                                          gralloc_info);
1894 
1895    struct anv_image_create_info create_info = {
1896       .vk_info = pCreateInfo,
1897       .no_private_binding_alloc = no_private_binding_alloc,
1898    };
1899 
1900    return anv_image_init(device, image, &create_info);
1901 }
1902 
anv_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)1903 VkResult anv_CreateImage(
1904     VkDevice                                    _device,
1905     const VkImageCreateInfo*                    pCreateInfo,
1906     const VkAllocationCallbacks*                pAllocator,
1907     VkImage*                                    pImage)
1908 {
1909    ANV_FROM_HANDLE(anv_device, device, _device);
1910 
1911    if ((device->physical->sparse_type == ANV_SPARSE_TYPE_NOT_SUPPORTED) &&
1912        INTEL_DEBUG(DEBUG_SPARSE) &&
1913        pCreateInfo->flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
1914                              VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT |
1915                              VK_IMAGE_CREATE_SPARSE_ALIASED_BIT))
1916       fprintf(stderr, "=== %s %s:%d flags:0x%08x\n", __func__, __FILE__,
1917               __LINE__, pCreateInfo->flags);
1918 
1919 #ifndef VK_USE_PLATFORM_ANDROID_KHR
1920    /* Skip the WSI common swapchain creation here on Android. Similar to ahw,
1921     * this case is handled by a partial image init and then resolved when the
1922     * image is bound and gralloc info is passed.
1923     */
1924    const VkImageSwapchainCreateInfoKHR *swapchain_info =
1925       vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1926    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1927       return wsi_common_create_swapchain_image(&device->physical->wsi_device,
1928                                                pCreateInfo,
1929                                                swapchain_info->swapchain,
1930                                                pImage);
1931    }
1932 #endif
1933 
1934    struct anv_image *image =
1935       vk_object_zalloc(&device->vk, pAllocator, sizeof(*image),
1936                        VK_OBJECT_TYPE_IMAGE);
1937    if (!image)
1938       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1939 
1940    VkResult result = anv_image_init_from_create_info(device, image,
1941                                                      pCreateInfo,
1942                                                      false);
1943    if (result != VK_SUCCESS) {
1944       vk_object_free(&device->vk, pAllocator, image);
1945       return result;
1946    }
1947 
1948    ANV_RMV(image_create, device, false, image);
1949 
1950    *pImage = anv_image_to_handle(image);
1951 
1952    return result;
1953 }
1954 
1955 void
anv_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)1956 anv_DestroyImage(VkDevice _device, VkImage _image,
1957                  const VkAllocationCallbacks *pAllocator)
1958 {
1959    ANV_FROM_HANDLE(anv_device, device, _device);
1960    ANV_FROM_HANDLE(anv_image, image, _image);
1961 
1962    if (!image)
1963       return;
1964 
1965    ANV_RMV(image_destroy, device, image);
1966 
1967    assert(&device->vk == image->vk.base.device);
1968    anv_image_finish(image);
1969 
1970    vk_free2(&device->vk.alloc, pAllocator, image);
1971 }
1972 
1973 /* We are binding AHardwareBuffer. Get a description, resolve the
1974  * format and prepare anv_image properly.
1975  */
1976 static void
resolve_ahw_image(struct anv_device * device,struct anv_image * image,struct anv_device_memory * mem)1977 resolve_ahw_image(struct anv_device *device,
1978                   struct anv_image *image,
1979                   struct anv_device_memory *mem)
1980 {
1981 #if DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 26
1982    assert(mem->vk.ahardware_buffer);
1983    AHardwareBuffer_Desc desc;
1984    AHardwareBuffer_describe(mem->vk.ahardware_buffer, &desc);
1985    VkResult result;
1986 
1987    /* Check tiling. */
1988    enum isl_tiling tiling;
1989    const native_handle_t *handle =
1990       AHardwareBuffer_getNativeHandle(mem->vk.ahardware_buffer);
1991    struct u_gralloc_buffer_handle gr_handle = {
1992       .handle = handle,
1993       .hal_format = desc.format,
1994       .pixel_stride = desc.stride,
1995    };
1996    result = anv_android_get_tiling(device, &gr_handle, &tiling);
1997    assert(result == VK_SUCCESS);
1998    isl_tiling_flags_t isl_tiling_flags = (1u << tiling);
1999 
2000    /* Check format. */
2001    VkFormat vk_format = vk_format_from_android(desc.format, desc.usage);
2002    assert(vk_format != VK_FORMAT_UNDEFINED);
2003 
2004    /* Now we are able to fill anv_image fields properly and create
2005     * isl_surface for it.
2006     */
2007    vk_image_set_format(&image->vk, vk_format);
2008    image->n_planes = anv_get_format_planes(image->vk.format);
2009 
2010    result = add_all_surfaces_implicit_layout(device, image, NULL, desc.stride,
2011                                              isl_tiling_flags,
2012                                              ISL_SURF_USAGE_DISABLE_AUX_BIT);
2013    assert(result == VK_SUCCESS);
2014 #endif
2015 }
2016 
2017 static void
resolve_anb_image(struct anv_device * device,struct anv_image * image,const VkNativeBufferANDROID * gralloc_info)2018 resolve_anb_image(struct anv_device *device,
2019                   struct anv_image *image,
2020                   const VkNativeBufferANDROID *gralloc_info)
2021 {
2022 #if DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 29
2023    VkResult result;
2024 
2025    /* Check tiling. */
2026    enum isl_tiling tiling;
2027    struct u_gralloc_buffer_handle gr_handle = {
2028       .handle = gralloc_info->handle,
2029       .hal_format = gralloc_info->format,
2030       .pixel_stride = gralloc_info->stride,
2031    };
2032    result = anv_android_get_tiling(device, &gr_handle, &tiling);
2033    assert(result == VK_SUCCESS);
2034 
2035    isl_tiling_flags_t isl_tiling_flags = (1u << tiling);
2036 
2037    /* Now we are able to fill anv_image fields properly and create
2038     * isl_surface for it.
2039     */
2040    result = add_all_surfaces_implicit_layout(device, image, NULL, gralloc_info->stride,
2041                                              isl_tiling_flags,
2042                                              ISL_SURF_USAGE_DISABLE_AUX_BIT);
2043    assert(result == VK_SUCCESS);
2044 #endif
2045 }
2046 
2047 static bool
anv_image_is_pat_compressible(struct anv_device * device,struct anv_image * image)2048 anv_image_is_pat_compressible(struct anv_device *device, struct anv_image *image)
2049 {
2050    if (INTEL_DEBUG(DEBUG_NO_CCS))
2051       return false;
2052 
2053    if (device->info->ver < 20)
2054       return false;
2055 
2056    /*
2057     * Be aware that Vulkan spec requires that Images with some properties
2058     * always returns the same memory types, so this function also needs to
2059     * have the same return for the same set of properties.
2060     *
2061     *    For images created with a color format, the memoryTypeBits member is
2062     *    identical for all VkImage objects created with the same combination
2063     *    of values for the tiling member, the
2064     *    VK_IMAGE_CREATE_SPARSE_BINDING_BIT bit of the flags member, the
2065     *    VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT bit of the flags
2066     *    member, handleTypes member of VkExternalMemoryImageCreateInfo, and
2067     *    the VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT of the usage member in
2068     *    the VkImageCreateInfo structure passed to vkCreateImage.
2069     *
2070     *    For images created with a depth/stencil format, the memoryTypeBits
2071     *    member is identical for all VkImage objects created with the same
2072     *    combination of values for the format member, the tiling member, the
2073     *    VK_IMAGE_CREATE_SPARSE_BINDING_BIT bit of the flags member, the
2074     *    VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT bit of the flags
2075     *    member, handleTypes member of VkExternalMemoryImageCreateInfo, and
2076     *    the VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT of the usage member in
2077     *    the VkImageCreateInfo structure passed to vkCreateImage.
2078     */
2079 
2080    /* There are no compression-enabled modifiers on Xe2, and all legacy
2081     * modifiers are not defined with compression. We simply disable
2082     * compression on all modifiers.
2083     *
2084     * We disable this in anv_AllocateMemory() as well.
2085     */
2086    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
2087       return false;
2088 
2089    return true;
2090 }
2091 
2092 void
anv_image_get_memory_requirements(struct anv_device * device,struct anv_image * image,VkImageAspectFlags aspects,VkMemoryRequirements2 * pMemoryRequirements)2093 anv_image_get_memory_requirements(struct anv_device *device,
2094                                   struct anv_image *image,
2095                                   VkImageAspectFlags aspects,
2096                                   VkMemoryRequirements2 *pMemoryRequirements)
2097 {
2098    /* The Vulkan spec (git aaed022) says:
2099     *
2100     *    memoryTypeBits is a bitfield and contains one bit set for every
2101     *    supported memory type for the resource. The bit `1<<i` is set if and
2102     *    only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
2103     *    structure for the physical device is supported.
2104     */
2105    uint32_t memory_types;
2106 
2107    if (image->vk.create_flags & VK_IMAGE_CREATE_PROTECTED_BIT) {
2108       memory_types = device->physical->memory.protected_mem_types;
2109    } else {
2110       memory_types = device->physical->memory.default_buffer_mem_types;
2111       if (anv_image_is_pat_compressible(device, image))
2112          memory_types |= device->physical->memory.compressed_mem_types;
2113    }
2114 
2115    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
2116       switch (ext->sType) {
2117       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
2118          VkMemoryDedicatedRequirements *requirements = (void *)ext;
2119          if (image->vk.wsi_legacy_scanout ||
2120              image->from_ahb ||
2121              (isl_drm_modifier_has_aux(image->vk.drm_format_mod) &&
2122               anv_image_uses_aux_map(device, image))) {
2123             /* If we need to set the tiling for external consumers or the
2124              * modifier involves AUX tables, we need a dedicated allocation.
2125              *
2126              * See also anv_AllocateMemory.
2127              */
2128             requirements->prefersDedicatedAllocation = true;
2129             requirements->requiresDedicatedAllocation = true;
2130          } else {
2131             requirements->prefersDedicatedAllocation = false;
2132             requirements->requiresDedicatedAllocation = false;
2133          }
2134          break;
2135       }
2136 
2137       default:
2138          vk_debug_ignored_stype(ext->sType);
2139          break;
2140       }
2141    }
2142 
2143    /* If the image is disjoint, then we must return the memory requirements for
2144     * the single plane specified in VkImagePlaneMemoryRequirementsInfo. If
2145     * non-disjoint, then exactly one set of memory requirements exists for the
2146     * whole image.
2147     *
2148     * This is enforced by the Valid Usage for VkImageMemoryRequirementsInfo2,
2149     * which requires that the app provide VkImagePlaneMemoryRequirementsInfo if
2150     * and only if the image is disjoint (that is, multi-planar format and
2151     * VK_IMAGE_CREATE_DISJOINT_BIT).
2152     */
2153    const struct anv_image_binding *binding;
2154    if (image->disjoint) {
2155       assert(util_bitcount(aspects) == 1);
2156       assert(aspects & image->vk.aspects);
2157       binding = anv_image_aspect_to_binding(image, aspects);
2158    } else {
2159       assert(aspects == image->vk.aspects);
2160       binding = &image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN];
2161    }
2162 
2163    pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
2164       .size = binding->memory_range.size,
2165       .alignment = binding->memory_range.alignment,
2166       .memoryTypeBits = memory_types,
2167    };
2168 }
2169 
anv_GetImageMemoryRequirements2(VkDevice _device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)2170 void anv_GetImageMemoryRequirements2(
2171     VkDevice                                    _device,
2172     const VkImageMemoryRequirementsInfo2*       pInfo,
2173     VkMemoryRequirements2*                      pMemoryRequirements)
2174 {
2175    ANV_FROM_HANDLE(anv_device, device, _device);
2176    ANV_FROM_HANDLE(anv_image, image, pInfo->image);
2177 
2178    VkImageAspectFlags aspects = image->vk.aspects;
2179 
2180    vk_foreach_struct_const(ext, pInfo->pNext) {
2181       switch (ext->sType) {
2182       case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: {
2183          assert(image->disjoint);
2184          const VkImagePlaneMemoryRequirementsInfo *plane_reqs =
2185             (const VkImagePlaneMemoryRequirementsInfo *) ext;
2186          aspects = plane_reqs->planeAspect;
2187          break;
2188       }
2189 
2190       default:
2191          vk_debug_ignored_stype(ext->sType);
2192          break;
2193       }
2194    }
2195 
2196    anv_image_get_memory_requirements(device, image, aspects,
2197                                      pMemoryRequirements);
2198 }
2199 
anv_GetDeviceImageMemoryRequirements(VkDevice _device,const VkDeviceImageMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)2200 void anv_GetDeviceImageMemoryRequirements(
2201     VkDevice                                    _device,
2202     const VkDeviceImageMemoryRequirements*   pInfo,
2203     VkMemoryRequirements2*                      pMemoryRequirements)
2204 {
2205    ANV_FROM_HANDLE(anv_device, device, _device);
2206    struct anv_image image = { 0 };
2207 
2208    if ((device->physical->sparse_type == ANV_SPARSE_TYPE_NOT_SUPPORTED) &&
2209        INTEL_DEBUG(DEBUG_SPARSE) &&
2210        pInfo->pCreateInfo->flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
2211                                     VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT |
2212                                     VK_IMAGE_CREATE_SPARSE_ALIASED_BIT))
2213       fprintf(stderr, "=== %s %s:%d flags:0x%08x\n", __func__, __FILE__,
2214               __LINE__, pInfo->pCreateInfo->flags);
2215 
2216    ASSERTED VkResult result =
2217       anv_image_init_from_create_info(device, &image, pInfo->pCreateInfo, true);
2218    assert(result == VK_SUCCESS);
2219 
2220    VkImageAspectFlags aspects =
2221       image.disjoint ? pInfo->planeAspect : image.vk.aspects;
2222 
2223    anv_image_get_memory_requirements(device, &image, aspects,
2224                                      pMemoryRequirements);
2225    anv_image_finish(&image);
2226 }
2227 
2228 static void
anv_image_get_sparse_memory_requirements(struct anv_device * device,struct anv_image * image,VkImageAspectFlags aspects,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)2229 anv_image_get_sparse_memory_requirements(
2230       struct anv_device *device,
2231       struct anv_image *image,
2232       VkImageAspectFlags aspects,
2233       uint32_t *pSparseMemoryRequirementCount,
2234       VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
2235 {
2236    VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, reqs,
2237                           pSparseMemoryRequirements,
2238                           pSparseMemoryRequirementCount);
2239 
2240    /* From the spec:
2241     *   "The sparse image must have been created using the
2242     *    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT flag to retrieve valid sparse
2243     *    image memory requirements."
2244     */
2245    if (!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT))
2246       return;
2247 
2248    VkSparseImageMemoryRequirements ds_mem_reqs = {};
2249    VkSparseImageMemoryRequirements2 *ds_reqs_ptr = NULL;
2250 
2251    u_foreach_bit(b, aspects) {
2252       VkImageAspectFlagBits aspect = 1 << b;
2253       const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2254       struct isl_surf *surf = &image->planes[plane].primary_surface.isl;
2255 
2256       VkSparseImageFormatProperties format_props =
2257          anv_sparse_calc_image_format_properties(device->physical, aspect,
2258                                                  image->vk.image_type,
2259                                                  image->vk.samples, surf);
2260 
2261       uint32_t miptail_first_lod;
2262       VkDeviceSize miptail_size, miptail_offset, miptail_stride;
2263       anv_sparse_calc_miptail_properties(device, image, aspect,
2264                                          &miptail_first_lod, &miptail_size,
2265                                          &miptail_offset, &miptail_stride);
2266 
2267       VkSparseImageMemoryRequirements mem_reqs = {
2268          .formatProperties = format_props,
2269          .imageMipTailFirstLod = miptail_first_lod,
2270          .imageMipTailSize = miptail_size,
2271          .imageMipTailOffset = miptail_offset,
2272          .imageMipTailStride = miptail_stride,
2273       };
2274 
2275       /* If both depth and stencil are the same, unify them if possible. */
2276       if (aspect & (VK_IMAGE_ASPECT_DEPTH_BIT |
2277                     VK_IMAGE_ASPECT_STENCIL_BIT)) {
2278          if (!ds_reqs_ptr) {
2279             ds_mem_reqs = mem_reqs;
2280          } else if (ds_mem_reqs.formatProperties.imageGranularity.width ==
2281                        mem_reqs.formatProperties.imageGranularity.width &&
2282                     ds_mem_reqs.formatProperties.imageGranularity.height ==
2283                        mem_reqs.formatProperties.imageGranularity.height &&
2284                     ds_mem_reqs.formatProperties.imageGranularity.depth ==
2285                        mem_reqs.formatProperties.imageGranularity.depth &&
2286                     ds_mem_reqs.imageMipTailFirstLod ==
2287                        mem_reqs.imageMipTailFirstLod &&
2288                     ds_mem_reqs.imageMipTailSize ==
2289                        mem_reqs.imageMipTailSize &&
2290                     ds_mem_reqs.imageMipTailOffset ==
2291                        mem_reqs.imageMipTailOffset &&
2292                     ds_mem_reqs.imageMipTailStride ==
2293                        mem_reqs.imageMipTailStride) {
2294             ds_reqs_ptr->memoryRequirements.formatProperties.aspectMask |=
2295                aspect;
2296             continue;
2297          }
2298       }
2299 
2300       vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &reqs, r) {
2301          r->memoryRequirements = mem_reqs;
2302          if (aspect & (VK_IMAGE_ASPECT_DEPTH_BIT |
2303                        VK_IMAGE_ASPECT_STENCIL_BIT))
2304             ds_reqs_ptr = r;
2305       }
2306    }
2307 }
2308 
anv_GetImageSparseMemoryRequirements2(VkDevice _device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)2309 void anv_GetImageSparseMemoryRequirements2(
2310     VkDevice                                    _device,
2311     const VkImageSparseMemoryRequirementsInfo2* pInfo,
2312     uint32_t*                                   pSparseMemoryRequirementCount,
2313     VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements)
2314 {
2315    ANV_FROM_HANDLE(anv_device, device, _device);
2316    ANV_FROM_HANDLE(anv_image, image, pInfo->image);
2317 
2318    if (!anv_sparse_residency_is_enabled(device)) {
2319       if ((device->physical->sparse_type == ANV_SPARSE_TYPE_NOT_SUPPORTED) &&
2320           INTEL_DEBUG(DEBUG_SPARSE))
2321          fprintf(stderr, "=== [%s:%d] [%s]\n", __FILE__, __LINE__, __func__);
2322 
2323       *pSparseMemoryRequirementCount = 0;
2324       return;
2325    }
2326 
2327    anv_image_get_sparse_memory_requirements(device, image, image->vk.aspects,
2328                                             pSparseMemoryRequirementCount,
2329                                             pSparseMemoryRequirements);
2330 }
2331 
anv_GetDeviceImageSparseMemoryRequirements(VkDevice _device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)2332 void anv_GetDeviceImageSparseMemoryRequirements(
2333     VkDevice                                    _device,
2334     const VkDeviceImageMemoryRequirements*      pInfo,
2335     uint32_t*                                   pSparseMemoryRequirementCount,
2336     VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements)
2337 {
2338    ANV_FROM_HANDLE(anv_device, device, _device);
2339    struct anv_image image = { 0 };
2340 
2341    if (!anv_sparse_residency_is_enabled(device)) {
2342       if ((device->physical->sparse_type == ANV_SPARSE_TYPE_NOT_SUPPORTED) &&
2343           INTEL_DEBUG(DEBUG_SPARSE))
2344          fprintf(stderr, "=== [%s:%d] [%s]\n", __FILE__, __LINE__, __func__);
2345 
2346       *pSparseMemoryRequirementCount = 0;
2347       return;
2348    }
2349 
2350    /* This function is similar to anv_GetDeviceImageMemoryRequirements, in
2351     * which it actually creates an image, gets the properties and then
2352     * destroys the image.
2353     *
2354     * We could one day refactor things to allow us to gather the properties
2355     * without having to actually create the image, maybe by reworking ISL to
2356     * separate creation from parameter computing.
2357     */
2358    VkResult result =
2359       anv_image_init_from_create_info(device, &image, pInfo->pCreateInfo,
2360                                       true /* no_private_binding_alloc */);
2361    if (result != VK_SUCCESS) {
2362       *pSparseMemoryRequirementCount = 0;
2363       return;
2364    }
2365 
2366    /* The spec says:
2367     *  "planeAspect is a VkImageAspectFlagBits value specifying the aspect
2368     *   corresponding to the image plane to query. This parameter is ignored
2369     *   unless pCreateInfo::tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
2370     *   or pCreateInfo::flags has VK_IMAGE_CREATE_DISJOINT_BIT set."
2371     */
2372    VkImageAspectFlags aspects =
2373       (pInfo->pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT) ||
2374       (pInfo->pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
2375          ? pInfo->planeAspect : image.vk.aspects;
2376 
2377    anv_image_get_sparse_memory_requirements(device, &image, aspects,
2378                                             pSparseMemoryRequirementCount,
2379                                             pSparseMemoryRequirements);
2380 
2381    anv_image_finish(&image);
2382 }
2383 
2384 static bool
anv_image_map_aux_tt(struct anv_device * device,struct anv_image * image,uint32_t plane)2385 anv_image_map_aux_tt(struct anv_device *device,
2386                      struct anv_image *image, uint32_t plane)
2387 {
2388    const struct anv_address main_addr = anv_image_address(
2389       image, &image->planes[plane].primary_surface.memory_range);
2390    struct anv_bo *bo = main_addr.bo;
2391    assert(bo != NULL);
2392 
2393    /* If the additional memory padding was added at the end of the BO for CCS
2394     * data, map this region at the granularity of the main/CCS pages.
2395     *
2396     * Otherwise the image should have additional CCS data at the computed
2397     * offset.
2398     */
2399    if (device->physical->alloc_aux_tt_mem &&
2400        (bo->alloc_flags & ANV_BO_ALLOC_AUX_CCS)) {
2401       uint64_t main_aux_alignment =
2402          intel_aux_map_get_alignment(device->aux_map_ctx);
2403       assert(bo->offset % main_aux_alignment == 0);
2404       const struct anv_address start_addr = (struct anv_address) {
2405          .bo = bo,
2406          .offset = ROUND_DOWN_TO(main_addr.offset, main_aux_alignment),
2407       };
2408       const struct anv_address aux_addr = (struct anv_address) {
2409          .bo = bo,
2410          .offset = bo->ccs_offset +
2411                    intel_aux_main_to_aux_offset(device->aux_map_ctx,
2412                                                 start_addr.offset),
2413       };
2414       const struct isl_surf *surf = &image->planes[plane].primary_surface.isl;
2415       const uint64_t format_bits =
2416          intel_aux_map_format_bits_for_isl_surf(surf);
2417       /* Make sure to have the mapping cover the entire image from the aux
2418        * aligned start.
2419        */
2420       const uint64_t main_size = align(
2421          (main_addr.offset - start_addr.offset) + surf->size_B,
2422          main_aux_alignment);
2423 
2424       if (intel_aux_map_add_mapping(device->aux_map_ctx,
2425                                     anv_address_physical(start_addr),
2426                                     anv_address_physical(aux_addr),
2427                                     main_size, format_bits)) {
2428          image->planes[plane].aux_tt.mapped = true;
2429          image->planes[plane].aux_tt.addr = anv_address_physical(start_addr);
2430          image->planes[plane].aux_tt.size = main_size;
2431          return true;
2432       }
2433    } else {
2434       if (anv_address_allows_aux_map(device, main_addr)) {
2435          const struct anv_address aux_addr =
2436             anv_image_address(image,
2437                               &image->planes[plane].compr_ctrl_memory_range);
2438          const struct isl_surf *surf =
2439             &image->planes[plane].primary_surface.isl;
2440          const uint64_t format_bits =
2441             intel_aux_map_format_bits_for_isl_surf(surf);
2442          if (intel_aux_map_add_mapping(device->aux_map_ctx,
2443                                        anv_address_physical(main_addr),
2444                                        anv_address_physical(aux_addr),
2445                                        surf->size_B, format_bits)) {
2446             image->planes[plane].aux_tt.mapped = true;
2447             image->planes[plane].aux_tt.addr = anv_address_physical(main_addr);
2448             image->planes[plane].aux_tt.size = surf->size_B;
2449             return true;
2450          }
2451       }
2452    }
2453 
2454    return false;
2455 
2456 }
2457 
2458 static VkResult
anv_bind_image_memory(struct anv_device * device,const VkBindImageMemoryInfo * bind_info)2459 anv_bind_image_memory(struct anv_device *device,
2460                       const VkBindImageMemoryInfo *bind_info)
2461 {
2462    ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory);
2463    ANV_FROM_HANDLE(anv_image, image, bind_info->image);
2464    bool did_bind = false;
2465 
2466    const VkBindMemoryStatusKHR *bind_status =
2467       vk_find_struct_const(bind_info->pNext, BIND_MEMORY_STATUS_KHR);
2468 
2469    assert(!anv_image_is_sparse(image));
2470 
2471    /* Resolve will alter the image's aspects, do this first. */
2472    if (mem && mem->vk.ahardware_buffer)
2473       resolve_ahw_image(device, image, mem);
2474 
2475    vk_foreach_struct_const(s, bind_info->pNext) {
2476       switch (s->sType) {
2477       case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: {
2478          const VkBindImagePlaneMemoryInfo *plane_info =
2479             (const VkBindImagePlaneMemoryInfo *) s;
2480 
2481          /* Workaround for possible spec bug.
2482           *
2483           * Unlike VkImagePlaneMemoryRequirementsInfo, which requires that
2484           * the image be disjoint (that is, multi-planar format and
2485           * VK_IMAGE_CREATE_DISJOINT_BIT), VkBindImagePlaneMemoryInfo allows
2486           * the image to be non-disjoint and requires only that the image
2487           * have the DISJOINT flag. In this case, regardless of the value of
2488           * VkImagePlaneMemoryRequirementsInfo::planeAspect, the behavior is
2489           * the same as if VkImagePlaneMemoryRequirementsInfo were omitted.
2490           */
2491          if (!image->disjoint)
2492             break;
2493 
2494          struct anv_image_binding *binding =
2495             anv_image_aspect_to_binding(image, plane_info->planeAspect);
2496 
2497          binding->address = (struct anv_address) {
2498             .bo = mem->bo,
2499             .offset = bind_info->memoryOffset,
2500          };
2501 
2502          ANV_RMV(image_bind, device, image,
2503                  binding - image->bindings);
2504 
2505          did_bind = true;
2506          break;
2507       }
2508       case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: {
2509          /* Ignore this struct on Android, we cannot access swapchain
2510           * structures there.
2511           */
2512 #ifndef VK_USE_PLATFORM_ANDROID_KHR
2513          const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
2514             (const VkBindImageMemorySwapchainInfoKHR *) s;
2515          struct anv_image *swapchain_image =
2516             anv_swapchain_get_image(swapchain_info->swapchain,
2517                                     swapchain_info->imageIndex);
2518          assert(swapchain_image);
2519          assert(image->vk.aspects == swapchain_image->vk.aspects);
2520          assert(mem == NULL);
2521 
2522          for (int j = 0; j < ARRAY_SIZE(image->bindings); ++j) {
2523             assert(memory_ranges_equal(image->bindings[j].memory_range,
2524                                        swapchain_image->bindings[j].memory_range));
2525             image->bindings[j].address = swapchain_image->bindings[j].address;
2526          }
2527 
2528          /* We must bump the private binding's bo's refcount because, unlike the other
2529           * bindings, its lifetime is not application-managed.
2530           */
2531          struct anv_bo *private_bo =
2532             image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].address.bo;
2533          if (private_bo)
2534             anv_bo_ref(private_bo);
2535 
2536          did_bind = true;
2537 #endif
2538          break;
2539       }
2540 #pragma GCC diagnostic push
2541 #pragma GCC diagnostic ignored "-Wswitch"
2542       case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID: {
2543          const VkNativeBufferANDROID *gralloc_info =
2544             (const VkNativeBufferANDROID *)s;
2545          VkResult result = anv_image_bind_from_gralloc(device, image,
2546                                                        gralloc_info);
2547          if (result != VK_SUCCESS)
2548             return result;
2549 
2550          resolve_anb_image(device, image, gralloc_info);
2551          did_bind = true;
2552          break;
2553       }
2554 #pragma GCC diagnostic pop
2555       default:
2556          vk_debug_ignored_stype(s->sType);
2557          break;
2558       }
2559    }
2560 
2561    if (!did_bind) {
2562       assert(!image->disjoint);
2563 
2564       image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address =
2565          (struct anv_address) {
2566          .bo = mem->bo,
2567          .offset = bind_info->memoryOffset,
2568       };
2569 
2570       ANV_RMV(image_bind, device, image,
2571               ANV_IMAGE_MEMORY_BINDING_MAIN);
2572 
2573       did_bind = true;
2574    }
2575 
2576    /* Now that we have the BO, finalize CCS setup. */
2577    for (int p = 0; p < image->n_planes; ++p) {
2578       enum anv_image_memory_binding binding =
2579          image->planes[p].primary_surface.memory_range.binding;
2580       const struct anv_bo *bo =
2581          image->bindings[binding].address.bo;
2582 
2583       if (!bo || !isl_aux_usage_has_ccs(image->planes[p].aux_usage))
2584          continue;
2585 
2586       /* Do nothing if flat CCS requirements are satisfied.
2587        *
2588        * Also, assume that imported BOs with a modifier including
2589        * CCS live only in local memory. Otherwise the exporter should
2590        * have failed the creation of the BO.
2591        */
2592       if (device->info->has_flat_ccs &&
2593           (anv_bo_is_vram_only(bo) ||
2594            (bo->alloc_flags & ANV_BO_ALLOC_IMPORTED)))
2595          continue;
2596 
2597       /* If the AUX-TT mapping succeeds, there is nothing else to do. */
2598       if (device->info->has_aux_map && anv_image_map_aux_tt(device, image, p))
2599          continue;
2600 
2601       /* Do nothing except for gfx12. There are no special requirements. */
2602       if (device->info->ver != 12)
2603          continue;
2604 
2605       /* The plane's BO cannot support CCS, disable compression on it. */
2606       assert(!isl_drm_modifier_has_aux(image->vk.drm_format_mod));
2607 
2608       anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
2609                     "BO lacks CCS support. Disabling the CCS aux usage.");
2610 
2611       if (image->planes[p].aux_surface.memory_range.size > 0) {
2612          assert(image->planes[p].aux_usage == ISL_AUX_USAGE_HIZ_CCS ||
2613                 image->planes[p].aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT);
2614          image->planes[p].aux_usage = ISL_AUX_USAGE_HIZ;
2615       } else {
2616          assert(image->planes[p].aux_usage == ISL_AUX_USAGE_CCS_E ||
2617                 image->planes[p].aux_usage == ISL_AUX_USAGE_FCV_CCS_E ||
2618                 image->planes[p].aux_usage == ISL_AUX_USAGE_STC_CCS);
2619          image->planes[p].aux_usage = ISL_AUX_USAGE_NONE;
2620       }
2621    }
2622 
2623    if (bind_status)
2624       *bind_status->pResult = VK_SUCCESS;
2625 
2626    return VK_SUCCESS;
2627 }
2628 
anv_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)2629 VkResult anv_BindImageMemory2(
2630     VkDevice                                    _device,
2631     uint32_t                                    bindInfoCount,
2632     const VkBindImageMemoryInfo*                pBindInfos)
2633 {
2634    ANV_FROM_HANDLE(anv_device, device, _device);
2635    VkResult result = VK_SUCCESS;
2636 
2637    for (uint32_t i = 0; i < bindInfoCount; i++) {
2638       VkResult res = anv_bind_image_memory(device, &pBindInfos[i]);
2639       if (result == VK_SUCCESS && res != VK_SUCCESS)
2640          result = res;
2641    }
2642 
2643    return result;
2644 }
2645 
2646 static void
anv_get_image_subresource_layout(const struct anv_image * image,const VkImageSubresource2KHR * subresource,VkSubresourceLayout2KHR * layout)2647 anv_get_image_subresource_layout(const struct anv_image *image,
2648                                  const VkImageSubresource2KHR *subresource,
2649                                  VkSubresourceLayout2KHR *layout)
2650 {
2651    const struct anv_image_memory_range *mem_range;
2652 
2653    assert(__builtin_popcount(subresource->imageSubresource.aspectMask) == 1);
2654 
2655    /* The Vulkan spec requires that aspectMask be
2656     * VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT if tiling is
2657     * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
2658     *
2659     * For swapchain images, the Vulkan spec says that every swapchain image has
2660     * tiling VK_IMAGE_TILING_OPTIMAL, but we may choose
2661     * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT internally.  Vulkan doesn't allow
2662     * vkGetImageSubresourceLayout for images with VK_IMAGE_TILING_OPTIMAL,
2663     * therefore it's invalid for the application to call this on a swapchain
2664     * image.  The WSI code, however, knows when it has internally created
2665     * a swapchain image with VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
2666     * so it _should_ correctly use VK_IMAGE_ASPECT_MEMORY_PLANE_* in that case.
2667     * But it incorrectly uses VK_IMAGE_ASPECT_PLANE_*, so we have a temporary
2668     * workaround.
2669     *
2670     * https://gitlab.freedesktop.org/mesa/mesa/-/issues/10176
2671     */
2672    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
2673       /* TODO(chadv): Drop this workaround when WSI gets fixed. */
2674       uint32_t mem_plane;
2675       switch (subresource->imageSubresource.aspectMask) {
2676       case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT:
2677       case VK_IMAGE_ASPECT_PLANE_0_BIT:
2678          mem_plane = 0;
2679          break;
2680       case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:
2681       case VK_IMAGE_ASPECT_PLANE_1_BIT:
2682          mem_plane = 1;
2683          break;
2684       case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:
2685       case VK_IMAGE_ASPECT_PLANE_2_BIT:
2686          mem_plane = 2;
2687          break;
2688       default:
2689          unreachable("bad VkImageAspectFlags");
2690       }
2691 
2692       uint32_t row_pitch_B;
2693       if (isl_drm_modifier_plane_is_clear_color(image->vk.drm_format_mod,
2694                                                 mem_plane)) {
2695          assert(image->n_planes == 1);
2696 
2697          mem_range = &image->planes[0].fast_clear_memory_range;
2698          row_pitch_B = ISL_DRM_CC_PLANE_PITCH_B;
2699       } else if (mem_plane == 1 &&
2700                  image->planes[0].compr_ctrl_memory_range.size > 0) {
2701          assert(image->n_planes == 1);
2702          assert(isl_drm_modifier_has_aux(image->vk.drm_format_mod));
2703 
2704          mem_range = &image->planes[0].compr_ctrl_memory_range;
2705          row_pitch_B = image->planes[0].primary_surface.isl.row_pitch_B /
2706                        INTEL_AUX_MAP_MAIN_PITCH_SCALEDOWN;
2707       } else if (mem_plane == 1 &&
2708                  image->planes[0].aux_surface.memory_range.size > 0) {
2709          assert(image->n_planes == 1);
2710          assert(image->vk.drm_format_mod == I915_FORMAT_MOD_Y_TILED_CCS);
2711 
2712          mem_range = &image->planes[0].aux_surface.memory_range;
2713          row_pitch_B = image->planes[0].aux_surface.isl.row_pitch_B;
2714       } else {
2715          assert(mem_plane < image->n_planes);
2716 
2717          mem_range = &image->planes[mem_plane].primary_surface.memory_range;
2718          row_pitch_B =
2719             image->planes[mem_plane].primary_surface.isl.row_pitch_B;
2720       }
2721 
2722       /* If the memory binding differs between the primary plane and the
2723        * specified memory plane, the returned offset will be incorrect.
2724        */
2725       assert(mem_range->binding ==
2726              image->planes[0].primary_surface.memory_range.binding);
2727 
2728       layout->subresourceLayout.offset = mem_range->offset;
2729       layout->subresourceLayout.size = mem_range->size;
2730       layout->subresourceLayout.rowPitch = row_pitch_B;
2731       /* The spec for VkSubresourceLayout says,
2732        *
2733        *    The value of arrayPitch is undefined for images that were not
2734        *    created as arrays. depthPitch is defined only for 3D images.
2735        *
2736        * We are working with a non-arrayed 2D image. So, we leave the
2737        * remaining pitches undefined.
2738        */
2739       assert(image->vk.image_type == VK_IMAGE_TYPE_2D);
2740       assert(image->vk.array_layers == 1);
2741    } else {
2742       const uint32_t plane =
2743          anv_image_aspect_to_plane(image,
2744                                    subresource->imageSubresource.aspectMask);
2745       const struct isl_surf *isl_surf =
2746          &image->planes[plane].primary_surface.isl;
2747       mem_range = &image->planes[plane].primary_surface.memory_range;
2748 
2749       layout->subresourceLayout.offset = mem_range->offset;
2750       layout->subresourceLayout.rowPitch = isl_surf->row_pitch_B;
2751       layout->subresourceLayout.depthPitch =
2752          isl_surf_get_array_pitch(isl_surf);
2753       layout->subresourceLayout.arrayPitch =
2754          isl_surf_get_array_pitch(isl_surf);
2755 
2756       const uint32_t level = subresource->imageSubresource.mipLevel;
2757       const uint32_t layer = subresource->imageSubresource.arrayLayer;
2758       if (level > 0 || layer > 0) {
2759          assert(isl_surf->tiling == ISL_TILING_LINEAR);
2760 
2761          uint64_t offset_B;
2762          isl_surf_get_image_offset_B_tile_sa(isl_surf, level, layer,
2763                                              0 /* logical_z_offset_px */,
2764                                              &offset_B, NULL, NULL);
2765          layout->subresourceLayout.offset += offset_B;
2766          layout->subresourceLayout.size =
2767             layout->subresourceLayout.rowPitch *
2768             u_minify(image->vk.extent.height, level) *
2769             image->vk.extent.depth;
2770       } else {
2771          layout->subresourceLayout.size = mem_range->size;
2772       }
2773    }
2774 
2775    VkImageCompressionPropertiesEXT *comp_props =
2776       vk_find_struct(layout->pNext, IMAGE_COMPRESSION_PROPERTIES_EXT);
2777    if (comp_props) {
2778       comp_props->imageCompressionFixedRateFlags =
2779          VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT;
2780       comp_props->imageCompressionFlags = VK_IMAGE_COMPRESSION_DISABLED_EXT;
2781       for (uint32_t p = 0; p < image->n_planes; p++) {
2782          if (image->planes[p].aux_usage != ISL_AUX_USAGE_NONE) {
2783             comp_props->imageCompressionFlags = VK_IMAGE_COMPRESSION_DEFAULT_EXT;
2784             break;
2785          }
2786       }
2787    }
2788 }
2789 
anv_GetDeviceImageSubresourceLayoutKHR(VkDevice _device,const VkDeviceImageSubresourceInfoKHR * pInfo,VkSubresourceLayout2KHR * pLayout)2790 void anv_GetDeviceImageSubresourceLayoutKHR(
2791     VkDevice                                    _device,
2792     const VkDeviceImageSubresourceInfoKHR*      pInfo,
2793     VkSubresourceLayout2KHR*                    pLayout)
2794 {
2795    ANV_FROM_HANDLE(anv_device, device, _device);
2796 
2797    struct anv_image image = { 0 };
2798 
2799    if (anv_image_init_from_create_info(device, &image, pInfo->pCreateInfo,
2800                                        true) != VK_SUCCESS) {
2801       pLayout->subresourceLayout = (VkSubresourceLayout) { 0, };
2802       return;
2803    }
2804 
2805    anv_get_image_subresource_layout(&image, pInfo->pSubresource, pLayout);
2806 }
2807 
anv_GetImageSubresourceLayout2KHR(VkDevice device,VkImage _image,const VkImageSubresource2KHR * pSubresource,VkSubresourceLayout2KHR * pLayout)2808 void anv_GetImageSubresourceLayout2KHR(
2809     VkDevice                                    device,
2810     VkImage                                     _image,
2811     const VkImageSubresource2KHR*               pSubresource,
2812     VkSubresourceLayout2KHR*                    pLayout)
2813 {
2814    ANV_FROM_HANDLE(anv_image, image, _image);
2815 
2816    anv_get_image_subresource_layout(image, pSubresource, pLayout);
2817 }
2818 
2819 static VkImageUsageFlags
anv_image_flags_filter_for_queue(VkImageUsageFlags usages,VkQueueFlagBits queue_flags)2820 anv_image_flags_filter_for_queue(VkImageUsageFlags usages,
2821                                  VkQueueFlagBits queue_flags)
2822 {
2823    /* Eliminate graphics usages if the queue is not graphics capable */
2824    if (!(queue_flags & VK_QUEUE_GRAPHICS_BIT)) {
2825       usages &= ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
2826                   VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
2827                   VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
2828                   VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
2829                   VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT |
2830                   VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
2831                   VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
2832    }
2833 
2834    /* Eliminate sampling & storage usages if the queue is neither graphics nor
2835     * compute capable
2836     */
2837    if (!(queue_flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))) {
2838       usages &= ~(VK_IMAGE_USAGE_SAMPLED_BIT |
2839                   VK_IMAGE_USAGE_STORAGE_BIT);
2840    }
2841 
2842    /* Eliminate transfer usages if the queue is neither transfer, compute or
2843     * graphics capable
2844     */
2845    if (!(queue_flags & (VK_QUEUE_TRANSFER_BIT |
2846                         VK_QUEUE_COMPUTE_BIT |
2847                         VK_QUEUE_GRAPHICS_BIT))) {
2848       usages &= ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2849                   VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2850    }
2851 
2852    return usages;
2853 }
2854 
2855 /**
2856  * This function returns the assumed isl_aux_state for a given VkImageLayout.
2857  * Because Vulkan image layouts don't map directly to isl_aux_state enums, the
2858  * returned enum is the assumed worst case.
2859  *
2860  * @param devinfo The device information of the Intel GPU.
2861  * @param image The image that may contain a collection of buffers.
2862  * @param aspect The aspect of the image to be accessed.
2863  * @param layout The current layout of the image aspect(s).
2864  *
2865  * @return The primary buffer that should be used for the given layout.
2866  */
2867 enum isl_aux_state ATTRIBUTE_PURE
anv_layout_to_aux_state(const struct intel_device_info * const devinfo,const struct anv_image * const image,const VkImageAspectFlagBits aspect,const VkImageLayout layout,const VkQueueFlagBits queue_flags)2868 anv_layout_to_aux_state(const struct intel_device_info * const devinfo,
2869                         const struct anv_image * const image,
2870                         const VkImageAspectFlagBits aspect,
2871                         const VkImageLayout layout,
2872                         const VkQueueFlagBits queue_flags)
2873 {
2874    /* Validate the inputs. */
2875 
2876    /* The devinfo is needed as the optimal buffer varies across generations. */
2877    assert(devinfo != NULL);
2878 
2879    /* The layout of a NULL image is not properly defined. */
2880    assert(image != NULL);
2881 
2882    /* The aspect must be exactly one of the image aspects. */
2883    assert(util_bitcount(aspect) == 1 && (aspect & image->vk.aspects));
2884 
2885    /* Determine the optimal buffer. */
2886 
2887    const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2888 
2889    /* If we don't have an aux buffer then aux state makes no sense */
2890    const enum isl_aux_usage aux_usage = image->planes[plane].aux_usage;
2891    assert(aux_usage != ISL_AUX_USAGE_NONE);
2892 
2893    /* All images that use an auxiliary surface are required to be tiled. */
2894    assert(image->planes[plane].primary_surface.isl.tiling != ISL_TILING_LINEAR);
2895 
2896    /* Handle a few special cases */
2897    switch (layout) {
2898    /* Invalid layouts */
2899    case VK_IMAGE_LAYOUT_MAX_ENUM:
2900       unreachable("Invalid image layout.");
2901 
2902    /* Undefined layouts
2903     *
2904     * The pre-initialized layout is equivalent to the undefined layout for
2905     * optimally-tiled images.  We can only do color compression (CCS or HiZ)
2906     * on tiled images.
2907     */
2908    case VK_IMAGE_LAYOUT_UNDEFINED:
2909    case VK_IMAGE_LAYOUT_PREINITIALIZED:
2910       return ISL_AUX_STATE_AUX_INVALID;
2911 
2912    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
2913       assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT);
2914 
2915       enum isl_aux_state aux_state =
2916          isl_drm_modifier_get_default_aux_state(image->vk.drm_format_mod);
2917 
2918       switch (aux_state) {
2919       case ISL_AUX_STATE_AUX_INVALID:
2920          /* The modifier does not support compression. But, if we arrived
2921           * here, then we have enabled compression on it anyway, in which case
2922           * we must resolve the aux surface before we release ownership to the
2923           * presentation engine (because, having no modifier, the presentation
2924           * engine will not be aware of the aux surface). The presentation
2925           * engine will not access the aux surface (because it is unware of
2926           * it), and so the aux surface will still be resolved when we
2927           * re-acquire ownership.
2928           *
2929           * Therefore, at ownership transfers in either direction, there does
2930           * exist an aux surface despite the lack of modifier and its state is
2931           * pass-through.
2932           */
2933          return ISL_AUX_STATE_PASS_THROUGH;
2934       case ISL_AUX_STATE_COMPRESSED_CLEAR:
2935          return ISL_AUX_STATE_COMPRESSED_CLEAR;
2936       case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2937          return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
2938       default:
2939          unreachable("unexpected isl_aux_state");
2940       }
2941    }
2942 
2943    default:
2944       break;
2945    }
2946 
2947    const bool read_only = vk_image_layout_is_read_only(layout, aspect);
2948 
2949    const VkImageUsageFlags image_aspect_usage =
2950       anv_image_flags_filter_for_queue(
2951          vk_image_usage(&image->vk, aspect), queue_flags);
2952    const VkImageUsageFlags usage =
2953       vk_image_layout_to_usage_flags(layout, aspect) & image_aspect_usage;
2954 
2955    bool aux_supported = true;
2956    bool clear_supported = isl_aux_usage_has_fast_clears(aux_usage);
2957 
2958    if ((usage & (VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
2959                  VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT)) &&
2960        !read_only) {
2961       /* This image could be used as both an input attachment and a render
2962        * target (depth, stencil, or color) at the same time and this can cause
2963        * corruption.
2964        *
2965        * We currently only disable aux in this way for depth even though we
2966        * disable it for color in GL.
2967        *
2968        * TODO: Should we be disabling this in more cases?
2969        */
2970       if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT && devinfo->ver <= 9) {
2971          aux_supported = false;
2972          clear_supported = false;
2973       }
2974    }
2975 
2976    if (usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2977                 VK_IMAGE_USAGE_SAMPLED_BIT |
2978                 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
2979       switch (aux_usage) {
2980       case ISL_AUX_USAGE_HIZ:
2981          if (!anv_can_sample_with_hiz(devinfo, image)) {
2982             aux_supported = false;
2983             clear_supported = false;
2984          }
2985          break;
2986 
2987       case ISL_AUX_USAGE_HIZ_CCS:
2988          aux_supported = false;
2989          clear_supported = false;
2990          break;
2991 
2992       case ISL_AUX_USAGE_HIZ_CCS_WT:
2993          break;
2994 
2995       case ISL_AUX_USAGE_CCS_D:
2996          aux_supported = false;
2997          clear_supported = false;
2998          break;
2999 
3000       case ISL_AUX_USAGE_MCS:
3001          if (!anv_can_sample_mcs_with_clear(devinfo, image))
3002             clear_supported = false;
3003          break;
3004 
3005       case ISL_AUX_USAGE_CCS_E:
3006       case ISL_AUX_USAGE_FCV_CCS_E:
3007       case ISL_AUX_USAGE_STC_CCS:
3008          break;
3009 
3010       default:
3011          unreachable("Unsupported aux usage");
3012       }
3013    }
3014 
3015    switch (aux_usage) {
3016    case ISL_AUX_USAGE_HIZ:
3017    case ISL_AUX_USAGE_HIZ_CCS:
3018    case ISL_AUX_USAGE_HIZ_CCS_WT:
3019       if (aux_supported) {
3020          assert(clear_supported);
3021          return ISL_AUX_STATE_COMPRESSED_CLEAR;
3022       } else if (read_only) {
3023          return ISL_AUX_STATE_RESOLVED;
3024       } else {
3025          return ISL_AUX_STATE_AUX_INVALID;
3026       }
3027 
3028    case ISL_AUX_USAGE_CCS_D:
3029       /* We only support clear in exactly one state */
3030       if (layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ||
3031           layout == VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL) {
3032          assert(aux_supported);
3033          assert(clear_supported);
3034          return ISL_AUX_STATE_PARTIAL_CLEAR;
3035       } else {
3036          return ISL_AUX_STATE_PASS_THROUGH;
3037       }
3038 
3039    case ISL_AUX_USAGE_CCS_E:
3040    case ISL_AUX_USAGE_FCV_CCS_E:
3041       if (aux_supported) {
3042          assert(clear_supported);
3043          return ISL_AUX_STATE_COMPRESSED_CLEAR;
3044       } else {
3045          return ISL_AUX_STATE_PASS_THROUGH;
3046       }
3047 
3048    case ISL_AUX_USAGE_MCS:
3049       assert(aux_supported);
3050       if (clear_supported) {
3051          return ISL_AUX_STATE_COMPRESSED_CLEAR;
3052       } else {
3053          return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
3054       }
3055 
3056    case ISL_AUX_USAGE_STC_CCS:
3057       assert(aux_supported);
3058       assert(!clear_supported);
3059       return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
3060 
3061    default:
3062       unreachable("Unsupported aux usage");
3063    }
3064 }
3065 
3066 /**
3067  * This function determines the optimal buffer to use for a given
3068  * VkImageLayout and other pieces of information needed to make that
3069  * determination. This does not determine the optimal buffer to use
3070  * during a resolve operation.
3071  *
3072  * @param devinfo The device information of the Intel GPU.
3073  * @param image The image that may contain a collection of buffers.
3074  * @param aspect The aspect of the image to be accessed.
3075  * @param usage The usage which describes how the image will be accessed.
3076  * @param layout The current layout of the image aspect(s).
3077  *
3078  * @return The primary buffer that should be used for the given layout.
3079  */
3080 enum isl_aux_usage ATTRIBUTE_PURE
anv_layout_to_aux_usage(const struct intel_device_info * const devinfo,const struct anv_image * const image,const VkImageAspectFlagBits aspect,const VkImageUsageFlagBits usage,const VkImageLayout layout,const VkQueueFlagBits queue_flags)3081 anv_layout_to_aux_usage(const struct intel_device_info * const devinfo,
3082                         const struct anv_image * const image,
3083                         const VkImageAspectFlagBits aspect,
3084                         const VkImageUsageFlagBits usage,
3085                         const VkImageLayout layout,
3086                         const VkQueueFlagBits queue_flags)
3087 {
3088    const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
3089 
3090    /* If there is no auxiliary surface allocated, we must use the one and only
3091     * main buffer.
3092     */
3093    if (image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE)
3094       return ISL_AUX_USAGE_NONE;
3095 
3096    enum isl_aux_state aux_state =
3097       anv_layout_to_aux_state(devinfo, image, aspect, layout, queue_flags);
3098 
3099    switch (aux_state) {
3100    case ISL_AUX_STATE_CLEAR:
3101       unreachable("We never use this state");
3102 
3103    case ISL_AUX_STATE_PARTIAL_CLEAR:
3104       assert(image->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
3105       assert(image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_D);
3106       assert(image->vk.samples == 1);
3107       return ISL_AUX_USAGE_CCS_D;
3108 
3109    case ISL_AUX_STATE_COMPRESSED_CLEAR:
3110    case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
3111       return image->planes[plane].aux_usage;
3112 
3113    case ISL_AUX_STATE_RESOLVED:
3114       /* We can only use RESOLVED in read-only layouts because any write will
3115        * either land us in AUX_INVALID or COMPRESSED_NO_CLEAR.  We can do
3116        * writes in PASS_THROUGH without destroying it so that is allowed.
3117        */
3118       assert(vk_image_layout_is_read_only(layout, aspect));
3119       assert(util_is_power_of_two_or_zero(usage));
3120       if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
3121          /* If we have valid HiZ data and are using the image as a read-only
3122           * depth/stencil attachment, we should enable HiZ so that we can get
3123           * faster depth testing.
3124           */
3125          return image->planes[plane].aux_usage;
3126       } else {
3127          return ISL_AUX_USAGE_NONE;
3128       }
3129 
3130    case ISL_AUX_STATE_PASS_THROUGH:
3131    case ISL_AUX_STATE_AUX_INVALID:
3132       return ISL_AUX_USAGE_NONE;
3133    }
3134 
3135    unreachable("Invalid isl_aux_state");
3136 }
3137 
3138 /**
3139  * This function returns the level of unresolved fast-clear support of the
3140  * given image in the given VkImageLayout.
3141  *
3142  * @param devinfo The device information of the Intel GPU.
3143  * @param image The image that may contain a collection of buffers.
3144  * @param aspect The aspect of the image to be accessed.
3145  * @param usage The usage which describes how the image will be accessed.
3146  * @param layout The current layout of the image aspect(s).
3147  */
3148 enum anv_fast_clear_type ATTRIBUTE_PURE
anv_layout_to_fast_clear_type(const struct intel_device_info * const devinfo,const struct anv_image * const image,const VkImageAspectFlagBits aspect,const VkImageLayout layout,const VkQueueFlagBits queue_flags)3149 anv_layout_to_fast_clear_type(const struct intel_device_info * const devinfo,
3150                               const struct anv_image * const image,
3151                               const VkImageAspectFlagBits aspect,
3152                               const VkImageLayout layout,
3153                               const VkQueueFlagBits queue_flags)
3154 {
3155    if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
3156       return ANV_FAST_CLEAR_NONE;
3157 
3158    /* Xe2+ platforms don't have fast clear type and can always support
3159     * arbitrary fast-clear values.
3160     */
3161    if (devinfo->ver >= 20)
3162       return ANV_FAST_CLEAR_ANY;
3163 
3164    const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
3165 
3166    /* If there is no auxiliary surface allocated, there are no fast-clears */
3167    if (image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE)
3168       return ANV_FAST_CLEAR_NONE;
3169 
3170    enum isl_aux_state aux_state =
3171       anv_layout_to_aux_state(devinfo, image, aspect, layout, queue_flags);
3172 
3173    const VkImageUsageFlags layout_usage =
3174       vk_image_layout_to_usage_flags(layout, aspect);
3175 
3176    switch (aux_state) {
3177    case ISL_AUX_STATE_CLEAR:
3178       unreachable("We never use this state");
3179 
3180    case ISL_AUX_STATE_PARTIAL_CLEAR:
3181    case ISL_AUX_STATE_COMPRESSED_CLEAR:
3182       if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
3183          return ANV_FAST_CLEAR_DEFAULT_VALUE;
3184       } else if (layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ||
3185                  layout == VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL) {
3186          /* The image might not support non zero fast clears when mutable. */
3187          if (!image->planes[plane].can_non_zero_fast_clear)
3188             return ANV_FAST_CLEAR_DEFAULT_VALUE;
3189 
3190          /* When we're in a render pass we have the clear color data from the
3191           * VkRenderPassBeginInfo and we can use arbitrary clear colors.  They
3192           * must get partially resolved before we leave the render pass.
3193           */
3194          return ANV_FAST_CLEAR_ANY;
3195       } else if (layout_usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
3196                                  VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
3197          /* Fast clear with non zero color is not supported during transfer
3198           * operations since transfer may do format reinterpretation.
3199           */
3200          return ANV_FAST_CLEAR_DEFAULT_VALUE;
3201       } else if (image->planes[plane].aux_usage == ISL_AUX_USAGE_MCS ||
3202                  image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E ||
3203                  image->planes[plane].aux_usage == ISL_AUX_USAGE_FCV_CCS_E) {
3204          if (devinfo->ver >= 11) {
3205             /* The image might not support non zero fast clears when mutable. */
3206             if (!image->planes[plane].can_non_zero_fast_clear)
3207                return ANV_FAST_CLEAR_DEFAULT_VALUE;
3208 
3209             /* On ICL and later, the sampler hardware uses a copy of the clear
3210              * value that is encoded as a pixel value.  Therefore, we can use
3211              * any clear color we like for sampling.
3212              */
3213             return ANV_FAST_CLEAR_ANY;
3214          } else {
3215             /* If the image has MCS or CCS_E enabled all the time then we can
3216              * use fast-clear as long as the clear color is the default value
3217              * of zero since this is the default value we program into every
3218              * surface state used for texturing.
3219              */
3220             return ANV_FAST_CLEAR_DEFAULT_VALUE;
3221          }
3222       } else {
3223          return ANV_FAST_CLEAR_NONE;
3224       }
3225 
3226    case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
3227    case ISL_AUX_STATE_RESOLVED:
3228    case ISL_AUX_STATE_PASS_THROUGH:
3229    case ISL_AUX_STATE_AUX_INVALID:
3230       return ANV_FAST_CLEAR_NONE;
3231    }
3232 
3233    unreachable("Invalid isl_aux_state");
3234 }
3235 
3236 
3237 /**
3238  * This function determines if the layout & usage of an image can have
3239  * untracked aux writes. When we see a transition that matches this criteria,
3240  * we need to mark the image as compressed written so that our predicated
3241  * resolves work properly.
3242  *
3243  * @param devinfo The device information of the Intel GPU.
3244  * @param image The image that may contain a collection of buffers.
3245  * @param aspect The aspect of the image to be accessed.
3246  * @param layout The current layout of the image aspect(s).
3247  */
3248 bool
anv_layout_has_untracked_aux_writes(const struct intel_device_info * const devinfo,const struct anv_image * const image,const VkImageAspectFlagBits aspect,const VkImageLayout layout,const VkQueueFlagBits queue_flags)3249 anv_layout_has_untracked_aux_writes(const struct intel_device_info * const devinfo,
3250                                     const struct anv_image * const image,
3251                                     const VkImageAspectFlagBits aspect,
3252                                     const VkImageLayout layout,
3253                                     const VkQueueFlagBits queue_flags)
3254 {
3255    const VkImageUsageFlags image_aspect_usage =
3256       vk_image_usage(&image->vk, aspect);
3257    const VkImageUsageFlags usage =
3258       vk_image_layout_to_usage_flags(layout, aspect) & image_aspect_usage;
3259 
3260    /* Storage is the only usage where we do not write the image through a
3261     * render target but through a descriptor. Since VK_EXT_descriptor_indexing
3262     * and the update-after-bind feature, it has become impossible to track
3263     * writes to images in descriptor at the command buffer build time. So it's
3264     * not possible to mark an image as compressed like we do in
3265     * genX_cmd_buffer.c(EndRendering) or anv_blorp.c for all transfer
3266     * operations.
3267     */
3268    if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT))
3269       return false;
3270 
3271    /* No AUX, no writes to the AUX surface :) */
3272    const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
3273    const enum isl_aux_usage aux_usage = image->planes[plane].aux_usage;
3274    if (aux_usage == ISL_AUX_USAGE_NONE)
3275       return false;
3276 
3277    return true;
3278 }
3279 
anv_GetRenderingAreaGranularityKHR(VkDevice _device,const VkRenderingAreaInfoKHR * pRenderingAreaInfo,VkExtent2D * pGranularity)3280 void anv_GetRenderingAreaGranularityKHR(
3281     VkDevice                                    _device,
3282     const VkRenderingAreaInfoKHR*               pRenderingAreaInfo,
3283     VkExtent2D*                                 pGranularity)
3284 {
3285    *pGranularity = (VkExtent2D) {
3286       .width = 1,
3287       .height = 1,
3288    };
3289 }
3290