1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "tu_formats.h"
8
9 #include "fdl/fd6_format_table.h"
10 #include "common/freedreno_ubwc.h"
11
12 #include "vk_android.h"
13 #include "vk_enum_defines.h"
14 #include "vk_util.h"
15 #include "vk_acceleration_structure.h"
16 #include "drm-uapi/drm_fourcc.h"
17
18 #include "tu_android.h"
19 #include "tu_device.h"
20 #include "tu_image.h"
21
22 #include <vulkan/vulkan_android.h>
23
24 static bool
tu6_format_vtx_supported(enum pipe_format format)25 tu6_format_vtx_supported(enum pipe_format format)
26 {
27 return fd6_vertex_format(format) != FMT6_NONE;
28 }
29
30 struct tu_native_format
tu6_format_vtx(enum pipe_format format)31 tu6_format_vtx(enum pipe_format format)
32 {
33 struct tu_native_format fmt = {
34 .fmt = fd6_vertex_format(format),
35 .swap = fd6_vertex_swap(format),
36 };
37 assert(tu6_format_vtx_supported(format));
38 return fmt;
39 }
40
41 static bool
tu6_format_color_supported(enum pipe_format format)42 tu6_format_color_supported(enum pipe_format format)
43 {
44 return fd6_color_format(format, TILE6_LINEAR) != FMT6_NONE;
45 }
46
47 struct tu_native_format
tu6_format_color(enum pipe_format format,enum a6xx_tile_mode tile_mode,bool is_mutable)48 tu6_format_color(enum pipe_format format, enum a6xx_tile_mode tile_mode,
49 bool is_mutable)
50 {
51 struct tu_native_format fmt = {
52 .fmt = fd6_color_format(format, tile_mode),
53 .swap = fd6_color_swap(format, tile_mode, is_mutable),
54 };
55 assert(fmt.fmt != FMT6_NONE);
56 return fmt;
57 }
58
59 static bool
tu6_format_texture_supported(enum pipe_format format)60 tu6_format_texture_supported(enum pipe_format format)
61 {
62 return fd6_texture_format(format, TILE6_LINEAR, false) != FMT6_NONE;
63 }
64
65 struct tu_native_format
tu6_format_texture(enum pipe_format format,enum a6xx_tile_mode tile_mode,bool is_mutable)66 tu6_format_texture(enum pipe_format format, enum a6xx_tile_mode tile_mode,
67 bool is_mutable)
68 {
69 struct tu_native_format fmt = {
70 .fmt = fd6_texture_format(format, tile_mode, is_mutable),
71 .swap = fd6_texture_swap(format, tile_mode, is_mutable),
72 };
73 assert(fmt.fmt != FMT6_NONE);
74 return fmt;
75 }
76
77 static enum fd6_ubwc_compat_type
tu6_ubwc_compat_mode(const struct fd_dev_info * info,VkFormat format)78 tu6_ubwc_compat_mode(const struct fd_dev_info *info, VkFormat format)
79 {
80 return fd6_ubwc_compat_mode(info, vk_format_to_pipe_format(format));
81 }
82
83 bool
tu6_mutable_format_list_ubwc_compatible(const struct fd_dev_info * info,const VkImageFormatListCreateInfo * fmt_list)84 tu6_mutable_format_list_ubwc_compatible(const struct fd_dev_info *info,
85 const VkImageFormatListCreateInfo *fmt_list)
86 {
87 if (!fmt_list || !fmt_list->viewFormatCount)
88 return false;
89
90 /* We're only looking at format list cross compatibility here, check
91 * ubwc_possible() for the base "is the format UBWC-able at all?"
92 */
93 if (fmt_list->viewFormatCount == 1)
94 return true;
95
96 enum fd6_ubwc_compat_type type =
97 tu6_ubwc_compat_mode(info, fmt_list->pViewFormats[0]);
98 if (type == FD6_UBWC_UNKNOWN_COMPAT)
99 return false;
100
101 for (uint32_t i = 1; i < fmt_list->viewFormatCount; i++) {
102 if (tu6_ubwc_compat_mode(info, fmt_list->pViewFormats[i]) != type)
103 return false;
104 }
105
106 return true;
107 }
108
109 static void
tu_physical_device_get_format_properties(struct tu_physical_device * physical_device,VkFormat vk_format,VkFormatProperties3 * out_properties)110 tu_physical_device_get_format_properties(
111 struct tu_physical_device *physical_device,
112 VkFormat vk_format,
113 VkFormatProperties3 *out_properties)
114 {
115 VkFormatFeatureFlags2 linear = 0, optimal = 0, buffer = 0;
116 enum pipe_format format = vk_format_to_pipe_format(vk_format);
117 const struct util_format_description *desc = util_format_description(format);
118 const struct vk_format_ycbcr_info *ycbcr_info = vk_format_get_ycbcr_info(vk_format);
119
120 bool supported_vtx = tu6_format_vtx_supported(format);
121 bool supported_color = tu6_format_color_supported(format);
122 bool supported_tex = tu6_format_texture_supported(format);
123 bool is_npot = !util_is_power_of_two_or_zero(desc->block.bits);
124
125 if (format == PIPE_FORMAT_NONE ||
126 !(supported_vtx || supported_color || supported_tex)) {
127 goto end;
128 }
129
130 /* We don't support BufferToImage/ImageToBuffer for npot formats */
131 if (!is_npot)
132 buffer |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
133
134 if (supported_vtx)
135 buffer |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT;
136
137 if (supported_tex)
138 buffer |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT;
139
140 /* We don't support D24S8 because copying just one aspect would require a
141 * special codepath and that doesn't seem worth it.
142 */
143 if (!is_npot && vk_format != VK_FORMAT_D24_UNORM_S8_UINT) {
144 optimal |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
145 }
146
147 /* Don't support anything but texel buffers for non-power-of-two formats
148 * with 3 components. We'd need several workarounds for copying and
149 * clearing them because they're not renderable.
150 */
151 if (supported_tex && !is_npot) {
152 optimal |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
153 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT |
154 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
155 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
156
157 if (ycbcr_info) {
158 /* This is supported on all YCbCr formats */
159 optimal |= VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT;
160
161 if (ycbcr_info->n_planes > 1) {
162 optimal |= VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT |
163 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
164 if (physical_device->info->a6xx.has_separate_chroma_filter)
165 optimal |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT;
166 }
167 } else {
168 /* BLIT_SRC_BIT isn't allowed for YCbCr formats */
169 optimal |= VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
170 }
171
172 if (!vk_format_is_int(vk_format)) {
173 optimal |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
174
175 if (physical_device->vk.supported_extensions.EXT_filter_cubic)
176 optimal |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT;
177 }
178
179 /* We sample on the CPU so we can technically support anything as long
180 * as it's floating point, but this restricts it to "reasonable" formats
181 * to use, which means two channels and not something weird like
182 * luminance-alpha.
183 */
184 if (vk_format_is_float(vk_format) && desc->nr_channels == 2 &&
185 desc->swizzle[0] == PIPE_SWIZZLE_X &&
186 desc->swizzle[1] == PIPE_SWIZZLE_Y) {
187 optimal |= VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT;
188 }
189 }
190
191 if (supported_color) {
192 assert(supported_tex);
193 optimal |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
194 VK_FORMAT_FEATURE_2_BLIT_DST_BIT |
195 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
196 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
197 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
198
199 buffer |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT |
200 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
201 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
202
203 /* TODO: The blob also exposes these for R16G16_UINT/R16G16_SINT/
204 * R32G32_SFLOAT/R32G32B32A32_SFLOAT, but we don't have any tests for those.
205 * R32_SFLOAT is also included here by the blob, but that requires
206 * implementing VK_EXT_shader_atomic_float.
207 */
208 if (vk_format == VK_FORMAT_R32_UINT || vk_format == VK_FORMAT_R32_SINT) {
209 optimal |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
210 buffer |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
211 }
212
213 if (!vk_format_is_int(vk_format))
214 optimal |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
215 }
216
217 /* All our depth formats support shadow comparisons. */
218 if (vk_format_has_depth(vk_format) && (optimal & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
219 optimal |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
220 }
221
222 /* We don't support writing into VK_FORMAT_*_PACK16 images/buffers */
223 if (desc->nr_channels > 2 && desc->block.bits == 16) {
224 buffer &= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT;
225 optimal &= ~(VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
226 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT);
227 }
228
229 /* For the most part, we can do anything with a linear image that we could
230 * do with a tiled image. However, we can't support sysmem rendering with a
231 * linear depth texture, because we don't know if there's a bit to control
232 * the tiling of the depth buffer in BYPASS mode, and the blob also
233 * disables linear depth rendering, so there's no way to discover it. We
234 * also can't force GMEM mode, because there are other situations where we
235 * have to use sysmem rendering. So follow the blob here, and only enable
236 * DEPTH_STENCIL_ATTACHMENT_BIT for the optimal features.
237 */
238 linear = optimal;
239 if (tu6_pipe2depth(vk_format) != DEPTH6_NONE)
240 optimal |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
241
242 if (!tiling_possible(vk_format) &&
243 /* We don't actually support tiling for this format, but we need to
244 * fake it as it's required by VK_KHR_sampler_ycbcr_conversion.
245 */
246 vk_format != VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) {
247 optimal = 0;
248 }
249
250 /* Disable buffer texturing of subsampled (422) and planar YUV textures,
251 * as well as for depth/stencil formats. The subsampling requirement comes
252 * from "If format is a block-compressed format, then bufferFeatures must
253 * not support any features for the format" plus the specification of
254 * subsampled as 2x1 compressed block format. I couldn't find the citation
255 * for planar, but 1D access of planar YUV would be really silly.
256 *
257 * From the Vulkan 1.3.205 spec, section 19.3 "43.3. Required Format Support":
258 *
259 * Mandatory format support: depth/stencil with VkImageType
260 * VK_IMAGE_TYPE_2D
261 * [...]
262 * bufferFeatures must not support any features for these formats
263 */
264 if (ycbcr_info || vk_format_is_depth_or_stencil(vk_format))
265 buffer = 0;
266
267 /* D32_SFLOAT_S8_UINT is tiled as two images, so no linear format */
268 if (vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT)
269 linear = 0;
270
271 if (vk_format == VK_FORMAT_R8_UINT)
272 optimal |= VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
273
274 if (vk_acceleration_struct_vtx_format_supported(vk_format))
275 buffer |= VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR;
276
277 end:
278 out_properties->linearTilingFeatures = linear;
279 out_properties->optimalTilingFeatures = optimal;
280 out_properties->bufferFeatures = buffer;
281 }
282
283 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)284 tu_GetPhysicalDeviceFormatProperties2(
285 VkPhysicalDevice physicalDevice,
286 VkFormat format,
287 VkFormatProperties2 *pFormatProperties)
288 {
289 VK_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
290
291 VkFormatProperties3 local_props3;
292 VkFormatProperties3 *props3 =
293 vk_find_struct(pFormatProperties->pNext, FORMAT_PROPERTIES_3);
294 if (!props3)
295 props3 = &local_props3;
296
297 tu_physical_device_get_format_properties(
298 physical_device, format, props3);
299
300 pFormatProperties->formatProperties = (VkFormatProperties) {
301 .linearTilingFeatures =
302 vk_format_features2_to_features(props3->linearTilingFeatures),
303 .optimalTilingFeatures =
304 vk_format_features2_to_features(props3->optimalTilingFeatures),
305 .bufferFeatures =
306 vk_format_features2_to_features(props3->bufferFeatures),
307 };
308
309 VkDrmFormatModifierPropertiesListEXT *list =
310 vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
311 if (list) {
312 VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
313 list->pDrmFormatModifierProperties,
314 &list->drmFormatModifierCount);
315
316 if (pFormatProperties->formatProperties.linearTilingFeatures) {
317 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mod_props) {
318 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
319 mod_props->drmFormatModifierPlaneCount = tu6_plane_count(format);
320 mod_props->drmFormatModifierTilingFeatures =
321 pFormatProperties->formatProperties.linearTilingFeatures;
322 }
323 }
324
325 /* note: ubwc_possible() argument values to be ignored except for format */
326 if (pFormatProperties->formatProperties.optimalTilingFeatures &&
327 tiling_possible(format) &&
328 ubwc_possible(NULL, format, VK_IMAGE_TYPE_2D, 0, 0,
329 physical_device->info, VK_SAMPLE_COUNT_1_BIT, 1,
330 false)) {
331 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mod_props) {
332 mod_props->drmFormatModifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
333 mod_props->drmFormatModifierPlaneCount = tu6_plane_count(format);
334 mod_props->drmFormatModifierTilingFeatures =
335 pFormatProperties->formatProperties.optimalTilingFeatures;
336 }
337 }
338 }
339 }
340
341 static VkResult
tu_image_unsupported_format(VkImageFormatProperties * pImageFormatProperties)342 tu_image_unsupported_format(VkImageFormatProperties *pImageFormatProperties)
343 {
344 *pImageFormatProperties = (VkImageFormatProperties) {
345 .maxExtent = { 0, 0, 0 },
346 .maxMipLevels = 0,
347 .maxArrayLayers = 0,
348 .sampleCounts = 0,
349 .maxResourceSize = 0,
350 };
351
352 return VK_ERROR_FORMAT_NOT_SUPPORTED;
353 }
354
355 static VkResult
tu_get_image_format_properties(struct tu_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties * pImageFormatProperties,VkFormatFeatureFlags * p_feature_flags)356 tu_get_image_format_properties(
357 struct tu_physical_device *physical_device,
358 const VkPhysicalDeviceImageFormatInfo2 *info,
359 VkImageFormatProperties *pImageFormatProperties,
360 VkFormatFeatureFlags *p_feature_flags)
361 {
362 VkFormatProperties3 format_props;
363 VkFormatFeatureFlags format_feature_flags;
364 VkExtent3D maxExtent;
365 uint32_t maxMipLevels;
366 uint32_t maxArraySize;
367 BITMASK_ENUM(VkSampleCountFlagBits) sampleCounts = VK_SAMPLE_COUNT_1_BIT;
368
369 tu_physical_device_get_format_properties(physical_device, info->format,
370 &format_props);
371
372 switch (info->tiling) {
373 case VK_IMAGE_TILING_LINEAR:
374 format_feature_flags = format_props.linearTilingFeatures;
375 break;
376
377 case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: {
378 const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_info =
379 vk_find_struct_const(info->pNext, PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT);
380
381 /* Subsampled format isn't stable yet, so don't allow
382 * importing/exporting with modifiers yet.
383 */
384 if (info->flags & VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT)
385 return VK_ERROR_FORMAT_NOT_SUPPORTED;
386
387 switch (drm_info->drmFormatModifier) {
388 case DRM_FORMAT_MOD_QCOM_COMPRESSED:
389 /* falling back to linear/non-UBWC isn't possible with explicit modifier */
390
391 /* formats which don't support tiling */
392 if (!format_props.optimalTilingFeatures ||
393 !tiling_possible(info->format))
394 return VK_ERROR_FORMAT_NOT_SUPPORTED;
395
396 if (info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
397 const VkImageFormatListCreateInfo *format_list =
398 vk_find_struct_const(info->pNext,
399 IMAGE_FORMAT_LIST_CREATE_INFO);
400 if (!tu6_mutable_format_list_ubwc_compatible(physical_device->info,
401 format_list))
402 return VK_ERROR_FORMAT_NOT_SUPPORTED;
403 }
404
405 if (!ubwc_possible(NULL, info->format, info->type, info->usage,
406 info->usage, physical_device->info, sampleCounts,
407 1, false)) {
408 return VK_ERROR_FORMAT_NOT_SUPPORTED;
409 }
410
411 format_feature_flags = format_props.optimalTilingFeatures;
412 break;
413 case DRM_FORMAT_MOD_LINEAR:
414 format_feature_flags = format_props.linearTilingFeatures;
415 break;
416 default:
417 return VK_ERROR_FORMAT_NOT_SUPPORTED;
418 }
419 } break;
420 case VK_IMAGE_TILING_OPTIMAL:
421 format_feature_flags = format_props.optimalTilingFeatures;
422 break;
423 default:
424 unreachable("bad VkPhysicalDeviceImageFormatInfo2");
425 }
426
427 if (format_feature_flags == 0)
428 return tu_image_unsupported_format(pImageFormatProperties);
429
430 if (info->type != VK_IMAGE_TYPE_2D &&
431 vk_format_is_depth_or_stencil(info->format))
432 return tu_image_unsupported_format(pImageFormatProperties);
433
434 switch (info->type) {
435 default:
436 unreachable("bad vkimage type\n");
437 case VK_IMAGE_TYPE_1D:
438 maxExtent.width = 16384;
439 maxExtent.height = 1;
440 maxExtent.depth = 1;
441 maxMipLevels = 15; /* log2(maxWidth) + 1 */
442 maxArraySize = 2048;
443 break;
444 case VK_IMAGE_TYPE_2D:
445 maxExtent.width = 16384;
446 maxExtent.height = 16384;
447 maxExtent.depth = 1;
448 maxMipLevels = 15; /* log2(maxWidth) + 1 */
449 maxArraySize = 2048;
450 break;
451 case VK_IMAGE_TYPE_3D:
452 maxExtent.width = 2048;
453 maxExtent.height = 2048;
454 maxExtent.depth = 2048;
455 maxMipLevels = 12; /* log2(maxWidth) + 1 */
456 maxArraySize = 1;
457 break;
458 }
459
460 if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
461 info->type == VK_IMAGE_TYPE_2D &&
462 (format_feature_flags &
463 (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
464 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
465 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
466 !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
467 sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
468
469 /* a7xx supports 8x MSAA except for 128-bit formats. */
470 if (physical_device->info->chip >= A7XX &&
471 vk_format_get_blocksizebits(info->format) <= 64)
472 sampleCounts |= VK_SAMPLE_COUNT_8_BIT;
473 }
474
475 /* From the Vulkan 1.3.206 spec:
476 *
477 * "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT specifies that the image can be
478 * created with usage flags that are not supported for the format the image
479 * is created with but are supported for at least one format a VkImageView
480 * created from the image can have."
481 *
482 * This means we should relax checks that only depend on the
483 * format_feature_flags, to allow the user to create images that may be
484 * e.g. reinterpreted as storage when the original format doesn't allow it.
485 * The user will have to check against the format features anyway.
486 * Otherwise we'd unnecessarily disallow it.
487 */
488
489 VkImageUsageFlags image_usage = info->usage;
490 if (info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
491 image_usage = 0;
492
493 if (image_usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
494 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
495 return tu_image_unsupported_format(pImageFormatProperties);
496 }
497 }
498
499 if (image_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
500 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT)) {
501 return tu_image_unsupported_format(pImageFormatProperties);
502 }
503 }
504
505 if (image_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
506 if (!(format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) {
507 return tu_image_unsupported_format(pImageFormatProperties);
508 }
509 }
510
511 if (image_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
512 if (!(format_feature_flags &
513 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
514 return tu_image_unsupported_format(pImageFormatProperties);
515 }
516 }
517
518 if (image_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
519 if (!(format_feature_flags &
520 (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
521 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT))) {
522 return tu_image_unsupported_format(pImageFormatProperties);
523 }
524 }
525
526 if (image_usage &
527 VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR) {
528 if (!(format_feature_flags &
529 VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)) {
530 return tu_image_unsupported_format(pImageFormatProperties);
531 }
532 }
533
534 *pImageFormatProperties = (VkImageFormatProperties) {
535 .maxExtent = maxExtent,
536 .maxMipLevels = maxMipLevels,
537 .maxArrayLayers = maxArraySize,
538 .sampleCounts = sampleCounts,
539
540 /* FINISHME: Accurately calculate
541 * VkImageFormatProperties::maxResourceSize.
542 */
543 .maxResourceSize = UINT32_MAX,
544 };
545
546 if (p_feature_flags)
547 *p_feature_flags = format_feature_flags;
548
549 return VK_SUCCESS;
550 }
551
552 static VkResult
tu_get_external_image_format_properties(const struct tu_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo,VkExternalMemoryHandleTypeFlagBits handleType,VkExternalImageFormatProperties * external_properties)553 tu_get_external_image_format_properties(
554 const struct tu_physical_device *physical_device,
555 const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
556 VkExternalMemoryHandleTypeFlagBits handleType,
557 VkExternalImageFormatProperties *external_properties)
558 {
559 BITMASK_ENUM(VkExternalMemoryFeatureFlagBits) flags = 0;
560 VkExternalMemoryHandleTypeFlags export_flags = 0;
561 VkExternalMemoryHandleTypeFlags compat_flags = 0;
562
563 /* From the Vulkan 1.1.98 spec:
564 *
565 * If handleType is not compatible with the format, type, tiling,
566 * usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,
567 * then vkGetPhysicalDeviceImageFormatProperties2 returns
568 * VK_ERROR_FORMAT_NOT_SUPPORTED.
569 */
570
571 switch (handleType) {
572 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
573 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
574 switch (pImageFormatInfo->type) {
575 case VK_IMAGE_TYPE_2D:
576 flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
577 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
578 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
579 compat_flags = export_flags =
580 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
581 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
582 break;
583 default:
584 return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
585 "VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",
586 handleType, pImageFormatInfo->type);
587 }
588 break;
589 #if DETECT_OS_ANDROID
590 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
591 flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
592 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
593 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
594 compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
595 break;
596 #endif
597 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
598 flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
599 compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
600 break;
601 default:
602 return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
603 "VkExternalMemoryTypeFlagBits(0x%x) unsupported",
604 handleType);
605 }
606
607 if (external_properties) {
608 external_properties->externalMemoryProperties =
609 (VkExternalMemoryProperties) {
610 .externalMemoryFeatures = flags,
611 .exportFromImportedHandleTypes = export_flags,
612 .compatibleHandleTypes = compat_flags,
613 };
614 }
615
616 return VK_SUCCESS;
617 }
618
619 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)620 tu_GetPhysicalDeviceImageFormatProperties2(
621 VkPhysicalDevice physicalDevice,
622 const VkPhysicalDeviceImageFormatInfo2 *base_info,
623 VkImageFormatProperties2 *base_props)
624 {
625 VK_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
626 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
627 const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL;
628 VkExternalImageFormatProperties *external_props = NULL;
629 VkAndroidHardwareBufferUsageANDROID *android_usage = NULL;
630 VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL;
631 VkFormatFeatureFlags format_feature_flags;
632 VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
633 VkHostImageCopyDevicePerformanceQueryEXT *hic_props = NULL;
634 VkResult result;
635
636 result = tu_get_image_format_properties(physical_device,
637 base_info, &base_props->imageFormatProperties, &format_feature_flags);
638 if (result != VK_SUCCESS)
639 return result;
640
641 /* Extract input structs */
642 vk_foreach_struct_const(s, base_info->pNext)
643 {
644 switch (s->sType) {
645 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
646 external_info = (const VkPhysicalDeviceExternalImageFormatInfo *) s;
647 break;
648 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT:
649 image_view_info = (const VkPhysicalDeviceImageViewImageFormatInfoEXT *) s;
650 break;
651 default:
652 break;
653 }
654 }
655
656 /* Extract output structs */
657 vk_foreach_struct(s, base_props->pNext)
658 {
659 switch (s->sType) {
660 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
661 external_props = (VkExternalImageFormatProperties *) s;
662 break;
663 case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:
664 android_usage = (VkAndroidHardwareBufferUsageANDROID *) s;
665 break;
666 case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT:
667 cubic_props = (VkFilterCubicImageViewImageFormatPropertiesEXT *) s;
668 break;
669 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
670 ycbcr_props = (VkSamplerYcbcrConversionImageFormatProperties *) s;
671 break;
672 case VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT:
673 hic_props = (VkHostImageCopyDevicePerformanceQueryEXT *) s;
674 break;
675 default:
676 break;
677 }
678 }
679
680 /* From the Vulkan 1.0.42 spec:
681 *
682 * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
683 * behave as if VkPhysicalDeviceExternalImageFormatInfo was not
684 * present and VkExternalImageFormatProperties will be ignored.
685 */
686 if (external_info && external_info->handleType != 0) {
687 result = tu_get_external_image_format_properties(
688 physical_device, base_info, external_info->handleType,
689 external_props);
690 if (result != VK_SUCCESS)
691 goto fail;
692 }
693
694 if (cubic_props) {
695 /* note: blob only allows cubic filtering for 2D and 2D array views
696 * its likely we can enable it for 1D and CUBE, needs testing however
697 */
698 if ((image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D ||
699 image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) &&
700 (format_feature_flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
701 cubic_props->filterCubic = true;
702 cubic_props->filterCubicMinmax = true;
703 } else {
704 cubic_props->filterCubic = false;
705 cubic_props->filterCubicMinmax = false;
706 }
707 }
708
709 if (android_usage) {
710 /* Don't expect gralloc to be able to allocate anything other than 3D: */
711 if (base_info->type != VK_IMAGE_TYPE_2D) {
712 result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
713 "type (%u) unsupported for AHB", base_info->type);
714 goto fail;
715 }
716 VkImageFormatProperties *props = &base_props->imageFormatProperties;
717 if (!(props->sampleCounts & VK_SAMPLE_COUNT_1_BIT)) {
718 result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
719 "sampleCounts (%x) unsupported for AHB", props->sampleCounts);
720 goto fail;
721 }
722 android_usage->androidHardwareBufferUsage =
723 vk_image_usage_to_ahb_usage(base_info->flags, base_info->usage);
724 uint32_t format = vk_image_format_to_ahb_format(base_info->format);
725 if (!format) {
726 result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
727 "format (%u) unsupported for AHB", base_info->format);
728 goto fail;
729 }
730 /* We can't advertise support for anything that gralloc cannot allocate
731 * so we are stuck without any better option than attempting a test
732 * allocation:
733 */
734 if (!vk_ahb_probe_format(base_info->format, base_info->flags, base_info->usage)) {
735 result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
736 "format (%x) with flags (%x) and usage (%x) unsupported for AHB",
737 base_info->format, base_info->flags, base_info->usage);
738 goto fail;
739 }
740
741 /* AHBs with mipmap usage will ignore this property */
742 props->maxMipLevels = 1;
743 props->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
744 }
745
746 if (ycbcr_props)
747 ycbcr_props->combinedImageSamplerDescriptorCount = 1;
748
749 if (hic_props) {
750 /* This should match tu_image_init() as much as possible given the
751 * information we have here. We are conservative and only return true if
752 * we know that UBWC would never be enabled and copying the tiled image
753 * is possible so we wouldn't have to fall back to linear. There are no
754 * cases where we modify the layout for HIC but still have optimal
755 * access, so we return the same value for both.
756 *
757 * ubwc_possible() returns false for block-compressed formats, which
758 * satisfies the spec requirement that:
759 *
760 * If VkPhysicalDeviceImageFormatInfo2::format is a block-compressed
761 * format and vkGetPhysicalDeviceImageFormatProperties2 returns
762 * VK_SUCCESS, the implementation must return VK_TRUE in
763 * optimalDeviceAccess.
764 */
765 hic_props->optimalDeviceAccess = hic_props->identicalMemoryLayout =
766 base_info->tiling == VK_IMAGE_TILING_LINEAR ||
767 base_info->type == VK_IMAGE_TYPE_1D ||
768 !tiling_possible(base_info->format) ||
769 (base_info->usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT) ||
770 /* If UBWC is impossible, tiling is possible, but it's a swapped
771 * format, we'd hit the force_linear_tile fallback.
772 */
773 (fd6_color_swap(vk_format_to_pipe_format(base_info->format),
774 TILE6_LINEAR, false) == WZYX &&
775 !ubwc_possible(NULL, base_info->format, base_info->type,
776 (base_info->usage & ~VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT),
777 (base_info->usage & ~VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT),
778 physical_device->info, VK_SAMPLE_COUNT_1_BIT, 1,
779 physical_device->info->a6xx.has_z24uint_s8uint));
780 }
781
782 return VK_SUCCESS;
783
784 fail:
785 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
786 /* From the Vulkan 1.0.42 spec:
787 *
788 * If the combination of parameters to
789 * vkGetPhysicalDeviceImageFormatProperties2 is not supported by
790 * the implementation for use in vkCreateImage, then all members of
791 * imageFormatProperties will be filled with zero.
792 */
793 base_props->imageFormatProperties = (VkImageFormatProperties) {};
794 }
795
796 return result;
797 }
798
799 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)800 tu_GetPhysicalDeviceSparseImageFormatProperties2(
801 VkPhysicalDevice physicalDevice,
802 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
803 uint32_t *pPropertyCount,
804 VkSparseImageFormatProperties2 *pProperties)
805 {
806 /* Sparse images are not yet supported. */
807 *pPropertyCount = 0;
808 }
809