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