1 /*
2 * Copyright © 2019 Raspberry Pi
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "v3dv_private.h"
25 #include "vk_util.h"
26 #include "vk_format_info.h"
27
28 #include "drm-uapi/drm_fourcc.h"
29 #include "util/format/u_format.h"
30 #include "vulkan/wsi/wsi_common.h"
31
32 const uint8_t *
v3dv_get_format_swizzle(struct v3dv_device * device,VkFormat f)33 v3dv_get_format_swizzle(struct v3dv_device *device, VkFormat f)
34 {
35 const struct v3dv_format *vf = v3dv_X(device, get_format)(f);
36 static const uint8_t fallback[] = {0, 1, 2, 3};
37
38 if (!vf)
39 return fallback;
40
41 return vf->swizzle;
42 }
43
44 uint8_t
v3dv_get_tex_return_size(const struct v3dv_format * vf,bool compare_enable)45 v3dv_get_tex_return_size(const struct v3dv_format *vf,
46 bool compare_enable)
47 {
48 if (unlikely(V3D_DEBUG & V3D_DEBUG_TMU_16BIT))
49 return 16;
50
51 if (unlikely(V3D_DEBUG & V3D_DEBUG_TMU_32BIT))
52 return 32;
53
54 if (compare_enable)
55 return 16;
56
57 return vf->return_size;
58 }
59
60 /* Some cases of transfer operations are raw data copies that don't depend
61 * on the semantics of the pixel format (no pixel format conversions are
62 * involved). In these cases, it is safe to choose any format supported by
63 * the TFU so long as it has the same texel size, which allows us to use the
64 * TFU paths with formats that are not TFU supported otherwise.
65 */
66 const struct v3dv_format *
v3dv_get_compatible_tfu_format(struct v3dv_device * device,uint32_t bpp,VkFormat * out_vk_format)67 v3dv_get_compatible_tfu_format(struct v3dv_device *device,
68 uint32_t bpp,
69 VkFormat *out_vk_format)
70 {
71 VkFormat vk_format;
72 switch (bpp) {
73 case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break;
74 case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break;
75 case 4: vk_format = VK_FORMAT_R32_SFLOAT; break;
76 case 2: vk_format = VK_FORMAT_R16_SFLOAT; break;
77 case 1: vk_format = VK_FORMAT_R8_UNORM; break;
78 default: unreachable("unsupported format bit-size"); break;
79 };
80
81 if (out_vk_format)
82 *out_vk_format = vk_format;
83
84 const struct v3dv_format *format = v3dv_X(device, get_format)(vk_format);
85 assert(v3dv_X(device, tfu_supports_tex_format)(format->tex_type));
86
87 return format;
88 }
89
90 static VkFormatFeatureFlags
image_format_features(struct v3dv_physical_device * pdevice,VkFormat vk_format,const struct v3dv_format * v3dv_format,VkImageTiling tiling)91 image_format_features(struct v3dv_physical_device *pdevice,
92 VkFormat vk_format,
93 const struct v3dv_format *v3dv_format,
94 VkImageTiling tiling)
95 {
96 if (!v3dv_format || !v3dv_format->supported)
97 return 0;
98
99 const VkImageAspectFlags aspects = vk_format_aspects(vk_format);
100
101 const VkImageAspectFlags zs_aspects = VK_IMAGE_ASPECT_DEPTH_BIT |
102 VK_IMAGE_ASPECT_STENCIL_BIT;
103 const VkImageAspectFlags supported_aspects = VK_IMAGE_ASPECT_COLOR_BIT |
104 zs_aspects;
105 if ((aspects & supported_aspects) != aspects)
106 return 0;
107
108 /* FIXME: We don't support separate stencil yet */
109 if ((aspects & zs_aspects) == VK_IMAGE_ASPECT_STENCIL_BIT)
110 return 0;
111
112 if (v3dv_format->tex_type == TEXTURE_DATA_FORMAT_NO &&
113 v3dv_format->rt_type == V3D_OUTPUT_IMAGE_FORMAT_NO) {
114 return 0;
115 }
116
117 VkFormatFeatureFlags flags = 0;
118
119 /* Raster format is only supported for 1D textures, so let's just
120 * always require optimal tiling for anything that requires sampling.
121 * Note: even if the user requests optimal for a 1D image, we will still
122 * use raster format since that is what the HW requires.
123 */
124 if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO &&
125 tiling == VK_IMAGE_TILING_OPTIMAL) {
126 flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
127 VK_FORMAT_FEATURE_BLIT_SRC_BIT;
128
129 if (v3dv_format->supports_filtering)
130 flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
131 }
132
133 if (v3dv_format->rt_type != V3D_OUTPUT_IMAGE_FORMAT_NO) {
134 if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
135 flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
136 VK_FORMAT_FEATURE_BLIT_DST_BIT;
137 if (v3dv_X(pdevice, format_supports_blending)(v3dv_format))
138 flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
139 } else if (aspects & zs_aspects) {
140 flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
141 VK_FORMAT_FEATURE_BLIT_DST_BIT;
142 }
143 }
144
145 const struct util_format_description *desc =
146 vk_format_description(vk_format);
147 assert(desc);
148
149 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && desc->is_array) {
150 flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
151 if (desc->nr_channels == 1 && vk_format_is_int(vk_format))
152 flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
153 } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
154 vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
155 vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
156 /* To comply with shaderStorageImageExtendedFormats */
157 flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
158 }
159
160 if (flags) {
161 flags |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
162 VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
163 }
164
165 return flags;
166 }
167
168 static VkFormatFeatureFlags
buffer_format_features(VkFormat vk_format,const struct v3dv_format * v3dv_format)169 buffer_format_features(VkFormat vk_format, const struct v3dv_format *v3dv_format)
170 {
171 if (!v3dv_format || !v3dv_format->supported)
172 return 0;
173
174 if (!v3dv_format->supported)
175 return 0;
176
177 /* We probably only want to support buffer formats that have a
178 * color format specification.
179 */
180 if (!vk_format_is_color(vk_format))
181 return 0;
182
183 const struct util_format_description *desc =
184 vk_format_description(vk_format);
185 assert(desc);
186
187 VkFormatFeatureFlags flags = 0;
188 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
189 desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB &&
190 desc->is_array) {
191 flags |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
192 if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO) {
193 flags |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
194 VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
195 }
196 } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) {
197 flags |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |
198 VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
199 VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
200 } else if (vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
201 vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
202 flags |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
203 VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
204 }
205
206 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
207 desc->is_array &&
208 desc->nr_channels == 1 &&
209 vk_format_is_int(vk_format)) {
210 flags |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
211 }
212
213 return flags;
214 }
215
216 bool
v3dv_buffer_format_supports_features(struct v3dv_device * device,VkFormat vk_format,VkFormatFeatureFlags features)217 v3dv_buffer_format_supports_features(struct v3dv_device *device,
218 VkFormat vk_format,
219 VkFormatFeatureFlags features)
220 {
221 const struct v3dv_format *v3dv_format = v3dv_X(device, get_format)(vk_format);
222 const VkFormatFeatureFlags supported =
223 buffer_format_features(vk_format, v3dv_format);
224 return (supported & features) == features;
225 }
226
227 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties * pFormatProperties)228 v3dv_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
229 VkFormat format,
230 VkFormatProperties* pFormatProperties)
231 {
232 V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
233 const struct v3dv_format *v3dv_format = v3dv_X(pdevice, get_format)(format);
234
235 *pFormatProperties = (VkFormatProperties) {
236 .linearTilingFeatures =
237 image_format_features(pdevice, format, v3dv_format, VK_IMAGE_TILING_LINEAR),
238 .optimalTilingFeatures =
239 image_format_features(pdevice, format, v3dv_format, VK_IMAGE_TILING_OPTIMAL),
240 .bufferFeatures =
241 buffer_format_features(format, v3dv_format),
242 };
243 }
244
245 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)246 v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
247 VkFormat format,
248 VkFormatProperties2 *pFormatProperties)
249 {
250 v3dv_GetPhysicalDeviceFormatProperties(physicalDevice, format,
251 &pFormatProperties->formatProperties);
252
253 vk_foreach_struct(ext, pFormatProperties->pNext) {
254 switch ((unsigned)ext->sType) {
255 case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {
256 struct VkDrmFormatModifierPropertiesListEXT *list = (void *)ext;
257 VK_OUTARRAY_MAKE(out, list->pDrmFormatModifierProperties,
258 &list->drmFormatModifierCount);
259 if (pFormatProperties->formatProperties.linearTilingFeatures) {
260 vk_outarray_append(&out, mod_props) {
261 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
262 mod_props->drmFormatModifierPlaneCount = 1;
263 mod_props->drmFormatModifierTilingFeatures =
264 pFormatProperties->formatProperties.linearTilingFeatures;
265 }
266 }
267 if (pFormatProperties->formatProperties.optimalTilingFeatures) {
268 vk_outarray_append(&out, mod_props) {
269 mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;
270 mod_props->drmFormatModifierPlaneCount = 1;
271 mod_props->drmFormatModifierTilingFeatures =
272 pFormatProperties->formatProperties.optimalTilingFeatures;
273 }
274 }
275 break;
276 }
277 default:
278 v3dv_debug_ignored_stype(ext->sType);
279 break;
280 }
281 }
282 }
283
284 static VkResult
get_image_format_properties(struct v3dv_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageTiling tiling,VkImageFormatProperties * pImageFormatProperties,VkSamplerYcbcrConversionImageFormatProperties * pYcbcrImageFormatProperties)285 get_image_format_properties(
286 struct v3dv_physical_device *physical_device,
287 const VkPhysicalDeviceImageFormatInfo2 *info,
288 VkImageTiling tiling,
289 VkImageFormatProperties *pImageFormatProperties,
290 VkSamplerYcbcrConversionImageFormatProperties *pYcbcrImageFormatProperties)
291 {
292 const struct v3dv_format *v3dv_format = v3dv_X(physical_device, get_format)(info->format);
293 VkFormatFeatureFlags format_feature_flags =
294 image_format_features(physical_device, info->format, v3dv_format, tiling);
295 if (!format_feature_flags)
296 goto unsupported;
297
298 /* This allows users to create uncompressed views of compressed images,
299 * however this is not something the hardware supports naturally and requires
300 * the driver to lie when programming the texture state to make the hardware
301 * sample with the uncompressed view correctly, and even then, there are
302 * issues when running on real hardware.
303 *
304 * See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11336
305 * for details.
306 */
307 if (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)
308 goto unsupported;
309
310 if (info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
311 if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) {
312 goto unsupported;
313 }
314
315 /* Sampling of raster depth/stencil images is not supported. Since 1D
316 * images are always raster, even if the user requested optimal tiling,
317 * we can't have them be used as transfer sources, since that includes
318 * using them for blit sources, which might require sampling.
319 */
320 if (info->type == VK_IMAGE_TYPE_1D &&
321 vk_format_is_depth_or_stencil(info->format)) {
322 goto unsupported;
323 }
324 }
325
326 if (info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
327 if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
328 goto unsupported;
329 }
330 }
331
332 if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
333 if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
334 goto unsupported;
335 }
336
337 /* Sampling of raster depth/stencil images is not supported. Since 1D
338 * images are always raster, even if the user requested optimal tiling,
339 * we can't allow sampling if the format is depth/stencil.
340 */
341 if (info->type == VK_IMAGE_TYPE_1D &&
342 vk_format_is_depth_or_stencil(info->format)) {
343 goto unsupported;
344 }
345 }
346
347 if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
348 if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
349 goto unsupported;
350 }
351 }
352
353 if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
354 if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
355 goto unsupported;
356 }
357 }
358
359 if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
360 if (!(format_feature_flags &
361 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
362 goto unsupported;
363 }
364 }
365
366 /* FIXME: these are taken from VkPhysicalDeviceLimits, we should just put
367 * these limits available in the physical device and read them from there
368 * wherever we need them.
369 */
370 switch (info->type) {
371 case VK_IMAGE_TYPE_1D:
372 pImageFormatProperties->maxExtent.width = 4096;
373 pImageFormatProperties->maxExtent.height = 1;
374 pImageFormatProperties->maxExtent.depth = 1;
375 pImageFormatProperties->maxArrayLayers = 2048;
376 pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */
377 break;
378 case VK_IMAGE_TYPE_2D:
379 pImageFormatProperties->maxExtent.width = 4096;
380 pImageFormatProperties->maxExtent.height = 4096;
381 pImageFormatProperties->maxExtent.depth = 1;
382 pImageFormatProperties->maxArrayLayers = 2048;
383 pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */
384 break;
385 case VK_IMAGE_TYPE_3D:
386 pImageFormatProperties->maxExtent.width = 4096;
387 pImageFormatProperties->maxExtent.height = 4096;
388 pImageFormatProperties->maxExtent.depth = 4096;
389 pImageFormatProperties->maxArrayLayers = 1;
390 pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */
391 break;
392 default:
393 unreachable("bad VkImageType");
394 }
395
396 /* Our hw doesn't support 1D compressed textures. */
397 if (info->type == VK_IMAGE_TYPE_1D &&
398 vk_format_is_compressed(info->format)) {
399 goto unsupported;
400 }
401
402 /* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:
403 *
404 * sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the
405 * following conditions is true:
406 *
407 * - tiling is VK_IMAGE_TILING_LINEAR
408 * - type is not VK_IMAGE_TYPE_2D
409 * - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
410 * - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
411 * VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
412 * VkFormatProperties::optimalTilingFeatures returned by
413 * vkGetPhysicalDeviceFormatProperties is set.
414 */
415 pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
416 if (tiling != VK_IMAGE_TILING_LINEAR &&
417 info->type == VK_IMAGE_TYPE_2D &&
418 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
419 (format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
420 format_feature_flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
421 pImageFormatProperties->sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
422 }
423
424 if (tiling == VK_IMAGE_TILING_LINEAR)
425 pImageFormatProperties->maxMipLevels = 1;
426
427 pImageFormatProperties->maxResourceSize = 0xffffffff; /* 32-bit allocation */
428
429 return VK_SUCCESS;
430
431 unsupported:
432 *pImageFormatProperties = (VkImageFormatProperties) {
433 .maxExtent = { 0, 0, 0 },
434 .maxMipLevels = 0,
435 .maxArrayLayers = 0,
436 .sampleCounts = 0,
437 .maxResourceSize = 0,
438 };
439
440 return VK_ERROR_FORMAT_NOT_SUPPORTED;
441 }
442
443 static const VkExternalMemoryProperties prime_fd_props = {
444 .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
445 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
446 .exportFromImportedHandleTypes =
447 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
448 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
449 .compatibleHandleTypes =
450 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
451 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
452 };
453
454 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags createFlags,VkImageFormatProperties * pImageFormatProperties)455 v3dv_GetPhysicalDeviceImageFormatProperties(
456 VkPhysicalDevice physicalDevice,
457 VkFormat format,
458 VkImageType type,
459 VkImageTiling tiling,
460 VkImageUsageFlags usage,
461 VkImageCreateFlags createFlags,
462 VkImageFormatProperties *pImageFormatProperties)
463 {
464 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
465
466 const VkPhysicalDeviceImageFormatInfo2 info = {
467 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
468 .pNext = NULL,
469 .format = format,
470 .type = type,
471 .tiling = tiling,
472 .usage = usage,
473 .flags = createFlags,
474 };
475
476 return get_image_format_properties(physical_device, &info, tiling,
477 pImageFormatProperties, NULL);
478 }
479
480 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)481 v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
482 const VkPhysicalDeviceImageFormatInfo2 *base_info,
483 VkImageFormatProperties2 *base_props)
484 {
485 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
486 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
487 const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info = NULL;
488 VkExternalImageFormatProperties *external_props = NULL;
489 VkImageTiling tiling = base_info->tiling;
490
491 /* Extract input structs */
492 vk_foreach_struct_const(s, base_info->pNext) {
493 switch (s->sType) {
494 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
495 external_info = (const void *) s;
496 break;
497 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT:
498 drm_format_mod_info = (const void *) s;
499 switch (drm_format_mod_info->drmFormatModifier) {
500 case DRM_FORMAT_MOD_LINEAR:
501 tiling = VK_IMAGE_TILING_LINEAR;
502 break;
503 case DRM_FORMAT_MOD_BROADCOM_UIF:
504 tiling = VK_IMAGE_TILING_OPTIMAL;
505 break;
506 default:
507 assert("Unknown DRM format modifier");
508 }
509 break;
510 default:
511 v3dv_debug_ignored_stype(s->sType);
512 break;
513 }
514 }
515
516 assert(tiling == VK_IMAGE_TILING_OPTIMAL ||
517 tiling == VK_IMAGE_TILING_LINEAR);
518
519 /* Extract output structs */
520 vk_foreach_struct(s, base_props->pNext) {
521 switch (s->sType) {
522 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
523 external_props = (void *) s;
524 break;
525 default:
526 v3dv_debug_ignored_stype(s->sType);
527 break;
528 }
529 }
530
531 VkResult result =
532 get_image_format_properties(physical_device, base_info, tiling,
533 &base_props->imageFormatProperties, NULL);
534 if (result != VK_SUCCESS)
535 goto done;
536
537 if (external_info && external_info->handleType != 0) {
538 switch (external_info->handleType) {
539 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
540 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
541 if (external_props)
542 external_props->externalMemoryProperties = prime_fd_props;
543 break;
544 default:
545 result = VK_ERROR_FORMAT_NOT_SUPPORTED;
546 break;
547 }
548 }
549
550 done:
551 return result;
552 }
553
554 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkSampleCountFlagBits samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pPropertyCount,VkSparseImageFormatProperties * pProperties)555 v3dv_GetPhysicalDeviceSparseImageFormatProperties(
556 VkPhysicalDevice physicalDevice,
557 VkFormat format,
558 VkImageType type,
559 VkSampleCountFlagBits samples,
560 VkImageUsageFlags usage,
561 VkImageTiling tiling,
562 uint32_t *pPropertyCount,
563 VkSparseImageFormatProperties *pProperties)
564 {
565 *pPropertyCount = 0;
566 }
567
568 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)569 v3dv_GetPhysicalDeviceSparseImageFormatProperties2(
570 VkPhysicalDevice physicalDevice,
571 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
572 uint32_t *pPropertyCount,
573 VkSparseImageFormatProperties2 *pProperties)
574 {
575 *pPropertyCount = 0;
576 }
577
578 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)579 v3dv_GetPhysicalDeviceExternalBufferProperties(
580 VkPhysicalDevice physicalDevice,
581 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
582 VkExternalBufferProperties *pExternalBufferProperties)
583 {
584 switch (pExternalBufferInfo->handleType) {
585 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
586 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
587 pExternalBufferProperties->externalMemoryProperties = prime_fd_props;
588 return;
589 default: /* Unsupported */
590 pExternalBufferProperties->externalMemoryProperties =
591 (VkExternalMemoryProperties) {
592 .compatibleHandleTypes = pExternalBufferInfo->handleType,
593 };
594 break;
595 }
596 }
597