• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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        !ycbcr_info &&
198        pformat != PIPE_FORMAT_R10G10B10A2_SNORM &&
199        pformat != PIPE_FORMAT_B10G10R10A2_SNORM &&
200        pformat != PIPE_FORMAT_B10G10R10A2_UNORM) {
201       features |= (VK_FORMAT_FEATURE_2_BLIT_SRC_BIT |
202                    VK_FORMAT_FEATURE_2_BLIT_DST_BIT);
203    }
204 
205    switch (format) {
206    case VK_FORMAT_R32G32_SFLOAT:
207    case VK_FORMAT_R32G32B32_SFLOAT:
208    case VK_FORMAT_R32G32B32A32_SFLOAT:
209    case VK_FORMAT_R16G16_SFLOAT:
210    case VK_FORMAT_R16G16B16_SFLOAT:
211    case VK_FORMAT_R16G16B16A16_SFLOAT:
212    case VK_FORMAT_R16G16_SNORM:
213    case VK_FORMAT_R16G16_UNORM:
214    case VK_FORMAT_R16G16B16A16_SNORM:
215    case VK_FORMAT_R16G16B16A16_UNORM:
216    case VK_FORMAT_R8G8_SNORM:
217    case VK_FORMAT_R8G8_UNORM:
218    case VK_FORMAT_R8G8B8A8_SNORM:
219    case VK_FORMAT_R8G8B8A8_UNORM:
220    case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
221       buffer_features |= VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR;
222       break;
223    default:
224       break;
225    }
226 
227    out_properties->linearTilingFeatures = features;
228    out_properties->optimalTilingFeatures = features;
229    out_properties->bufferFeatures = buffer_features;
230    if (out_properties->linearTilingFeatures)
231       out_properties->linearTilingFeatures |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
232    if (out_properties->optimalTilingFeatures)
233       out_properties->optimalTilingFeatures |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
234 }
235 
236 
lvp_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)237 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFormatProperties2(
238         VkPhysicalDevice                            physicalDevice,
239         VkFormat                                    format,
240         VkFormatProperties2*                        pFormatProperties)
241 {
242    LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
243 
244    VkFormatProperties3 format_props;
245    lvp_physical_device_get_format_properties(physical_device,
246                                              format,
247                                              &format_props);
248    pFormatProperties->formatProperties.linearTilingFeatures = vk_format_features2_to_features(format_props.linearTilingFeatures);
249    pFormatProperties->formatProperties.optimalTilingFeatures = vk_format_features2_to_features(format_props.optimalTilingFeatures);
250    pFormatProperties->formatProperties.bufferFeatures = vk_format_features2_to_features(format_props.bufferFeatures);
251    VkFormatProperties3 *prop3 = (void*)vk_find_struct_const(pFormatProperties->pNext, FORMAT_PROPERTIES_3);
252    if (prop3) {
253       prop3->linearTilingFeatures = format_props.linearTilingFeatures;
254       prop3->optimalTilingFeatures = format_props.optimalTilingFeatures;
255       prop3->bufferFeatures = format_props.bufferFeatures;
256    }
257    VkSubpassResolvePerformanceQueryEXT *perf = (void*)vk_find_struct_const(pFormatProperties->pNext, SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT);
258    if (perf)
259       perf->optimal = VK_FALSE;
260 
261 #if DETECT_OS_LINUX
262    VkDrmFormatModifierPropertiesListEXT *modlist = (void*)vk_find_struct_const(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
263    if (modlist) {
264       modlist->drmFormatModifierCount = 0;
265       if (pFormatProperties->formatProperties.optimalTilingFeatures) {
266          modlist->drmFormatModifierCount = 1;
267          VkDrmFormatModifierPropertiesEXT *mods = &modlist->pDrmFormatModifierProperties[0];
268          if (mods) {
269             mods->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
270             mods->drmFormatModifierPlaneCount = util_format_get_num_planes(lvp_vk_format_to_pipe_format(format));
271             mods->drmFormatModifierTilingFeatures = pFormatProperties->formatProperties.optimalTilingFeatures;
272          }
273       }
274    }
275 #endif
276 }
277 
278 VKAPI_ATTR VkResult VKAPI_CALL
lvp_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device,VkImage _image,VkImageDrmFormatModifierPropertiesEXT * pProperties)279 lvp_GetImageDrmFormatModifierPropertiesEXT(VkDevice _device, VkImage _image,
280                                            VkImageDrmFormatModifierPropertiesEXT *pProperties)
281 {
282 #if DETECT_OS_LINUX
283    pProperties->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
284    return VK_SUCCESS;
285 #else
286    return VK_ERROR_OUT_OF_HOST_MEMORY;
287 #endif
288 }
289 
lvp_get_image_format_properties(struct lvp_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties * pImageFormatProperties)290 static VkResult lvp_get_image_format_properties(struct lvp_physical_device *physical_device,
291                                                  const VkPhysicalDeviceImageFormatInfo2 *info,
292                                                  VkImageFormatProperties *pImageFormatProperties)
293 {
294    VkFormatProperties3 format_props;
295    VkFormatFeatureFlags2 format_feature_flags;
296    VkExtent3D maxExtent;
297    uint32_t maxMipLevels;
298    uint32_t maxArraySize;
299    VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
300    enum pipe_format pformat = lvp_vk_format_to_pipe_format(info->format);
301    lvp_physical_device_get_format_properties(physical_device, info->format,
302                                              &format_props);
303    if (info->tiling == VK_IMAGE_TILING_LINEAR) {
304       format_feature_flags = format_props.linearTilingFeatures;
305    } else if (info->tiling == VK_IMAGE_TILING_OPTIMAL ||
306               info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
307       format_feature_flags = format_props.optimalTilingFeatures;
308    } else {
309       unreachable("bad VkImageTiling");
310    }
311 
312    if (format_feature_flags == 0)
313       goto unsupported;
314 
315    uint32_t max_2d_ext = physical_device->pscreen->caps.max_texture_2d_size;
316    uint32_t max_layers = physical_device->pscreen->caps.max_texture_array_layers;
317    switch (info->type) {
318    default:
319       unreachable("bad vkimage type\n");
320    case VK_IMAGE_TYPE_1D:
321       if (util_format_is_compressed(pformat))
322          goto unsupported;
323 
324       maxExtent.width = max_2d_ext;
325       maxExtent.height = 1;
326       maxExtent.depth = 1;
327       maxMipLevels = util_logbase2(max_2d_ext) + 1;
328       maxArraySize = max_layers;
329       break;
330    case VK_IMAGE_TYPE_2D:
331       maxExtent.width = max_2d_ext;
332       maxExtent.height = max_2d_ext;
333       maxExtent.depth = 1;
334       maxMipLevels = util_logbase2(max_2d_ext) + 1;
335       maxArraySize = max_layers;
336       if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
337           !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
338           !util_format_is_compressed(pformat) &&
339           (format_feature_flags & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)))
340          sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
341       break;
342    case VK_IMAGE_TYPE_3D:
343       maxExtent.width = max_2d_ext;
344       maxExtent.height = max_2d_ext;
345       maxExtent.depth = (1 << physical_device->pscreen->caps.max_texture_3d_levels);
346       maxMipLevels = util_logbase2(max_2d_ext) + 1;
347       maxArraySize = 1;
348       break;
349    }
350 
351    if (info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
352       goto skip_checks;
353 
354    if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
355       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
356          goto unsupported;
357       }
358    }
359 
360    if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
361       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT)) {
362          goto unsupported;
363       }
364    }
365 
366    if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
367       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) {
368          goto unsupported;
369       }
370    }
371 
372    if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
373       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
374          goto unsupported;
375       }
376    }
377 
378    if (info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
379       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT)) {
380          goto unsupported;
381       }
382    }
383 
384    if (info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
385       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT)) {
386          goto unsupported;
387       }
388    }
389 
390    if (info->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
391       if (!(format_feature_flags & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
392                                     VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT))) {
393          goto unsupported;
394       }
395    }
396 
397 skip_checks:
398    *pImageFormatProperties = (VkImageFormatProperties) {
399       .maxExtent = maxExtent,
400       .maxMipLevels = maxMipLevels,
401       .maxArrayLayers = maxArraySize,
402       .sampleCounts = sampleCounts,
403 
404       /* FINISHME: Accurately calculate
405        * VkImageFormatProperties::maxResourceSize.
406        */
407       .maxResourceSize = UINT32_MAX,
408    };
409    return VK_SUCCESS;
410  unsupported:
411    *pImageFormatProperties = (VkImageFormatProperties) {
412       .maxExtent = { 0, 0, 0 },
413       .maxMipLevels = 0,
414       .maxArrayLayers = 0,
415       .sampleCounts = 0,
416       .maxResourceSize = 0,
417    };
418 
419    return VK_ERROR_FORMAT_NOT_SUPPORTED;
420 }
421 
lvp_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)422 VKAPI_ATTR VkResult VKAPI_CALL lvp_GetPhysicalDeviceImageFormatProperties2(
423         VkPhysicalDevice                            physicalDevice,
424         const VkPhysicalDeviceImageFormatInfo2     *base_info,
425         VkImageFormatProperties2                   *base_props)
426 {
427    LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
428    const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
429    VkExternalImageFormatProperties *external_props = NULL;
430    VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
431    VkHostImageCopyDevicePerformanceQueryEXT *hic;
432    VkResult result;
433    result = lvp_get_image_format_properties(physical_device, base_info,
434                                              &base_props->imageFormatProperties);
435    if (result != VK_SUCCESS)
436       return result;
437 
438    vk_foreach_struct_const(s, base_info->pNext) {
439       switch (s->sType) {
440       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
441          external_info = (const void *) s;
442          break;
443       default:
444          break;
445       }
446    }
447 
448    /* Extract output structs */
449    vk_foreach_struct(s, base_props->pNext) {
450       switch (s->sType) {
451       case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
452          external_props = (void *) s;
453          break;
454       case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
455          ycbcr_props = (void *) s;
456          break;
457       case VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT:
458          hic = (void*)s;
459          hic->optimalDeviceAccess = VK_TRUE;
460          hic->identicalMemoryLayout = VK_TRUE;
461          break;
462       default:
463          break;
464       }
465    }
466 
467    if (external_info && external_info->handleType != 0 && external_props) {
468       VkExternalMemoryFeatureFlagBits flags = 0;
469       VkExternalMemoryHandleTypeFlags export_flags = 0;
470       VkExternalMemoryHandleTypeFlags compat_flags = 0;
471 
472       switch (external_info->handleType) {
473 #ifdef HAVE_LIBDRM
474       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: {
475          int params = physical_device->pscreen->caps.dmabuf;
476          flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
477          if (params & DRM_PRIME_CAP_EXPORT)
478             flags |= VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
479 
480          export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
481          compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
482          break;
483       }
484 #endif
485 #ifdef PIPE_MEMORY_FD
486       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
487          flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
488          export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
489          compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
490          break;
491 #endif
492       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
493          flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
494          compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
495          break;
496       default:
497          break;
498       }
499       external_props->externalMemoryProperties = (VkExternalMemoryProperties) {
500          .externalMemoryFeatures = flags,
501          .exportFromImportedHandleTypes = export_flags,
502          .compatibleHandleTypes = compat_flags,
503       };
504    }
505    if (ycbcr_props)
506       ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(base_info->format);
507    return VK_SUCCESS;
508 }
509 
510 static void
fill_sparse_image_format_properties(struct lvp_physical_device * pdev,VkImageType type,VkFormat format,VkSampleCountFlagBits samples,VkSparseImageFormatProperties * prop)511 fill_sparse_image_format_properties(struct lvp_physical_device *pdev, VkImageType type,
512                                     VkFormat format, VkSampleCountFlagBits samples,
513                                     VkSparseImageFormatProperties *prop)
514 {
515    enum pipe_format pformat = vk_format_to_pipe_format(format);
516 
517    prop->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
518    prop->flags = 0;
519    prop->imageGranularity = (VkExtent3D){
520       .width = util_format_get_tilesize(pformat, type + 1, samples, 0),
521       .height = util_format_get_tilesize(pformat, type + 1, samples, 1),
522       .depth = util_format_get_tilesize(pformat, type + 1, samples, 2),
523    };
524 }
525 
lvp_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)526 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceSparseImageFormatProperties2(
527         VkPhysicalDevice                            physicalDevice,
528         const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
529         uint32_t                                   *pPropertyCount,
530         VkSparseImageFormatProperties2             *pProperties)
531 {
532    LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
533    VkResult result;
534 
535    if (pFormatInfo->samples > VK_SAMPLE_COUNT_1_BIT) {
536       *pPropertyCount = 0;
537       return;
538    }
539    const VkPhysicalDeviceImageFormatInfo2 fmt_info = {
540       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
541       .format = pFormatInfo->format,
542       .type = pFormatInfo->type,
543       .tiling = pFormatInfo->tiling,
544       .usage = pFormatInfo->usage,
545       .flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT};
546 
547    VkImageFormatProperties fmt_props;
548    result = lvp_get_image_format_properties(physical_device, &fmt_info,
549                                             &fmt_props);
550    if (result != VK_SUCCESS) {
551       *pPropertyCount = 0;
552       return;
553    }
554 
555    VK_OUTARRAY_MAKE_TYPED(VkSparseImageFormatProperties2, out, pProperties, pPropertyCount);
556 
557    vk_outarray_append_typed(VkSparseImageFormatProperties2, &out, prop)
558    {
559       fill_sparse_image_format_properties(physical_device, pFormatInfo->type, pFormatInfo->format,
560                                           pFormatInfo->samples, &prop->properties);
561    };
562 }
563 
lvp_GetDeviceImageSparseMemoryRequirements(VkDevice _device,const VkDeviceImageMemoryRequirements * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)564 VKAPI_ATTR void VKAPI_CALL lvp_GetDeviceImageSparseMemoryRequirements(
565     VkDevice                                    _device,
566     const VkDeviceImageMemoryRequirements*      pInfo,
567     uint32_t*                                   pSparseMemoryRequirementCount,
568     VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements)
569 {
570    LVP_FROM_HANDLE(lvp_device, device, _device);
571 
572    if (!(pInfo->pCreateInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
573       *pSparseMemoryRequirementCount = 0;
574       return;
575    }
576 
577    VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, out, pSparseMemoryRequirements,
578                           pSparseMemoryRequirementCount);
579 
580    vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &out, req)
581    {
582       fill_sparse_image_format_properties(device->physical_device, pInfo->pCreateInfo->imageType,
583                                           pInfo->pCreateInfo->format, pInfo->pCreateInfo->samples,
584                                           &req->memoryRequirements.formatProperties);
585 
586       req->memoryRequirements.imageMipTailFirstLod = pInfo->pCreateInfo->mipLevels;
587       req->memoryRequirements.imageMipTailSize = 0;
588       req->memoryRequirements.imageMipTailOffset = 0;
589       req->memoryRequirements.imageMipTailStride = 0;
590    };
591 }
592 
lvp_GetImageSparseMemoryRequirements2(VkDevice _device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)593 VKAPI_ATTR void VKAPI_CALL lvp_GetImageSparseMemoryRequirements2(
594    VkDevice                                    _device,
595    const VkImageSparseMemoryRequirementsInfo2* pInfo,
596    uint32_t* pSparseMemoryRequirementCount,
597    VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
598 {
599    LVP_FROM_HANDLE(lvp_device, device, _device);
600    LVP_FROM_HANDLE(lvp_image, image, pInfo->image);
601 
602    if (!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
603       *pSparseMemoryRequirementCount = 0;
604       return;
605    }
606 
607    VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, out, pSparseMemoryRequirements,
608                           pSparseMemoryRequirementCount);
609 
610    vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &out, req)
611    {
612       fill_sparse_image_format_properties(device->physical_device, image->vk.image_type,
613                                           image->vk.format, image->vk.samples,
614                                           &req->memoryRequirements.formatProperties);
615 
616       req->memoryRequirements.imageMipTailFirstLod = image->vk.mip_levels;
617       req->memoryRequirements.imageMipTailSize = 0;
618       req->memoryRequirements.imageMipTailOffset = 0;
619       req->memoryRequirements.imageMipTailStride = 0;
620    };
621 }
622 
623 
lvp_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)624 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalBufferProperties(
625    VkPhysicalDevice                            physicalDevice,
626    const VkPhysicalDeviceExternalBufferInfo    *pExternalBufferInfo,
627    VkExternalBufferProperties                  *pExternalBufferProperties)
628 {
629    VkExternalMemoryFeatureFlagBits flags = 0;
630    VkExternalMemoryHandleTypeFlags export_flags = 0;
631    VkExternalMemoryHandleTypeFlags compat_flags = 0;
632    switch (pExternalBufferInfo->handleType) {
633 #ifdef HAVE_LIBDRM
634       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: {
635          LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
636          int params = physical_device->pscreen->caps.dmabuf;
637          flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
638          if (params & DRM_PRIME_CAP_EXPORT)
639             flags |= VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
640 
641          export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
642          compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
643          break;
644       }
645 #endif
646 #ifdef PIPE_MEMORY_FD
647    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
648       flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
649       export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
650       compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
651       break;
652 #endif
653    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
654       flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
655       compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
656       break;
657    default:
658       break;
659    }
660 
661    pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties) {
662       .externalMemoryFeatures = flags,
663       .exportFromImportedHandleTypes = export_flags,
664       .compatibleHandleTypes = compat_flags,
665    };
666 }
667