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