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
17 struct tu_native_format
tu6_format_vtx(VkFormat vk_format)18 tu6_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
29 bool
tu6_format_vtx_supported(VkFormat vk_format)30 tu6_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 */
44 enum pipe_format
tu_vk_format_to_pipe_format(VkFormat vk_format)45 tu_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
61 static struct tu_native_format
tu6_format_color_unchecked(enum pipe_format format,enum a6xx_tile_mode tile_mode)62 tu6_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
82 bool
tu6_format_color_supported(enum pipe_format format)83 tu6_format_color_supported(enum pipe_format format)
84 {
85 return tu6_format_color_unchecked(format, TILE6_LINEAR).fmt != FMT6_NONE;
86 }
87
88 struct tu_native_format
tu6_format_color(enum pipe_format format,enum a6xx_tile_mode tile_mode)89 tu6_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
96 static struct tu_native_format
tu6_format_texture_unchecked(enum pipe_format format,enum a6xx_tile_mode tile_mode)97 tu6_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
121 struct tu_native_format
tu6_format_texture(enum pipe_format format,enum a6xx_tile_mode tile_mode)122 tu6_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
129 bool
tu6_format_texture_supported(enum pipe_format format)130 tu6_format_texture_supported(enum pipe_format format)
131 {
132 return tu6_format_texture_unchecked(format, TILE6_LINEAR).fmt != FMT6_NONE;
133 }
134
135 static void
tu_physical_device_get_format_properties(struct tu_physical_device * physical_device,VkFormat vk_format,VkFormatProperties3 * out_properties)136 tu_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
284 end:
285 out_properties->linearTilingFeatures = linear;
286 out_properties->optimalTilingFeatures = optimal;
287 out_properties->bufferFeatures = buffer;
288 }
289
290 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)291 tu_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
343 static VkResult
tu_get_image_format_properties(struct tu_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties * pImageFormatProperties,VkFormatFeatureFlags * p_feature_flags)344 tu_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;
508 unsupported:
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
520 static VkResult
tu_get_external_image_format_properties(const struct tu_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo,VkExternalMemoryHandleTypeFlagBits handleType,VkExternalImageFormatProperties * external_properties)521 tu_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
579 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)580 tu_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
666 fail:
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
681 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)682 tu_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
692 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)693 tu_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