1 /*
2 * Copyright © 2019 Raspberry Pi Ltd
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_enum_defines.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 bool
v3dv_format_swizzle_needs_rb_swap(const uint8_t * swizzle)45 v3dv_format_swizzle_needs_rb_swap(const uint8_t *swizzle)
46 {
47 /* Normal case */
48 if (swizzle[0] == PIPE_SWIZZLE_Z)
49 return swizzle[2] == PIPE_SWIZZLE_X;
50
51 /* Format uses reverse flag */
52 if (swizzle[0] == PIPE_SWIZZLE_Y)
53 return swizzle[2] == PIPE_SWIZZLE_W;
54
55 return false;
56 }
57
58 bool
v3dv_format_swizzle_needs_reverse(const uint8_t * swizzle)59 v3dv_format_swizzle_needs_reverse(const uint8_t *swizzle)
60 {
61 /* Normal case */
62 if (swizzle[0] == PIPE_SWIZZLE_W &&
63 swizzle[1] == PIPE_SWIZZLE_Z &&
64 swizzle[2] == PIPE_SWIZZLE_Y &&
65 swizzle[3] == PIPE_SWIZZLE_X) {
66 return true;
67 }
68
69 /* Format uses RB swap flag */
70 if (swizzle[0] == PIPE_SWIZZLE_Y &&
71 swizzle[1] == PIPE_SWIZZLE_Z &&
72 swizzle[2] == PIPE_SWIZZLE_W &&
73 swizzle[3] == PIPE_SWIZZLE_X) {
74 return true;
75 }
76
77 return false;
78 }
79
80 uint8_t
v3dv_get_tex_return_size(const struct v3dv_format * vf,bool compare_enable)81 v3dv_get_tex_return_size(const struct v3dv_format *vf,
82 bool compare_enable)
83 {
84 if (unlikely(V3D_DEBUG & V3D_DEBUG_TMU_16BIT))
85 return 16;
86
87 if (unlikely(V3D_DEBUG & V3D_DEBUG_TMU_32BIT))
88 return 32;
89
90 if (compare_enable)
91 return 16;
92
93 return vf->return_size;
94 }
95
96 /* Some cases of transfer operations are raw data copies that don't depend
97 * on the semantics of the pixel format (no pixel format conversions are
98 * involved). In these cases, it is safe to choose any format supported by
99 * the TFU so long as it has the same texel size, which allows us to use the
100 * TFU paths with formats that are not TFU supported otherwise.
101 */
102 const struct v3dv_format *
v3dv_get_compatible_tfu_format(struct v3dv_device * device,uint32_t bpp,VkFormat * out_vk_format)103 v3dv_get_compatible_tfu_format(struct v3dv_device *device,
104 uint32_t bpp,
105 VkFormat *out_vk_format)
106 {
107 VkFormat vk_format;
108 switch (bpp) {
109 case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break;
110 case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break;
111 case 4: vk_format = VK_FORMAT_R32_SFLOAT; break;
112 case 2: vk_format = VK_FORMAT_R16_SFLOAT; break;
113 case 1: vk_format = VK_FORMAT_R8_UNORM; break;
114 default: unreachable("unsupported format bit-size"); break;
115 };
116
117 if (out_vk_format)
118 *out_vk_format = vk_format;
119
120 const struct v3dv_format *format = v3dv_X(device, get_format)(vk_format);
121 assert(v3dv_X(device, tfu_supports_tex_format)(format->tex_type));
122
123 return format;
124 }
125
126 static VkFormatFeatureFlags2
image_format_features(struct v3dv_physical_device * pdevice,VkFormat vk_format,const struct v3dv_format * v3dv_format,VkImageTiling tiling)127 image_format_features(struct v3dv_physical_device *pdevice,
128 VkFormat vk_format,
129 const struct v3dv_format *v3dv_format,
130 VkImageTiling tiling)
131 {
132 if (!v3dv_format || !v3dv_format->supported)
133 return 0;
134
135 const VkImageAspectFlags aspects = vk_format_aspects(vk_format);
136
137 const VkImageAspectFlags zs_aspects = VK_IMAGE_ASPECT_DEPTH_BIT |
138 VK_IMAGE_ASPECT_STENCIL_BIT;
139 const VkImageAspectFlags supported_aspects = VK_IMAGE_ASPECT_COLOR_BIT |
140 zs_aspects;
141 if ((aspects & supported_aspects) != aspects)
142 return 0;
143
144 /* FIXME: We don't support separate stencil yet */
145 if ((aspects & zs_aspects) == VK_IMAGE_ASPECT_STENCIL_BIT)
146 return 0;
147
148 if (v3dv_format->tex_type == TEXTURE_DATA_FORMAT_NO &&
149 v3dv_format->rt_type == V3D_OUTPUT_IMAGE_FORMAT_NO) {
150 return 0;
151 }
152
153 VkFormatFeatureFlags2 flags = 0;
154
155 /* Raster format is only supported for 1D textures, so let's just
156 * always require optimal tiling for anything that requires sampling.
157 * Note: even if the user requests optimal for a 1D image, we will still
158 * use raster format since that is what the HW requires.
159 */
160 if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO &&
161 tiling == VK_IMAGE_TILING_OPTIMAL) {
162 flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
163 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
164
165 if (v3dv_format->supports_filtering)
166 flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
167 }
168
169 if (v3dv_format->rt_type != V3D_OUTPUT_IMAGE_FORMAT_NO) {
170 if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
171 flags |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
172 VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
173 if (v3dv_X(pdevice, format_supports_blending)(v3dv_format))
174 flags |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
175 } else if (aspects & zs_aspects) {
176 flags |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT |
177 VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
178 }
179 }
180
181 const struct util_format_description *desc =
182 vk_format_description(vk_format);
183
184 if (tiling != VK_IMAGE_TILING_LINEAR) {
185 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && desc->is_array) {
186 flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT;
187 if (desc->nr_channels == 1 && vk_format_is_int(vk_format))
188 flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
189 } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
190 vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
191 vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
192 /* To comply with shaderStorageImageExtendedFormats */
193 flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT;
194 }
195 }
196
197 /* All our depth formats support shadow comparisons. */
198 if (vk_format_has_depth(vk_format) &&
199 (flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
200 flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
201 }
202
203 if (flags) {
204 flags |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
205 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
206 }
207
208 return flags;
209 }
210
211 static VkFormatFeatureFlags2
buffer_format_features(VkFormat vk_format,const struct v3dv_format * v3dv_format)212 buffer_format_features(VkFormat vk_format, const struct v3dv_format *v3dv_format)
213 {
214 if (!v3dv_format || !v3dv_format->supported)
215 return 0;
216
217 if (!v3dv_format->supported)
218 return 0;
219
220 /* We probably only want to support buffer formats that have a
221 * color format specification.
222 */
223 if (!vk_format_is_color(vk_format))
224 return 0;
225
226 const struct util_format_description *desc =
227 vk_format_description(vk_format);
228
229 VkFormatFeatureFlags2 flags = 0;
230 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
231 desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB &&
232 desc->is_array) {
233 flags |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT;
234 if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO) {
235 flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
236 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT;
237 }
238 } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) {
239 flags |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT |
240 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
241 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT;
242 } else if (vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
243 vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
244 flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
245 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT;
246 }
247
248 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
249 desc->is_array &&
250 desc->nr_channels == 1 &&
251 vk_format_is_int(vk_format)) {
252 flags |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
253 }
254
255 return flags;
256 }
257
258 bool
v3dv_buffer_format_supports_features(struct v3dv_device * device,VkFormat vk_format,VkFormatFeatureFlags2 features)259 v3dv_buffer_format_supports_features(struct v3dv_device *device,
260 VkFormat vk_format,
261 VkFormatFeatureFlags2 features)
262 {
263 const struct v3dv_format *v3dv_format = v3dv_X(device, get_format)(vk_format);
264 const VkFormatFeatureFlags2 supported =
265 buffer_format_features(vk_format, v3dv_format);
266 return (supported & features) == features;
267 }
268
269 /* FIXME: this helper now on anv, radv, lvp, and v3dv. Perhaps common
270 * place?
271 */
272 static inline VkFormatFeatureFlags
features2_to_features(VkFormatFeatureFlags2 features2)273 features2_to_features(VkFormatFeatureFlags2 features2)
274 {
275 return features2 & VK_ALL_FORMAT_FEATURE_FLAG_BITS;
276 }
277
278 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)279 v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
280 VkFormat format,
281 VkFormatProperties2 *pFormatProperties)
282 {
283 V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
284 const struct v3dv_format *v3dv_format = v3dv_X(pdevice, get_format)(format);
285
286 VkFormatFeatureFlags2 linear2, optimal2, buffer2;
287 linear2 = image_format_features(pdevice, format, v3dv_format,
288 VK_IMAGE_TILING_LINEAR);
289 optimal2 = image_format_features(pdevice, format, v3dv_format,
290 VK_IMAGE_TILING_OPTIMAL);
291 buffer2 = buffer_format_features(format, v3dv_format);
292 pFormatProperties->formatProperties = (VkFormatProperties) {
293 .linearTilingFeatures = features2_to_features(linear2),
294 .optimalTilingFeatures = features2_to_features(optimal2),
295 .bufferFeatures = features2_to_features(buffer2),
296 };
297
298 vk_foreach_struct(ext, pFormatProperties->pNext) {
299 switch ((unsigned)ext->sType) {
300 case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {
301 struct VkDrmFormatModifierPropertiesListEXT *list = (void *)ext;
302 VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
303 list->pDrmFormatModifierProperties,
304 &list->drmFormatModifierCount);
305 if (pFormatProperties->formatProperties.linearTilingFeatures) {
306 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT,
307 &out, mod_props) {
308 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
309 mod_props->drmFormatModifierPlaneCount = 1;
310 mod_props->drmFormatModifierTilingFeatures =
311 pFormatProperties->formatProperties.linearTilingFeatures;
312 }
313 }
314 if (pFormatProperties->formatProperties.optimalTilingFeatures) {
315 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT,
316 &out, mod_props) {
317 mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;
318 mod_props->drmFormatModifierPlaneCount = 1;
319 mod_props->drmFormatModifierTilingFeatures =
320 pFormatProperties->formatProperties.optimalTilingFeatures;
321 }
322 }
323 break;
324 }
325 case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: {
326 struct VkDrmFormatModifierPropertiesList2EXT *list = (void *)ext;
327 VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierProperties2EXT, out,
328 list->pDrmFormatModifierProperties,
329 &list->drmFormatModifierCount);
330 if (linear2) {
331 vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT,
332 &out, mod_props) {
333 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
334 mod_props->drmFormatModifierPlaneCount = 1;
335 mod_props->drmFormatModifierTilingFeatures = linear2;
336 }
337 }
338 if (optimal2) {
339 vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT,
340 &out, mod_props) {
341 mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;
342 mod_props->drmFormatModifierPlaneCount = 1;
343 mod_props->drmFormatModifierTilingFeatures = optimal2;
344 }
345 }
346 break;
347 }
348 case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3: {
349 VkFormatProperties3 *props = (VkFormatProperties3 *)ext;
350 props->linearTilingFeatures = linear2;
351 props->optimalTilingFeatures = optimal2;
352 props->bufferFeatures = buffer2;
353 break;
354 }
355 default:
356 v3dv_debug_ignored_stype(ext->sType);
357 break;
358 }
359 }
360 }
361
362 static VkResult
get_image_format_properties(struct v3dv_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageTiling tiling,VkImageFormatProperties * pImageFormatProperties,VkSamplerYcbcrConversionImageFormatProperties * pYcbcrImageFormatProperties)363 get_image_format_properties(
364 struct v3dv_physical_device *physical_device,
365 const VkPhysicalDeviceImageFormatInfo2 *info,
366 VkImageTiling tiling,
367 VkImageFormatProperties *pImageFormatProperties,
368 VkSamplerYcbcrConversionImageFormatProperties *pYcbcrImageFormatProperties)
369 {
370 const struct v3dv_format *v3dv_format = v3dv_X(physical_device, get_format)(info->format);
371 VkFormatFeatureFlags2 format_feature_flags =
372 image_format_features(physical_device, info->format, v3dv_format, tiling);
373 if (!format_feature_flags)
374 goto unsupported;
375
376 /* This allows users to create uncompressed views of compressed images,
377 * however this is not something the hardware supports naturally and requires
378 * the driver to lie when programming the texture state to make the hardware
379 * sample with the uncompressed view correctly, and even then, there are
380 * issues when running on real hardware.
381 *
382 * See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11336
383 * for details.
384 */
385 if (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)
386 goto unsupported;
387
388 const VkImageStencilUsageCreateInfo *stencil_usage_info =
389 vk_find_struct_const(info->pNext, IMAGE_STENCIL_USAGE_CREATE_INFO);
390
391 VkImageUsageFlags image_usage =
392 info->usage | (stencil_usage_info ? stencil_usage_info->stencilUsage : 0);
393
394 /* If VK_IMAGE_CREATE_EXTENDED_USAGE_BIT is set it means the usage flags may
395 * not be be supported for the image format but are supported for at least
396 * one compatible format from which an image view can be created for the
397 * image. This means we should not report the format as unsupported based
398 * on the usage flags when usage refers to how an image view may be used
399 * (i.e. as a framebuffer attachment, for sampling, etc).
400 */
401 VkImageUsageFlags view_usage =
402 info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT ? 0 : image_usage;
403
404 if (image_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
405 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT)) {
406 goto unsupported;
407 }
408
409 /* Sampling of raster depth/stencil images is not supported. Since 1D
410 * images are always raster, even if the user requested optimal tiling,
411 * we can't have them be used as transfer sources, since that includes
412 * using them for blit sources, which might require sampling.
413 */
414 if (info->type == VK_IMAGE_TYPE_1D &&
415 vk_format_is_depth_or_stencil(info->format)) {
416 goto unsupported;
417 }
418 }
419
420 if (image_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
421 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT)) {
422 goto unsupported;
423 }
424 }
425
426 if (view_usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
427 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
428 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
429 goto unsupported;
430 }
431
432 /* Sampling of raster depth/stencil images is not supported. Since 1D
433 * images are always raster, even if the user requested optimal tiling,
434 * we can't allow sampling if the format is depth/stencil.
435 */
436 if (info->type == VK_IMAGE_TYPE_1D &&
437 vk_format_is_depth_or_stencil(info->format)) {
438 goto unsupported;
439 }
440 }
441
442 if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
443 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT)) {
444 goto unsupported;
445 }
446 }
447
448 if (view_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
449 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) {
450 goto unsupported;
451 }
452 }
453
454 if (view_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
455 if (!(format_feature_flags &
456 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
457 goto unsupported;
458 }
459 }
460
461 switch (info->type) {
462 case VK_IMAGE_TYPE_1D:
463 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
464 pImageFormatProperties->maxExtent.height = 1;
465 pImageFormatProperties->maxExtent.depth = 1;
466 pImageFormatProperties->maxArrayLayers = V3D_MAX_ARRAY_LAYERS;
467 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
468 break;
469 case VK_IMAGE_TYPE_2D:
470 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
471 pImageFormatProperties->maxExtent.height = V3D_MAX_IMAGE_DIMENSION;
472 pImageFormatProperties->maxExtent.depth = 1;
473 pImageFormatProperties->maxArrayLayers = V3D_MAX_ARRAY_LAYERS;
474 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
475 break;
476 case VK_IMAGE_TYPE_3D:
477 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
478 pImageFormatProperties->maxExtent.height = V3D_MAX_IMAGE_DIMENSION;
479 pImageFormatProperties->maxExtent.depth = V3D_MAX_IMAGE_DIMENSION;
480 pImageFormatProperties->maxArrayLayers = 1;
481 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
482 break;
483 default:
484 unreachable("bad VkImageType");
485 }
486
487 /* Our hw doesn't support 1D compressed textures. */
488 if (info->type == VK_IMAGE_TYPE_1D &&
489 vk_format_is_compressed(info->format)) {
490 goto unsupported;
491 }
492
493 /* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:
494 *
495 * sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the
496 * following conditions is true:
497 *
498 * - tiling is VK_IMAGE_TILING_LINEAR
499 * - type is not VK_IMAGE_TYPE_2D
500 * - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
501 * - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
502 * VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
503 * VkFormatProperties::optimalTilingFeatures returned by
504 * vkGetPhysicalDeviceFormatProperties is set.
505 */
506 pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
507 if (tiling != VK_IMAGE_TILING_LINEAR &&
508 info->type == VK_IMAGE_TYPE_2D &&
509 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
510 (format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT ||
511 format_feature_flags & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
512 pImageFormatProperties->sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
513 }
514
515 if (tiling == VK_IMAGE_TILING_LINEAR)
516 pImageFormatProperties->maxMipLevels = 1;
517
518 pImageFormatProperties->maxResourceSize = 0xffffffff; /* 32-bit allocation */
519
520 return VK_SUCCESS;
521
522 unsupported:
523 *pImageFormatProperties = (VkImageFormatProperties) {
524 .maxExtent = { 0, 0, 0 },
525 .maxMipLevels = 0,
526 .maxArrayLayers = 0,
527 .sampleCounts = 0,
528 .maxResourceSize = 0,
529 };
530
531 return VK_ERROR_FORMAT_NOT_SUPPORTED;
532 }
533
534 static const VkExternalMemoryProperties prime_fd_props = {
535 .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
536 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
537 .exportFromImportedHandleTypes =
538 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
539 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
540 .compatibleHandleTypes =
541 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
542 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
543 };
544
545 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags createFlags,VkImageFormatProperties * pImageFormatProperties)546 v3dv_GetPhysicalDeviceImageFormatProperties(
547 VkPhysicalDevice physicalDevice,
548 VkFormat format,
549 VkImageType type,
550 VkImageTiling tiling,
551 VkImageUsageFlags usage,
552 VkImageCreateFlags createFlags,
553 VkImageFormatProperties *pImageFormatProperties)
554 {
555 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
556
557 const VkPhysicalDeviceImageFormatInfo2 info = {
558 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
559 .pNext = NULL,
560 .format = format,
561 .type = type,
562 .tiling = tiling,
563 .usage = usage,
564 .flags = createFlags,
565 };
566
567 return get_image_format_properties(physical_device, &info, tiling,
568 pImageFormatProperties, NULL);
569 }
570
571 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)572 v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
573 const VkPhysicalDeviceImageFormatInfo2 *base_info,
574 VkImageFormatProperties2 *base_props)
575 {
576 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
577 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
578 const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info = NULL;
579 VkExternalImageFormatProperties *external_props = NULL;
580 VkImageTiling tiling = base_info->tiling;
581
582 /* Extract input structs */
583 vk_foreach_struct_const(s, base_info->pNext) {
584 switch (s->sType) {
585 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
586 external_info = (const void *) s;
587 break;
588 case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
589 /* Do nothing, get_image_format_properties() below will handle it */;
590 break;
591 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT:
592 drm_format_mod_info = (const void *) s;
593 switch (drm_format_mod_info->drmFormatModifier) {
594 case DRM_FORMAT_MOD_LINEAR:
595 tiling = VK_IMAGE_TILING_LINEAR;
596 break;
597 case DRM_FORMAT_MOD_BROADCOM_UIF:
598 tiling = VK_IMAGE_TILING_OPTIMAL;
599 break;
600 default:
601 assert("Unknown DRM format modifier");
602 }
603 break;
604 default:
605 v3dv_debug_ignored_stype(s->sType);
606 break;
607 }
608 }
609
610 assert(tiling == VK_IMAGE_TILING_OPTIMAL ||
611 tiling == VK_IMAGE_TILING_LINEAR);
612
613 /* Extract output structs */
614 vk_foreach_struct(s, base_props->pNext) {
615 switch (s->sType) {
616 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
617 external_props = (void *) s;
618 break;
619 default:
620 v3dv_debug_ignored_stype(s->sType);
621 break;
622 }
623 }
624
625 VkResult result =
626 get_image_format_properties(physical_device, base_info, tiling,
627 &base_props->imageFormatProperties, NULL);
628 if (result != VK_SUCCESS)
629 goto done;
630
631 if (external_info && external_info->handleType != 0) {
632 switch (external_info->handleType) {
633 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
634 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
635 if (external_props)
636 external_props->externalMemoryProperties = prime_fd_props;
637 break;
638 default:
639 result = VK_ERROR_FORMAT_NOT_SUPPORTED;
640 break;
641 }
642 }
643
644 done:
645 return result;
646 }
647
648 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkSampleCountFlagBits samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pPropertyCount,VkSparseImageFormatProperties * pProperties)649 v3dv_GetPhysicalDeviceSparseImageFormatProperties(
650 VkPhysicalDevice physicalDevice,
651 VkFormat format,
652 VkImageType type,
653 VkSampleCountFlagBits samples,
654 VkImageUsageFlags usage,
655 VkImageTiling tiling,
656 uint32_t *pPropertyCount,
657 VkSparseImageFormatProperties *pProperties)
658 {
659 *pPropertyCount = 0;
660 }
661
662 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)663 v3dv_GetPhysicalDeviceSparseImageFormatProperties2(
664 VkPhysicalDevice physicalDevice,
665 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
666 uint32_t *pPropertyCount,
667 VkSparseImageFormatProperties2 *pProperties)
668 {
669 *pPropertyCount = 0;
670 }
671
672 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)673 v3dv_GetPhysicalDeviceExternalBufferProperties(
674 VkPhysicalDevice physicalDevice,
675 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
676 VkExternalBufferProperties *pExternalBufferProperties)
677 {
678 switch (pExternalBufferInfo->handleType) {
679 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
680 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
681 pExternalBufferProperties->externalMemoryProperties = prime_fd_props;
682 return;
683 default: /* Unsupported */
684 pExternalBufferProperties->externalMemoryProperties =
685 (VkExternalMemoryProperties) {
686 .compatibleHandleTypes = pExternalBufferInfo->handleType,
687 };
688 break;
689 }
690 }
691