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