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