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