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