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