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