• 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 "util/debug.h"
34 #include "vk_util.h"
35 #include "util/u_math.h"
36 
37 #include "vk_format.h"
38 
39 #define ANV_OFFSET_IMPLICIT UINT64_MAX
40 
41 static const enum isl_surf_dim
42 vk_to_isl_surf_dim[] = {
43    [VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D,
44    [VK_IMAGE_TYPE_2D] = ISL_SURF_DIM_2D,
45    [VK_IMAGE_TYPE_3D] = ISL_SURF_DIM_3D,
46 };
47 
48 static uint64_t MUST_CHECK UNUSED
memory_range_end(struct anv_image_memory_range memory_range)49 memory_range_end(struct anv_image_memory_range memory_range)
50 {
51    assert(anv_is_aligned(memory_range.offset, memory_range.alignment));
52    return memory_range.offset + memory_range.size;
53 }
54 
55 /**
56  * Get binding for VkImagePlaneMemoryRequirementsInfo,
57  * VkBindImagePlaneMemoryInfo and VkDeviceImageMemoryRequirements.
58  */
59 static struct anv_image_binding *
image_aspect_to_binding(struct anv_image * image,VkImageAspectFlags aspect)60 image_aspect_to_binding(struct anv_image *image, VkImageAspectFlags aspect)
61 {
62    uint32_t plane;
63 
64    assert(image->disjoint);
65 
66    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
67       /* Spec requires special aspects for modifier images. */
68       assert(aspect >= VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT &&
69              aspect <= VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT);
70 
71       /* We don't advertise DISJOINT for modifiers with aux, and therefore we
72        * don't handle queries of the modifier's "aux plane" here.
73        */
74       assert(!isl_drm_modifier_has_aux(image->vk.drm_format_mod));
75 
76       plane = aspect - VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
77    } else {
78       plane = anv_image_aspect_to_plane(image, aspect);
79    }
80 
81    return &image->bindings[ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane];
82 }
83 
84 /**
85  * Extend the memory binding's range by appending a new memory range with `size`
86  * and `alignment` at `offset`. Return the appended range.
87  *
88  * Offset is ignored if ANV_OFFSET_IMPLICIT.
89  *
90  * The given binding must not be ANV_IMAGE_MEMORY_BINDING_MAIN. The function
91  * converts to MAIN as needed.
92  */
93 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)94 image_binding_grow(const struct anv_device *device,
95                    struct anv_image *image,
96                    enum anv_image_memory_binding binding,
97                    uint64_t offset,
98                    uint64_t size,
99                    uint32_t alignment,
100                    struct anv_image_memory_range *out_range)
101 {
102    /* We overwrite 'offset' but need to remember if it was implicit. */
103    const bool has_implicit_offset = (offset == ANV_OFFSET_IMPLICIT);
104 
105    assert(size > 0);
106    assert(util_is_power_of_two_or_zero(alignment));
107 
108    switch (binding) {
109    case ANV_IMAGE_MEMORY_BINDING_MAIN:
110       /* The caller must not pre-translate BINDING_PLANE_i to BINDING_MAIN. */
111       unreachable("ANV_IMAGE_MEMORY_BINDING_MAIN");
112    case ANV_IMAGE_MEMORY_BINDING_PLANE_0:
113    case ANV_IMAGE_MEMORY_BINDING_PLANE_1:
114    case ANV_IMAGE_MEMORY_BINDING_PLANE_2:
115       if (!image->disjoint)
116          binding = ANV_IMAGE_MEMORY_BINDING_MAIN;
117       break;
118    case ANV_IMAGE_MEMORY_BINDING_PRIVATE:
119       assert(offset == ANV_OFFSET_IMPLICIT);
120       break;
121    case ANV_IMAGE_MEMORY_BINDING_END:
122       unreachable("ANV_IMAGE_MEMORY_BINDING_END");
123    }
124 
125    struct anv_image_memory_range *container =
126       &image->bindings[binding].memory_range;
127 
128    if (has_implicit_offset) {
129       offset = align_u64(container->offset + container->size, alignment);
130    } else {
131       /* Offset must be validated because it comes from
132        * VkImageDrmFormatModifierExplicitCreateInfoEXT.
133        */
134       if (unlikely(!anv_is_aligned(offset, alignment))) {
135          return vk_errorf(device,
136                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
137                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
138                           "pPlaneLayouts[]::offset is misaligned");
139       }
140 
141       /* We require that surfaces be added in memory-order. This simplifies the
142        * layout validation required by
143        * VkImageDrmFormatModifierExplicitCreateInfoEXT,
144        */
145       if (unlikely(offset < container->size)) {
146          return vk_errorf(device,
147                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
148                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
149                           "pPlaneLayouts[]::offset is too small");
150       }
151    }
152 
153    if (__builtin_add_overflow(offset, size, &container->size)) {
154       if (has_implicit_offset) {
155          assert(!"overflow");
156          return vk_errorf(device, VK_ERROR_UNKNOWN,
157                           "internal error: overflow in %s", __func__);
158       } else {
159          return vk_errorf(device,
160                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
161                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
162                           "pPlaneLayouts[]::offset is too large");
163       }
164    }
165 
166    container->alignment = MAX2(container->alignment, alignment);
167 
168    *out_range = (struct anv_image_memory_range) {
169       .binding = binding,
170       .offset = offset,
171       .size = size,
172       .alignment = alignment,
173    };
174 
175    return VK_SUCCESS;
176 }
177 
178 /**
179  * Adjust range 'a' to contain range 'b'.
180  *
181  * For simplicity's sake, the offset of 'a' must be 0 and remains 0.
182  * If 'a' and 'b' target different bindings, then no merge occurs.
183  */
184 static void
memory_range_merge(struct anv_image_memory_range * a,const struct anv_image_memory_range b)185 memory_range_merge(struct anv_image_memory_range *a,
186                    const struct anv_image_memory_range b)
187 {
188    if (b.size == 0)
189       return;
190 
191    if (a->binding != b.binding)
192       return;
193 
194    assert(a->offset == 0);
195    assert(anv_is_aligned(a->offset, a->alignment));
196    assert(anv_is_aligned(b.offset, b.alignment));
197 
198    a->alignment = MAX2(a->alignment, b.alignment);
199    a->size = MAX2(a->size, b.offset + b.size);
200 }
201 
202 static isl_surf_usage_flags_t
choose_isl_surf_usage(VkImageCreateFlags vk_create_flags,VkImageUsageFlags vk_usage,isl_surf_usage_flags_t isl_extra_usage,VkImageAspectFlagBits aspect)203 choose_isl_surf_usage(VkImageCreateFlags vk_create_flags,
204                       VkImageUsageFlags vk_usage,
205                       isl_surf_usage_flags_t isl_extra_usage,
206                       VkImageAspectFlagBits aspect)
207 {
208    isl_surf_usage_flags_t isl_usage = isl_extra_usage;
209 
210    if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
211       isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
212 
213    if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
214       isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
215 
216    if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
217       isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
218 
219    if (vk_usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)
220       isl_usage |= ISL_SURF_USAGE_CPB_BIT;
221 
222    if (vk_create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
223       isl_usage |= ISL_SURF_USAGE_CUBE_BIT;
224 
225    /* Even if we're only using it for transfer operations, clears to depth and
226     * stencil images happen as depth and stencil so they need the right ISL
227     * usage bits or else things will fall apart.
228     */
229    switch (aspect) {
230    case VK_IMAGE_ASPECT_DEPTH_BIT:
231       isl_usage |= ISL_SURF_USAGE_DEPTH_BIT;
232       break;
233    case VK_IMAGE_ASPECT_STENCIL_BIT:
234       isl_usage |= ISL_SURF_USAGE_STENCIL_BIT;
235       break;
236    case VK_IMAGE_ASPECT_COLOR_BIT:
237    case VK_IMAGE_ASPECT_PLANE_0_BIT:
238    case VK_IMAGE_ASPECT_PLANE_1_BIT:
239    case VK_IMAGE_ASPECT_PLANE_2_BIT:
240       break;
241    default:
242       unreachable("bad VkImageAspect");
243    }
244 
245    if (vk_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
246       /* blorp implements transfers by sampling from the source image. */
247       isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
248    }
249 
250    if (vk_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT &&
251        aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
252       /* blorp implements transfers by rendering into the destination image.
253        * Only request this with color images, as we deal with depth/stencil
254        * formats differently. */
255       isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
256    }
257 
258    return isl_usage;
259 }
260 
261 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)262 choose_isl_tiling_flags(const struct intel_device_info *devinfo,
263                         const struct anv_image_create_info *anv_info,
264                         const struct isl_drm_modifier_info *isl_mod_info,
265                         bool legacy_scanout)
266 {
267    const VkImageCreateInfo *base_info = anv_info->vk_info;
268    isl_tiling_flags_t flags = 0;
269 
270    assert((isl_mod_info != NULL) ==
271           (base_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT));
272 
273    switch (base_info->tiling) {
274    default:
275       unreachable("bad VkImageTiling");
276    case VK_IMAGE_TILING_OPTIMAL:
277       flags = ISL_TILING_ANY_MASK;
278       break;
279    case VK_IMAGE_TILING_LINEAR:
280       flags = ISL_TILING_LINEAR_BIT;
281       break;
282    case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
283       flags = 1 << isl_mod_info->tiling;
284    }
285 
286    if (anv_info->isl_tiling_flags) {
287       assert(isl_mod_info == NULL);
288       flags &= anv_info->isl_tiling_flags;
289    }
290 
291    if (legacy_scanout) {
292       isl_tiling_flags_t legacy_mask = ISL_TILING_LINEAR_BIT;
293       if (devinfo->has_tiling_uapi)
294          legacy_mask |= ISL_TILING_X_BIT;
295       flags &= legacy_mask;
296    }
297 
298    assert(flags);
299 
300    return flags;
301 }
302 
303 /**
304  * Add the surface to the binding at the given offset.
305  *
306  * \see image_binding_grow()
307  */
308 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)309 add_surface(struct anv_device *device,
310             struct anv_image *image,
311             struct anv_surface *surf,
312             enum anv_image_memory_binding binding,
313             uint64_t offset)
314 {
315    /* isl surface must be initialized */
316    assert(surf->isl.size_B > 0);
317 
318    return image_binding_grow(device, image, binding, offset,
319                              surf->isl.size_B,
320                              surf->isl.alignment_B,
321                              &surf->memory_range);
322 }
323 
324 /**
325  * Do hardware limitations require the image plane to use a shadow surface?
326  *
327  * If hardware limitations force us to use a shadow surface, then the same
328  * limitations may also constrain the tiling of the primary surface; therefore
329  * parameter @a inout_primary_tiling_flags.
330  *
331  * If the image plane is a separate stencil plane and if the user provided
332  * VkImageStencilUsageCreateInfo, then @a usage must be stencilUsage.
333  *
334  * @see anv_image::planes[]::shadow_surface
335  */
336 static bool
anv_image_plane_needs_shadow_surface(const struct intel_device_info * devinfo,struct anv_format_plane plane_format,VkImageTiling vk_tiling,VkImageUsageFlags vk_plane_usage,VkImageCreateFlags vk_create_flags,isl_tiling_flags_t * inout_primary_tiling_flags)337 anv_image_plane_needs_shadow_surface(const struct intel_device_info *devinfo,
338                                      struct anv_format_plane plane_format,
339                                      VkImageTiling vk_tiling,
340                                      VkImageUsageFlags vk_plane_usage,
341                                      VkImageCreateFlags vk_create_flags,
342                                      isl_tiling_flags_t *inout_primary_tiling_flags)
343 {
344    if (devinfo->ver <= 8 &&
345        (vk_create_flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) &&
346        vk_tiling == VK_IMAGE_TILING_OPTIMAL) {
347       /* We must fallback to a linear surface because we may not be able to
348        * correctly handle the offsets if tiled. (On gfx9,
349        * RENDER_SURFACE_STATE::X/Y Offset are sufficient). To prevent garbage
350        * performance while texturing, we maintain a tiled shadow surface.
351        */
352       assert(isl_format_is_compressed(plane_format.isl_format));
353 
354       if (inout_primary_tiling_flags) {
355          *inout_primary_tiling_flags = ISL_TILING_LINEAR_BIT;
356       }
357 
358       return true;
359    }
360 
361    if (devinfo->ver <= 7 &&
362        plane_format.aspect == VK_IMAGE_ASPECT_STENCIL_BIT &&
363        (vk_plane_usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
364                           VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))) {
365       /* gfx7 can't sample from W-tiled surfaces. */
366       return true;
367    }
368 
369    return false;
370 }
371 
372 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)373 can_fast_clear_with_non_zero_color(const struct intel_device_info *devinfo,
374                                    const struct anv_image *image,
375                                    uint32_t plane,
376                                    const VkImageFormatListCreateInfo *fmt_list)
377 {
378    /* If we don't have an AUX surface where fast clears apply, we can return
379     * early.
380     */
381    if (!isl_aux_usage_has_fast_clears(image->planes[plane].aux_usage))
382       return false;
383 
384    /* On TGL, if a block of fragment shader outputs match the surface's clear
385     * color, the HW may convert them to fast-clears (see HSD 14010672564).
386     * This can lead to rendering corruptions if not handled properly. We
387     * restrict the clear color to zero to avoid issues that can occur with:
388     *     - Texture view rendering (including blorp_copy calls)
389     *     - Images with multiple levels or array layers
390     */
391    if (devinfo->ver >= 12 &&
392        image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E)
393       return false;
394 
395    /* Non mutable image, we can fast clear with any color supported by HW.
396     */
397    if (!(image->vk.create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
398       return true;
399 
400    /* Mutable image with no format list, we have to assume all formats */
401    if (!fmt_list || fmt_list->viewFormatCount == 0)
402       return false;
403 
404    enum isl_format img_format = image->planes[plane].primary_surface.isl.format;
405 
406    /* Check bit compatibility for clear color components */
407    for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
408       struct anv_format_plane view_format_plane =
409          anv_get_format_plane(devinfo, fmt_list->pViewFormats[i],
410                               plane, image->vk.tiling);
411 
412       enum isl_format view_format = view_format_plane.isl_format;
413 
414       if (!isl_formats_have_same_bits_per_channel(img_format, view_format))
415          return false;
416 
417       /* Switching between any of those format types on Gfx7/8 will cause
418        * problems https://gitlab.freedesktop.org/mesa/mesa/-/issues/1711
419        */
420       if (devinfo->ver <= 8) {
421          if (isl_format_has_float_channel(img_format) &&
422              !isl_format_has_float_channel(view_format))
423             return false;
424 
425          if (isl_format_has_int_channel(img_format) &&
426              !isl_format_has_int_channel(view_format))
427             return false;
428 
429          if (isl_format_has_unorm_channel(img_format) &&
430              !isl_format_has_unorm_channel(view_format))
431             return false;
432 
433          if (isl_format_has_snorm_channel(img_format) &&
434              !isl_format_has_snorm_channel(view_format))
435             return false;
436       }
437    }
438 
439    return true;
440 }
441 
442 /**
443  * Return true if the storage image could be used with atomics.
444  *
445  * If the image was created with an explicit format, we check it for typed
446  * atomic support.  If MUTABLE_FORMAT_BIT is set, then we check the optional
447  * format list, seeing if /any/ of the formats support typed atomics.  If no
448  * list is supplied, we fall back to using the bpb, as the application could
449  * make an image view with a format that does use atomics.
450  */
451 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)452 storage_image_format_supports_atomic(const struct intel_device_info *devinfo,
453                                      VkImageCreateFlags create_flags,
454                                      enum isl_format format,
455                                      VkImageTiling vk_tiling,
456                                      const VkImageFormatListCreateInfo *fmt_list)
457 {
458    if (isl_format_supports_typed_atomics(devinfo, format))
459       return true;
460 
461    if (!(create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
462       return false;
463 
464    if (fmt_list) {
465       for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
466          enum isl_format view_format =
467             anv_get_isl_format(devinfo, fmt_list->pViewFormats[i],
468                                VK_IMAGE_ASPECT_COLOR_BIT, vk_tiling);
469 
470          if (isl_format_supports_typed_atomics(devinfo, view_format))
471             return true;
472       }
473 
474       return false;
475    }
476 
477    /* No explicit format list.  Any 16/32/64bpp format could be used with atomics. */
478    unsigned bpb = isl_format_get_layout(format)->bpb;
479    return bpb == 16 || bpb == 32 || bpb == 64;
480 }
481 
482 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)483 anv_get_isl_format_with_usage(const struct intel_device_info *devinfo,
484                               VkFormat vk_format,
485                               VkImageAspectFlagBits vk_aspect,
486                               VkImageUsageFlags vk_usage,
487                               VkImageTiling vk_tiling)
488 {
489    assert(util_bitcount(vk_usage) == 1);
490    struct anv_format_plane format =
491       anv_get_format_aspect(devinfo, vk_format, vk_aspect,
492                             vk_tiling);
493 
494    if ((vk_usage == VK_IMAGE_USAGE_STORAGE_BIT) &&
495        isl_is_storage_image_format(format.isl_format)) {
496       enum isl_format lowered_format =
497          isl_lower_storage_image_format(devinfo, format.isl_format);
498 
499       /* If we lower the format, we should ensure either they both match in
500        * bits per channel or that there is no swizzle, because we can't use
501        * the swizzle for a different bit pattern.
502        */
503       assert(isl_formats_have_same_bits_per_channel(lowered_format,
504                                                     format.isl_format) ||
505              isl_swizzle_is_identity(format.swizzle));
506 
507       format.isl_format = lowered_format;
508    }
509 
510    return format.isl_format;
511 }
512 
513 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)514 formats_ccs_e_compatible(const struct intel_device_info *devinfo,
515                          VkImageCreateFlags create_flags,
516                          enum isl_format format, VkImageTiling vk_tiling,
517                          VkImageUsageFlags vk_usage,
518                          const VkImageFormatListCreateInfo *fmt_list)
519 {
520    if (!isl_format_supports_ccs_e(devinfo, format))
521       return false;
522 
523    /* For images created without MUTABLE_FORMAT_BIT set, we know that they will
524     * always be used with the original format. In particular, they will always
525     * be used with a format that supports color compression.
526     */
527    if (!(create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
528       return true;
529 
530    if (!fmt_list || fmt_list->viewFormatCount == 0)
531       return false;
532 
533    for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
534       enum isl_format view_format =
535          anv_get_isl_format_with_usage(devinfo, fmt_list->pViewFormats[i],
536                                        VK_IMAGE_ASPECT_COLOR_BIT, vk_usage,
537                                        vk_tiling);
538 
539       if (!isl_formats_are_ccs_e_compatible(devinfo, format, view_format))
540          return false;
541    }
542 
543    return true;
544 }
545 
546 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)547 anv_formats_ccs_e_compatible(const struct intel_device_info *devinfo,
548                              VkImageCreateFlags create_flags,
549                              VkFormat vk_format, VkImageTiling vk_tiling,
550                              VkImageUsageFlags vk_usage,
551                              const VkImageFormatListCreateInfo *fmt_list)
552 {
553    enum isl_format format =
554       anv_get_isl_format_with_usage(devinfo, vk_format,
555                                     VK_IMAGE_ASPECT_COLOR_BIT,
556                                     VK_IMAGE_USAGE_SAMPLED_BIT, vk_tiling);
557 
558    if (!formats_ccs_e_compatible(devinfo, create_flags, format, vk_tiling,
559                                  VK_IMAGE_USAGE_SAMPLED_BIT, fmt_list))
560       return false;
561 
562    if (vk_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
563       if (devinfo->verx10 < 125)
564          return false;
565 
566       enum isl_format lower_format =
567          anv_get_isl_format_with_usage(devinfo, vk_format,
568                                        VK_IMAGE_ASPECT_COLOR_BIT,
569                                        VK_IMAGE_USAGE_STORAGE_BIT, vk_tiling);
570 
571       if (!isl_formats_are_ccs_e_compatible(devinfo, format, lower_format))
572          return false;
573 
574       if (!formats_ccs_e_compatible(devinfo, create_flags, format, vk_tiling,
575                                     VK_IMAGE_USAGE_STORAGE_BIT, fmt_list))
576          return false;
577 
578       /* Disable compression when surface can be potentially used for atomic
579        * operation.
580        */
581       if (storage_image_format_supports_atomic(devinfo, create_flags, format,
582                                                vk_tiling, fmt_list))
583          return false;
584    }
585 
586    return true;
587 }
588 
589 /**
590  * For color images that have an auxiliary surface, request allocation for an
591  * additional buffer that mainly stores fast-clear values. Use of this buffer
592  * allows us to access the image's subresources while being aware of their
593  * fast-clear values in non-trivial cases (e.g., outside of a render pass in
594  * which a fast clear has occurred).
595  *
596  * In order to avoid having multiple clear colors for a single plane of an
597  * image (hence a single RENDER_SURFACE_STATE), we only allow fast-clears on
598  * the first slice (level 0, layer 0).  At the time of our testing (Jan 17,
599  * 2018), there were no known applications which would benefit from fast-
600  * clearing more than just the first slice.
601  *
602  * The fast clear portion of the image is laid out in the following order:
603  *
604  *  * 1 or 4 dwords (depending on hardware generation) for the clear color
605  *  * 1 dword for the anv_fast_clear_type of the clear color
606  *  * On gfx9+, 1 dword per level and layer of the image (3D levels count
607  *    multiple layers) in level-major order for compression state.
608  *
609  * For the purpose of discoverability, the algorithm used to manage
610  * compression and fast-clears is described here:
611  *
612  *  * On a transition from UNDEFINED or PREINITIALIZED to a defined layout,
613  *    all of the values in the fast clear portion of the image are initialized
614  *    to default values.
615  *
616  *  * On fast-clear, the clear value is written into surface state and also
617  *    into the buffer and the fast clear type is set appropriately.  Both
618  *    setting the fast-clear value in the buffer and setting the fast-clear
619  *    type happen from the GPU using MI commands.
620  *
621  *  * Whenever a render or blorp operation is performed with CCS_E, we call
622  *    genX(cmd_buffer_mark_image_written) to set the compression state to
623  *    true (which is represented by UINT32_MAX).
624  *
625  *  * On pipeline barrier transitions, the worst-case transition is computed
626  *    from the image layouts.  The command streamer inspects the fast clear
627  *    type and compression state dwords and constructs a predicate.  The
628  *    worst-case resolve is performed with the given predicate and the fast
629  *    clear and compression state is set accordingly.
630  *
631  * See anv_layout_to_aux_usage and anv_layout_to_fast_clear_type functions for
632  * details on exactly what is allowed in what layouts.
633  *
634  * On gfx7-9, we do not have a concept of indirect clear colors in hardware.
635  * In order to deal with this, we have to do some clear color management.
636  *
637  *  * For LOAD_OP_LOAD at the top of a renderpass, we have to copy the clear
638  *    value from the buffer into the surface state with MI commands.
639  *
640  *  * For any blorp operations, we pass the address to the clear value into
641  *    blorp and it knows to copy the clear color.
642  */
643 static VkResult MUST_CHECK
add_aux_state_tracking_buffer(struct anv_device * device,struct anv_image * image,uint32_t plane)644 add_aux_state_tracking_buffer(struct anv_device *device,
645                               struct anv_image *image,
646                               uint32_t plane)
647 {
648    assert(image && device);
649    assert(image->planes[plane].aux_usage != ISL_AUX_USAGE_NONE &&
650           image->vk.aspects & (VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV |
651                                VK_IMAGE_ASPECT_DEPTH_BIT));
652 
653    const unsigned clear_color_state_size = device->info.ver >= 10 ?
654       device->isl_dev.ss.clear_color_state_size :
655       device->isl_dev.ss.clear_value_size;
656 
657    /* Clear color and fast clear type */
658    unsigned state_size = clear_color_state_size + 4;
659 
660    /* We only need to track compression on CCS_E surfaces. */
661    if (image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E) {
662       if (image->vk.image_type == VK_IMAGE_TYPE_3D) {
663          for (uint32_t l = 0; l < image->vk.mip_levels; l++)
664             state_size += anv_minify(image->vk.extent.depth, l) * 4;
665       } else {
666          state_size += image->vk.mip_levels * image->vk.array_layers * 4;
667       }
668    }
669 
670    enum anv_image_memory_binding binding =
671       ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane;
672 
673    /* If an auxiliary surface is used for an externally-shareable image,
674     * we have to hide this from the memory of the image since other
675     * processes with access to the memory may not be aware of it or of
676     * its current state. So put that auxiliary data into a separate
677     * buffer (ANV_IMAGE_MEMORY_BINDING_PRIVATE).
678     */
679    if (anv_image_is_externally_shared(image)) {
680       binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
681    }
682 
683    /* We believe that 256B alignment may be sufficient, but we choose 4K due to
684     * lack of testing.  And MI_LOAD/STORE operations require dword-alignment.
685     */
686    return image_binding_grow(device, image, binding,
687                              ANV_OFFSET_IMPLICIT, state_size, 4096,
688                              &image->planes[plane].fast_clear_memory_range);
689 }
690 
691 /**
692  * The return code indicates whether creation of the VkImage should continue
693  * or fail, not whether the creation of the aux surface succeeded.  If the aux
694  * surface is not required (for example, by neither hardware nor DRM format
695  * modifier), then this may return VK_SUCCESS when creation of the aux surface
696  * fails.
697  *
698  * @param offset See add_surface()
699  */
700 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,isl_surf_usage_flags_t isl_extra_usage_flags)701 add_aux_surface_if_supported(struct anv_device *device,
702                              struct anv_image *image,
703                              uint32_t plane,
704                              struct anv_format_plane plane_format,
705                              const VkImageFormatListCreateInfo *fmt_list,
706                              uint64_t offset,
707                              uint32_t stride,
708                              isl_surf_usage_flags_t isl_extra_usage_flags)
709 {
710    VkImageAspectFlags aspect = plane_format.aspect;
711    VkResult result;
712    bool ok;
713 
714    /* The aux surface must not be already added. */
715    assert(!anv_surface_is_valid(&image->planes[plane].aux_surface));
716 
717    if ((isl_extra_usage_flags & ISL_SURF_USAGE_DISABLE_AUX_BIT))
718       return VK_SUCCESS;
719 
720    if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
721       /* We don't advertise that depth buffers could be used as storage
722        * images.
723        */
724        assert(!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT));
725 
726       /* Allow the user to control HiZ enabling. Disable by default on gfx7
727        * because resolves are not currently implemented pre-BDW.
728        */
729       if (!(image->vk.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
730          /* It will never be used as an attachment, HiZ is pointless. */
731          return VK_SUCCESS;
732       }
733 
734       if (device->info.ver == 7) {
735          anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Implement gfx7 HiZ");
736          return VK_SUCCESS;
737       }
738 
739       if (image->vk.mip_levels > 1) {
740          anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Enable multi-LOD HiZ");
741          return VK_SUCCESS;
742       }
743 
744       if (device->info.ver == 8 && image->vk.samples > 1) {
745          anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
746                        "Enable gfx8 multisampled HiZ");
747          return VK_SUCCESS;
748       }
749 
750       if (INTEL_DEBUG(DEBUG_NO_HIZ))
751          return VK_SUCCESS;
752 
753       ok = isl_surf_get_hiz_surf(&device->isl_dev,
754                                  &image->planes[plane].primary_surface.isl,
755                                  &image->planes[plane].aux_surface.isl);
756       if (!ok)
757          return VK_SUCCESS;
758 
759       if (!isl_surf_supports_ccs(&device->isl_dev,
760                                  &image->planes[plane].primary_surface.isl,
761                                  &image->planes[plane].aux_surface.isl)) {
762          image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ;
763       } else if (image->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
764                                     VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) &&
765                  image->vk.samples == 1) {
766          /* If it's used as an input attachment or a texture and it's
767           * single-sampled (this is a requirement for HiZ+CCS write-through
768           * mode), use write-through mode so that we don't need to resolve
769           * before texturing.  This will make depth testing a bit slower but
770           * texturing faster.
771           *
772           * TODO: This is a heuristic trade-off; we haven't tuned it at all.
773           */
774          assert(device->info.ver >= 12);
775          image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ_CCS_WT;
776       } else {
777          assert(device->info.ver >= 12);
778          image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ_CCS;
779       }
780 
781       result = add_surface(device, image, &image->planes[plane].aux_surface,
782                            ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
783                            ANV_OFFSET_IMPLICIT);
784       if (result != VK_SUCCESS)
785          return result;
786 
787       if (image->planes[plane].aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT)
788          return add_aux_state_tracking_buffer(device, image, plane);
789    } else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
790 
791       if (INTEL_DEBUG(DEBUG_NO_CCS))
792          return VK_SUCCESS;
793 
794       if (!isl_surf_supports_ccs(&device->isl_dev,
795                                  &image->planes[plane].primary_surface.isl,
796                                  NULL))
797          return VK_SUCCESS;
798 
799       image->planes[plane].aux_usage = ISL_AUX_USAGE_STC_CCS;
800    } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->vk.samples == 1) {
801       if (image->n_planes != 1) {
802          /* Multiplanar images seem to hit a sampler bug with CCS and R16G16
803           * format. (Putting the clear state a page/4096bytes further fixes
804           * the issue).
805           */
806          return VK_SUCCESS;
807       }
808 
809       if ((image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT)) {
810          /* The image may alias a plane of a multiplanar image. Above we ban
811           * CCS on multiplanar images.
812           *
813           * We must also reject aliasing of any image that uses
814           * ANV_IMAGE_MEMORY_BINDING_PRIVATE. Since we're already rejecting all
815           * aliasing here, there's no need to further analyze if the image needs
816           * a private binding.
817           */
818          return VK_SUCCESS;
819       }
820 
821       if (INTEL_DEBUG(DEBUG_NO_CCS))
822          return VK_SUCCESS;
823 
824       ok = isl_surf_get_ccs_surf(&device->isl_dev,
825                                  &image->planes[plane].primary_surface.isl,
826                                  NULL,
827                                  &image->planes[plane].aux_surface.isl,
828                                  stride);
829       if (!ok)
830          return VK_SUCCESS;
831 
832       /* Choose aux usage */
833       if (anv_formats_ccs_e_compatible(&device->info, image->vk.create_flags,
834                                        image->vk.format, image->vk.tiling,
835                                        image->vk.usage, fmt_list)) {
836          image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_E;
837       } else if (device->info.ver >= 12) {
838          anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
839                        "The CCS_D aux mode is not yet handled on "
840                        "Gfx12+. Not allocating a CCS buffer.");
841          image->planes[plane].aux_surface.isl.size_B = 0;
842          return VK_SUCCESS;
843       } else {
844          image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_D;
845       }
846 
847       if (!device->physical->has_implicit_ccs) {
848          enum anv_image_memory_binding binding =
849             ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane;
850 
851          if (image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID &&
852              !isl_drm_modifier_has_aux(image->vk.drm_format_mod))
853             binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
854 
855          result = add_surface(device, image, &image->planes[plane].aux_surface,
856                               binding, offset);
857          if (result != VK_SUCCESS)
858             return result;
859       }
860 
861       return add_aux_state_tracking_buffer(device, image, plane);
862    } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->vk.samples > 1) {
863       assert(!(image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT));
864       ok = isl_surf_get_mcs_surf(&device->isl_dev,
865                                  &image->planes[plane].primary_surface.isl,
866                                  &image->planes[plane].aux_surface.isl);
867       if (!ok)
868          return VK_SUCCESS;
869 
870       image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
871 
872       result = add_surface(device, image, &image->planes[plane].aux_surface,
873                            ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
874                            ANV_OFFSET_IMPLICIT);
875       if (result != VK_SUCCESS)
876          return result;
877 
878       return add_aux_state_tracking_buffer(device, image, plane);
879    }
880 
881    return VK_SUCCESS;
882 }
883 
884 static VkResult
add_shadow_surface(struct anv_device * device,struct anv_image * image,uint32_t plane,struct anv_format_plane plane_format,uint32_t stride,VkImageUsageFlags vk_plane_usage)885 add_shadow_surface(struct anv_device *device,
886                    struct anv_image *image,
887                    uint32_t plane,
888                    struct anv_format_plane plane_format,
889                    uint32_t stride,
890                    VkImageUsageFlags vk_plane_usage)
891 {
892    ASSERTED bool ok;
893 
894    ok = isl_surf_init(&device->isl_dev,
895                       &image->planes[plane].shadow_surface.isl,
896                      .dim = vk_to_isl_surf_dim[image->vk.image_type],
897                      .format = plane_format.isl_format,
898                      .width = image->vk.extent.width,
899                      .height = image->vk.extent.height,
900                      .depth = image->vk.extent.depth,
901                      .levels = image->vk.mip_levels,
902                      .array_len = image->vk.array_layers,
903                      .samples = image->vk.samples,
904                      .min_alignment_B = 0,
905                      .row_pitch_B = stride,
906                      .usage = ISL_SURF_USAGE_TEXTURE_BIT |
907                               (vk_plane_usage & ISL_SURF_USAGE_CUBE_BIT),
908                      .tiling_flags = ISL_TILING_ANY_MASK);
909 
910    /* isl_surf_init() will fail only if provided invalid input. Invalid input
911     * here is illegal in Vulkan.
912     */
913    assert(ok);
914 
915    return add_surface(device, image, &image->planes[plane].shadow_surface,
916                       ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
917                       ANV_OFFSET_IMPLICIT);
918 }
919 
920 /**
921  * Initialize the anv_image::*_surface selected by \a aspect. Then update the
922  * image's memory requirements (that is, the image's size and alignment).
923  *
924  * @param offset See add_surface()
925  */
926 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)927 add_primary_surface(struct anv_device *device,
928                     struct anv_image *image,
929                     uint32_t plane,
930                     struct anv_format_plane plane_format,
931                     uint64_t offset,
932                     uint32_t stride,
933                     isl_tiling_flags_t isl_tiling_flags,
934                     isl_surf_usage_flags_t isl_usage)
935 {
936    struct anv_surface *anv_surf = &image->planes[plane].primary_surface;
937    bool ok;
938 
939    ok = isl_surf_init(&device->isl_dev, &anv_surf->isl,
940       .dim = vk_to_isl_surf_dim[image->vk.image_type],
941       .format = plane_format.isl_format,
942       .width = image->vk.extent.width / plane_format.denominator_scales[0],
943       .height = image->vk.extent.height / plane_format.denominator_scales[1],
944       .depth = image->vk.extent.depth,
945       .levels = image->vk.mip_levels,
946       .array_len = image->vk.array_layers,
947       .samples = image->vk.samples,
948       .min_alignment_B = 0,
949       .row_pitch_B = stride,
950       .usage = isl_usage,
951       .tiling_flags = isl_tiling_flags);
952 
953    if (!ok) {
954       /* TODO: Should return
955        * VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT in come cases.
956        */
957       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
958    }
959 
960    image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
961 
962    return add_surface(device, image, anv_surf,
963                       ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane, offset);
964 }
965 
966 #ifndef NDEBUG
967 static bool MUST_CHECK
memory_range_is_aligned(struct anv_image_memory_range memory_range)968 memory_range_is_aligned(struct anv_image_memory_range memory_range)
969 {
970    return anv_is_aligned(memory_range.offset, memory_range.alignment);
971 }
972 
973 static bool MUST_CHECK
memory_ranges_equal(struct anv_image_memory_range a,struct anv_image_memory_range b)974 memory_ranges_equal(struct anv_image_memory_range a,
975                     struct anv_image_memory_range b)
976 {
977    return a.binding == b.binding &&
978           a.offset == b.offset &&
979           a.size == b.size &&
980           a.alignment == b.alignment;
981 }
982 #endif
983 
984 struct check_memory_range_params {
985    struct anv_image_memory_range *accum_ranges;
986    const struct anv_surface *test_surface;
987    const struct anv_image_memory_range *test_range;
988    enum anv_image_memory_binding expect_binding;
989 };
990 
991 #define check_memory_range(...) \
992    check_memory_range_s(&(struct check_memory_range_params) { __VA_ARGS__ })
993 
994 static void UNUSED
check_memory_range_s(const struct check_memory_range_params * p)995 check_memory_range_s(const struct check_memory_range_params *p)
996 {
997    assert((p->test_surface == NULL) != (p->test_range == NULL));
998 
999    const struct anv_image_memory_range *test_range =
1000       p->test_range ?: &p->test_surface->memory_range;
1001 
1002    struct anv_image_memory_range *accum_range =
1003       &p->accum_ranges[p->expect_binding];
1004 
1005    assert(test_range->binding == p->expect_binding);
1006    assert(test_range->offset >= memory_range_end(*accum_range));
1007    assert(memory_range_is_aligned(*test_range));
1008 
1009    if (p->test_surface) {
1010       assert(anv_surface_is_valid(p->test_surface));
1011       assert(p->test_surface->memory_range.alignment ==
1012              p->test_surface->isl.alignment_B);
1013    }
1014 
1015    memory_range_merge(accum_range, *test_range);
1016 }
1017 
1018 /**
1019  * Validate the image's memory bindings *after* all its surfaces and memory
1020  * ranges are final.
1021  *
1022  * For simplicity's sake, we do not validate free-form layout of the image's
1023  * memory bindings. We validate the layout described in the comments of struct
1024  * anv_image.
1025  */
1026 static void
check_memory_bindings(const struct anv_device * device,const struct anv_image * image)1027 check_memory_bindings(const struct anv_device *device,
1028                      const struct anv_image *image)
1029 {
1030 #ifdef DEBUG
1031    /* As we inspect each part of the image, we merge the part's memory range
1032     * into these accumulation ranges.
1033     */
1034    struct anv_image_memory_range accum_ranges[ANV_IMAGE_MEMORY_BINDING_END];
1035    for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; ++i) {
1036       accum_ranges[i] = (struct anv_image_memory_range) {
1037          .binding = i,
1038       };
1039    }
1040 
1041    for (uint32_t p = 0; p < image->n_planes; ++p) {
1042       const struct anv_image_plane *plane = &image->planes[p];
1043 
1044       /* The binding that must contain the plane's primary surface. */
1045       const enum anv_image_memory_binding primary_binding = image->disjoint
1046          ? ANV_IMAGE_MEMORY_BINDING_PLANE_0 + p
1047          : ANV_IMAGE_MEMORY_BINDING_MAIN;
1048 
1049       /* Aliasing is incompatible with the private binding because it does not
1050        * live in a VkDeviceMemory.  The one exception is swapchain images.
1051        */
1052       assert(!(image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT) ||
1053              image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].memory_range.size == 0);
1054 
1055       /* Check primary surface */
1056       check_memory_range(accum_ranges,
1057                          .test_surface = &plane->primary_surface,
1058                          .expect_binding = primary_binding);
1059 
1060       /* Check shadow surface */
1061       if (anv_surface_is_valid(&plane->shadow_surface)) {
1062          check_memory_range(accum_ranges,
1063                             .test_surface = &plane->shadow_surface,
1064                             .expect_binding = primary_binding);
1065       }
1066 
1067       /* Check aux_surface */
1068       if (anv_surface_is_valid(&plane->aux_surface)) {
1069          enum anv_image_memory_binding binding = primary_binding;
1070 
1071          /* If an auxiliary surface is used for an externally-shareable image,
1072           * we have to hide this from the memory of the image since other
1073           * processes with access to the memory may not be aware of it or of
1074           * its current state. So put that auxiliary data into a separate
1075           * buffer (ANV_IMAGE_MEMORY_BINDING_PRIVATE).
1076           */
1077          if (anv_image_is_externally_shared(image) &&
1078              !isl_drm_modifier_has_aux(image->vk.drm_format_mod)) {
1079             binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
1080          }
1081 
1082          /* Display hardware requires that the aux surface start at
1083           * a higher address than the primary surface. The 3D hardware
1084           * doesn't care, but we enforce the display requirement in case
1085           * the image is sent to display.
1086           */
1087          check_memory_range(accum_ranges,
1088                             .test_surface = &plane->aux_surface,
1089                             .expect_binding = binding);
1090       }
1091 
1092       /* Check fast clear state */
1093       if (plane->fast_clear_memory_range.size > 0) {
1094          enum anv_image_memory_binding binding = primary_binding;
1095 
1096          /* If an auxiliary surface is used for an externally-shareable image,
1097           * we have to hide this from the memory of the image since other
1098           * processes with access to the memory may not be aware of it or of
1099           * its current state. So put that auxiliary data into a separate
1100           * buffer (ANV_IMAGE_MEMORY_BINDING_PRIVATE).
1101           */
1102          if (anv_image_is_externally_shared(image)) {
1103             binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
1104          }
1105 
1106          /* We believe that 256B alignment may be sufficient, but we choose 4K
1107           * due to lack of testing.  And MI_LOAD/STORE operations require
1108           * dword-alignment.
1109           */
1110          assert(plane->fast_clear_memory_range.alignment == 4096);
1111          check_memory_range(accum_ranges,
1112                             .test_range = &plane->fast_clear_memory_range,
1113                             .expect_binding = binding);
1114       }
1115    }
1116 #endif
1117 }
1118 
1119 /**
1120  * Check that the fully-initialized anv_image is compatible with its DRM format
1121  * modifier.
1122  *
1123  * Checking compatibility at the end of image creation is prudent, not
1124  * superfluous, because usage of modifiers triggers numerous special cases
1125  * throughout queries and image creation, and because
1126  * vkGetPhysicalDeviceImageFormatProperties2 has difficulty detecting all
1127  * incompatibilities.
1128  *
1129  * Return VK_ERROR_UNKNOWN if the incompatibility is difficult to detect in
1130  * vkGetPhysicalDeviceImageFormatProperties2.  Otherwise, assert fail.
1131  *
1132  * Ideally, if vkGetPhysicalDeviceImageFormatProperties2() succeeds with a given
1133  * modifier, then vkCreateImage() produces an image that is compatible with the
1134  * modifier. However, it is difficult to reconcile the two functions to agree
1135  * due to their complexity. For example, isl_surf_get_ccs_surf() may
1136  * unexpectedly fail in vkCreateImage(), eliminating the image's aux surface
1137  * even when the modifier requires one. (Maybe we should reconcile the two
1138  * functions despite the difficulty).
1139  */
1140 static VkResult MUST_CHECK
check_drm_format_mod(const struct anv_device * device,const struct anv_image * image)1141 check_drm_format_mod(const struct anv_device *device,
1142                      const struct anv_image *image)
1143 {
1144    /* Image must have a modifier if and only if it has modifier tiling. */
1145    assert((image->vk.drm_format_mod != DRM_FORMAT_MOD_INVALID) ==
1146           (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT));
1147 
1148    if (image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID)
1149       return VK_SUCCESS;
1150 
1151    const struct isl_drm_modifier_info *isl_mod_info =
1152       isl_drm_modifier_get_info(image->vk.drm_format_mod);
1153 
1154    /* Driver must support the modifier. */
1155    assert(isl_drm_modifier_get_score(&device->info, isl_mod_info->modifier));
1156 
1157    /* Enforced by us, not the Vulkan spec. */
1158    assert(image->vk.image_type == VK_IMAGE_TYPE_2D);
1159    assert(!(image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT));
1160    assert(!(image->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT));
1161    assert(image->vk.mip_levels == 1);
1162    assert(image->vk.array_layers == 1);
1163    assert(image->vk.samples == 1);
1164 
1165    for (int i = 0; i < image->n_planes; ++i) {
1166       const struct anv_image_plane *plane = &image->planes[i];
1167       ASSERTED const struct isl_format_layout *isl_layout =
1168          isl_format_get_layout(plane->primary_surface.isl.format);
1169 
1170       /* Enforced by us, not the Vulkan spec. */
1171       assert(isl_layout->txc == ISL_TXC_NONE);
1172       assert(isl_layout->colorspace == ISL_COLORSPACE_LINEAR ||
1173              isl_layout->colorspace == ISL_COLORSPACE_SRGB);
1174       assert(!anv_surface_is_valid(&plane->shadow_surface));
1175 
1176       if (isl_mod_info->aux_usage != ISL_AUX_USAGE_NONE) {
1177          /* Reject DISJOINT for consistency with the GL driver. */
1178          assert(!image->disjoint);
1179 
1180          /* The modifier's required aux usage mandates the image's aux usage.
1181           * The inverse, however, does not hold; if the modifier has no aux
1182           * usage, then we may enable a private aux surface.
1183           */
1184          if (plane->aux_usage != isl_mod_info->aux_usage) {
1185             return vk_errorf(device, VK_ERROR_UNKNOWN,
1186                              "image with modifier unexpectedly has wrong aux "
1187                              "usage");
1188          }
1189       }
1190    }
1191 
1192    return VK_SUCCESS;
1193 }
1194 
1195 /**
1196  * Use when the app does not provide
1197  * VkImageDrmFormatModifierExplicitCreateInfoEXT.
1198  */
1199 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)1200 add_all_surfaces_implicit_layout(
1201    struct anv_device *device,
1202    struct anv_image *image,
1203    const VkImageFormatListCreateInfo *format_list_info,
1204    uint32_t stride,
1205    isl_tiling_flags_t isl_tiling_flags,
1206    isl_surf_usage_flags_t isl_extra_usage_flags)
1207 {
1208    const struct intel_device_info *devinfo = &device->info;
1209    VkResult result;
1210 
1211    u_foreach_bit(b, image->vk.aspects) {
1212       VkImageAspectFlagBits aspect = 1 << b;
1213       const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1214       const  struct anv_format_plane plane_format =
1215          anv_get_format_plane(devinfo, image->vk.format, plane, image->vk.tiling);
1216 
1217       VkImageUsageFlags vk_usage = vk_image_usage(&image->vk, aspect);
1218       isl_surf_usage_flags_t isl_usage =
1219          choose_isl_surf_usage(image->vk.create_flags, vk_usage,
1220                                isl_extra_usage_flags, aspect);
1221 
1222       /* Must call this before adding any surfaces because it may modify
1223        * isl_tiling_flags.
1224        */
1225       bool needs_shadow =
1226          anv_image_plane_needs_shadow_surface(devinfo, plane_format,
1227                                               image->vk.tiling, vk_usage,
1228                                               image->vk.create_flags,
1229                                               &isl_tiling_flags);
1230 
1231       result = add_primary_surface(device, image, plane, plane_format,
1232                                    ANV_OFFSET_IMPLICIT, stride,
1233                                    isl_tiling_flags, isl_usage);
1234       if (result != VK_SUCCESS)
1235          return result;
1236 
1237       if (needs_shadow) {
1238          result = add_shadow_surface(device, image, plane, plane_format,
1239                                      stride, vk_usage);
1240          if (result != VK_SUCCESS)
1241             return result;
1242       }
1243 
1244       /* Disable aux if image supports export without modifiers. */
1245       if (image->vk.external_handle_types != 0 &&
1246           image->vk.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
1247          continue;
1248 
1249       result = add_aux_surface_if_supported(device, image, plane, plane_format,
1250                                             format_list_info,
1251                                             ANV_OFFSET_IMPLICIT, stride,
1252                                             isl_extra_usage_flags);
1253       if (result != VK_SUCCESS)
1254          return result;
1255    }
1256 
1257    return VK_SUCCESS;
1258 }
1259 
1260 /**
1261  * Use when the app provides VkImageDrmFormatModifierExplicitCreateInfoEXT.
1262  */
1263 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)1264 add_all_surfaces_explicit_layout(
1265    struct anv_device *device,
1266    struct anv_image *image,
1267    const VkImageFormatListCreateInfo *format_list_info,
1268    const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_info,
1269    isl_tiling_flags_t isl_tiling_flags,
1270    isl_surf_usage_flags_t isl_extra_usage_flags)
1271 {
1272    const struct intel_device_info *devinfo = &device->info;
1273    const uint32_t mod_plane_count = drm_info->drmFormatModifierPlaneCount;
1274    const bool mod_has_aux =
1275       isl_drm_modifier_has_aux(drm_info->drmFormatModifier);
1276    VkResult result;
1277 
1278    /* About valid usage in the Vulkan spec:
1279     *
1280     * Unlike vanilla vkCreateImage, which produces undefined behavior on user
1281     * error, here the spec requires the implementation to return
1282     * VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT if the app provides
1283     * a bad plane layout. However, the spec does require
1284     * drmFormatModifierPlaneCount to be valid.
1285     *
1286     * Most validation of plane layout occurs in add_surface().
1287     */
1288 
1289    /* We support a restricted set of images with modifiers.
1290     *
1291     * With aux usage,
1292     * - Format plane count must be 1.
1293     * - Memory plane count must be 2.
1294     * Without aux usage,
1295     * - Each format plane must map to a distint memory plane.
1296     *
1297     * For the other cases, currently there is no way to properly map memory
1298     * planes to format planes and aux planes due to the lack of defined ABI
1299     * for external multi-planar images.
1300     */
1301    if (image->n_planes == 1)
1302       assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT);
1303    else
1304       assert(!(image->vk.aspects & ~VK_IMAGE_ASPECT_PLANES_BITS_ANV));
1305 
1306    if (mod_has_aux)
1307       assert(image->n_planes == 1 && mod_plane_count == 2);
1308    else
1309       assert(image->n_planes == mod_plane_count);
1310 
1311    /* Reject special values in the app-provided plane layouts. */
1312    for (uint32_t i = 0; i < mod_plane_count; ++i) {
1313       if (drm_info->pPlaneLayouts[i].rowPitch == 0) {
1314          return vk_errorf(device,
1315                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
1316                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
1317                           "pPlaneLayouts[%u]::rowPitch is 0", i);
1318       }
1319 
1320       if (drm_info->pPlaneLayouts[i].offset == ANV_OFFSET_IMPLICIT) {
1321          return vk_errorf(device,
1322                           VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
1323                           "VkImageDrmFormatModifierExplicitCreateInfoEXT::"
1324                           "pPlaneLayouts[%u]::offset is %" PRIu64,
1325                           i, ANV_OFFSET_IMPLICIT);
1326       }
1327    }
1328 
1329    u_foreach_bit(b, image->vk.aspects) {
1330       const VkImageAspectFlagBits aspect = 1 << b;
1331       const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1332       const struct anv_format_plane format_plane =
1333          anv_get_format_plane(devinfo, image->vk.format, plane, image->vk.tiling);
1334       const VkSubresourceLayout *primary_layout = &drm_info->pPlaneLayouts[plane];
1335 
1336       result = add_primary_surface(device, image, plane,
1337                                    format_plane,
1338                                    primary_layout->offset,
1339                                    primary_layout->rowPitch,
1340                                    isl_tiling_flags,
1341                                    isl_extra_usage_flags);
1342       if (result != VK_SUCCESS)
1343          return result;
1344 
1345       if (mod_has_aux) {
1346          const VkSubresourceLayout *aux_layout = &drm_info->pPlaneLayouts[1];
1347          result = add_aux_surface_if_supported(device, image, plane,
1348                                                format_plane,
1349                                                format_list_info,
1350                                                aux_layout->offset,
1351                                                aux_layout->rowPitch,
1352                                                isl_extra_usage_flags);
1353          if (result != VK_SUCCESS)
1354             return result;
1355       }
1356    }
1357 
1358    return VK_SUCCESS;
1359 }
1360 
1361 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)1362 choose_drm_format_mod(const struct anv_physical_device *device,
1363                       uint32_t modifier_count, const uint64_t *modifiers)
1364 {
1365    uint64_t best_mod = UINT64_MAX;
1366    uint32_t best_score = 0;
1367 
1368    for (uint32_t i = 0; i < modifier_count; ++i) {
1369       uint32_t score = isl_drm_modifier_get_score(&device->info, modifiers[i]);
1370       if (score > best_score) {
1371          best_mod = modifiers[i];
1372          best_score = score;
1373       }
1374    }
1375 
1376    if (best_score > 0)
1377       return isl_drm_modifier_get_info(best_mod);
1378    else
1379       return NULL;
1380 }
1381 
1382 static VkImageUsageFlags
anv_image_create_usage(const VkImageCreateInfo * pCreateInfo,VkImageUsageFlags usage)1383 anv_image_create_usage(const VkImageCreateInfo *pCreateInfo,
1384                        VkImageUsageFlags usage)
1385 {
1386    /* Add TRANSFER_SRC usage for multisample attachment images. This is
1387     * because we might internally use the TRANSFER_SRC layout on them for
1388     * blorp operations associated with resolving those into other attachments
1389     * at the end of a subpass.
1390     *
1391     * Without this additional usage, we compute an incorrect AUX state in
1392     * anv_layout_to_aux_state().
1393     */
1394    if (pCreateInfo->samples > VK_SAMPLE_COUNT_1_BIT &&
1395        (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1396                  VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)))
1397       usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1398    return usage;
1399 }
1400 
1401 static VkResult MUST_CHECK
alloc_private_binding(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * create_info)1402 alloc_private_binding(struct anv_device *device,
1403                       struct anv_image *image,
1404                       const VkImageCreateInfo *create_info)
1405 {
1406    struct anv_image_binding *binding =
1407       &image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE];
1408 
1409    if (binding->memory_range.size == 0)
1410       return VK_SUCCESS;
1411 
1412    const VkImageSwapchainCreateInfoKHR *swapchain_info =
1413       vk_find_struct_const(create_info->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1414 
1415    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1416       /* The image will be bound to swapchain memory. */
1417       return VK_SUCCESS;
1418    }
1419 
1420    return anv_device_alloc_bo(device, "image-binding-private",
1421                               binding->memory_range.size, 0, 0,
1422                               &binding->address.bo);
1423 }
1424 
1425 VkResult
anv_image_init(struct anv_device * device,struct anv_image * image,const struct anv_image_create_info * create_info)1426 anv_image_init(struct anv_device *device, struct anv_image *image,
1427                const struct anv_image_create_info *create_info)
1428 {
1429    const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
1430    const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_explicit_info = NULL;
1431    const struct isl_drm_modifier_info *isl_mod_info = NULL;
1432    VkResult r;
1433 
1434    vk_image_init(&device->vk, &image->vk, pCreateInfo);
1435 
1436    image->vk.usage = anv_image_create_usage(pCreateInfo, image->vk.usage);
1437    image->vk.stencil_usage =
1438       anv_image_create_usage(pCreateInfo, image->vk.stencil_usage);
1439 
1440    if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1441       assert(!image->vk.wsi_legacy_scanout);
1442       mod_explicit_info =
1443          vk_find_struct_const(pCreateInfo->pNext,
1444                               IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
1445       if (mod_explicit_info) {
1446          isl_mod_info = isl_drm_modifier_get_info(mod_explicit_info->drmFormatModifier);
1447       } else {
1448          const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list_info =
1449             vk_find_struct_const(pCreateInfo->pNext,
1450                                  IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
1451          isl_mod_info = choose_drm_format_mod(device->physical,
1452                                               mod_list_info->drmFormatModifierCount,
1453                                               mod_list_info->pDrmFormatModifiers);
1454       }
1455 
1456       assert(isl_mod_info);
1457       assert(image->vk.drm_format_mod == DRM_FORMAT_MOD_INVALID);
1458       image->vk.drm_format_mod = isl_mod_info->modifier;
1459    }
1460 
1461    for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; ++i) {
1462       image->bindings[i] = (struct anv_image_binding) {
1463          .memory_range = { .binding = i },
1464       };
1465    }
1466 
1467    /* In case of AHardwareBuffer import, we don't know the layout yet */
1468    if (image->vk.external_handle_types &
1469        VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
1470       image->from_ahb = true;
1471       return VK_SUCCESS;
1472    }
1473 
1474    image->n_planes = anv_get_format_planes(image->vk.format);
1475 
1476    /* The Vulkan 1.2.165 glossary says:
1477     *
1478     *    A disjoint image consists of multiple disjoint planes, and is created
1479     *    with the VK_IMAGE_CREATE_DISJOINT_BIT bit set.
1480     */
1481    image->disjoint = image->n_planes > 1 &&
1482                      (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
1483 
1484    const isl_tiling_flags_t isl_tiling_flags =
1485       choose_isl_tiling_flags(&device->info, create_info, isl_mod_info,
1486                               image->vk.wsi_legacy_scanout);
1487 
1488    const VkImageFormatListCreateInfo *fmt_list =
1489       vk_find_struct_const(pCreateInfo->pNext,
1490                            IMAGE_FORMAT_LIST_CREATE_INFO);
1491 
1492    if (mod_explicit_info) {
1493       r = add_all_surfaces_explicit_layout(device, image, fmt_list,
1494                                            mod_explicit_info, isl_tiling_flags,
1495                                            create_info->isl_extra_usage_flags);
1496    } else {
1497       r = add_all_surfaces_implicit_layout(device, image, fmt_list, 0,
1498                                            isl_tiling_flags,
1499                                            create_info->isl_extra_usage_flags);
1500    }
1501 
1502    if (r != VK_SUCCESS)
1503       goto fail;
1504 
1505    r = alloc_private_binding(device, image, pCreateInfo);
1506    if (r != VK_SUCCESS)
1507       goto fail;
1508 
1509    check_memory_bindings(device, image);
1510 
1511    r = check_drm_format_mod(device, image);
1512    if (r != VK_SUCCESS)
1513       goto fail;
1514 
1515    /* Once we have all the bindings, determine whether we can do non 0 fast
1516     * clears for each plane.
1517     */
1518    for (uint32_t p = 0; p < image->n_planes; p++) {
1519       image->planes[p].can_non_zero_fast_clear =
1520          can_fast_clear_with_non_zero_color(&device->info, image, p, fmt_list);
1521    }
1522 
1523    return VK_SUCCESS;
1524 
1525 fail:
1526    vk_image_finish(&image->vk);
1527    return r;
1528 }
1529 
1530 void
anv_image_finish(struct anv_image * image)1531 anv_image_finish(struct anv_image *image)
1532 {
1533    struct anv_device *device =
1534       container_of(image->vk.base.device, struct anv_device, vk);
1535 
1536    if (image->from_gralloc) {
1537       assert(!image->disjoint);
1538       assert(image->n_planes == 1);
1539       assert(image->planes[0].primary_surface.memory_range.binding ==
1540              ANV_IMAGE_MEMORY_BINDING_MAIN);
1541       assert(image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo != NULL);
1542       anv_device_release_bo(device, image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address.bo);
1543    }
1544 
1545    struct anv_bo *private_bo = image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].address.bo;
1546    if (private_bo)
1547       anv_device_release_bo(device, private_bo);
1548 
1549    vk_image_finish(&image->vk);
1550 }
1551 
1552 static struct anv_image *
anv_swapchain_get_image(VkSwapchainKHR swapchain,uint32_t index)1553 anv_swapchain_get_image(VkSwapchainKHR swapchain,
1554                         uint32_t index)
1555 {
1556    VkImage image = wsi_common_get_image(swapchain, index);
1557    return anv_image_from_handle(image);
1558 }
1559 
1560 static VkResult
anv_image_init_from_create_info(struct anv_device * device,struct anv_image * image,const VkImageCreateInfo * pCreateInfo)1561 anv_image_init_from_create_info(struct anv_device *device,
1562                                 struct anv_image *image,
1563                                 const VkImageCreateInfo *pCreateInfo)
1564 {
1565    const VkNativeBufferANDROID *gralloc_info =
1566       vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
1567    if (gralloc_info)
1568       return anv_image_init_from_gralloc(device, image, pCreateInfo,
1569                                          gralloc_info);
1570 
1571    struct anv_image_create_info create_info = {
1572       .vk_info = pCreateInfo,
1573    };
1574 
1575    /* For dmabuf imports, configure the primary surface without support for
1576     * compression if the modifier doesn't specify it. This helps to create
1577     * VkImages with memory requirements that are compatible with the buffers
1578     * apps provide.
1579     */
1580    const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_explicit_info =
1581       vk_find_struct_const(pCreateInfo->pNext,
1582                            IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
1583    if (mod_explicit_info &&
1584        !isl_drm_modifier_has_aux(mod_explicit_info->drmFormatModifier))
1585       create_info.isl_extra_usage_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT;
1586 
1587    return anv_image_init(device, image, &create_info);
1588 }
1589 
anv_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)1590 VkResult anv_CreateImage(
1591     VkDevice                                    _device,
1592     const VkImageCreateInfo*                    pCreateInfo,
1593     const VkAllocationCallbacks*                pAllocator,
1594     VkImage*                                    pImage)
1595 {
1596    ANV_FROM_HANDLE(anv_device, device, _device);
1597 
1598 #ifndef VK_USE_PLATFORM_ANDROID_KHR
1599    /* Ignore swapchain creation info on Android. Since we don't have an
1600     * implementation in Mesa, we're guaranteed to access an Android object
1601     * incorrectly.
1602     */
1603    const VkImageSwapchainCreateInfoKHR *swapchain_info =
1604       vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
1605    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
1606       return wsi_common_create_swapchain_image(&device->physical->wsi_device,
1607                                                pCreateInfo,
1608                                                swapchain_info->swapchain,
1609                                                pImage);
1610    }
1611 #endif
1612 
1613    struct anv_image *image =
1614       vk_object_zalloc(&device->vk, pAllocator, sizeof(*image),
1615                        VK_OBJECT_TYPE_IMAGE);
1616    if (!image)
1617       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1618 
1619    VkResult result = anv_image_init_from_create_info(device, image,
1620                                                      pCreateInfo);
1621    if (result != VK_SUCCESS) {
1622       vk_object_free(&device->vk, pAllocator, image);
1623       return result;
1624    }
1625 
1626    *pImage = anv_image_to_handle(image);
1627 
1628    return result;
1629 }
1630 
1631 void
anv_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)1632 anv_DestroyImage(VkDevice _device, VkImage _image,
1633                  const VkAllocationCallbacks *pAllocator)
1634 {
1635    ANV_FROM_HANDLE(anv_device, device, _device);
1636    ANV_FROM_HANDLE(anv_image, image, _image);
1637 
1638    if (!image)
1639       return;
1640 
1641    assert(&device->vk == image->vk.base.device);
1642    anv_image_finish(image);
1643 
1644    vk_free2(&device->vk.alloc, pAllocator, image);
1645 }
1646 
1647 /* We are binding AHardwareBuffer. Get a description, resolve the
1648  * format and prepare anv_image properly.
1649  */
1650 static void
resolve_ahw_image(struct anv_device * device,struct anv_image * image,struct anv_device_memory * mem)1651 resolve_ahw_image(struct anv_device *device,
1652                   struct anv_image *image,
1653                   struct anv_device_memory *mem)
1654 {
1655 #if defined(ANDROID) && ANDROID_API_LEVEL >= 26
1656    assert(mem->ahw);
1657    AHardwareBuffer_Desc desc;
1658    AHardwareBuffer_describe(mem->ahw, &desc);
1659    VkResult result;
1660 
1661    /* Check tiling. */
1662    enum isl_tiling tiling;
1663    result = anv_device_get_bo_tiling(device, mem->bo, &tiling);
1664    assert(result == VK_SUCCESS);
1665 
1666    VkImageTiling vk_tiling =
1667       tiling == ISL_TILING_LINEAR ? VK_IMAGE_TILING_LINEAR :
1668                                     VK_IMAGE_TILING_OPTIMAL;
1669    isl_tiling_flags_t isl_tiling_flags = (1u << tiling);
1670 
1671    /* Check format. */
1672    VkFormat vk_format = vk_format_from_android(desc.format, desc.usage);
1673    enum isl_format isl_fmt = anv_get_isl_format(&device->info,
1674                                                 vk_format,
1675                                                 VK_IMAGE_ASPECT_COLOR_BIT,
1676                                                 vk_tiling);
1677    assert(isl_fmt != ISL_FORMAT_UNSUPPORTED);
1678 
1679    /* Handle RGB(X)->RGBA fallback. */
1680    switch (desc.format) {
1681    case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
1682    case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
1683       if (isl_format_is_rgb(isl_fmt))
1684          isl_fmt = isl_format_rgb_to_rgba(isl_fmt);
1685       break;
1686    }
1687 
1688    /* Now we are able to fill anv_image fields properly and create
1689     * isl_surface for it.
1690     */
1691    vk_image_set_format(&image->vk, vk_format);
1692    image->n_planes = anv_get_format_planes(image->vk.format);
1693 
1694    uint32_t stride = desc.stride *
1695                      (isl_format_get_layout(isl_fmt)->bpb / 8);
1696 
1697    result = add_all_surfaces_implicit_layout(device, image, NULL, stride,
1698                                              isl_tiling_flags,
1699                                              ISL_SURF_USAGE_DISABLE_AUX_BIT);
1700    assert(result == VK_SUCCESS);
1701 #endif
1702 }
1703 
1704 void
anv_image_get_memory_requirements(struct anv_device * device,struct anv_image * image,VkImageAspectFlags aspects,VkMemoryRequirements2 * pMemoryRequirements)1705 anv_image_get_memory_requirements(struct anv_device *device,
1706                                   struct anv_image *image,
1707                                   VkImageAspectFlags aspects,
1708                                   VkMemoryRequirements2 *pMemoryRequirements)
1709 {
1710    /* The Vulkan spec (git aaed022) says:
1711     *
1712     *    memoryTypeBits is a bitfield and contains one bit set for every
1713     *    supported memory type for the resource. The bit `1<<i` is set if and
1714     *    only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
1715     *    structure for the physical device is supported.
1716     *
1717     * All types are currently supported for images.
1718     */
1719    uint32_t memory_types = (1ull << device->physical->memory.type_count) - 1;
1720 
1721    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
1722       switch (ext->sType) {
1723       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1724          VkMemoryDedicatedRequirements *requirements = (void *)ext;
1725          if (image->vk.wsi_legacy_scanout || image->from_ahb) {
1726             /* If we need to set the tiling for external consumers, we need a
1727              * dedicated allocation.
1728              *
1729              * See also anv_AllocateMemory.
1730              */
1731             requirements->prefersDedicatedAllocation = true;
1732             requirements->requiresDedicatedAllocation = true;
1733          } else {
1734             requirements->prefersDedicatedAllocation = false;
1735             requirements->requiresDedicatedAllocation = false;
1736          }
1737          break;
1738       }
1739 
1740       default:
1741          anv_debug_ignored_stype(ext->sType);
1742          break;
1743       }
1744    }
1745 
1746    /* If the image is disjoint, then we must return the memory requirements for
1747     * the single plane specified in VkImagePlaneMemoryRequirementsInfo. If
1748     * non-disjoint, then exactly one set of memory requirements exists for the
1749     * whole image.
1750     *
1751     * This is enforced by the Valid Usage for VkImageMemoryRequirementsInfo2,
1752     * which requires that the app provide VkImagePlaneMemoryRequirementsInfo if
1753     * and only if the image is disjoint (that is, multi-planar format and
1754     * VK_IMAGE_CREATE_DISJOINT_BIT).
1755     */
1756    const struct anv_image_binding *binding;
1757    if (image->disjoint) {
1758       assert(util_bitcount(aspects) == 1);
1759       assert(aspects & image->vk.aspects);
1760       binding = image_aspect_to_binding(image, aspects);
1761    } else {
1762       assert(aspects == image->vk.aspects);
1763       binding = &image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN];
1764    }
1765 
1766    pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
1767       .size = binding->memory_range.size,
1768       .alignment = binding->memory_range.alignment,
1769       .memoryTypeBits = memory_types,
1770    };
1771 }
1772 
anv_GetImageMemoryRequirements2(VkDevice _device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1773 void anv_GetImageMemoryRequirements2(
1774     VkDevice                                    _device,
1775     const VkImageMemoryRequirementsInfo2*       pInfo,
1776     VkMemoryRequirements2*                      pMemoryRequirements)
1777 {
1778    ANV_FROM_HANDLE(anv_device, device, _device);
1779    ANV_FROM_HANDLE(anv_image, image, pInfo->image);
1780 
1781    VkImageAspectFlags aspects = image->vk.aspects;
1782 
1783    vk_foreach_struct_const(ext, pInfo->pNext) {
1784       switch (ext->sType) {
1785       case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: {
1786          assert(image->disjoint);
1787          const VkImagePlaneMemoryRequirementsInfo *plane_reqs =
1788             (const VkImagePlaneMemoryRequirementsInfo *) ext;
1789          aspects = plane_reqs->planeAspect;
1790          break;
1791       }
1792 
1793       default:
1794          anv_debug_ignored_stype(ext->sType);
1795          break;
1796       }
1797    }
1798 
1799    anv_image_get_memory_requirements(device, image, aspects,
1800                                      pMemoryRequirements);
1801 }
1802 
anv_GetDeviceImageMemoryRequirementsKHR(VkDevice _device,const VkDeviceImageMemoryRequirements * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1803 void anv_GetDeviceImageMemoryRequirementsKHR(
1804     VkDevice                                    _device,
1805     const VkDeviceImageMemoryRequirements*   pInfo,
1806     VkMemoryRequirements2*                      pMemoryRequirements)
1807 {
1808    ANV_FROM_HANDLE(anv_device, device, _device);
1809    struct anv_image image = { 0 };
1810 
1811    ASSERTED VkResult result =
1812       anv_image_init_from_create_info(device, &image, pInfo->pCreateInfo);
1813    assert(result == VK_SUCCESS);
1814 
1815    VkImageAspectFlags aspects =
1816       image.disjoint ? pInfo->planeAspect : image.vk.aspects;
1817 
1818    anv_image_get_memory_requirements(device, &image, aspects,
1819                                      pMemoryRequirements);
1820 }
1821 
anv_GetImageSparseMemoryRequirements(VkDevice device,VkImage image,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements * pSparseMemoryRequirements)1822 void anv_GetImageSparseMemoryRequirements(
1823     VkDevice                                    device,
1824     VkImage                                     image,
1825     uint32_t*                                   pSparseMemoryRequirementCount,
1826     VkSparseImageMemoryRequirements*            pSparseMemoryRequirements)
1827 {
1828    *pSparseMemoryRequirementCount = 0;
1829 }
1830 
anv_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1831 void anv_GetImageSparseMemoryRequirements2(
1832     VkDevice                                    device,
1833     const VkImageSparseMemoryRequirementsInfo2* pInfo,
1834     uint32_t*                                   pSparseMemoryRequirementCount,
1835     VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements)
1836 {
1837    *pSparseMemoryRequirementCount = 0;
1838 }
1839 
anv_GetDeviceImageSparseMemoryRequirementsKHR(VkDevice device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1840 void anv_GetDeviceImageSparseMemoryRequirementsKHR(
1841     VkDevice                                    device,
1842     const VkDeviceImageMemoryRequirements* pInfo,
1843     uint32_t*                                   pSparseMemoryRequirementCount,
1844     VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements)
1845 {
1846    *pSparseMemoryRequirementCount = 0;
1847 }
1848 
anv_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1849 VkResult anv_BindImageMemory2(
1850     VkDevice                                    _device,
1851     uint32_t                                    bindInfoCount,
1852     const VkBindImageMemoryInfo*                pBindInfos)
1853 {
1854    ANV_FROM_HANDLE(anv_device, device, _device);
1855 
1856    for (uint32_t i = 0; i < bindInfoCount; i++) {
1857       const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
1858       ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory);
1859       ANV_FROM_HANDLE(anv_image, image, bind_info->image);
1860       bool did_bind = false;
1861 
1862       /* Resolve will alter the image's aspects, do this first. */
1863       if (mem && mem->ahw)
1864          resolve_ahw_image(device, image, mem);
1865 
1866       vk_foreach_struct_const(s, bind_info->pNext) {
1867          switch (s->sType) {
1868          case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: {
1869             const VkBindImagePlaneMemoryInfo *plane_info =
1870                (const VkBindImagePlaneMemoryInfo *) s;
1871 
1872             /* Workaround for possible spec bug.
1873              *
1874              * Unlike VkImagePlaneMemoryRequirementsInfo, which requires that
1875              * the image be disjoint (that is, multi-planar format and
1876              * VK_IMAGE_CREATE_DISJOINT_BIT), VkBindImagePlaneMemoryInfo allows
1877              * the image to be non-disjoint and requires only that the image
1878              * have the DISJOINT flag. In this case, regardless of the value of
1879              * VkImagePlaneMemoryRequirementsInfo::planeAspect, the behavior is
1880              * the same as if VkImagePlaneMemoryRequirementsInfo were omitted.
1881              */
1882             if (!image->disjoint)
1883                break;
1884 
1885             struct anv_image_binding *binding =
1886                image_aspect_to_binding(image, plane_info->planeAspect);
1887 
1888             binding->address = (struct anv_address) {
1889                .bo = mem->bo,
1890                .offset = bind_info->memoryOffset,
1891             };
1892 
1893             did_bind = true;
1894             break;
1895          }
1896          case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: {
1897             /* Ignore this struct on Android, we cannot access swapchain
1898              * structures there.
1899              */
1900 #ifndef VK_USE_PLATFORM_ANDROID_KHR
1901             const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
1902                (const VkBindImageMemorySwapchainInfoKHR *) s;
1903             struct anv_image *swapchain_image =
1904                anv_swapchain_get_image(swapchain_info->swapchain,
1905                                        swapchain_info->imageIndex);
1906             assert(swapchain_image);
1907             assert(image->vk.aspects == swapchain_image->vk.aspects);
1908             assert(mem == NULL);
1909 
1910             for (int j = 0; j < ARRAY_SIZE(image->bindings); ++j) {
1911                assert(memory_ranges_equal(image->bindings[j].memory_range,
1912                                           swapchain_image->bindings[j].memory_range));
1913                image->bindings[j].address = swapchain_image->bindings[j].address;
1914             }
1915 
1916             /* We must bump the private binding's bo's refcount because, unlike the other
1917              * bindings, its lifetime is not application-managed.
1918              */
1919             struct anv_bo *private_bo =
1920                image->bindings[ANV_IMAGE_MEMORY_BINDING_PRIVATE].address.bo;
1921             if (private_bo)
1922                anv_bo_ref(private_bo);
1923 
1924             did_bind = true;
1925 #endif
1926             break;
1927          }
1928 #pragma GCC diagnostic push
1929 #pragma GCC diagnostic ignored "-Wswitch"
1930          case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID: {
1931             const VkNativeBufferANDROID *gralloc_info =
1932                (const VkNativeBufferANDROID *)s;
1933             VkResult result = anv_image_bind_from_gralloc(device, image,
1934                                                           gralloc_info);
1935             if (result != VK_SUCCESS)
1936                return result;
1937             did_bind = true;
1938             break;
1939          }
1940 #pragma GCC diagnostic pop
1941          default:
1942             anv_debug_ignored_stype(s->sType);
1943             break;
1944          }
1945       }
1946 
1947       if (!did_bind) {
1948          assert(!image->disjoint);
1949 
1950          image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address =
1951             (struct anv_address) {
1952                .bo = mem->bo,
1953                .offset = bind_info->memoryOffset,
1954             };
1955 
1956          did_bind = true;
1957       }
1958 
1959       /* On platforms that use implicit CCS, if the plane's bo lacks implicit
1960        * CCS then disable compression on the plane.
1961        */
1962       for (int p = 0; p < image->n_planes; ++p) {
1963          enum anv_image_memory_binding binding =
1964             image->planes[p].primary_surface.memory_range.binding;
1965          const struct anv_bo *bo =
1966             image->bindings[binding].address.bo;
1967 
1968          if (!bo || bo->has_implicit_ccs)
1969             continue;
1970 
1971          if (!device->physical->has_implicit_ccs)
1972             continue;
1973 
1974          if (!isl_aux_usage_has_ccs(image->planes[p].aux_usage))
1975             continue;
1976 
1977          anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
1978                        "BO lacks implicit CCS. Disabling the CCS aux usage.");
1979 
1980          if (image->planes[p].aux_surface.memory_range.size > 0) {
1981             assert(image->planes[p].aux_usage == ISL_AUX_USAGE_HIZ_CCS ||
1982                    image->planes[p].aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT);
1983             image->planes[p].aux_usage = ISL_AUX_USAGE_HIZ;
1984          } else {
1985             assert(image->planes[p].aux_usage == ISL_AUX_USAGE_CCS_E ||
1986                    image->planes[p].aux_usage == ISL_AUX_USAGE_STC_CCS);
1987             image->planes[p].aux_usage = ISL_AUX_USAGE_NONE;
1988          }
1989       }
1990    }
1991 
1992    return VK_SUCCESS;
1993 }
1994 
anv_GetImageSubresourceLayout(VkDevice device,VkImage _image,const VkImageSubresource * subresource,VkSubresourceLayout * layout)1995 void anv_GetImageSubresourceLayout(
1996     VkDevice                                    device,
1997     VkImage                                     _image,
1998     const VkImageSubresource*                   subresource,
1999     VkSubresourceLayout*                        layout)
2000 {
2001    ANV_FROM_HANDLE(anv_image, image, _image);
2002    const struct anv_surface *surface;
2003 
2004    assert(__builtin_popcount(subresource->aspectMask) == 1);
2005 
2006    /* The Vulkan spec requires that aspectMask be
2007     * VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT if tiling is
2008     * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
2009     *
2010     * For swapchain images, the Vulkan spec says that every swapchain image has
2011     * tiling VK_IMAGE_TILING_OPTIMAL, but we may choose
2012     * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT internally.  Vulkan doesn't allow
2013     * vkGetImageSubresourceLayout for images with VK_IMAGE_TILING_OPTIMAL,
2014     * therefore it's invalid for the application to call this on a swapchain
2015     * image.  The WSI code, however, knows when it has internally created
2016     * a swapchain image with VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
2017     * so it _should_ correctly use VK_IMAGE_ASPECT_MEMORY_PLANE_* in that case.
2018     * But it incorrectly uses VK_IMAGE_ASPECT_PLANE_*, so we have a temporary
2019     * workaround.
2020     */
2021    if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
2022       /* TODO(chadv): Drop this workaround when WSI gets fixed. */
2023       uint32_t mem_plane;
2024       switch (subresource->aspectMask) {
2025       case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT:
2026       case VK_IMAGE_ASPECT_PLANE_0_BIT:
2027          mem_plane = 0;
2028          break;
2029       case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:
2030       case VK_IMAGE_ASPECT_PLANE_1_BIT:
2031          mem_plane = 1;
2032          break;
2033       case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:
2034       case VK_IMAGE_ASPECT_PLANE_2_BIT:
2035          mem_plane = 2;
2036          break;
2037       default:
2038          unreachable("bad VkImageAspectFlags");
2039       }
2040 
2041       if (mem_plane == 1 && isl_drm_modifier_has_aux(image->vk.drm_format_mod)) {
2042          assert(image->n_planes == 1);
2043          /* If the memory binding differs between primary and aux, then the
2044           * returned offset will be incorrect.
2045           */
2046          assert(image->planes[0].aux_surface.memory_range.binding ==
2047                 image->planes[0].primary_surface.memory_range.binding);
2048          surface = &image->planes[0].aux_surface;
2049       } else {
2050          assert(mem_plane < image->n_planes);
2051          surface = &image->planes[mem_plane].primary_surface;
2052       }
2053    } else {
2054       const uint32_t plane =
2055          anv_image_aspect_to_plane(image, subresource->aspectMask);
2056       surface = &image->planes[plane].primary_surface;
2057    }
2058 
2059    layout->offset = surface->memory_range.offset;
2060    layout->rowPitch = surface->isl.row_pitch_B;
2061    layout->depthPitch = isl_surf_get_array_pitch(&surface->isl);
2062    layout->arrayPitch = isl_surf_get_array_pitch(&surface->isl);
2063 
2064    if (subresource->mipLevel > 0 || subresource->arrayLayer > 0) {
2065       assert(surface->isl.tiling == ISL_TILING_LINEAR);
2066 
2067       uint64_t offset_B;
2068       isl_surf_get_image_offset_B_tile_sa(&surface->isl,
2069                                           subresource->mipLevel,
2070                                           subresource->arrayLayer,
2071                                           0 /* logical_z_offset_px */,
2072                                           &offset_B, NULL, NULL);
2073       layout->offset += offset_B;
2074       layout->size = layout->rowPitch * anv_minify(image->vk.extent.height,
2075                                                    subresource->mipLevel) *
2076                      image->vk.extent.depth;
2077    } else {
2078       layout->size = surface->memory_range.size;
2079    }
2080 }
2081 
2082 /**
2083  * This function returns the assumed isl_aux_state for a given VkImageLayout.
2084  * Because Vulkan image layouts don't map directly to isl_aux_state enums, the
2085  * returned enum is the assumed worst case.
2086  *
2087  * @param devinfo The device information of the Intel GPU.
2088  * @param image The image that may contain a collection of buffers.
2089  * @param aspect The aspect of the image to be accessed.
2090  * @param layout The current layout of the image aspect(s).
2091  *
2092  * @return The primary buffer that should be used for the given layout.
2093  */
2094 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)2095 anv_layout_to_aux_state(const struct intel_device_info * const devinfo,
2096                         const struct anv_image * const image,
2097                         const VkImageAspectFlagBits aspect,
2098                         const VkImageLayout layout)
2099 {
2100    /* Validate the inputs. */
2101 
2102    /* The devinfo is needed as the optimal buffer varies across generations. */
2103    assert(devinfo != NULL);
2104 
2105    /* The layout of a NULL image is not properly defined. */
2106    assert(image != NULL);
2107 
2108    /* The aspect must be exactly one of the image aspects. */
2109    assert(util_bitcount(aspect) == 1 && (aspect & image->vk.aspects));
2110 
2111    /* Determine the optimal buffer. */
2112 
2113    const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2114 
2115    /* If we don't have an aux buffer then aux state makes no sense */
2116    const enum isl_aux_usage aux_usage = image->planes[plane].aux_usage;
2117    assert(aux_usage != ISL_AUX_USAGE_NONE);
2118 
2119    /* All images that use an auxiliary surface are required to be tiled. */
2120    assert(image->planes[plane].primary_surface.isl.tiling != ISL_TILING_LINEAR);
2121 
2122    /* Handle a few special cases */
2123    switch (layout) {
2124    /* Invalid layouts */
2125    case VK_IMAGE_LAYOUT_MAX_ENUM:
2126       unreachable("Invalid image layout.");
2127 
2128    /* Undefined layouts
2129     *
2130     * The pre-initialized layout is equivalent to the undefined layout for
2131     * optimally-tiled images.  We can only do color compression (CCS or HiZ)
2132     * on tiled images.
2133     */
2134    case VK_IMAGE_LAYOUT_UNDEFINED:
2135    case VK_IMAGE_LAYOUT_PREINITIALIZED:
2136       return ISL_AUX_STATE_AUX_INVALID;
2137 
2138    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
2139       assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT);
2140 
2141       enum isl_aux_state aux_state =
2142          isl_drm_modifier_get_default_aux_state(image->vk.drm_format_mod);
2143 
2144       switch (aux_state) {
2145       case ISL_AUX_STATE_AUX_INVALID:
2146          /* The modifier does not support compression. But, if we arrived
2147           * here, then we have enabled compression on it anyway, in which case
2148           * we must resolve the aux surface before we release ownership to the
2149           * presentation engine (because, having no modifier, the presentation
2150           * engine will not be aware of the aux surface). The presentation
2151           * engine will not access the aux surface (because it is unware of
2152           * it), and so the aux surface will still be resolved when we
2153           * re-acquire ownership.
2154           *
2155           * Therefore, at ownership transfers in either direction, there does
2156           * exist an aux surface despite the lack of modifier and its state is
2157           * pass-through.
2158           */
2159          return ISL_AUX_STATE_PASS_THROUGH;
2160       case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2161          return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
2162       default:
2163          unreachable("unexpected isl_aux_state");
2164       }
2165    }
2166 
2167    default:
2168       break;
2169    }
2170 
2171    const bool read_only = vk_image_layout_is_read_only(layout, aspect);
2172 
2173    const VkImageUsageFlags image_aspect_usage =
2174       vk_image_usage(&image->vk, aspect);
2175    const VkImageUsageFlags usage =
2176       vk_image_layout_to_usage_flags(layout, aspect) & image_aspect_usage;
2177 
2178    bool aux_supported = true;
2179    bool clear_supported = isl_aux_usage_has_fast_clears(aux_usage);
2180 
2181    if ((usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) && !read_only) {
2182       /* This image could be used as both an input attachment and a render
2183        * target (depth, stencil, or color) at the same time and this can cause
2184        * corruption.
2185        *
2186        * We currently only disable aux in this way for depth even though we
2187        * disable it for color in GL.
2188        *
2189        * TODO: Should we be disabling this in more cases?
2190        */
2191       if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT && devinfo->ver <= 9) {
2192          aux_supported = false;
2193          clear_supported = false;
2194       }
2195    }
2196 
2197    if (usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2198                 VK_IMAGE_USAGE_SAMPLED_BIT |
2199                 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
2200       switch (aux_usage) {
2201       case ISL_AUX_USAGE_HIZ:
2202          if (!anv_can_sample_with_hiz(devinfo, image)) {
2203             aux_supported = false;
2204             clear_supported = false;
2205          }
2206          break;
2207 
2208       case ISL_AUX_USAGE_HIZ_CCS:
2209          aux_supported = false;
2210          clear_supported = false;
2211          break;
2212 
2213       case ISL_AUX_USAGE_HIZ_CCS_WT:
2214          break;
2215 
2216       case ISL_AUX_USAGE_CCS_D:
2217          aux_supported = false;
2218          clear_supported = false;
2219          break;
2220 
2221       case ISL_AUX_USAGE_MCS:
2222          if (!anv_can_sample_mcs_with_clear(devinfo, image))
2223             clear_supported = false;
2224          break;
2225 
2226       case ISL_AUX_USAGE_CCS_E:
2227       case ISL_AUX_USAGE_STC_CCS:
2228          break;
2229 
2230       default:
2231          unreachable("Unsupported aux usage");
2232       }
2233    }
2234 
2235    switch (aux_usage) {
2236    case ISL_AUX_USAGE_HIZ:
2237    case ISL_AUX_USAGE_HIZ_CCS:
2238    case ISL_AUX_USAGE_HIZ_CCS_WT:
2239       if (aux_supported) {
2240          assert(clear_supported);
2241          return ISL_AUX_STATE_COMPRESSED_CLEAR;
2242       } else if (read_only) {
2243          return ISL_AUX_STATE_RESOLVED;
2244       } else {
2245          return ISL_AUX_STATE_AUX_INVALID;
2246       }
2247 
2248    case ISL_AUX_USAGE_CCS_D:
2249       /* We only support clear in exactly one state */
2250       if (layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
2251          assert(aux_supported);
2252          assert(clear_supported);
2253          return ISL_AUX_STATE_PARTIAL_CLEAR;
2254       } else {
2255          return ISL_AUX_STATE_PASS_THROUGH;
2256       }
2257 
2258    case ISL_AUX_USAGE_CCS_E:
2259       if (aux_supported) {
2260          assert(clear_supported);
2261          return ISL_AUX_STATE_COMPRESSED_CLEAR;
2262       } else {
2263          return ISL_AUX_STATE_PASS_THROUGH;
2264       }
2265 
2266    case ISL_AUX_USAGE_MCS:
2267       assert(aux_supported);
2268       if (clear_supported) {
2269          return ISL_AUX_STATE_COMPRESSED_CLEAR;
2270       } else {
2271          return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
2272       }
2273 
2274    case ISL_AUX_USAGE_STC_CCS:
2275       assert(aux_supported);
2276       assert(!clear_supported);
2277       return ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
2278 
2279    default:
2280       unreachable("Unsupported aux usage");
2281    }
2282 }
2283 
2284 /**
2285  * This function determines the optimal buffer to use for a given
2286  * VkImageLayout and other pieces of information needed to make that
2287  * determination. This does not determine the optimal buffer to use
2288  * during a resolve operation.
2289  *
2290  * @param devinfo The device information of the Intel GPU.
2291  * @param image The image that may contain a collection of buffers.
2292  * @param aspect The aspect of the image to be accessed.
2293  * @param usage The usage which describes how the image will be accessed.
2294  * @param layout The current layout of the image aspect(s).
2295  *
2296  * @return The primary buffer that should be used for the given layout.
2297  */
2298 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)2299 anv_layout_to_aux_usage(const struct intel_device_info * const devinfo,
2300                         const struct anv_image * const image,
2301                         const VkImageAspectFlagBits aspect,
2302                         const VkImageUsageFlagBits usage,
2303                         const VkImageLayout layout)
2304 {
2305    const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2306 
2307    /* If there is no auxiliary surface allocated, we must use the one and only
2308     * main buffer.
2309     */
2310    if (image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE)
2311       return ISL_AUX_USAGE_NONE;
2312 
2313    enum isl_aux_state aux_state =
2314       anv_layout_to_aux_state(devinfo, image, aspect, layout);
2315 
2316    switch (aux_state) {
2317    case ISL_AUX_STATE_CLEAR:
2318       unreachable("We never use this state");
2319 
2320    case ISL_AUX_STATE_PARTIAL_CLEAR:
2321       assert(image->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
2322       assert(image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_D);
2323       assert(image->vk.samples == 1);
2324       return ISL_AUX_USAGE_CCS_D;
2325 
2326    case ISL_AUX_STATE_COMPRESSED_CLEAR:
2327    case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2328       return image->planes[plane].aux_usage;
2329 
2330    case ISL_AUX_STATE_RESOLVED:
2331       /* We can only use RESOLVED in read-only layouts because any write will
2332        * either land us in AUX_INVALID or COMPRESSED_NO_CLEAR.  We can do
2333        * writes in PASS_THROUGH without destroying it so that is allowed.
2334        */
2335       assert(vk_image_layout_is_read_only(layout, aspect));
2336       assert(util_is_power_of_two_or_zero(usage));
2337       if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
2338          /* If we have valid HiZ data and are using the image as a read-only
2339           * depth/stencil attachment, we should enable HiZ so that we can get
2340           * faster depth testing.
2341           */
2342          return image->planes[plane].aux_usage;
2343       } else {
2344          return ISL_AUX_USAGE_NONE;
2345       }
2346 
2347    case ISL_AUX_STATE_PASS_THROUGH:
2348    case ISL_AUX_STATE_AUX_INVALID:
2349       return ISL_AUX_USAGE_NONE;
2350    }
2351 
2352    unreachable("Invalid isl_aux_state");
2353 }
2354 
2355 /**
2356  * This function returns the level of unresolved fast-clear support of the
2357  * given image in the given VkImageLayout.
2358  *
2359  * @param devinfo The device information of the Intel GPU.
2360  * @param image The image that may contain a collection of buffers.
2361  * @param aspect The aspect of the image to be accessed.
2362  * @param usage The usage which describes how the image will be accessed.
2363  * @param layout The current layout of the image aspect(s).
2364  */
2365 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)2366 anv_layout_to_fast_clear_type(const struct intel_device_info * const devinfo,
2367                               const struct anv_image * const image,
2368                               const VkImageAspectFlagBits aspect,
2369                               const VkImageLayout layout)
2370 {
2371    if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
2372       return ANV_FAST_CLEAR_NONE;
2373 
2374    const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2375 
2376    /* If there is no auxiliary surface allocated, there are no fast-clears */
2377    if (image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE)
2378       return ANV_FAST_CLEAR_NONE;
2379 
2380    /* We don't support MSAA fast-clears on Ivybridge or Bay Trail because they
2381     * lack the MI ALU which we need to determine the predicates.
2382     */
2383    if (devinfo->verx10 == 70 && image->vk.samples > 1)
2384       return ANV_FAST_CLEAR_NONE;
2385 
2386    enum isl_aux_state aux_state =
2387       anv_layout_to_aux_state(devinfo, image, aspect, layout);
2388 
2389    switch (aux_state) {
2390    case ISL_AUX_STATE_CLEAR:
2391       unreachable("We never use this state");
2392 
2393    case ISL_AUX_STATE_PARTIAL_CLEAR:
2394    case ISL_AUX_STATE_COMPRESSED_CLEAR:
2395       if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
2396          return ANV_FAST_CLEAR_DEFAULT_VALUE;
2397       } else if (layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
2398          /* The image might not support non zero fast clears when mutable. */
2399          if (!image->planes[plane].can_non_zero_fast_clear)
2400             return ANV_FAST_CLEAR_DEFAULT_VALUE;
2401 
2402          /* When we're in a render pass we have the clear color data from the
2403           * VkRenderPassBeginInfo and we can use arbitrary clear colors.  They
2404           * must get partially resolved before we leave the render pass.
2405           */
2406          return ANV_FAST_CLEAR_ANY;
2407       } else if (image->planes[plane].aux_usage == ISL_AUX_USAGE_MCS ||
2408                  image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E) {
2409          if (devinfo->ver >= 11) {
2410             /* The image might not support non zero fast clears when mutable. */
2411             if (!image->planes[plane].can_non_zero_fast_clear)
2412                return ANV_FAST_CLEAR_DEFAULT_VALUE;
2413 
2414             /* On ICL and later, the sampler hardware uses a copy of the clear
2415              * value that is encoded as a pixel value.  Therefore, we can use
2416              * any clear color we like for sampling.
2417              */
2418             return ANV_FAST_CLEAR_ANY;
2419          } else {
2420             /* If the image has MCS or CCS_E enabled all the time then we can
2421              * use fast-clear as long as the clear color is the default value
2422              * of zero since this is the default value we program into every
2423              * surface state used for texturing.
2424              */
2425             return ANV_FAST_CLEAR_DEFAULT_VALUE;
2426          }
2427       } else {
2428          return ANV_FAST_CLEAR_NONE;
2429       }
2430 
2431    case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
2432    case ISL_AUX_STATE_RESOLVED:
2433    case ISL_AUX_STATE_PASS_THROUGH:
2434    case ISL_AUX_STATE_AUX_INVALID:
2435       return ANV_FAST_CLEAR_NONE;
2436    }
2437 
2438    unreachable("Invalid isl_aux_state");
2439 }
2440 
2441 
2442 static struct anv_state
alloc_surface_state(struct anv_device * device)2443 alloc_surface_state(struct anv_device *device)
2444 {
2445    return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
2446 }
2447 
2448 static enum isl_channel_select
remap_swizzle(VkComponentSwizzle swizzle,struct isl_swizzle format_swizzle)2449 remap_swizzle(VkComponentSwizzle swizzle,
2450               struct isl_swizzle format_swizzle)
2451 {
2452    switch (swizzle) {
2453    case VK_COMPONENT_SWIZZLE_ZERO:  return ISL_CHANNEL_SELECT_ZERO;
2454    case VK_COMPONENT_SWIZZLE_ONE:   return ISL_CHANNEL_SELECT_ONE;
2455    case VK_COMPONENT_SWIZZLE_R:     return format_swizzle.r;
2456    case VK_COMPONENT_SWIZZLE_G:     return format_swizzle.g;
2457    case VK_COMPONENT_SWIZZLE_B:     return format_swizzle.b;
2458    case VK_COMPONENT_SWIZZLE_A:     return format_swizzle.a;
2459    default:
2460       unreachable("Invalid swizzle");
2461    }
2462 }
2463 
2464 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,struct brw_image_param * image_param_out)2465 anv_image_fill_surface_state(struct anv_device *device,
2466                              const struct anv_image *image,
2467                              VkImageAspectFlagBits aspect,
2468                              const struct isl_view *view_in,
2469                              isl_surf_usage_flags_t view_usage,
2470                              enum isl_aux_usage aux_usage,
2471                              const union isl_color_value *clear_color,
2472                              enum anv_image_view_state_flags flags,
2473                              struct anv_surface_state *state_inout,
2474                              struct brw_image_param *image_param_out)
2475 {
2476    const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
2477 
2478    const struct anv_surface *surface = &image->planes[plane].primary_surface,
2479       *aux_surface = &image->planes[plane].aux_surface;
2480 
2481    struct isl_view view = *view_in;
2482    view.usage |= view_usage;
2483 
2484    /* For texturing with VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL from a
2485     * compressed surface with a shadow surface, we use the shadow instead of
2486     * the primary surface.  The shadow surface will be tiled, unlike the main
2487     * surface, so it should get significantly better performance.
2488     */
2489    if (anv_surface_is_valid(&image->planes[plane].shadow_surface) &&
2490        isl_format_is_compressed(view.format) &&
2491        (flags & ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL)) {
2492       assert(isl_format_is_compressed(surface->isl.format));
2493       assert(surface->isl.tiling == ISL_TILING_LINEAR);
2494       assert(image->planes[plane].shadow_surface.isl.tiling != ISL_TILING_LINEAR);
2495       surface = &image->planes[plane].shadow_surface;
2496    }
2497 
2498    /* For texturing from stencil on gfx7, we have to sample from a shadow
2499     * surface because we don't support W-tiling in the sampler.
2500     */
2501    if (anv_surface_is_valid(&image->planes[plane].shadow_surface) &&
2502        aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
2503       assert(device->info.ver == 7);
2504       assert(view_usage & ISL_SURF_USAGE_TEXTURE_BIT);
2505       surface = &image->planes[plane].shadow_surface;
2506    }
2507 
2508    if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
2509       view.swizzle = anv_swizzle_for_render(view.swizzle);
2510 
2511    /* On Ivy Bridge and Bay Trail we do the swizzle in the shader */
2512    if (device->info.verx10 == 70)
2513       view.swizzle = ISL_SWIZZLE_IDENTITY;
2514 
2515    /* If this is a HiZ buffer we can sample from with a programmable clear
2516     * value (SKL+), define the clear value to the optimal constant.
2517     */
2518    union isl_color_value default_clear_color = { .u32 = { 0, } };
2519    if (device->info.ver >= 9 && aspect == VK_IMAGE_ASPECT_DEPTH_BIT)
2520       default_clear_color.f32[0] = ANV_HZ_FC_VAL;
2521    if (!clear_color)
2522       clear_color = &default_clear_color;
2523 
2524    const struct anv_address address =
2525       anv_image_address(image, &surface->memory_range);
2526 
2527    if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
2528        (flags & ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED) &&
2529        !isl_has_matching_typed_storage_image_format(&device->info,
2530                                                     view.format)) {
2531       /* In this case, we are a writeable storage buffer which needs to be
2532        * lowered to linear. All tiling and offset calculations will be done in
2533        * the shader.
2534        */
2535       assert(aux_usage == ISL_AUX_USAGE_NONE);
2536       isl_buffer_fill_state(&device->isl_dev, state_inout->state.map,
2537                             .address = anv_address_physical(address),
2538                             .size_B = surface->isl.size_B,
2539                             .format = ISL_FORMAT_RAW,
2540                             .swizzle = ISL_SWIZZLE_IDENTITY,
2541                             .stride_B = 1,
2542                             .mocs = anv_mocs(device, address.bo, view_usage));
2543       state_inout->address = address,
2544       state_inout->aux_address = ANV_NULL_ADDRESS;
2545       state_inout->clear_address = ANV_NULL_ADDRESS;
2546    } else {
2547       if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
2548           (flags & ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED)) {
2549          /* Typed surface reads support a very limited subset of the shader
2550           * image formats.  Translate it into the closest format the hardware
2551           * supports.
2552           */
2553          enum isl_format lower_format =
2554             isl_lower_storage_image_format(&device->info, view.format);
2555          if (aux_usage != ISL_AUX_USAGE_NONE) {
2556             assert(device->info.verx10 >= 125);
2557             assert(aux_usage == ISL_AUX_USAGE_CCS_E);
2558             assert(isl_formats_are_ccs_e_compatible(&device->info,
2559                                                     view.format,
2560                                                     lower_format));
2561          }
2562 
2563          /* If we lower the format, we should ensure either they both match in
2564           * bits per channel or that there is no swizzle, because we can't use
2565           * the swizzle for a different bit pattern.
2566           */
2567          assert(isl_formats_have_same_bits_per_channel(lower_format,
2568                                                        view.format) ||
2569                 isl_swizzle_is_identity_for_format(view.format, view.swizzle));
2570 
2571          view.format = lower_format;
2572       }
2573 
2574       const struct isl_surf *isl_surf = &surface->isl;
2575 
2576       struct isl_surf tmp_surf;
2577       uint64_t offset_B = 0;
2578       uint32_t tile_x_sa = 0, tile_y_sa = 0;
2579       if (isl_format_is_compressed(surface->isl.format) &&
2580           !isl_format_is_compressed(view.format)) {
2581          /* We're creating an uncompressed view of a compressed surface.  This
2582           * is allowed but only for a single level/layer.
2583           */
2584          assert(surface->isl.samples == 1);
2585          assert(view.levels == 1);
2586          assert(view.array_len == 1);
2587 
2588          ASSERTED bool ok =
2589             isl_surf_get_uncompressed_surf(&device->isl_dev, isl_surf, &view,
2590                                            &tmp_surf, &view,
2591                                            &offset_B, &tile_x_sa, &tile_y_sa);
2592          assert(ok);
2593          isl_surf = &tmp_surf;
2594 
2595          if (device->info.ver <= 8) {
2596             assert(surface->isl.tiling == ISL_TILING_LINEAR);
2597             assert(tile_x_sa == 0);
2598             assert(tile_y_sa == 0);
2599          }
2600       }
2601 
2602       state_inout->address = anv_address_add(address, offset_B);
2603 
2604       struct anv_address aux_address = ANV_NULL_ADDRESS;
2605       if (aux_usage != ISL_AUX_USAGE_NONE)
2606          aux_address = anv_image_address(image, &aux_surface->memory_range);
2607       state_inout->aux_address = aux_address;
2608 
2609       struct anv_address clear_address = ANV_NULL_ADDRESS;
2610       if (device->info.ver >= 10 && isl_aux_usage_has_fast_clears(aux_usage)) {
2611          clear_address = anv_image_get_clear_color_addr(device, image, aspect);
2612       }
2613       state_inout->clear_address = clear_address;
2614 
2615       isl_surf_fill_state(&device->isl_dev, state_inout->state.map,
2616                           .surf = isl_surf,
2617                           .view = &view,
2618                           .address = anv_address_physical(state_inout->address),
2619                           .clear_color = *clear_color,
2620                           .aux_surf = &aux_surface->isl,
2621                           .aux_usage = aux_usage,
2622                           .aux_address = anv_address_physical(aux_address),
2623                           .clear_address = anv_address_physical(clear_address),
2624                           .use_clear_address = !anv_address_is_null(clear_address),
2625                           .mocs = anv_mocs(device, state_inout->address.bo,
2626                                            view_usage),
2627                           .x_offset_sa = tile_x_sa,
2628                           .y_offset_sa = tile_y_sa);
2629 
2630       /* With the exception of gfx8, the bottom 12 bits of the MCS base address
2631        * are used to store other information.  This should be ok, however,
2632        * because the surface buffer addresses are always 4K page aligned.
2633        */
2634       if (!anv_address_is_null(aux_address)) {
2635          uint32_t *aux_addr_dw = state_inout->state.map +
2636             device->isl_dev.ss.aux_addr_offset;
2637          assert((aux_address.offset & 0xfff) == 0);
2638          state_inout->aux_address.offset |= *aux_addr_dw & 0xfff;
2639       }
2640 
2641       if (device->info.ver >= 10 && clear_address.bo) {
2642          uint32_t *clear_addr_dw = state_inout->state.map +
2643                                    device->isl_dev.ss.clear_color_state_offset;
2644          assert((clear_address.offset & 0x3f) == 0);
2645          state_inout->clear_address.offset |= *clear_addr_dw & 0x3f;
2646       }
2647    }
2648 
2649    if (image_param_out) {
2650       assert(view_usage == ISL_SURF_USAGE_STORAGE_BIT);
2651       isl_surf_fill_image_param(&device->isl_dev, image_param_out,
2652                                 &surface->isl, &view);
2653    }
2654 }
2655 
2656 static uint32_t
anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)2657 anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)
2658 {
2659    anv_assert_valid_aspect_set(aspect_mask);
2660    return util_bitcount(aspect_mask);
2661 }
2662 
2663 VkResult
anv_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)2664 anv_CreateImageView(VkDevice _device,
2665                     const VkImageViewCreateInfo *pCreateInfo,
2666                     const VkAllocationCallbacks *pAllocator,
2667                     VkImageView *pView)
2668 {
2669    ANV_FROM_HANDLE(anv_device, device, _device);
2670    ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
2671    struct anv_image_view *iview;
2672 
2673    iview = vk_image_view_create(&device->vk, false, pCreateInfo,
2674                                 pAllocator, sizeof(*iview));
2675    if (iview == NULL)
2676       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2677 
2678    iview->image = image;
2679    iview->n_planes = anv_image_aspect_get_planes(iview->vk.aspects);
2680 
2681    /* Check if a conversion info was passed. */
2682    const struct anv_format *conv_format = NULL;
2683    const VkSamplerYcbcrConversionInfo *conv_info =
2684       vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
2685 
2686 #ifdef ANDROID
2687    /* If image has an external format, the pNext chain must contain an
2688     * instance of VKSamplerYcbcrConversionInfo with a conversion object
2689     * created with the same external format as image."
2690     */
2691    assert(!image->vk.android_external_format || conv_info);
2692 #endif
2693 
2694    if (conv_info) {
2695       ANV_FROM_HANDLE(anv_ycbcr_conversion, conversion, conv_info->conversion);
2696       conv_format = conversion->format;
2697    }
2698 
2699 #ifdef ANDROID
2700    /* "If image has an external format, format must be VK_FORMAT_UNDEFINED." */
2701    assert(!image->vk.android_external_format ||
2702           pCreateInfo->format == VK_FORMAT_UNDEFINED);
2703 #endif
2704 
2705    /* Format is undefined, this can happen when using external formats. Set
2706     * view format from the passed conversion info.
2707     */
2708    if (iview->vk.view_format == VK_FORMAT_UNDEFINED && conv_format)
2709       iview->vk.view_format = conv_format->vk_format;
2710 
2711    /* Now go through the underlying image selected planes and map them to
2712     * planes in the image view.
2713     */
2714    anv_foreach_image_aspect_bit(iaspect_bit, image, iview->vk.aspects) {
2715       const uint32_t iplane =
2716          anv_aspect_to_plane(image->vk.aspects, 1UL << iaspect_bit);
2717       const uint32_t vplane =
2718          anv_aspect_to_plane(iview->vk.aspects, 1UL << iaspect_bit);
2719       struct anv_format_plane format;
2720       format = anv_get_format_plane(&device->info, iview->vk.view_format,
2721                                     vplane, image->vk.tiling);
2722 
2723       iview->planes[vplane].image_plane = iplane;
2724 
2725       iview->planes[vplane].isl = (struct isl_view) {
2726          .format = format.isl_format,
2727          .base_level = iview->vk.base_mip_level,
2728          .levels = iview->vk.level_count,
2729          .base_array_layer = iview->vk.base_array_layer,
2730          .array_len = iview->vk.layer_count,
2731          .min_lod_clamp = iview->vk.min_lod,
2732          .swizzle = {
2733             .r = remap_swizzle(iview->vk.swizzle.r, format.swizzle),
2734             .g = remap_swizzle(iview->vk.swizzle.g, format.swizzle),
2735             .b = remap_swizzle(iview->vk.swizzle.b, format.swizzle),
2736             .a = remap_swizzle(iview->vk.swizzle.a, format.swizzle),
2737          },
2738       };
2739 
2740       if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
2741          iview->planes[vplane].isl.base_array_layer = 0;
2742          iview->planes[vplane].isl.array_len = iview->vk.extent.depth;
2743       }
2744 
2745       if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
2746           pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
2747          iview->planes[vplane].isl.usage = ISL_SURF_USAGE_CUBE_BIT;
2748       } else {
2749          iview->planes[vplane].isl.usage = 0;
2750       }
2751 
2752       if (iview->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
2753                              VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
2754          iview->planes[vplane].optimal_sampler_surface_state.state = alloc_surface_state(device);
2755          iview->planes[vplane].general_sampler_surface_state.state = alloc_surface_state(device);
2756 
2757          enum isl_aux_usage general_aux_usage =
2758             anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
2759                                     VK_IMAGE_USAGE_SAMPLED_BIT,
2760                                     VK_IMAGE_LAYOUT_GENERAL);
2761          enum isl_aux_usage optimal_aux_usage =
2762             anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
2763                                     VK_IMAGE_USAGE_SAMPLED_BIT,
2764                                     VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2765 
2766          anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2767                                       &iview->planes[vplane].isl,
2768                                       ISL_SURF_USAGE_TEXTURE_BIT,
2769                                       optimal_aux_usage, NULL,
2770                                       ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL,
2771                                       &iview->planes[vplane].optimal_sampler_surface_state,
2772                                       NULL);
2773 
2774          anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2775                                       &iview->planes[vplane].isl,
2776                                       ISL_SURF_USAGE_TEXTURE_BIT,
2777                                       general_aux_usage, NULL,
2778                                       0,
2779                                       &iview->planes[vplane].general_sampler_surface_state,
2780                                       NULL);
2781       }
2782 
2783       /* NOTE: This one needs to go last since it may stomp isl_view.format */
2784       if (iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
2785          enum isl_aux_usage general_aux_usage =
2786             anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
2787                                     VK_IMAGE_USAGE_STORAGE_BIT,
2788                                     VK_IMAGE_LAYOUT_GENERAL);
2789          iview->planes[vplane].storage_surface_state.state = alloc_surface_state(device);
2790          anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2791                                       &iview->planes[vplane].isl,
2792                                       ISL_SURF_USAGE_STORAGE_BIT,
2793                                       general_aux_usage, NULL,
2794                                       0,
2795                                       &iview->planes[vplane].storage_surface_state,
2796                                       NULL);
2797 
2798          if (isl_is_storage_image_format(format.isl_format)) {
2799             iview->planes[vplane].lowered_storage_surface_state.state =
2800                alloc_surface_state(device);
2801 
2802             anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
2803                                          &iview->planes[vplane].isl,
2804                                          ISL_SURF_USAGE_STORAGE_BIT,
2805                                          general_aux_usage, NULL,
2806                                          ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED,
2807                                          &iview->planes[vplane].lowered_storage_surface_state,
2808                                          device->info.ver >= 9 ? NULL :
2809                                          &iview->planes[vplane].lowered_storage_image_param);
2810          } else {
2811             /* In this case, we support the format but, because there's no
2812              * SPIR-V format specifier corresponding to it, we only support it
2813              * if the hardware can do it natively.  This is possible for some
2814              * reads but for most writes.  Instead of hanging if someone gets
2815              * it wrong, we give them a NULL descriptor.
2816              */
2817             assert(isl_format_supports_typed_writes(&device->info,
2818                                                     format.isl_format));
2819             iview->planes[vplane].lowered_storage_surface_state.state =
2820                device->null_surface_state;
2821          }
2822       }
2823    }
2824 
2825    *pView = anv_image_view_to_handle(iview);
2826 
2827    return VK_SUCCESS;
2828 }
2829 
2830 void
anv_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)2831 anv_DestroyImageView(VkDevice _device, VkImageView _iview,
2832                      const VkAllocationCallbacks *pAllocator)
2833 {
2834    ANV_FROM_HANDLE(anv_device, device, _device);
2835    ANV_FROM_HANDLE(anv_image_view, iview, _iview);
2836 
2837    if (!iview)
2838       return;
2839 
2840    for (uint32_t plane = 0; plane < iview->n_planes; plane++) {
2841       /* Check offset instead of alloc_size because this they might be
2842        * device->null_surface_state which always has offset == 0.  We don't
2843        * own that one so we don't want to accidentally free it.
2844        */
2845       if (iview->planes[plane].optimal_sampler_surface_state.state.offset) {
2846          anv_state_pool_free(&device->surface_state_pool,
2847                              iview->planes[plane].optimal_sampler_surface_state.state);
2848       }
2849 
2850       if (iview->planes[plane].general_sampler_surface_state.state.offset) {
2851          anv_state_pool_free(&device->surface_state_pool,
2852                              iview->planes[plane].general_sampler_surface_state.state);
2853       }
2854 
2855       if (iview->planes[plane].storage_surface_state.state.offset) {
2856          anv_state_pool_free(&device->surface_state_pool,
2857                              iview->planes[plane].storage_surface_state.state);
2858       }
2859 
2860       if (iview->planes[plane].lowered_storage_surface_state.state.offset) {
2861          anv_state_pool_free(&device->surface_state_pool,
2862                              iview->planes[plane].lowered_storage_surface_state.state);
2863       }
2864    }
2865 
2866    vk_image_view_destroy(&device->vk, pAllocator, &iview->vk);
2867 }
2868 
2869 
2870 VkResult
anv_CreateBufferView(VkDevice _device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)2871 anv_CreateBufferView(VkDevice _device,
2872                      const VkBufferViewCreateInfo *pCreateInfo,
2873                      const VkAllocationCallbacks *pAllocator,
2874                      VkBufferView *pView)
2875 {
2876    ANV_FROM_HANDLE(anv_device, device, _device);
2877    ANV_FROM_HANDLE(anv_buffer, buffer, pCreateInfo->buffer);
2878    struct anv_buffer_view *view;
2879 
2880    view = vk_object_alloc(&device->vk, pAllocator, sizeof(*view),
2881                           VK_OBJECT_TYPE_BUFFER_VIEW);
2882    if (!view)
2883       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2884 
2885    struct anv_format_plane format;
2886    format = anv_get_format_plane(&device->info, pCreateInfo->format,
2887                                  0, VK_IMAGE_TILING_LINEAR);
2888 
2889    const uint32_t format_bs = isl_format_get_layout(format.isl_format)->bpb / 8;
2890    view->range = vk_buffer_range(&buffer->vk, pCreateInfo->offset,
2891                                               pCreateInfo->range);
2892    view->range = align_down_npot_u32(view->range, format_bs);
2893 
2894    view->address = anv_address_add(buffer->address, pCreateInfo->offset);
2895 
2896    if (buffer->vk.usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) {
2897       view->surface_state = alloc_surface_state(device);
2898 
2899       anv_fill_buffer_surface_state(device, view->surface_state,
2900                                     format.isl_format, format.swizzle,
2901                                     ISL_SURF_USAGE_TEXTURE_BIT,
2902                                     view->address, view->range, format_bs);
2903    } else {
2904       view->surface_state = (struct anv_state){ 0 };
2905    }
2906 
2907    if (buffer->vk.usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
2908       view->storage_surface_state = alloc_surface_state(device);
2909       view->lowered_storage_surface_state = alloc_surface_state(device);
2910 
2911       anv_fill_buffer_surface_state(device, view->storage_surface_state,
2912                                     format.isl_format, format.swizzle,
2913                                     ISL_SURF_USAGE_STORAGE_BIT,
2914                                     view->address, view->range, format_bs);
2915 
2916       enum isl_format lowered_format =
2917          isl_has_matching_typed_storage_image_format(&device->info,
2918                                                      format.isl_format) ?
2919          isl_lower_storage_image_format(&device->info, format.isl_format) :
2920          ISL_FORMAT_RAW;
2921 
2922       /* If we lower the format, we should ensure either they both match in
2923        * bits per channel or that there is no swizzle because we can't use
2924        * the swizzle for a different bit pattern.
2925        */
2926       assert(isl_formats_have_same_bits_per_channel(lowered_format,
2927                                                     format.isl_format) ||
2928              isl_swizzle_is_identity(format.swizzle));
2929 
2930       anv_fill_buffer_surface_state(device, view->lowered_storage_surface_state,
2931                                     lowered_format, format.swizzle,
2932                                     ISL_SURF_USAGE_STORAGE_BIT,
2933                                     view->address, view->range,
2934                                     (lowered_format == ISL_FORMAT_RAW ? 1 :
2935                                      isl_format_get_layout(lowered_format)->bpb / 8));
2936 
2937       isl_buffer_fill_image_param(&device->isl_dev,
2938                                   &view->lowered_storage_image_param,
2939                                   format.isl_format, view->range);
2940    } else {
2941       view->storage_surface_state = (struct anv_state){ 0 };
2942       view->lowered_storage_surface_state = (struct anv_state){ 0 };
2943    }
2944 
2945    *pView = anv_buffer_view_to_handle(view);
2946 
2947    return VK_SUCCESS;
2948 }
2949 
2950 void
anv_DestroyBufferView(VkDevice _device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)2951 anv_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
2952                       const VkAllocationCallbacks *pAllocator)
2953 {
2954    ANV_FROM_HANDLE(anv_device, device, _device);
2955    ANV_FROM_HANDLE(anv_buffer_view, view, bufferView);
2956 
2957    if (!view)
2958       return;
2959 
2960    if (view->surface_state.alloc_size > 0)
2961       anv_state_pool_free(&device->surface_state_pool,
2962                           view->surface_state);
2963 
2964    if (view->storage_surface_state.alloc_size > 0)
2965       anv_state_pool_free(&device->surface_state_pool,
2966                           view->storage_surface_state);
2967 
2968    if (view->lowered_storage_surface_state.alloc_size > 0)
2969       anv_state_pool_free(&device->surface_state_pool,
2970                           view->lowered_storage_surface_state);
2971 
2972    vk_object_free(&device->vk, pAllocator, view);
2973 }
2974