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