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