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