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