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
36 struct tu_native_format
tu6_format_vtx(VkFormat vk_format)37 tu6_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
48 bool
tu6_format_vtx_supported(VkFormat vk_format)49 tu6_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 */
63 static enum pipe_format
tu_vk_format_to_pipe_format(VkFormat vk_format)64 tu_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
80 static struct tu_native_format
tu6_format_color_unchecked(VkFormat vk_format,enum a6xx_tile_mode tile_mode)81 tu6_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
102 bool
tu6_format_color_supported(VkFormat vk_format)103 tu6_format_color_supported(VkFormat vk_format)
104 {
105 return tu6_format_color_unchecked(vk_format, TILE6_LINEAR).fmt != FMT6_NONE;
106 }
107
108 struct tu_native_format
tu6_format_color(VkFormat vk_format,enum a6xx_tile_mode tile_mode)109 tu6_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
116 static struct tu_native_format
tu6_format_texture_unchecked(VkFormat vk_format,enum a6xx_tile_mode tile_mode)117 tu6_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
150 struct tu_native_format
tu6_format_texture(VkFormat vk_format,enum a6xx_tile_mode tile_mode)151 tu6_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
158 bool
tu6_format_texture_supported(VkFormat vk_format)159 tu6_format_texture_supported(VkFormat vk_format)
160 {
161 return tu6_format_texture_unchecked(vk_format, TILE6_LINEAR).fmt != FMT6_NONE;
162 }
163
164 static void
tu_physical_device_get_format_properties(struct tu_physical_device * physical_device,VkFormat vk_format,VkFormatProperties * out_properties)165 tu_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
283 end:
284 out_properties->linearTilingFeatures = linear;
285 out_properties->optimalTilingFeatures = optimal;
286 out_properties->bufferFeatures = buffer;
287 }
288
289 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)290 tu_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
324 static VkResult
tu_get_image_format_properties(struct tu_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties * pImageFormatProperties,VkFormatFeatureFlags * p_feature_flags)325 tu_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;
470 unsupported:
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
482 static VkResult
tu_get_external_image_format_properties(const struct tu_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo,VkExternalMemoryHandleTypeFlagBits handleType,VkExternalMemoryProperties * external_properties)483 tu_get_external_image_format_properties(
484 const struct tu_physical_device *physical_device,
485 const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
486 VkExternalMemoryHandleTypeFlagBits handleType,
487 VkExternalMemoryProperties *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 *external_properties = (VkExternalMemoryProperties) {
530 .externalMemoryFeatures = flags,
531 .exportFromImportedHandleTypes = export_flags,
532 .compatibleHandleTypes = compat_flags,
533 };
534
535 return VK_SUCCESS;
536 }
537
538 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)539 tu_GetPhysicalDeviceImageFormatProperties2(
540 VkPhysicalDevice physicalDevice,
541 const VkPhysicalDeviceImageFormatInfo2 *base_info,
542 VkImageFormatProperties2 *base_props)
543 {
544 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
545 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
546 const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL;
547 VkExternalImageFormatProperties *external_props = NULL;
548 VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL;
549 VkFormatFeatureFlags format_feature_flags;
550 VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
551 VkResult result;
552
553 result = tu_get_image_format_properties(physical_device,
554 base_info, &base_props->imageFormatProperties, &format_feature_flags);
555 if (result != VK_SUCCESS)
556 return result;
557
558 /* Extract input structs */
559 vk_foreach_struct_const(s, base_info->pNext)
560 {
561 switch (s->sType) {
562 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
563 external_info = (const void *) s;
564 break;
565 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT:
566 image_view_info = (const void *) s;
567 break;
568 default:
569 break;
570 }
571 }
572
573 /* Extract output structs */
574 vk_foreach_struct(s, base_props->pNext)
575 {
576 switch (s->sType) {
577 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
578 external_props = (void *) s;
579 break;
580 case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT:
581 cubic_props = (void *) s;
582 break;
583 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
584 ycbcr_props = (void *) s;
585 break;
586 default:
587 break;
588 }
589 }
590
591 /* From the Vulkan 1.0.42 spec:
592 *
593 * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
594 * behave as if VkPhysicalDeviceExternalImageFormatInfo was not
595 * present and VkExternalImageFormatProperties will be ignored.
596 */
597 if (external_info && external_info->handleType != 0) {
598 result = tu_get_external_image_format_properties(
599 physical_device, base_info, external_info->handleType,
600 &external_props->externalMemoryProperties);
601 if (result != VK_SUCCESS)
602 goto fail;
603 }
604
605 if (cubic_props) {
606 /* note: blob only allows cubic filtering for 2D and 2D array views
607 * its likely we can enable it for 1D and CUBE, needs testing however
608 */
609 if ((image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D ||
610 image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) &&
611 (format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
612 cubic_props->filterCubic = true;
613 cubic_props->filterCubicMinmax = true;
614 } else {
615 cubic_props->filterCubic = false;
616 cubic_props->filterCubicMinmax = false;
617 }
618 }
619
620 if (ycbcr_props)
621 ycbcr_props->combinedImageSamplerDescriptorCount = 1;
622
623 return VK_SUCCESS;
624
625 fail:
626 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
627 /* From the Vulkan 1.0.42 spec:
628 *
629 * If the combination of parameters to
630 * vkGetPhysicalDeviceImageFormatProperties2 is not supported by
631 * the implementation for use in vkCreateImage, then all members of
632 * imageFormatProperties will be filled with zero.
633 */
634 base_props->imageFormatProperties = (VkImageFormatProperties) {};
635 }
636
637 return result;
638 }
639
640 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)641 tu_GetPhysicalDeviceSparseImageFormatProperties2(
642 VkPhysicalDevice physicalDevice,
643 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
644 uint32_t *pPropertyCount,
645 VkSparseImageFormatProperties2 *pProperties)
646 {
647 /* Sparse images are not yet supported. */
648 *pPropertyCount = 0;
649 }
650
651 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)652 tu_GetPhysicalDeviceExternalBufferProperties(
653 VkPhysicalDevice physicalDevice,
654 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
655 VkExternalBufferProperties *pExternalBufferProperties)
656 {
657 VkExternalMemoryFeatureFlagBits flags = 0;
658 VkExternalMemoryHandleTypeFlags export_flags = 0;
659 VkExternalMemoryHandleTypeFlags compat_flags = 0;
660 switch (pExternalBufferInfo->handleType) {
661 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
662 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
663 flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
664 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
665 compat_flags = export_flags =
666 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
667 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
668 break;
669 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
670 flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
671 compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
672 break;
673 default:
674 break;
675 }
676 pExternalBufferProperties->externalMemoryProperties =
677 (VkExternalMemoryProperties) {
678 .externalMemoryFeatures = flags,
679 .exportFromImportedHandleTypes = export_flags,
680 .compatibleHandleTypes = compat_flags,
681 };
682 }
683