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 = v3dv_X(device, 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 = v3dv_X(device, get_format)(vk_format);
113 assert(format->plane_count == 1);
114 assert(v3dv_X(device, 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 v3dv_X(pdevice, 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 = v3dv_X(device, 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 = v3dv_X(pdevice, 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 = v3dv_X(physical_device, 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 switch (info->type) {
515 case VK_IMAGE_TYPE_1D:
516 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
517 pImageFormatProperties->maxExtent.height = 1;
518 pImageFormatProperties->maxExtent.depth = 1;
519 pImageFormatProperties->maxArrayLayers = V3D_MAX_ARRAY_LAYERS;
520 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
521 break;
522 case VK_IMAGE_TYPE_2D:
523 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
524 pImageFormatProperties->maxExtent.height = V3D_MAX_IMAGE_DIMENSION;
525 pImageFormatProperties->maxExtent.depth = 1;
526 pImageFormatProperties->maxArrayLayers =
527 v3dv_format->plane_count == 1 ? V3D_MAX_ARRAY_LAYERS : 1;
528 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
529 break;
530 case VK_IMAGE_TYPE_3D:
531 pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
532 pImageFormatProperties->maxExtent.height = V3D_MAX_IMAGE_DIMENSION;
533 pImageFormatProperties->maxExtent.depth = V3D_MAX_IMAGE_DIMENSION;
534 pImageFormatProperties->maxArrayLayers = 1;
535 pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
536 break;
537 default:
538 unreachable("bad VkImageType");
539 }
540
541 /* Our hw doesn't support 1D compressed textures. */
542 if (info->type == VK_IMAGE_TYPE_1D &&
543 vk_format_is_compressed(info->format)) {
544 goto unsupported;
545 }
546
547 /* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:
548 *
549 * sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the
550 * following conditions is true:
551 *
552 * - tiling is VK_IMAGE_TILING_LINEAR
553 * - type is not VK_IMAGE_TYPE_2D
554 * - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
555 * - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
556 * VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
557 * VkFormatProperties::optimalTilingFeatures returned by
558 * vkGetPhysicalDeviceFormatProperties is set.
559 */
560 pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
561 if (tiling != VK_IMAGE_TILING_LINEAR &&
562 info->type == VK_IMAGE_TYPE_2D &&
563 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
564 (format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT ||
565 format_feature_flags & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
566 pImageFormatProperties->sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
567 }
568
569 if (tiling == VK_IMAGE_TILING_LINEAR)
570 pImageFormatProperties->maxMipLevels = 1;
571
572 /* From the Vulkan 1.2 spec, section 12.3. Images, VkImageCreateInfo structure:
573 *
574 * "Images created with one of the formats that require a sampler Y′CBCR
575 * conversion, have further restrictions on their limits and
576 * capabilities compared to images created with other formats. Creation
577 * of images with a format requiring Y′CBCR conversion may not be
578 * supported unless other parameters meet all of the constraints:
579 *
580 * * imageType is VK_IMAGE_TYPE_2D
581 * * mipLevels is 1
582 * * arrayLayers is 1, unless the ycbcrImageArrays feature is enabled, or
583 * otherwise indicated by VkImageFormatProperties::maxArrayLayers, as
584 * returned by vkGetPhysicalDeviceImageFormatProperties
585 * * samples is VK_SAMPLE_COUNT_1_BIT
586 *
587 * Implementations may support additional limits and capabilities beyond
588 * those listed above."
589 *
590 * We don't provide such additional limits, so we set those limits, or just
591 * return unsupported.
592 */
593 if (vk_format_get_plane_count(info->format) > 1) {
594 if (info->type != VK_IMAGE_TYPE_2D)
595 goto unsupported;
596 pImageFormatProperties->maxMipLevels = 1;
597 pImageFormatProperties->maxArrayLayers = 1;
598 pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
599 }
600
601 pImageFormatProperties->maxResourceSize = 0xffffffff; /* 32-bit allocation */
602
603 if (pYcbcrImageFormatProperties) {
604 pYcbcrImageFormatProperties->combinedImageSamplerDescriptorCount =
605 vk_format_get_plane_count(info->format);
606 }
607
608 return VK_SUCCESS;
609
610 unsupported:
611 *pImageFormatProperties = (VkImageFormatProperties) {
612 .maxExtent = { 0, 0, 0 },
613 .maxMipLevels = 0,
614 .maxArrayLayers = 0,
615 .sampleCounts = 0,
616 .maxResourceSize = 0,
617 };
618
619 return VK_ERROR_FORMAT_NOT_SUPPORTED;
620 }
621
622 static const VkExternalMemoryProperties prime_fd_props = {
623 .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
624 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
625 .exportFromImportedHandleTypes =
626 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
627 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
628 .compatibleHandleTypes =
629 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
630 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
631 };
632
633 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags createFlags,VkImageFormatProperties * pImageFormatProperties)634 v3dv_GetPhysicalDeviceImageFormatProperties(
635 VkPhysicalDevice physicalDevice,
636 VkFormat format,
637 VkImageType type,
638 VkImageTiling tiling,
639 VkImageUsageFlags usage,
640 VkImageCreateFlags createFlags,
641 VkImageFormatProperties *pImageFormatProperties)
642 {
643 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
644
645 const VkPhysicalDeviceImageFormatInfo2 info = {
646 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
647 .pNext = NULL,
648 .format = format,
649 .type = type,
650 .tiling = tiling,
651 .usage = usage,
652 .flags = createFlags,
653 };
654
655 return get_image_format_properties(physical_device, &info, tiling,
656 pImageFormatProperties, NULL);
657 }
658
659 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)660 v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
661 const VkPhysicalDeviceImageFormatInfo2 *base_info,
662 VkImageFormatProperties2 *base_props)
663 {
664 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
665 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
666 const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info = NULL;
667 VkExternalImageFormatProperties *external_props = NULL;
668 UNUSED VkAndroidHardwareBufferUsageANDROID *android_usage = NULL;
669 VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
670 VkImageTiling tiling = base_info->tiling;
671
672 /* Extract input structs */
673 vk_foreach_struct_const(s, base_info->pNext) {
674 switch (s->sType) {
675 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
676 external_info = (const void *) s;
677 break;
678 case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
679 /* Do nothing, get_image_format_properties() below will handle it */;
680 break;
681 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT:
682 drm_format_mod_info = (const void *) s;
683 switch (drm_format_mod_info->drmFormatModifier) {
684 case DRM_FORMAT_MOD_LINEAR:
685 tiling = VK_IMAGE_TILING_LINEAR;
686 break;
687 case DRM_FORMAT_MOD_BROADCOM_UIF:
688 tiling = VK_IMAGE_TILING_OPTIMAL;
689 break;
690 default:
691 assert("Unknown DRM format modifier");
692 }
693 break;
694 default:
695 vk_debug_ignored_stype(s->sType);
696 break;
697 }
698 }
699
700 assert(tiling == VK_IMAGE_TILING_OPTIMAL ||
701 tiling == VK_IMAGE_TILING_LINEAR);
702
703 /* Extract output structs */
704 vk_foreach_struct(s, base_props->pNext) {
705 switch (s->sType) {
706 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
707 external_props = (void *) s;
708 break;
709 case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:
710 android_usage = (void *)s;
711 break;
712 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
713 ycbcr_props = (void *) s;
714 break;
715 default:
716 vk_debug_ignored_stype(s->sType);
717 break;
718 }
719 }
720
721 VkResult result =
722 get_image_format_properties(physical_device, base_info, tiling,
723 &base_props->imageFormatProperties,
724 ycbcr_props);
725 if (result != VK_SUCCESS)
726 goto done;
727
728 if (external_info && external_info->handleType != 0) {
729 switch (external_info->handleType) {
730 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
731 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
732 if (external_props)
733 external_props->externalMemoryProperties = prime_fd_props;
734 break;
735 #if DETECT_OS_ANDROID
736 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
737 if (external_props) {
738 external_props->externalMemoryProperties.exportFromImportedHandleTypes = 0;
739 external_props->externalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
740 external_props->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
741 }
742 break;
743 #endif
744 default:
745 result = VK_ERROR_FORMAT_NOT_SUPPORTED;
746 break;
747 }
748 }
749
750 if (android_usage) {
751 #if DETECT_OS_ANDROID
752 android_usage->androidHardwareBufferUsage =
753 vk_image_usage_to_ahb_usage(base_info->flags, base_info->usage);
754 #endif
755 }
756
757 done:
758 return result;
759 }
760
761 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkSampleCountFlagBits samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pPropertyCount,VkSparseImageFormatProperties * pProperties)762 v3dv_GetPhysicalDeviceSparseImageFormatProperties(
763 VkPhysicalDevice physicalDevice,
764 VkFormat format,
765 VkImageType type,
766 VkSampleCountFlagBits samples,
767 VkImageUsageFlags usage,
768 VkImageTiling tiling,
769 uint32_t *pPropertyCount,
770 VkSparseImageFormatProperties *pProperties)
771 {
772 *pPropertyCount = 0;
773 }
774
775 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)776 v3dv_GetPhysicalDeviceSparseImageFormatProperties2(
777 VkPhysicalDevice physicalDevice,
778 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
779 uint32_t *pPropertyCount,
780 VkSparseImageFormatProperties2 *pProperties)
781 {
782 *pPropertyCount = 0;
783 }
784
785 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)786 v3dv_GetPhysicalDeviceExternalBufferProperties(
787 VkPhysicalDevice physicalDevice,
788 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
789 VkExternalBufferProperties *pExternalBufferProperties)
790 {
791 switch (pExternalBufferInfo->handleType) {
792 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
793 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
794 pExternalBufferProperties->externalMemoryProperties = prime_fd_props;
795 return;
796 default: /* Unsupported */
797 pExternalBufferProperties->externalMemoryProperties =
798 (VkExternalMemoryProperties) {
799 .compatibleHandleTypes = pExternalBufferInfo->handleType,
800 };
801 break;
802 }
803 }
804