xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/lavapipe/lvp_formats.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2019 Red Hat.
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 "lvp_private.h"
25 #include "util/detect.h"
26 #include "pipe/p_defines.h"
27 #include "util/format/u_format.h"
28 #include "util/u_math.h"
29 #include "vk_util.h"
30 #include "vk_enum_defines.h"
31 
lvp_is_filter_minmax_format_supported(VkFormat format)32 static bool lvp_is_filter_minmax_format_supported(VkFormat format)
33 {
34    /* From the Vulkan spec 1.1.71:
35     *
36     * "The following formats must support the
37     *  VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT feature with
38     *  VK_IMAGE_TILING_OPTIMAL, if they support
39     *  VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT."
40     */
41    /* TODO: enable more formats. */
42    switch (format) {
43    case VK_FORMAT_R8_UNORM:
44    case VK_FORMAT_R8_SNORM:
45    case VK_FORMAT_R16_UNORM:
46    case VK_FORMAT_R16_SNORM:
47    case VK_FORMAT_R16_SFLOAT:
48    case VK_FORMAT_R32_SFLOAT:
49    case VK_FORMAT_D16_UNORM:
50    case VK_FORMAT_X8_D24_UNORM_PACK32:
51    case VK_FORMAT_D32_SFLOAT:
52    case VK_FORMAT_D16_UNORM_S8_UINT:
53    case VK_FORMAT_D24_UNORM_S8_UINT:
54    case VK_FORMAT_D32_SFLOAT_S8_UINT:
55       return true;
56    default:
57       return false;
58    }
59 }
60 
61 
62 static void
lvp_physical_device_get_format_properties(struct lvp_physical_device * physical_device,VkFormat format,VkFormatProperties3 * out_properties)63 lvp_physical_device_get_format_properties(struct lvp_physical_device *physical_device,
64                                           VkFormat format,
65                                           VkFormatProperties3 *out_properties)
66 {
67    const enum pipe_format pformat = lvp_vk_format_to_pipe_format(format);
68    struct pipe_screen *pscreen = physical_device->pscreen;
69    VkFormatFeatureFlags2 features = 0, buffer_features = 0;
70 
71    if (pformat == PIPE_FORMAT_NONE) {
72      out_properties->linearTilingFeatures = 0;
73      out_properties->optimalTilingFeatures = 0;
74      out_properties->bufferFeatures = 0;
75      return;
76    }
77 
78    if (pscreen->is_format_supported(pscreen, pformat, PIPE_TEXTURE_2D, 0, 0,
79                                     PIPE_BIND_DEPTH_STENCIL)) {
80       out_properties->linearTilingFeatures = 0;
81       out_properties->optimalTilingFeatures =
82          (VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT |
83           VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
84           VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
85           VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT |
86           VK_FORMAT_FEATURE_2_BLIT_SRC_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT |
87           VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT |
88           VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
89 
90       if (lvp_is_filter_minmax_format_supported(format))
91          out_properties->optimalTilingFeatures |=
92             VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
93       out_properties->bufferFeatures = 0;
94       return;
95    }
96 
97    if (util_format_is_compressed(pformat)) {
98       if (pscreen->is_format_supported(pscreen, pformat, PIPE_TEXTURE_2D, 0, 0,
99                                        PIPE_BIND_SAMPLER_VIEW)) {
100          features |= (VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
101                       VK_FORMAT_FEATURE_2_BLIT_SRC_BIT |
102                       VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
103                       VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT |
104                       VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
105                       VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT);
106       }
107       out_properties->linearTilingFeatures = features;
108       out_properties->optimalTilingFeatures = features;
109       out_properties->bufferFeatures = buffer_features;
110       return;
111    }
112 
113    if (!util_format_is_srgb(pformat) &&
114        pscreen->is_format_supported(pscreen, pformat, PIPE_BUFFER, 0, 0,
115                                     PIPE_BIND_VERTEX_BUFFER)) {
116       buffer_features |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT;
117    }
118 
119    if (pscreen->is_format_supported(pscreen, pformat, PIPE_BUFFER, 0, 0,
120                                     PIPE_BIND_CONSTANT_BUFFER)) {
121       buffer_features |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT;
122    }
123 
124    if (pscreen->is_format_supported(pscreen, pformat, PIPE_BUFFER, 0, 0,
125                                     PIPE_BIND_SHADER_IMAGE)) {
126       buffer_features |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT |
127                          VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
128                          VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
129    }
130 
131    const struct vk_format_ycbcr_info *ycbcr_info =
132          vk_format_get_ycbcr_info(format);
133    if (pscreen->is_format_supported(pscreen, pformat, PIPE_TEXTURE_2D, 0, 0,
134                                     PIPE_BIND_SAMPLER_VIEW) || ycbcr_info) {
135       features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT;
136       if (util_format_has_depth(util_format_description(pformat)))
137          features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
138       if (!util_format_is_pure_integer(pformat))
139          features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
140       if (lvp_is_filter_minmax_format_supported(format))
141          features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
142       if (ycbcr_info) {
143          if (ycbcr_info->n_planes > 1)
144             features |= VK_FORMAT_FEATURE_DISJOINT_BIT;
145          else
146             features |= VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT;
147 
148          for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
149             const struct vk_format_ycbcr_plane *plane_info = &ycbcr_info->planes[plane];
150             if (plane_info->denominator_scales[0] > 1 ||
151                 plane_info->denominator_scales[1] > 1)
152                features |= VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT;
153          }
154 
155          /* The subsampled formats have no support for linear filters. */
156          const struct util_format_description *desc = util_format_description(pformat);
157          if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED)
158             features |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
159       }
160    }
161 
162    if (pscreen->is_format_supported(pscreen, pformat, PIPE_TEXTURE_2D, 0, 0,
163                                     PIPE_BIND_RENDER_TARGET)) {
164       features |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT;
165       if (!util_format_is_pure_integer(pformat) &&
166           !(util_format_is_snorm(pformat) && !physical_device->snorm_blend))
167          features |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
168    }
169 
170    if (pscreen->is_format_supported(pscreen, pformat, PIPE_TEXTURE_2D, 0, 0,
171                                     PIPE_BIND_SHADER_IMAGE)) {
172       features |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
173                   VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
174                   VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
175    }
176 
177    if (pformat == PIPE_FORMAT_R32_UINT ||
178        pformat == PIPE_FORMAT_R32_SINT ||
179        pformat == PIPE_FORMAT_R32_FLOAT) {
180       features |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
181       buffer_features |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
182    } else if (pformat == PIPE_FORMAT_R11G11B10_FLOAT ||
183               pformat == PIPE_FORMAT_R9G9B9E5_FLOAT) {
184       features |= VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
185    }
186 
187    if (features && buffer_features != VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT) {
188       features |= (VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
189                    VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT);
190    }
191    if (pformat == PIPE_FORMAT_B5G6R5_UNORM) {
192       features |= (VK_FORMAT_FEATURE_2_BLIT_SRC_BIT |
193                    VK_FORMAT_FEATURE_2_BLIT_DST_BIT);
194    }
195    if ((pformat != PIPE_FORMAT_R9G9B9E5_FLOAT) &&
196        util_format_get_nr_components(pformat) != 3 &&
197        !util_format_is_subsampled_422(pformat) &&
198        !util_format_is_yuv(pformat) &&
199        pformat != PIPE_FORMAT_G8_B8R8_420_UNORM &&
200        pformat != PIPE_FORMAT_G8_B8_R8_420_UNORM &&
201        pformat != PIPE_FORMAT_R10G10B10A2_SNORM &&
202        pformat != PIPE_FORMAT_B10G10R10A2_SNORM &&
203        pformat != PIPE_FORMAT_B10G10R10A2_UNORM) {
204       features |= (VK_FORMAT_FEATURE_2_BLIT_SRC_BIT |
205                    VK_FORMAT_FEATURE_2_BLIT_DST_BIT);
206    }
207 
208    switch (format) {
209    case VK_FORMAT_R32G32_SFLOAT:
210    case VK_FORMAT_R32G32B32_SFLOAT:
211    case VK_FORMAT_R32G32B32A32_SFLOAT:
212    case VK_FORMAT_R16G16_SFLOAT:
213    case VK_FORMAT_R16G16B16_SFLOAT:
214    case VK_FORMAT_R16G16B16A16_SFLOAT:
215    case VK_FORMAT_R16G16_SNORM:
216    case VK_FORMAT_R16G16_UNORM:
217    case VK_FORMAT_R16G16B16A16_SNORM:
218    case VK_FORMAT_R16G16B16A16_UNORM:
219    case VK_FORMAT_R8G8_SNORM:
220    case VK_FORMAT_R8G8_UNORM:
221    case VK_FORMAT_R8G8B8A8_SNORM:
222    case VK_FORMAT_R8G8B8A8_UNORM:
223    case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
224       buffer_features |= VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR;
225       break;
226    default:
227       break;
228    }
229 
230    out_properties->linearTilingFeatures = features;
231    out_properties->optimalTilingFeatures = features;
232    out_properties->bufferFeatures = buffer_features;
233    if (out_properties->linearTilingFeatures)
234       out_properties->linearTilingFeatures |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
235    if (out_properties->optimalTilingFeatures)
236       out_properties->optimalTilingFeatures |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
237 }
238 
239 
lvp_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)240 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFormatProperties2(
241         VkPhysicalDevice                            physicalDevice,
242         VkFormat                                    format,
243         VkFormatProperties2*                        pFormatProperties)
244 {
245    LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
246 
247    VkFormatProperties3 format_props;
248    lvp_physical_device_get_format_properties(physical_device,
249                                              format,
250                                              &format_props);
251    pFormatProperties->formatProperties.linearTilingFeatures = vk_format_features2_to_features(format_props.linearTilingFeatures);
252    pFormatProperties->formatProperties.optimalTilingFeatures = vk_format_features2_to_features(format_props.optimalTilingFeatures);
253    pFormatProperties->formatProperties.bufferFeatures = vk_format_features2_to_features(format_props.bufferFeatures);
254    VkFormatProperties3 *prop3 = (void*)vk_find_struct_const(pFormatProperties->pNext, FORMAT_PROPERTIES_3);
255    if (prop3) {
256       prop3->linearTilingFeatures = format_props.linearTilingFeatures;
257       prop3->optimalTilingFeatures = format_props.optimalTilingFeatures;
258       prop3->bufferFeatures = format_props.bufferFeatures;
259    }
260    VkSubpassResolvePerformanceQueryEXT *perf = (void*)vk_find_struct_const(pFormatProperties->pNext, SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT);
261    if (perf)
262       perf->optimal = VK_FALSE;
263 
264 #if DETECT_OS_LINUX
265    VkDrmFormatModifierPropertiesListEXT *modlist = (void*)vk_find_struct_const(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
266    if (modlist) {
267       modlist->drmFormatModifierCount = 0;
268       if (pFormatProperties->formatProperties.optimalTilingFeatures) {
269          modlist->drmFormatModifierCount = 1;
270          VkDrmFormatModifierPropertiesEXT *mods = &modlist->pDrmFormatModifierProperties[0];
271          if (mods) {
272             mods->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
273             mods->drmFormatModifierPlaneCount = util_format_get_num_planes(lvp_vk_format_to_pipe_format(format));
274             mods->drmFormatModifierTilingFeatures = pFormatProperties->formatProperties.optimalTilingFeatures;
275          }
276       }
277    }
278 #endif
279 }
280 
281 VKAPI_ATTR VkResult VKAPI_CALL
lvp_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device,VkImage _image,VkImageDrmFormatModifierPropertiesEXT * pProperties)282 lvp_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device, VkImage _image,
283                                            VkImageDrmFormatModifierPropertiesEXT *pProperties)
284 {
285 #if DETECT_OS_LINUX
286    pProperties->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
287    return VK_SUCCESS;
288 #else
289    return VK_ERROR_OUT_OF_HOST_MEMORY;
290 #endif
291 }
292 
lvp_get_image_format_properties(struct lvp_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties * pImageFormatProperties)293 static VkResult lvp_get_image_format_properties(struct lvp_physical_device *physical_device,
294                                                  const VkPhysicalDeviceImageFormatInfo2 *info,
295                                                  VkImageFormatProperties *pImageFormatProperties)
296 {
297    VkFormatProperties3 format_props;
298    VkFormatFeatureFlags2 format_feature_flags;
299    VkExtent3D maxExtent;
300    uint32_t maxMipLevels;
301    uint32_t maxArraySize;
302    VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
303    enum pipe_format pformat = lvp_vk_format_to_pipe_format(info->format);
304    lvp_physical_device_get_format_properties(physical_device, info->format,
305                                              &format_props);
306    if (info->tiling == VK_IMAGE_TILING_LINEAR) {
307       format_feature_flags = format_props.linearTilingFeatures;
308    } else if (info->tiling == VK_IMAGE_TILING_OPTIMAL ||
309               info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
310       format_feature_flags = format_props.optimalTilingFeatures;
311    } else {
312       unreachable("bad VkImageTiling");
313    }
314 
315    if (format_feature_flags == 0)
316       goto unsupported;
317 
318    uint32_t max_2d_ext = physical_device->pscreen->get_param(physical_device->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
319    uint32_t max_layers = physical_device->pscreen->get_param(physical_device->pscreen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS);
320    switch (info->type) {
321    default:
322       unreachable("bad vkimage type\n");
323    case VK_IMAGE_TYPE_1D:
324       if (util_format_is_compressed(pformat))
325          goto unsupported;
326 
327       maxExtent.width = max_2d_ext;
328       maxExtent.height = 1;
329       maxExtent.depth = 1;
330       maxMipLevels = util_logbase2(max_2d_ext) + 1;
331       maxArraySize = max_layers;
332       break;
333    case VK_IMAGE_TYPE_2D:
334       maxExtent.width = max_2d_ext;
335       maxExtent.height = max_2d_ext;
336       maxExtent.depth = 1;
337       maxMipLevels = util_logbase2(max_2d_ext) + 1;
338       maxArraySize = max_layers;
339       if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
340           !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
341           !util_format_is_compressed(pformat) &&
342           (format_feature_flags & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)))
343          sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
344       break;
345    case VK_IMAGE_TYPE_3D:
346       maxExtent.width = max_2d_ext;
347       maxExtent.height = max_2d_ext;
348       maxExtent.depth = (1 << physical_device->pscreen->get_param(physical_device->pscreen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS));
349       maxMipLevels = util_logbase2(max_2d_ext) + 1;
350       maxArraySize = 1;
351       break;
352    }
353 
354    if (info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
355       goto skip_checks;
356 
357    if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
358       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
359          goto unsupported;
360       }
361    }
362 
363    if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
364       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT)) {
365          goto unsupported;
366       }
367    }
368 
369    if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
370       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) {
371          goto unsupported;
372       }
373    }
374 
375    if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
376       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
377          goto unsupported;
378       }
379    }
380 
381    if (info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
382       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT)) {
383          goto unsupported;
384       }
385    }
386 
387    if (info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
388       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT)) {
389          goto unsupported;
390       }
391    }
392 
393    if (info->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
394       if (!(format_feature_flags & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
395                                     VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT))) {
396          goto unsupported;
397       }
398    }
399 
400 skip_checks:
401    *pImageFormatProperties = (VkImageFormatProperties) {
402       .maxExtent = maxExtent,
403       .maxMipLevels = maxMipLevels,
404       .maxArrayLayers = maxArraySize,
405       .sampleCounts = sampleCounts,
406 
407       /* FINISHME: Accurately calculate
408        * VkImageFormatProperties::maxResourceSize.
409        */
410       .maxResourceSize = UINT32_MAX,
411    };
412    return VK_SUCCESS;
413  unsupported:
414    *pImageFormatProperties = (VkImageFormatProperties) {
415       .maxExtent = { 0, 0, 0 },
416       .maxMipLevels = 0,
417       .maxArrayLayers = 0,
418       .sampleCounts = 0,
419       .maxResourceSize = 0,
420    };
421 
422    return VK_ERROR_FORMAT_NOT_SUPPORTED;
423 }
424 
lvp_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)425 VKAPI_ATTR VkResult VKAPI_CALL lvp_GetPhysicalDeviceImageFormatProperties2(
426         VkPhysicalDevice                            physicalDevice,
427         const VkPhysicalDeviceImageFormatInfo2     *base_info,
428         VkImageFormatProperties2                   *base_props)
429 {
430    LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
431    const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
432    VkExternalImageFormatProperties *external_props = NULL;
433    VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
434    VkHostImageCopyDevicePerformanceQueryEXT *hic;
435    VkResult result;
436    result = lvp_get_image_format_properties(physical_device, base_info,
437                                              &base_props->imageFormatProperties);
438    if (result != VK_SUCCESS)
439       return result;
440 
441    vk_foreach_struct_const(s, base_info->pNext) {
442       switch (s->sType) {
443       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
444          external_info = (const void *) s;
445          break;
446       default:
447          break;
448       }
449    }
450 
451    /* Extract output structs */
452    vk_foreach_struct(s, base_props->pNext) {
453       switch (s->sType) {
454       case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
455          external_props = (void *) s;
456          break;
457       case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
458          ycbcr_props = (void *) s;
459          break;
460       case VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT:
461          hic = (void*)s;
462          hic->optimalDeviceAccess = VK_TRUE;
463          hic->identicalMemoryLayout = VK_TRUE;
464          break;
465       default:
466          break;
467       }
468    }
469 
470    if (external_info && external_info->handleType != 0 && external_props) {
471       VkExternalMemoryFeatureFlagBits flags = 0;
472       VkExternalMemoryHandleTypeFlags export_flags = 0;
473       VkExternalMemoryHandleTypeFlags compat_flags = 0;
474 
475       switch (external_info->handleType) {
476 #ifdef HAVE_LIBDRM
477       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: {
478          int params = physical_device->pscreen->get_param(physical_device->pscreen, PIPE_CAP_DMABUF);
479          flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
480          if (params & DRM_PRIME_CAP_EXPORT)
481             flags |= VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
482 
483          export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
484          compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
485          break;
486       }
487 #endif
488 #ifdef PIPE_MEMORY_FD
489       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
490          flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
491          export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
492          compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
493          break;
494 #endif
495       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
496          flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
497          compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
498          break;
499       default:
500          break;
501       }
502       external_props->externalMemoryProperties = (VkExternalMemoryProperties) {
503          .externalMemoryFeatures = flags,
504          .exportFromImportedHandleTypes = export_flags,
505          .compatibleHandleTypes = compat_flags,
506       };
507    }
508    if (ycbcr_props)
509       ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(base_info->format);
510    return VK_SUCCESS;
511 }
512 
513 static void
fill_sparse_image_format_properties(struct lvp_physical_device * pdev,VkImageType type,VkFormat format,VkSampleCountFlagBits samples,VkSparseImageFormatProperties * prop)514 fill_sparse_image_format_properties(struct lvp_physical_device *pdev, VkImageType type,
515                                     VkFormat format, VkSampleCountFlagBits samples,
516                                     VkSparseImageFormatProperties *prop)
517 {
518    enum pipe_format pformat = vk_format_to_pipe_format(format);
519 
520    prop->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
521    prop->flags = 0;
522    prop->imageGranularity = (VkExtent3D){
523       .width = util_format_get_tilesize(pformat, type + 1, samples, 0),
524       .height = util_format_get_tilesize(pformat, type + 1, samples, 1),
525       .depth = util_format_get_tilesize(pformat, type + 1, samples, 2),
526    };
527 }
528 
lvp_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)529 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceSparseImageFormatProperties2(
530         VkPhysicalDevice                            physicalDevice,
531         const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
532         uint32_t                                   *pPropertyCount,
533         VkSparseImageFormatProperties2             *pProperties)
534 {
535    LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
536    VkResult result;
537 
538    if (pFormatInfo->samples > VK_SAMPLE_COUNT_1_BIT) {
539       *pPropertyCount = 0;
540       return;
541    }
542    const VkPhysicalDeviceImageFormatInfo2 fmt_info = {
543       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
544       .format = pFormatInfo->format,
545       .type = pFormatInfo->type,
546       .tiling = pFormatInfo->tiling,
547       .usage = pFormatInfo->usage,
548       .flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT};
549 
550    VkImageFormatProperties fmt_props;
551    result = lvp_get_image_format_properties(physical_device, &fmt_info,
552                                             &fmt_props);
553    if (result != VK_SUCCESS) {
554       *pPropertyCount = 0;
555       return;
556    }
557 
558    VK_OUTARRAY_MAKE_TYPED(VkSparseImageFormatProperties2, out, pProperties, pPropertyCount);
559 
560    vk_outarray_append_typed(VkSparseImageFormatProperties2, &out, prop)
561    {
562       fill_sparse_image_format_properties(physical_device, pFormatInfo->type, pFormatInfo->format,
563                                           pFormatInfo->samples, &prop->properties);
564    };
565 }
566 
lvp_GetDeviceImageSparseMemoryRequirements(VkDevice _device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)567 VKAPI_ATTR void VKAPI_CALL lvp_GetDeviceImageSparseMemoryRequirements(
568     VkDevice                                    _device,
569     const VkDeviceImageMemoryRequirements*      pInfo,
570     uint32_t*                                   pSparseMemoryRequirementCount,
571     VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements)
572 {
573    LVP_FROM_HANDLE(lvp_device, device, _device);
574 
575    if (!(pInfo->pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
576       *pSparseMemoryRequirementCount = 0;
577       return;
578    }
579 
580    VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, out, pSparseMemoryRequirements,
581                           pSparseMemoryRequirementCount);
582 
583    vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &out, req)
584    {
585       fill_sparse_image_format_properties(device->physical_device, pInfo->pCreateInfo->imageType,
586                                           pInfo->pCreateInfo->format, pInfo->pCreateInfo->samples,
587                                           &req->memoryRequirements.formatProperties);
588 
589       req->memoryRequirements.imageMipTailFirstLod = pInfo->pCreateInfo->mipLevels;
590       req->memoryRequirements.imageMipTailSize = 0;
591       req->memoryRequirements.imageMipTailOffset = 0;
592       req->memoryRequirements.imageMipTailStride = 0;
593    };
594 }
595 
lvp_GetImageSparseMemoryRequirements2(VkDevice _device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)596 VKAPI_ATTR void VKAPI_CALL lvp_GetImageSparseMemoryRequirements2(
597    VkDevice                                    _device,
598    const VkImageSparseMemoryRequirementsInfo2* pInfo,
599    uint32_t* pSparseMemoryRequirementCount,
600    VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
601 {
602    LVP_FROM_HANDLE(lvp_device, device, _device);
603    LVP_FROM_HANDLE(lvp_image, image, pInfo->image);
604 
605    if (!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
606       *pSparseMemoryRequirementCount = 0;
607       return;
608    }
609 
610    VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, out, pSparseMemoryRequirements,
611                           pSparseMemoryRequirementCount);
612 
613    vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &out, req)
614    {
615       fill_sparse_image_format_properties(device->physical_device, image->vk.image_type,
616                                           image->vk.format, image->vk.samples,
617                                           &req->memoryRequirements.formatProperties);
618 
619       req->memoryRequirements.imageMipTailFirstLod = image->vk.mip_levels;
620       req->memoryRequirements.imageMipTailSize = 0;
621       req->memoryRequirements.imageMipTailOffset = 0;
622       req->memoryRequirements.imageMipTailStride = 0;
623    };
624 }
625 
626 
lvp_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)627 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalBufferProperties(
628    VkPhysicalDevice                            physicalDevice,
629    const VkPhysicalDeviceExternalBufferInfo    *pExternalBufferInfo,
630    VkExternalBufferProperties                  *pExternalBufferProperties)
631 {
632    VkExternalMemoryFeatureFlagBits flags = 0;
633    VkExternalMemoryHandleTypeFlags export_flags = 0;
634    VkExternalMemoryHandleTypeFlags compat_flags = 0;
635    switch (pExternalBufferInfo->handleType) {
636 #ifdef HAVE_LIBDRM
637       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: {
638          LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
639          int params = physical_device->pscreen->get_param(physical_device->pscreen, PIPE_CAP_DMABUF);
640          flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
641          if (params & DRM_PRIME_CAP_EXPORT)
642             flags |= VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
643 
644          export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
645          compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
646          break;
647       }
648 #endif
649 #ifdef PIPE_MEMORY_FD
650    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
651       flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
652       export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
653       compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
654       break;
655 #endif
656    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
657       flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
658       compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
659       break;
660    default:
661       break;
662    }
663 
664    pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties) {
665       .externalMemoryFeatures = flags,
666       .exportFromImportedHandleTypes = export_flags,
667       .compatibleHandleTypes = compat_flags,
668    };
669 }
670