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 #if DETECT_OS_ANDROID
26 #include "vk_android.h"
27 #endif
28 #include "vk_enum_defines.h"
29 #include "vk_util.h"
30
31 #include "drm-uapi/drm_fourcc.h"
32 #include "util/format/u_format.h"
33 #include "vulkan/wsi/wsi_common.h"
34
35 #include <vulkan/vulkan_android.h>
36
37 const uint8_t *
v3dv_get_format_swizzle(struct v3dv_device * device,VkFormat f,uint8_t plane)38 v3dv_get_format_swizzle(struct v3dv_device *device, VkFormat f, uint8_t plane)
39 {
40 const struct v3dv_format *vf = v3d_X((&device->devinfo), get_format)(f);
41 static const uint8_t fallback[] = {0, 1, 2, 3};
42
43 if (!vf)
44 return fallback;
45
46 return vf->planes[plane].swizzle;
47 }
48
49 bool
v3dv_format_swizzle_needs_rb_swap(const uint8_t * swizzle)50 v3dv_format_swizzle_needs_rb_swap(const uint8_t *swizzle)
51 {
52 /* Normal case */
53 if (swizzle[0] == PIPE_SWIZZLE_Z)
54 return swizzle[2] == PIPE_SWIZZLE_X;
55
56 /* Format uses reverse flag */
57 if (swizzle[0] == PIPE_SWIZZLE_Y)
58 return swizzle[2] == PIPE_SWIZZLE_W;
59
60 return false;
61 }
62
63 bool
v3dv_format_swizzle_needs_reverse(const uint8_t * swizzle)64 v3dv_format_swizzle_needs_reverse(const uint8_t *swizzle)
65 {
66 /* Normal case */
67 if (swizzle[0] == PIPE_SWIZZLE_W &&
68 swizzle[1] == PIPE_SWIZZLE_Z &&
69 swizzle[2] == PIPE_SWIZZLE_Y &&
70 swizzle[3] == PIPE_SWIZZLE_X) {
71 return true;
72 }
73
74 /* Format uses RB swap flag */
75 if (swizzle[0] == PIPE_SWIZZLE_Y &&
76 swizzle[1] == PIPE_SWIZZLE_Z &&
77 swizzle[2] == PIPE_SWIZZLE_W &&
78 swizzle[3] == PIPE_SWIZZLE_X) {
79 return true;
80 }
81
82 return false;
83 }
84
85 /* Some cases of transfer operations are raw data copies that don't depend
86 * on the semantics of the pixel format (no pixel format conversions are
87 * involved). In these cases, it is safe to choose any format supported by
88 * the TFU so long as it has the same texel size, which allows us to use the
89 * TFU paths with formats that are not TFU supported otherwise.
90 *
91 * Even when copying multi-plane images, we are copying per-plane, so the
92 * compatible TFU format will be single-plane.
93 */
94 const struct v3dv_format *
v3dv_get_compatible_tfu_format(struct v3dv_device * device,uint32_t bpp,VkFormat * out_vk_format)95 v3dv_get_compatible_tfu_format(struct v3dv_device *device,
96 uint32_t bpp,
97 VkFormat *out_vk_format)
98 {
99 VkFormat vk_format;
100 switch (bpp) {
101 case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break;
102 case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break;
103 case 4: vk_format = VK_FORMAT_R32_SFLOAT; break;
104 case 2: vk_format = VK_FORMAT_R16_SFLOAT; break;
105 case 1: vk_format = VK_FORMAT_R8_UNORM; break;
106 default: unreachable("unsupported format bit-size"); break;
107 };
108
109 if (out_vk_format)
110 *out_vk_format = vk_format;
111
112 const struct v3dv_format *format = v3d_X((&device->devinfo), get_format)(vk_format);
113 assert(format->plane_count == 1);
114 assert(v3d_X((&device->devinfo), tfu_supports_tex_format)(format->planes[0].tex_type));
115
116 return format;
117 }
118
119 static VkFormatFeatureFlags2
image_format_plane_features(struct v3dv_physical_device * pdevice,VkFormat vk_format,const struct v3dv_format_plane * v3dv_format,VkImageTiling tiling)120 image_format_plane_features(struct v3dv_physical_device *pdevice,
121 VkFormat vk_format,
122 const struct v3dv_format_plane *v3dv_format,
123 VkImageTiling tiling)
124 {
125 const VkImageAspectFlags aspects = vk_format_aspects(vk_format);
126
127 const VkImageAspectFlags zs_aspects = VK_IMAGE_ASPECT_DEPTH_BIT |
128 VK_IMAGE_ASPECT_STENCIL_BIT;
129 const VkImageAspectFlags supported_aspects = VK_IMAGE_ASPECT_COLOR_BIT |
130 zs_aspects;
131 if ((aspects & supported_aspects) != aspects)
132 return 0;
133
134 /* FIXME: We don't support separate stencil yet */
135 if ((aspects & zs_aspects) == VK_IMAGE_ASPECT_STENCIL_BIT)
136 return 0;
137
138 if (v3dv_format->tex_type == TEXTURE_DATA_FORMAT_NO &&
139 v3dv_format->rt_type == V3D_OUTPUT_IMAGE_FORMAT_NO) {
140 return 0;
141 }
142
143 VkFormatFeatureFlags2 flags = 0;
144
145 /* Raster format is only supported for 1D textures, so let's just
146 * always require optimal tiling for anything that requires sampling.
147 * Note: even if the user requests optimal for a 1D image, we will still
148 * use raster format since that is what the HW requires.
149 */
150 if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO &&
151 tiling == VK_IMAGE_TILING_OPTIMAL) {
152 flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
153 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
154
155 }
156
157 if (v3dv_format->rt_type != V3D_OUTPUT_IMAGE_FORMAT_NO) {
158 if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
159 flags |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
160 VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
161 } else if (aspects & zs_aspects) {
162 flags |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT |
163 VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
164 }
165 }
166
167 const struct util_format_description *desc =
168 vk_format_description(vk_format);
169
170 if (tiling != VK_IMAGE_TILING_LINEAR) {
171 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && desc->is_array) {
172 flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
173 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT;
174 if (desc->nr_channels == 1 && vk_format_is_int(vk_format))
175 flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
176 } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
177 vk_format == VK_FORMAT_A2R10G10B10_UNORM_PACK32 ||
178 vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
179 vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
180 /* To comply with shaderStorageImageExtendedFormats */
181 flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
182 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT;
183 }
184 }
185
186 /* All our depth formats support shadow comparisons. */
187 if (vk_format_has_depth(vk_format) &&
188 (flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
189 flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
190 }
191
192 if (flags) {
193 flags |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
194 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
195 }
196
197 return flags;
198 }
199
200 static VkFormatFeatureFlags2
image_format_features(struct v3dv_physical_device * pdevice,VkFormat vk_format,const struct v3dv_format * v3dv_format,VkImageTiling tiling)201 image_format_features(struct v3dv_physical_device *pdevice,
202 VkFormat vk_format,
203 const struct v3dv_format *v3dv_format,
204 VkImageTiling tiling)
205 {
206 if (!v3dv_format || !v3dv_format->plane_count)
207 return 0;
208
209 VkFormatFeatureFlags2 flags = ~0ull;
210 for (uint8_t plane = 0;
211 flags && plane < v3dv_format->plane_count;
212 plane++) {
213 VkFormat plane_format = vk_format_get_plane_format(vk_format, plane);
214
215 flags &= image_format_plane_features(pdevice,
216 plane_format,
217 &v3dv_format->planes[plane],
218 tiling);
219 }
220
221 const struct vk_format_ycbcr_info *ycbcr_info =
222 vk_format_get_ycbcr_info(vk_format);
223
224 if (ycbcr_info) {
225 assert(v3dv_format->plane_count == ycbcr_info->n_planes);
226
227 flags |= VK_FORMAT_FEATURE_2_DISJOINT_BIT;
228
229 if (flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT) {
230 flags |= VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT;
231 for (unsigned p = 0; p < ycbcr_info->n_planes; p++) {
232 if (ycbcr_info->planes[p].denominator_scales[0] > 1 ||
233 ycbcr_info->planes[p].denominator_scales[1] > 1) {
234 flags |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
235 break;
236 }
237 }
238 }
239
240 /* FIXME: in the future we should be able to support BLIT_SRC via the
241 * blit_shader path
242 */
243 const VkFormatFeatureFlags2 disallowed_ycbcr_image_features =
244 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT |
245 VK_FORMAT_FEATURE_2_BLIT_DST_BIT |
246 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
247 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT |
248 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT;
249
250 flags &= ~disallowed_ycbcr_image_features;
251 }
252
253 if (flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT &&
254 v3dv_format->supports_filtering) {
255 flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
256 }
257
258 if (flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT &&
259 v3d_X((&pdevice->devinfo), format_supports_blending)(v3dv_format)) {
260 flags |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
261 }
262
263 return flags;
264 }
265
266 static VkFormatFeatureFlags2
buffer_format_features(VkFormat vk_format,const struct v3dv_format * v3dv_format)267 buffer_format_features(VkFormat vk_format, const struct v3dv_format *v3dv_format)
268 {
269 if (!v3dv_format)
270 return 0;
271
272 if (v3dv_format->plane_count != 1)
273 return 0;
274
275 /* We probably only want to support buffer formats that have a
276 * color format specification.
277 */
278 if (!vk_format_is_color(vk_format))
279 return 0;
280
281 const struct util_format_description *desc =
282 vk_format_description(vk_format);
283
284 VkFormatFeatureFlags2 flags = 0;
285 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
286 desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB &&
287 desc->is_array) {
288 flags |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT;
289 if (v3dv_format->planes[0].tex_type != TEXTURE_DATA_FORMAT_NO) {
290 /* STORAGE_READ_WITHOUT_FORMAT can also be applied for buffers. From spec:
291 * "VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT specifies
292 * that image views or buffer views created with this format can
293 * be used as storage images for read operations without
294 * specifying a format."
295 */
296 flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
297 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT |
298 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT;
299 }
300 } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
301 vk_format == VK_FORMAT_A2R10G10B10_UNORM_PACK32) {
302 flags |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT |
303 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
304 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT;
305 } else if (vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
306 vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
307 flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
308 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT;
309 }
310
311 if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
312 desc->is_array &&
313 desc->nr_channels == 1 &&
314 vk_format_is_int(vk_format)) {
315 flags |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
316 }
317
318 return flags;
319 }
320
321 bool
v3dv_buffer_format_supports_features(struct v3dv_device * device,VkFormat vk_format,VkFormatFeatureFlags2 features)322 v3dv_buffer_format_supports_features(struct v3dv_device *device,
323 VkFormat vk_format,
324 VkFormatFeatureFlags2 features)
325 {
326 const struct v3dv_format *v3dv_format = v3d_X((&device->devinfo), get_format)(vk_format);
327 const VkFormatFeatureFlags2 supported =
328 buffer_format_features(vk_format, v3dv_format);
329 return (supported & features) == features;
330 }
331
332 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)333 v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
334 VkFormat format,
335 VkFormatProperties2 *pFormatProperties)
336 {
337 V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
338 const struct v3dv_format *v3dv_format = v3d_X((&pdevice->devinfo), get_format)(format);
339
340 VkFormatFeatureFlags2 linear2, optimal2, buffer2;
341 linear2 = image_format_features(pdevice, format, v3dv_format,
342 VK_IMAGE_TILING_LINEAR);
343 optimal2 = image_format_features(pdevice, format, v3dv_format,
344 VK_IMAGE_TILING_OPTIMAL);
345 buffer2 = buffer_format_features(format, v3dv_format);
346 pFormatProperties->formatProperties = (VkFormatProperties) {
347 .linearTilingFeatures = vk_format_features2_to_features(linear2),
348 .optimalTilingFeatures = vk_format_features2_to_features(optimal2),
349 .bufferFeatures = vk_format_features2_to_features(buffer2),
350 };
351
352 vk_foreach_struct(ext, pFormatProperties->pNext) {
353 switch ((unsigned)ext->sType) {
354 case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {
355 struct VkDrmFormatModifierPropertiesListEXT *list = (void *)ext;
356 VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
357 list->pDrmFormatModifierProperties,
358 &list->drmFormatModifierCount);
359 if (pFormatProperties->formatProperties.linearTilingFeatures) {
360 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT,
361 &out, mod_props) {
362 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
363 mod_props->drmFormatModifierPlaneCount = 1;
364 mod_props->drmFormatModifierTilingFeatures =
365 pFormatProperties->formatProperties.linearTilingFeatures;
366 }
367 }
368 if (pFormatProperties->formatProperties.optimalTilingFeatures) {
369 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT,
370 &out, mod_props) {
371 mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;
372 mod_props->drmFormatModifierPlaneCount = 1;
373 mod_props->drmFormatModifierTilingFeatures =
374 pFormatProperties->formatProperties.optimalTilingFeatures;
375 }
376 }
377 break;
378 }
379 case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: {
380 struct VkDrmFormatModifierPropertiesList2EXT *list = (void *)ext;
381 VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierProperties2EXT, out,
382 list->pDrmFormatModifierProperties,
383 &list->drmFormatModifierCount);
384 if (linear2) {
385 vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT,
386 &out, mod_props) {
387 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
388 mod_props->drmFormatModifierPlaneCount = 1;
389 mod_props->drmFormatModifierTilingFeatures = linear2;
390 }
391 }
392 if (optimal2) {
393 vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT,
394 &out, mod_props) {
395 mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;
396 mod_props->drmFormatModifierPlaneCount = 1;
397 mod_props->drmFormatModifierTilingFeatures = optimal2;
398 }
399 }
400 break;
401 }
402 case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3: {
403 VkFormatProperties3 *props = (VkFormatProperties3 *)ext;
404 props->linearTilingFeatures = linear2;
405 props->optimalTilingFeatures = optimal2;
406 props->bufferFeatures = buffer2;
407 break;
408 }
409 default:
410 vk_debug_ignored_stype(ext->sType);
411 break;
412 }
413 }
414 }
415
416 static VkResult
get_image_format_properties(struct v3dv_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageTiling tiling,VkImageFormatProperties * pImageFormatProperties,VkSamplerYcbcrConversionImageFormatProperties * pYcbcrImageFormatProperties)417 get_image_format_properties(
418 struct v3dv_physical_device *physical_device,
419 const VkPhysicalDeviceImageFormatInfo2 *info,
420 VkImageTiling tiling,
421 VkImageFormatProperties *pImageFormatProperties,
422 VkSamplerYcbcrConversionImageFormatProperties *pYcbcrImageFormatProperties)
423 {
424 const struct v3dv_format *v3dv_format = v3d_X((&physical_device->devinfo), get_format)(info->format);
425 VkFormatFeatureFlags2 format_feature_flags =
426 image_format_features(physical_device, info->format, v3dv_format, tiling);
427 if (!format_feature_flags)
428 goto unsupported;
429
430 /* This allows users to create uncompressed views of compressed images,
431 * however this is not something the hardware supports naturally and requires
432 * the driver to lie when programming the texture state to make the hardware
433 * sample with the uncompressed view correctly, and even then, there are
434 * issues when running on real hardware.
435 *
436 * See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11336
437 * for details.
438 */
439 if (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)
440 goto unsupported;
441
442 const VkImageStencilUsageCreateInfo *stencil_usage_info =
443 vk_find_struct_const(info->pNext, IMAGE_STENCIL_USAGE_CREATE_INFO);
444
445 VkImageUsageFlags image_usage =
446 info->usage | (stencil_usage_info ? stencil_usage_info->stencilUsage : 0);
447
448 /* If VK_IMAGE_CREATE_EXTENDED_USAGE_BIT is set it means the usage flags may
449 * not be be supported for the image format but are supported for at least
450 * one compatible format from which an image view can be created for the
451 * image. This means we should not report the format as unsupported based
452 * on the usage flags when usage refers to how an image view may be used
453 * (i.e. as a framebuffer attachment, for sampling, etc).
454 */
455 VkImageUsageFlags view_usage =
456 info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT ? 0 : image_usage;
457
458 if (image_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
459 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT)) {
460 goto unsupported;
461 }
462
463 /* Sampling of raster depth/stencil images is not supported. Since 1D
464 * images are always raster, even if the user requested optimal tiling,
465 * we can't have them be used as transfer sources, since that includes
466 * using them for blit sources, which might require sampling.
467 */
468 if (info->type == VK_IMAGE_TYPE_1D &&
469 vk_format_is_depth_or_stencil(info->format)) {
470 goto unsupported;
471 }
472 }
473
474 if (image_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
475 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT)) {
476 goto unsupported;
477 }
478 }
479
480 if (view_usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
481 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
482 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT))
483 goto unsupported;
484
485 /* Sampling of raster depth/stencil images is not supported. Since 1D
486 * images are always raster, even if the user requested optimal tiling,
487 * we can't allow sampling if the format is depth/stencil.
488 */
489 if (info->type == VK_IMAGE_TYPE_1D &&
490 vk_format_is_depth_or_stencil(info->format)) {
491 goto unsupported;
492 }
493 }
494
495 if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
496 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT)) {
497 goto unsupported;
498 }
499 }
500
501 if (view_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
502 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) {
503 goto unsupported;
504 }
505 }
506
507 if (view_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
508 if (!(format_feature_flags &
509 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
510 goto unsupported;
511 }
512 }
513
514 if (view_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
515 if (!(format_feature_flags & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
516 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT))) {
517 goto unsupported;
518 }
519 }
520
521 switch (info->type) {
522 case VK_IMAGE_TYPE_1D:
523 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
524 pImageFormatProperties->maxExtent.height = 1;
525 pImageFormatProperties->maxExtent.depth = 1;
526 pImageFormatProperties->maxArrayLayers = V3D_MAX_ARRAY_LAYERS;
527 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
528 break;
529 case VK_IMAGE_TYPE_2D:
530 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
531 pImageFormatProperties->maxExtent.height = V3D_MAX_IMAGE_DIMENSION;
532 pImageFormatProperties->maxExtent.depth = 1;
533 pImageFormatProperties->maxArrayLayers =
534 v3dv_format->plane_count == 1 ? V3D_MAX_ARRAY_LAYERS : 1;
535 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
536 break;
537 case VK_IMAGE_TYPE_3D:
538 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
539 pImageFormatProperties->maxExtent.height = V3D_MAX_IMAGE_DIMENSION;
540 pImageFormatProperties->maxExtent.depth = V3D_MAX_IMAGE_DIMENSION;
541 pImageFormatProperties->maxArrayLayers = 1;
542 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
543 break;
544 default:
545 unreachable("bad VkImageType");
546 }
547
548 /* Our hw doesn't support 1D compressed textures. */
549 if (info->type == VK_IMAGE_TYPE_1D &&
550 vk_format_is_compressed(info->format)) {
551 goto unsupported;
552 }
553
554 /* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:
555 *
556 * sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the
557 * following conditions is true:
558 *
559 * - tiling is VK_IMAGE_TILING_LINEAR
560 * - type is not VK_IMAGE_TYPE_2D
561 * - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
562 * - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
563 * VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
564 * VkFormatProperties::optimalTilingFeatures returned by
565 * vkGetPhysicalDeviceFormatProperties is set.
566 */
567 pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
568 if (tiling != VK_IMAGE_TILING_LINEAR &&
569 info->type == VK_IMAGE_TYPE_2D &&
570 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
571 (format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT ||
572 format_feature_flags & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
573 pImageFormatProperties->sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
574 }
575
576 if (tiling == VK_IMAGE_TILING_LINEAR)
577 pImageFormatProperties->maxMipLevels = 1;
578
579 /* From the Vulkan 1.2 spec, section 12.3. Images, VkImageCreateInfo structure:
580 *
581 * "Images created with one of the formats that require a sampler Y′CBCR
582 * conversion, have further restrictions on their limits and
583 * capabilities compared to images created with other formats. Creation
584 * of images with a format requiring Y′CBCR conversion may not be
585 * supported unless other parameters meet all of the constraints:
586 *
587 * * imageType is VK_IMAGE_TYPE_2D
588 * * mipLevels is 1
589 * * arrayLayers is 1, unless the ycbcrImageArrays feature is enabled, or
590 * otherwise indicated by VkImageFormatProperties::maxArrayLayers, as
591 * returned by vkGetPhysicalDeviceImageFormatProperties
592 * * samples is VK_SAMPLE_COUNT_1_BIT
593 *
594 * Implementations may support additional limits and capabilities beyond
595 * those listed above."
596 *
597 * We don't provide such additional limits, so we set those limits, or just
598 * return unsupported.
599 */
600 if (vk_format_get_plane_count(info->format) > 1) {
601 if (info->type != VK_IMAGE_TYPE_2D)
602 goto unsupported;
603 pImageFormatProperties->maxMipLevels = 1;
604 pImageFormatProperties->maxArrayLayers = 1;
605 pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
606 }
607
608 pImageFormatProperties->maxResourceSize = 0xffffffff; /* 32-bit allocation */
609
610 if (pYcbcrImageFormatProperties) {
611 pYcbcrImageFormatProperties->combinedImageSamplerDescriptorCount =
612 vk_format_get_plane_count(info->format);
613 }
614
615 return VK_SUCCESS;
616
617 unsupported:
618 *pImageFormatProperties = (VkImageFormatProperties) {
619 .maxExtent = { 0, 0, 0 },
620 .maxMipLevels = 0,
621 .maxArrayLayers = 0,
622 .sampleCounts = 0,
623 .maxResourceSize = 0,
624 };
625
626 return VK_ERROR_FORMAT_NOT_SUPPORTED;
627 }
628
629 static const VkExternalMemoryProperties prime_fd_props = {
630 .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
631 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
632 .exportFromImportedHandleTypes =
633 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
634 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
635 .compatibleHandleTypes =
636 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
637 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
638 };
639
640 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags createFlags,VkImageFormatProperties * pImageFormatProperties)641 v3dv_GetPhysicalDeviceImageFormatProperties(
642 VkPhysicalDevice physicalDevice,
643 VkFormat format,
644 VkImageType type,
645 VkImageTiling tiling,
646 VkImageUsageFlags usage,
647 VkImageCreateFlags createFlags,
648 VkImageFormatProperties *pImageFormatProperties)
649 {
650 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
651
652 const VkPhysicalDeviceImageFormatInfo2 info = {
653 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
654 .pNext = NULL,
655 .format = format,
656 .type = type,
657 .tiling = tiling,
658 .usage = usage,
659 .flags = createFlags,
660 };
661
662 return get_image_format_properties(physical_device, &info, tiling,
663 pImageFormatProperties, NULL);
664 }
665
666 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)667 v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
668 const VkPhysicalDeviceImageFormatInfo2 *base_info,
669 VkImageFormatProperties2 *base_props)
670 {
671 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
672 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
673 const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info = NULL;
674 VkExternalImageFormatProperties *external_props = NULL;
675 UNUSED VkAndroidHardwareBufferUsageANDROID *android_usage = NULL;
676 VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
677 VkImageTiling tiling = base_info->tiling;
678
679 /* Extract input structs */
680 vk_foreach_struct_const(s, base_info->pNext) {
681 switch (s->sType) {
682 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
683 external_info = (const void *) s;
684 break;
685 case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
686 /* Do nothing, get_image_format_properties() below will handle it */;
687 break;
688 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT:
689 drm_format_mod_info = (const void *) s;
690 switch (drm_format_mod_info->drmFormatModifier) {
691 case DRM_FORMAT_MOD_LINEAR:
692 tiling = VK_IMAGE_TILING_LINEAR;
693 break;
694 case DRM_FORMAT_MOD_BROADCOM_UIF:
695 tiling = VK_IMAGE_TILING_OPTIMAL;
696 break;
697 default:
698 assert("Unknown DRM format modifier");
699 }
700 break;
701 default:
702 vk_debug_ignored_stype(s->sType);
703 break;
704 }
705 }
706
707 assert(tiling == VK_IMAGE_TILING_OPTIMAL ||
708 tiling == VK_IMAGE_TILING_LINEAR);
709
710 /* Extract output structs */
711 vk_foreach_struct(s, base_props->pNext) {
712 switch (s->sType) {
713 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
714 external_props = (void *) s;
715 break;
716 case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:
717 android_usage = (void *)s;
718 break;
719 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
720 ycbcr_props = (void *) s;
721 break;
722 default:
723 vk_debug_ignored_stype(s->sType);
724 break;
725 }
726 }
727
728 VkResult result =
729 get_image_format_properties(physical_device, base_info, tiling,
730 &base_props->imageFormatProperties,
731 ycbcr_props);
732 if (result != VK_SUCCESS)
733 goto done;
734
735 if (external_info && external_info->handleType != 0) {
736 switch (external_info->handleType) {
737 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
738 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
739 if (external_props)
740 external_props->externalMemoryProperties = prime_fd_props;
741 break;
742 #if DETECT_OS_ANDROID
743 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
744 if (external_props) {
745 external_props->externalMemoryProperties.exportFromImportedHandleTypes = 0;
746 external_props->externalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
747 external_props->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
748 }
749 break;
750 #endif
751 default:
752 result = VK_ERROR_FORMAT_NOT_SUPPORTED;
753 break;
754 }
755 }
756
757 if (android_usage) {
758 #if DETECT_OS_ANDROID
759 android_usage->androidHardwareBufferUsage =
760 vk_image_usage_to_ahb_usage(base_info->flags, base_info->usage);
761 #endif
762 }
763
764 done:
765 return result;
766 }
767
768 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkSampleCountFlagBits samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pPropertyCount,VkSparseImageFormatProperties * pProperties)769 v3dv_GetPhysicalDeviceSparseImageFormatProperties(
770 VkPhysicalDevice physicalDevice,
771 VkFormat format,
772 VkImageType type,
773 VkSampleCountFlagBits samples,
774 VkImageUsageFlags usage,
775 VkImageTiling tiling,
776 uint32_t *pPropertyCount,
777 VkSparseImageFormatProperties *pProperties)
778 {
779 *pPropertyCount = 0;
780 }
781
782 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)783 v3dv_GetPhysicalDeviceSparseImageFormatProperties2(
784 VkPhysicalDevice physicalDevice,
785 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
786 uint32_t *pPropertyCount,
787 VkSparseImageFormatProperties2 *pProperties)
788 {
789 *pPropertyCount = 0;
790 }
791
792 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)793 v3dv_GetPhysicalDeviceExternalBufferProperties(
794 VkPhysicalDevice physicalDevice,
795 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
796 VkExternalBufferProperties *pExternalBufferProperties)
797 {
798 switch (pExternalBufferInfo->handleType) {
799 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
800 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
801 pExternalBufferProperties->externalMemoryProperties = prime_fd_props;
802 return;
803 default: /* Unsupported */
804 pExternalBufferProperties->externalMemoryProperties =
805 (VkExternalMemoryProperties) {
806 .compatibleHandleTypes = pExternalBufferInfo->handleType,
807 };
808 break;
809 }
810 }
811