1/* 2 * Copyright © 2016 Red Hat. 3 * Copyright © 2016 Bas Nieuwenhuizen 4 * SPDX-License-Identifier: MIT 5 */ 6 7#include "tu_formats.h" 8 9#include "fdl/fd6_format_table.h" 10 11#include "vk_util.h" 12#include "drm-uapi/drm_fourcc.h" 13 14#include "tu_device.h" 15#include "tu_image.h" 16 17struct tu_native_format 18tu6_format_vtx(VkFormat vk_format) 19{ 20 enum pipe_format format = vk_format_to_pipe_format(vk_format); 21 struct tu_native_format fmt = { 22 .fmt = fd6_vertex_format(format), 23 .swap = fd6_vertex_swap(format), 24 }; 25 assert(fmt.fmt != FMT6_NONE); 26 return fmt; 27} 28 29bool 30tu6_format_vtx_supported(VkFormat vk_format) 31{ 32 enum pipe_format format = vk_format_to_pipe_format(vk_format); 33 return fd6_vertex_format(format) != FMT6_NONE; 34} 35 36/* Map non-colorspace-converted YUV formats to RGB pipe formats where we can, 37 * since our hardware doesn't support colorspace conversion. 38 * 39 * Really, we should probably be returning the RGB formats in 40 * vk_format_to_pipe_format, but we don't have all the equivalent pipe formats 41 * for VK RGB formats yet, and we'd have to switch all consumers of that 42 * function at once. 43 */ 44enum pipe_format 45tu_vk_format_to_pipe_format(VkFormat vk_format) 46{ 47 switch (vk_format) { 48 case VK_FORMAT_G8B8G8R8_422_UNORM: /* YUYV */ 49 return PIPE_FORMAT_R8G8_R8B8_UNORM; 50 case VK_FORMAT_B8G8R8G8_422_UNORM: /* UYVY */ 51 return PIPE_FORMAT_G8R8_B8R8_UNORM; 52 case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: 53 return PIPE_FORMAT_G8_B8R8_420_UNORM; 54 case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: 55 return PIPE_FORMAT_G8_B8_R8_420_UNORM; 56 default: 57 return vk_format_to_pipe_format(vk_format); 58 } 59} 60 61static struct tu_native_format 62tu6_format_color_unchecked(enum pipe_format format, enum a6xx_tile_mode tile_mode) 63{ 64 struct tu_native_format fmt = { 65 .fmt = fd6_color_format(format, tile_mode), 66 .swap = fd6_color_swap(format, tile_mode), 67 }; 68 69 switch (format) { 70 case PIPE_FORMAT_Z24X8_UNORM: 71 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 72 fmt.fmt = FMT6_8_8_8_8_UNORM; 73 break; 74 75 default: 76 break; 77 } 78 79 return fmt; 80} 81 82bool 83tu6_format_color_supported(enum pipe_format format) 84{ 85 return tu6_format_color_unchecked(format, TILE6_LINEAR).fmt != FMT6_NONE; 86} 87 88struct tu_native_format 89tu6_format_color(enum pipe_format format, enum a6xx_tile_mode tile_mode) 90{ 91 struct tu_native_format fmt = tu6_format_color_unchecked(format, tile_mode); 92 assert(fmt.fmt != FMT6_NONE); 93 return fmt; 94} 95 96static struct tu_native_format 97tu6_format_texture_unchecked(enum pipe_format format, enum a6xx_tile_mode tile_mode) 98{ 99 struct tu_native_format fmt = { 100 .fmt = fd6_texture_format(format, tile_mode), 101 .swap = fd6_texture_swap(format, tile_mode), 102 }; 103 104 switch (format) { 105 case PIPE_FORMAT_Z24X8_UNORM: 106 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 107 /* freedreno uses Z24_UNORM_S8_UINT (sampling) or 108 * FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 (blits) for this format, while we use 109 * FMT6_8_8_8_8_UNORM or FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 110 */ 111 fmt.fmt = FMT6_8_8_8_8_UNORM; 112 break; 113 114 default: 115 break; 116 } 117 118 return fmt; 119} 120 121struct tu_native_format 122tu6_format_texture(enum pipe_format format, enum a6xx_tile_mode tile_mode) 123{ 124 struct tu_native_format fmt = tu6_format_texture_unchecked(format, tile_mode); 125 assert(fmt.fmt != FMT6_NONE); 126 return fmt; 127} 128 129bool 130tu6_format_texture_supported(enum pipe_format format) 131{ 132 return tu6_format_texture_unchecked(format, TILE6_LINEAR).fmt != FMT6_NONE; 133} 134 135static void 136tu_physical_device_get_format_properties( 137 struct tu_physical_device *physical_device, 138 VkFormat vk_format, 139 VkFormatProperties3 *out_properties) 140{ 141 VkFormatFeatureFlags2 linear = 0, optimal = 0, buffer = 0; 142 enum pipe_format format = tu_vk_format_to_pipe_format(vk_format); 143 const struct util_format_description *desc = util_format_description(format); 144 145 bool supported_vtx = tu6_format_vtx_supported(vk_format); 146 bool supported_color = tu6_format_color_supported(format); 147 bool supported_tex = tu6_format_texture_supported(format); 148 bool is_npot = !util_is_power_of_two_or_zero(desc->block.bits); 149 150 if (format == PIPE_FORMAT_NONE || 151 !(supported_vtx || supported_color || supported_tex)) { 152 goto end; 153 } 154 155 /* We don't support BufferToImage/ImageToBuffer for npot formats */ 156 if (!is_npot) 157 buffer |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT; 158 159 if (supported_vtx) 160 buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT; 161 162 if (supported_tex) 163 buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT; 164 165 /* Don't support anything but texel buffers for non-power-of-two formats 166 * with 3 components. We'd need several workarounds for copying and 167 * clearing them because they're not renderable. 168 */ 169 if (supported_tex && !is_npot) { 170 optimal |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | 171 VK_FORMAT_FEATURE_TRANSFER_DST_BIT | 172 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | 173 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT | 174 VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT | 175 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT; 176 177 /* no blit src bit for YUYV/NV12/I420 formats */ 178 if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED && 179 desc->layout != UTIL_FORMAT_LAYOUT_PLANAR2 && 180 desc->layout != UTIL_FORMAT_LAYOUT_PLANAR3) 181 optimal |= VK_FORMAT_FEATURE_BLIT_SRC_BIT; 182 183 if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED) 184 optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT; 185 186 if (!vk_format_is_int(vk_format)) { 187 optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; 188 189 if (physical_device->vk.supported_extensions.EXT_filter_cubic) 190 optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT; 191 } 192 } 193 194 if (supported_color) { 195 assert(supported_tex); 196 optimal |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | 197 VK_FORMAT_FEATURE_BLIT_DST_BIT | 198 VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | 199 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT | 200 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT; 201 202 buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | 203 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT | 204 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT; 205 206 /* TODO: The blob also exposes these for R16G16_UINT/R16G16_SINT, but we 207 * don't have any tests for those. 208 */ 209 if (vk_format == VK_FORMAT_R32_UINT || vk_format == VK_FORMAT_R32_SINT) { 210 optimal |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT; 211 buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT; 212 } 213 214 if (!util_format_is_pure_integer(format)) 215 optimal |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; 216 } 217 218 /* For the most part, we can do anything with a linear image that we could 219 * do with a tiled image. However, we can't support sysmem rendering with a 220 * linear depth texture, because we don't know if there's a bit to control 221 * the tiling of the depth buffer in BYPASS mode, and the blob also 222 * disables linear depth rendering, so there's no way to discover it. We 223 * also can't force GMEM mode, because there are other situations where we 224 * have to use sysmem rendering. So follow the blob here, and only enable 225 * DEPTH_STENCIL_ATTACHMENT_BIT for the optimal features. 226 */ 227 linear = optimal; 228 if (tu6_pipe2depth(vk_format) != (enum a6xx_depth_format)~0) 229 optimal |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; 230 231 if (!tiling_possible(vk_format) && 232 /* We don't actually support tiling for this format, but we need to 233 * fake it as it's required by VK_KHR_sampler_ycbcr_conversion. 234 */ 235 vk_format != VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) { 236 optimal = 0; 237 } 238 239 if (vk_format == VK_FORMAT_G8B8G8R8_422_UNORM || 240 vk_format == VK_FORMAT_B8G8R8G8_422_UNORM || 241 vk_format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM || 242 vk_format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) { 243 /* Disable buffer texturing of subsampled (422) and planar YUV textures. 244 * The subsampling requirement comes from "If format is a block-compressed 245 * format, then bufferFeatures must not support any features for the 246 * format" plus the specification of subsampled as 2x1 compressed block 247 * format. I couldn't find the citation for planar, but 1D access of 248 * planar YUV would be really silly. 249 */ 250 buffer = 0; 251 } 252 253 /* We don't support writing into VK__FORMAT_*_PACK16 images/buffers */ 254 if (desc->nr_channels > 2 && desc->block.bits == 16) { 255 buffer &= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT; 256 linear &= ~(VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | 257 VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT); 258 optimal &= ~(VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | 259 VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT); 260 } 261 262 /* All our depth formats support shadow comparisons. */ 263 if (vk_format_has_depth(vk_format) && (optimal & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { 264 optimal |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT; 265 linear |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT; 266 } 267 268 /* From the Vulkan 1.3.205 spec, section 19.3 "43.3. Required Format Support": 269 * 270 * Mandatory format support: depth/stencil with VkImageType 271 * VK_IMAGE_TYPE_2D 272 * [...] 273 * bufferFeatures must not support any features for these formats 274 */ 275 if (vk_format_is_depth_or_stencil(vk_format)) 276 buffer = 0; 277 278 /* D32_SFLOAT_S8_UINT is tiled as two images, so no linear format 279 * blob enables some linear features, but its not useful, so don't bother. 280 */ 281 if (vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT) 282 linear = 0; 283 284end: 285 out_properties->linearTilingFeatures = linear; 286 out_properties->optimalTilingFeatures = optimal; 287 out_properties->bufferFeatures = buffer; 288} 289 290VKAPI_ATTR void VKAPI_CALL 291tu_GetPhysicalDeviceFormatProperties2( 292 VkPhysicalDevice physicalDevice, 293 VkFormat format, 294 VkFormatProperties2 *pFormatProperties) 295{ 296 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice); 297 298 VkFormatProperties3 local_props3; 299 VkFormatProperties3 *props3 = 300 vk_find_struct(pFormatProperties->pNext, FORMAT_PROPERTIES_3); 301 if (!props3) 302 props3 = &local_props3; 303 304 tu_physical_device_get_format_properties( 305 physical_device, format, props3); 306 307 pFormatProperties->formatProperties = (VkFormatProperties) { 308 .linearTilingFeatures = props3->linearTilingFeatures, 309 .optimalTilingFeatures = props3->optimalTilingFeatures, 310 .bufferFeatures = props3->bufferFeatures, 311 }; 312 313 VkDrmFormatModifierPropertiesListEXT *list = 314 vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT); 315 if (list) { 316 VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out, 317 list->pDrmFormatModifierProperties, 318 &list->drmFormatModifierCount); 319 320 if (pFormatProperties->formatProperties.linearTilingFeatures) { 321 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mod_props) { 322 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR; 323 mod_props->drmFormatModifierPlaneCount = tu6_plane_count(format); 324 mod_props->drmFormatModifierTilingFeatures = 325 pFormatProperties->formatProperties.linearTilingFeatures; 326 } 327 } 328 329 /* note: ubwc_possible() argument values to be ignored except for format */ 330 if (pFormatProperties->formatProperties.optimalTilingFeatures && 331 tiling_possible(format) && 332 ubwc_possible(format, VK_IMAGE_TYPE_2D, 0, 0, physical_device->info, VK_SAMPLE_COUNT_1_BIT, false)) { 333 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mod_props) { 334 mod_props->drmFormatModifier = DRM_FORMAT_MOD_QCOM_COMPRESSED; 335 mod_props->drmFormatModifierPlaneCount = tu6_plane_count(format); 336 mod_props->drmFormatModifierTilingFeatures = 337 pFormatProperties->formatProperties.optimalTilingFeatures; 338 } 339 } 340 } 341} 342 343static VkResult 344tu_get_image_format_properties( 345 struct tu_physical_device *physical_device, 346 const VkPhysicalDeviceImageFormatInfo2 *info, 347 VkImageFormatProperties *pImageFormatProperties, 348 VkFormatFeatureFlags *p_feature_flags) 349{ 350 VkFormatProperties3 format_props; 351 VkFormatFeatureFlags format_feature_flags; 352 VkExtent3D maxExtent; 353 uint32_t maxMipLevels; 354 uint32_t maxArraySize; 355 VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT; 356 357 tu_physical_device_get_format_properties(physical_device, info->format, 358 &format_props); 359 360 switch (info->tiling) { 361 case VK_IMAGE_TILING_LINEAR: 362 format_feature_flags = format_props.linearTilingFeatures; 363 break; 364 365 case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: { 366 const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_info = 367 vk_find_struct_const(info->pNext, PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT); 368 369 switch (drm_info->drmFormatModifier) { 370 case DRM_FORMAT_MOD_QCOM_COMPRESSED: 371 /* falling back to linear/non-UBWC isn't possible with explicit modifier */ 372 373 /* formats which don't support tiling */ 374 if (!format_props.optimalTilingFeatures || 375 !tiling_possible(info->format)) 376 return VK_ERROR_FORMAT_NOT_SUPPORTED; 377 378 /* for mutable formats, its very unlikely to be possible to use UBWC */ 379 if (info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) 380 return VK_ERROR_FORMAT_NOT_SUPPORTED; 381 382 383 if (!ubwc_possible(info->format, info->type, info->usage, info->usage, physical_device->info, sampleCounts, false)) 384 return VK_ERROR_FORMAT_NOT_SUPPORTED; 385 386 format_feature_flags = format_props.optimalTilingFeatures; 387 break; 388 case DRM_FORMAT_MOD_LINEAR: 389 format_feature_flags = format_props.linearTilingFeatures; 390 break; 391 default: 392 return VK_ERROR_FORMAT_NOT_SUPPORTED; 393 } 394 } break; 395 case VK_IMAGE_TILING_OPTIMAL: 396 format_feature_flags = format_props.optimalTilingFeatures; 397 break; 398 default: 399 unreachable("bad VkPhysicalDeviceImageFormatInfo2"); 400 } 401 402 if (format_feature_flags == 0) 403 goto unsupported; 404 405 if (info->type != VK_IMAGE_TYPE_2D && 406 vk_format_is_depth_or_stencil(info->format)) 407 goto unsupported; 408 409 switch (info->type) { 410 default: 411 unreachable("bad vkimage type\n"); 412 case VK_IMAGE_TYPE_1D: 413 maxExtent.width = 16384; 414 maxExtent.height = 1; 415 maxExtent.depth = 1; 416 maxMipLevels = 15; /* log2(maxWidth) + 1 */ 417 maxArraySize = 2048; 418 break; 419 case VK_IMAGE_TYPE_2D: 420 maxExtent.width = 16384; 421 maxExtent.height = 16384; 422 maxExtent.depth = 1; 423 maxMipLevels = 15; /* log2(maxWidth) + 1 */ 424 maxArraySize = 2048; 425 break; 426 case VK_IMAGE_TYPE_3D: 427 maxExtent.width = 2048; 428 maxExtent.height = 2048; 429 maxExtent.depth = 2048; 430 maxMipLevels = 12; /* log2(maxWidth) + 1 */ 431 maxArraySize = 1; 432 break; 433 } 434 435 if (info->tiling == VK_IMAGE_TILING_OPTIMAL && 436 info->type == VK_IMAGE_TYPE_2D && 437 (format_feature_flags & 438 (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | 439 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) && 440 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && 441 !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) { 442 sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT; 443 /* note: most operations support 8 samples (GMEM render/resolve do at least) 444 * but some do not (which ones?), just disable 8 samples completely, 445 * (no 8x msaa matches the blob driver behavior) 446 */ 447 } 448 449 /* From the Vulkan 1.3.206 spec: 450 * 451 * "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT specifies that the image can be 452 * created with usage flags that are not supported for the format the image 453 * is created with but are supported for at least one format a VkImageView 454 * created from the image can have." 455 * 456 * This means we should relax checks that only depend on the 457 * format_feature_flags, to allow the user to create images that may be 458 * e.g. reinterpreted as storage when the original format doesn't allow it. 459 * The user will have to check against the format features anyway. 460 * Otherwise we'd unnecessarily disallow it. 461 */ 462 463 VkImageUsageFlags image_usage = info->usage; 464 if (info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) 465 image_usage = 0; 466 467 if (image_usage & VK_IMAGE_USAGE_SAMPLED_BIT) { 468 if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { 469 goto unsupported; 470 } 471 } 472 473 if (image_usage & VK_IMAGE_USAGE_STORAGE_BIT) { 474 if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) { 475 goto unsupported; 476 } 477 } 478 479 if (image_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { 480 if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) { 481 goto unsupported; 482 } 483 } 484 485 if (image_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { 486 if (!(format_feature_flags & 487 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) { 488 goto unsupported; 489 } 490 } 491 492 *pImageFormatProperties = (VkImageFormatProperties) { 493 .maxExtent = maxExtent, 494 .maxMipLevels = maxMipLevels, 495 .maxArrayLayers = maxArraySize, 496 .sampleCounts = sampleCounts, 497 498 /* FINISHME: Accurately calculate 499 * VkImageFormatProperties::maxResourceSize. 500 */ 501 .maxResourceSize = UINT32_MAX, 502 }; 503 504 if (p_feature_flags) 505 *p_feature_flags = format_feature_flags; 506 507 return VK_SUCCESS; 508unsupported: 509 *pImageFormatProperties = (VkImageFormatProperties) { 510 .maxExtent = { 0, 0, 0 }, 511 .maxMipLevels = 0, 512 .maxArrayLayers = 0, 513 .sampleCounts = 0, 514 .maxResourceSize = 0, 515 }; 516 517 return VK_ERROR_FORMAT_NOT_SUPPORTED; 518} 519 520static VkResult 521tu_get_external_image_format_properties( 522 const struct tu_physical_device *physical_device, 523 const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, 524 VkExternalMemoryHandleTypeFlagBits handleType, 525 VkExternalImageFormatProperties *external_properties) 526{ 527 VkExternalMemoryFeatureFlagBits flags = 0; 528 VkExternalMemoryHandleTypeFlags export_flags = 0; 529 VkExternalMemoryHandleTypeFlags compat_flags = 0; 530 531 /* From the Vulkan 1.1.98 spec: 532 * 533 * If handleType is not compatible with the format, type, tiling, 534 * usage, and flags specified in VkPhysicalDeviceImageFormatInfo2, 535 * then vkGetPhysicalDeviceImageFormatProperties2 returns 536 * VK_ERROR_FORMAT_NOT_SUPPORTED. 537 */ 538 539 switch (handleType) { 540 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: 541 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: 542 switch (pImageFormatInfo->type) { 543 case VK_IMAGE_TYPE_2D: 544 flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT | 545 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | 546 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; 547 compat_flags = export_flags = 548 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | 549 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 550 break; 551 default: 552 return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED, 553 "VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)", 554 handleType, pImageFormatInfo->type); 555 } 556 break; 557 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: 558 flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; 559 compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; 560 break; 561 default: 562 return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED, 563 "VkExternalMemoryTypeFlagBits(0x%x) unsupported", 564 handleType); 565 } 566 567 if (external_properties) { 568 external_properties->externalMemoryProperties = 569 (VkExternalMemoryProperties) { 570 .externalMemoryFeatures = flags, 571 .exportFromImportedHandleTypes = export_flags, 572 .compatibleHandleTypes = compat_flags, 573 }; 574 } 575 576 return VK_SUCCESS; 577} 578 579VKAPI_ATTR VkResult VKAPI_CALL 580tu_GetPhysicalDeviceImageFormatProperties2( 581 VkPhysicalDevice physicalDevice, 582 const VkPhysicalDeviceImageFormatInfo2 *base_info, 583 VkImageFormatProperties2 *base_props) 584{ 585 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice); 586 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL; 587 const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL; 588 VkExternalImageFormatProperties *external_props = NULL; 589 VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL; 590 VkFormatFeatureFlags format_feature_flags; 591 VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL; 592 VkResult result; 593 594 result = tu_get_image_format_properties(physical_device, 595 base_info, &base_props->imageFormatProperties, &format_feature_flags); 596 if (result != VK_SUCCESS) 597 return result; 598 599 /* Extract input structs */ 600 vk_foreach_struct_const(s, base_info->pNext) 601 { 602 switch (s->sType) { 603 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: 604 external_info = (const void *) s; 605 break; 606 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT: 607 image_view_info = (const void *) s; 608 break; 609 default: 610 break; 611 } 612 } 613 614 /* Extract output structs */ 615 vk_foreach_struct(s, base_props->pNext) 616 { 617 switch (s->sType) { 618 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: 619 external_props = (void *) s; 620 break; 621 case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT: 622 cubic_props = (void *) s; 623 break; 624 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES: 625 ycbcr_props = (void *) s; 626 break; 627 default: 628 break; 629 } 630 } 631 632 /* From the Vulkan 1.0.42 spec: 633 * 634 * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will 635 * behave as if VkPhysicalDeviceExternalImageFormatInfo was not 636 * present and VkExternalImageFormatProperties will be ignored. 637 */ 638 if (external_info && external_info->handleType != 0) { 639 result = tu_get_external_image_format_properties( 640 physical_device, base_info, external_info->handleType, 641 external_props); 642 if (result != VK_SUCCESS) 643 goto fail; 644 } 645 646 if (cubic_props) { 647 /* note: blob only allows cubic filtering for 2D and 2D array views 648 * its likely we can enable it for 1D and CUBE, needs testing however 649 */ 650 if ((image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D || 651 image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) && 652 (format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) { 653 cubic_props->filterCubic = true; 654 cubic_props->filterCubicMinmax = true; 655 } else { 656 cubic_props->filterCubic = false; 657 cubic_props->filterCubicMinmax = false; 658 } 659 } 660 661 if (ycbcr_props) 662 ycbcr_props->combinedImageSamplerDescriptorCount = 1; 663 664 return VK_SUCCESS; 665 666fail: 667 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) { 668 /* From the Vulkan 1.0.42 spec: 669 * 670 * If the combination of parameters to 671 * vkGetPhysicalDeviceImageFormatProperties2 is not supported by 672 * the implementation for use in vkCreateImage, then all members of 673 * imageFormatProperties will be filled with zero. 674 */ 675 base_props->imageFormatProperties = (VkImageFormatProperties) {}; 676 } 677 678 return result; 679} 680 681VKAPI_ATTR void VKAPI_CALL 682tu_GetPhysicalDeviceSparseImageFormatProperties2( 683 VkPhysicalDevice physicalDevice, 684 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, 685 uint32_t *pPropertyCount, 686 VkSparseImageFormatProperties2 *pProperties) 687{ 688 /* Sparse images are not yet supported. */ 689 *pPropertyCount = 0; 690} 691 692VKAPI_ATTR void VKAPI_CALL 693tu_GetPhysicalDeviceExternalBufferProperties( 694 VkPhysicalDevice physicalDevice, 695 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, 696 VkExternalBufferProperties *pExternalBufferProperties) 697{ 698 VkExternalMemoryFeatureFlagBits flags = 0; 699 VkExternalMemoryHandleTypeFlags export_flags = 0; 700 VkExternalMemoryHandleTypeFlags compat_flags = 0; 701 switch (pExternalBufferInfo->handleType) { 702 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: 703 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: 704 flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | 705 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; 706 compat_flags = export_flags = 707 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | 708 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 709 break; 710 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: 711 flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; 712 compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; 713 break; 714 default: 715 break; 716 } 717 pExternalBufferProperties->externalMemoryProperties = 718 (VkExternalMemoryProperties) { 719 .externalMemoryFeatures = flags, 720 .exportFromImportedHandleTypes = export_flags, 721 .compatibleHandleTypes = compat_flags, 722 }; 723} 724