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