gfx_backend_vulkan/
physical_device.rs

1use ash::{
2    extensions::{khr::DrawIndirectCount, khr::Swapchain, nv::MeshShader},
3    version::{DeviceV1_0, InstanceV1_0},
4    vk,
5};
6
7#[cfg(unix)]
8use ash::extensions::khr::ExternalMemoryFd;
9
10use hal::{
11    adapter,
12    device::{CreationError, OutOfMemory},
13    display, external_memory, format, image,
14    pso::PatchSize,
15    queue, DescriptorLimits, DownlevelProperties, DynamicStates, ExternalMemoryLimits, Features,
16    Limits, PhysicalDeviceProperties,
17};
18
19use std::{ffi::CStr, fmt, mem, ptr, sync::Arc};
20
21use crate::{
22    conv, info, native, Backend, Device, DeviceExtensionFunctions, ExtensionFn, Queue, QueueFamily,
23    RawDevice, RawInstance, Version,
24};
25
26/// Aggregate of the `vk::PhysicalDevice*Features` structs used by `gfx`.
27#[derive(Debug, Default)]
28pub struct PhysicalDeviceFeatures {
29    core: vk::PhysicalDeviceFeatures,
30    vulkan_1_2: Option<vk::PhysicalDeviceVulkan12Features>,
31    descriptor_indexing: Option<vk::PhysicalDeviceDescriptorIndexingFeaturesEXT>,
32    mesh_shader: Option<vk::PhysicalDeviceMeshShaderFeaturesNV>,
33    imageless_framebuffer: Option<vk::PhysicalDeviceImagelessFramebufferFeaturesKHR>,
34}
35
36// This is safe because the structs have `p_next: *mut c_void`, which we null out/never read.
37unsafe impl Send for PhysicalDeviceFeatures {}
38unsafe impl Sync for PhysicalDeviceFeatures {}
39
40impl PhysicalDeviceFeatures {
41    /// Add the members of `self` into `info.enabled_features` and its `p_next` chain.
42    fn add_to_device_create_builder<'a>(
43        &'a mut self,
44        mut info: vk::DeviceCreateInfoBuilder<'a>,
45    ) -> vk::DeviceCreateInfoBuilder<'a> {
46        info = info.enabled_features(&self.core);
47
48        if let Some(ref mut feature) = self.vulkan_1_2 {
49            info = info.push_next(feature);
50        }
51        if let Some(ref mut feature) = self.descriptor_indexing {
52            info = info.push_next(feature);
53        }
54        if let Some(ref mut feature) = self.mesh_shader {
55            info = info.push_next(feature);
56        }
57        if let Some(ref mut feature) = self.imageless_framebuffer {
58            info = info.push_next(feature);
59        }
60
61        info
62    }
63
64    /// Create a `PhysicalDeviceFeatures` that will be used to create a logical device.
65    ///
66    /// `requested_features` should be the same as what was used to generate `enabled_extensions`.
67    fn from_extensions_and_requested_features(
68        api_version: Version,
69        enabled_extensions: &[&'static CStr],
70        requested_features: Features,
71        supports_vulkan12_imageless_framebuffer: bool,
72    ) -> PhysicalDeviceFeatures {
73        // This must follow the "Valid Usage" requirements of [`VkDeviceCreateInfo`](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkDeviceCreateInfo.html).
74        let features = requested_features;
75        PhysicalDeviceFeatures {
76            // vk::PhysicalDeviceFeatures is a struct composed of Bool32's while
77            // Features is a bitfield so we need to map everything manually
78            core: vk::PhysicalDeviceFeatures::builder()
79                .robust_buffer_access(features.contains(Features::ROBUST_BUFFER_ACCESS))
80                .full_draw_index_uint32(features.contains(Features::FULL_DRAW_INDEX_U32))
81                .image_cube_array(features.contains(Features::IMAGE_CUBE_ARRAY))
82                .independent_blend(features.contains(Features::INDEPENDENT_BLENDING))
83                .geometry_shader(features.contains(Features::GEOMETRY_SHADER))
84                .tessellation_shader(features.contains(Features::TESSELLATION_SHADER))
85                .sample_rate_shading(features.contains(Features::SAMPLE_RATE_SHADING))
86                .dual_src_blend(features.contains(Features::DUAL_SRC_BLENDING))
87                .logic_op(features.contains(Features::LOGIC_OP))
88                .multi_draw_indirect(features.contains(Features::MULTI_DRAW_INDIRECT))
89                .draw_indirect_first_instance(
90                    features.contains(Features::DRAW_INDIRECT_FIRST_INSTANCE),
91                )
92                .depth_clamp(features.contains(Features::DEPTH_CLAMP))
93                .depth_bias_clamp(features.contains(Features::DEPTH_BIAS_CLAMP))
94                .fill_mode_non_solid(features.contains(Features::NON_FILL_POLYGON_MODE))
95                .depth_bounds(features.contains(Features::DEPTH_BOUNDS))
96                .wide_lines(features.contains(Features::LINE_WIDTH))
97                .large_points(features.contains(Features::POINT_SIZE))
98                .alpha_to_one(features.contains(Features::ALPHA_TO_ONE))
99                .multi_viewport(features.contains(Features::MULTI_VIEWPORTS))
100                .sampler_anisotropy(features.contains(Features::SAMPLER_ANISOTROPY))
101                .texture_compression_etc2(features.contains(Features::FORMAT_ETC2))
102                .texture_compression_astc_ldr(features.contains(Features::FORMAT_ASTC_LDR))
103                .texture_compression_bc(features.contains(Features::FORMAT_BC))
104                .occlusion_query_precise(features.contains(Features::PRECISE_OCCLUSION_QUERY))
105                .pipeline_statistics_query(features.contains(Features::PIPELINE_STATISTICS_QUERY))
106                .vertex_pipeline_stores_and_atomics(
107                    features.contains(Features::VERTEX_STORES_AND_ATOMICS),
108                )
109                .fragment_stores_and_atomics(
110                    features.contains(Features::FRAGMENT_STORES_AND_ATOMICS),
111                )
112                .shader_tessellation_and_geometry_point_size(
113                    features.contains(Features::SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE),
114                )
115                .shader_image_gather_extended(
116                    features.contains(Features::SHADER_IMAGE_GATHER_EXTENDED),
117                )
118                .shader_storage_image_extended_formats(
119                    features.contains(Features::SHADER_STORAGE_IMAGE_EXTENDED_FORMATS),
120                )
121                .shader_storage_image_multisample(
122                    features.contains(Features::SHADER_STORAGE_IMAGE_MULTISAMPLE),
123                )
124                .shader_storage_image_read_without_format(
125                    features.contains(Features::SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT),
126                )
127                .shader_storage_image_write_without_format(
128                    features.contains(Features::SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT),
129                )
130                .shader_uniform_buffer_array_dynamic_indexing(
131                    features.contains(Features::SHADER_UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING),
132                )
133                .shader_sampled_image_array_dynamic_indexing(
134                    features.contains(Features::SHADER_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING),
135                )
136                .shader_storage_buffer_array_dynamic_indexing(
137                    features.contains(Features::SHADER_STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING),
138                )
139                .shader_storage_image_array_dynamic_indexing(
140                    features.contains(Features::SHADER_STORAGE_IMAGE_ARRAY_DYNAMIC_INDEXING),
141                )
142                .shader_clip_distance(features.contains(Features::SHADER_CLIP_DISTANCE))
143                .shader_cull_distance(features.contains(Features::SHADER_CULL_DISTANCE))
144                .shader_float64(features.contains(Features::SHADER_FLOAT64))
145                .shader_int64(features.contains(Features::SHADER_INT64))
146                .shader_int16(features.contains(Features::SHADER_INT16))
147                .shader_resource_residency(features.contains(Features::SHADER_RESOURCE_RESIDENCY))
148                .shader_resource_min_lod(features.contains(Features::SHADER_RESOURCE_MIN_LOD))
149                .sparse_binding(features.contains(Features::SPARSE_BINDING))
150                .sparse_residency_buffer(features.contains(Features::SPARSE_RESIDENCY_BUFFER))
151                .sparse_residency_image2_d(features.contains(Features::SPARSE_RESIDENCY_IMAGE_2D))
152                .sparse_residency_image3_d(features.contains(Features::SPARSE_RESIDENCY_IMAGE_3D))
153                .sparse_residency2_samples(features.contains(Features::SPARSE_RESIDENCY_2_SAMPLES))
154                .sparse_residency4_samples(features.contains(Features::SPARSE_RESIDENCY_4_SAMPLES))
155                .sparse_residency8_samples(features.contains(Features::SPARSE_RESIDENCY_8_SAMPLES))
156                .sparse_residency16_samples(
157                    features.contains(Features::SPARSE_RESIDENCY_16_SAMPLES),
158                )
159                .sparse_residency_aliased(features.contains(Features::SPARSE_RESIDENCY_ALIASED))
160                .variable_multisample_rate(features.contains(Features::VARIABLE_MULTISAMPLE_RATE))
161                .inherited_queries(features.contains(Features::INHERITED_QUERIES))
162                .build(),
163            vulkan_1_2: if api_version >= Version::V1_2 {
164                Some(
165                    vk::PhysicalDeviceVulkan12Features::builder()
166                        .sampler_mirror_clamp_to_edge(
167                            features.contains(Features::SAMPLER_MIRROR_CLAMP_EDGE),
168                        )
169                        .draw_indirect_count(features.contains(Features::DRAW_INDIRECT_COUNT))
170                        .descriptor_indexing(
171                            features.intersects(Features::DESCRIPTOR_INDEXING_MASK),
172                        )
173                        .shader_sampled_image_array_non_uniform_indexing(
174                            features.contains(Features::SAMPLED_TEXTURE_DESCRIPTOR_INDEXING),
175                        )
176                        .shader_storage_image_array_non_uniform_indexing(
177                            features.contains(Features::STORAGE_TEXTURE_DESCRIPTOR_INDEXING),
178                        )
179                        .shader_storage_buffer_array_non_uniform_indexing(
180                            features.contains(Features::STORAGE_BUFFER_DESCRIPTOR_INDEXING),
181                        )
182                        .shader_uniform_buffer_array_non_uniform_indexing(
183                            features.contains(Features::UNIFORM_BUFFER_DESCRIPTOR_INDEXING),
184                        )
185                        .runtime_descriptor_array(
186                            features.contains(Features::UNSIZED_DESCRIPTOR_ARRAY),
187                        )
188                        .sampler_filter_minmax(features.contains(Features::SAMPLER_REDUCTION))
189                        .imageless_framebuffer(supports_vulkan12_imageless_framebuffer)
190                        .build(),
191                )
192            } else {
193                None
194            },
195            descriptor_indexing: if enabled_extensions
196                .contains(&vk::ExtDescriptorIndexingFn::name())
197            {
198                Some(
199                    vk::PhysicalDeviceDescriptorIndexingFeaturesEXT::builder()
200                        .shader_sampled_image_array_non_uniform_indexing(
201                            features.contains(Features::SAMPLED_TEXTURE_DESCRIPTOR_INDEXING),
202                        )
203                        .shader_storage_image_array_non_uniform_indexing(
204                            features.contains(Features::STORAGE_TEXTURE_DESCRIPTOR_INDEXING),
205                        )
206                        .shader_storage_buffer_array_non_uniform_indexing(
207                            features.contains(Features::STORAGE_BUFFER_DESCRIPTOR_INDEXING),
208                        )
209                        .shader_uniform_buffer_array_non_uniform_indexing(
210                            features.contains(Features::UNIFORM_BUFFER_DESCRIPTOR_INDEXING),
211                        )
212                        .runtime_descriptor_array(
213                            features.contains(Features::UNSIZED_DESCRIPTOR_ARRAY),
214                        )
215                        .build(),
216                )
217            } else {
218                None
219            },
220            mesh_shader: if enabled_extensions.contains(&vk::NvMeshShaderFn::name()) {
221                Some(
222                    vk::PhysicalDeviceMeshShaderFeaturesNV::builder()
223                        .task_shader(features.contains(Features::TASK_SHADER))
224                        .mesh_shader(features.contains(Features::MESH_SHADER))
225                        .build(),
226                )
227            } else {
228                None
229            },
230            imageless_framebuffer: if enabled_extensions
231                .contains(&vk::KhrImagelessFramebufferFn::name())
232            {
233                Some(
234                    vk::PhysicalDeviceImagelessFramebufferFeaturesKHR::builder()
235                        .imageless_framebuffer(true)
236                        .build(),
237                )
238            } else {
239                None
240            },
241        }
242    }
243
244    /// Get the `hal::Features` corresponding to the raw physical device's features and properties.
245    fn to_hal_features(&self, info: &PhysicalDeviceInfo) -> Features {
246        let mut bits = Features::empty()
247            | Features::TRIANGLE_FAN
248            | Features::SEPARATE_STENCIL_REF_VALUES
249            | Features::SAMPLER_MIP_LOD_BIAS
250            | Features::SAMPLER_BORDER_COLOR
251            | Features::MUTABLE_COMPARISON_SAMPLER
252            | Features::MUTABLE_UNNORMALIZED_SAMPLER
253            | Features::TEXTURE_DESCRIPTOR_ARRAY
254            | Features::BUFFER_DESCRIPTOR_ARRAY;
255
256        if self.core.robust_buffer_access != 0 {
257            bits |= Features::ROBUST_BUFFER_ACCESS;
258        }
259        if self.core.full_draw_index_uint32 != 0 {
260            bits |= Features::FULL_DRAW_INDEX_U32;
261        }
262        if self.core.image_cube_array != 0 {
263            bits |= Features::IMAGE_CUBE_ARRAY;
264        }
265        if self.core.independent_blend != 0 {
266            bits |= Features::INDEPENDENT_BLENDING;
267        }
268        if self.core.geometry_shader != 0 {
269            bits |= Features::GEOMETRY_SHADER;
270        }
271        if self.core.tessellation_shader != 0 {
272            bits |= Features::TESSELLATION_SHADER;
273        }
274        if self.core.sample_rate_shading != 0 {
275            bits |= Features::SAMPLE_RATE_SHADING;
276        }
277        if self.core.dual_src_blend != 0 {
278            bits |= Features::DUAL_SRC_BLENDING;
279        }
280        if self.core.logic_op != 0 {
281            bits |= Features::LOGIC_OP;
282        }
283        if self.core.multi_draw_indirect != 0 {
284            bits |= Features::MULTI_DRAW_INDIRECT;
285        }
286        if self.core.draw_indirect_first_instance != 0 {
287            bits |= Features::DRAW_INDIRECT_FIRST_INSTANCE;
288        }
289        if self.core.depth_clamp != 0 {
290            bits |= Features::DEPTH_CLAMP;
291        }
292        if self.core.depth_bias_clamp != 0 {
293            bits |= Features::DEPTH_BIAS_CLAMP;
294        }
295        if self.core.fill_mode_non_solid != 0 {
296            bits |= Features::NON_FILL_POLYGON_MODE;
297        }
298        if self.core.depth_bounds != 0 {
299            bits |= Features::DEPTH_BOUNDS;
300        }
301        if self.core.wide_lines != 0 {
302            bits |= Features::LINE_WIDTH;
303        }
304        if self.core.large_points != 0 {
305            bits |= Features::POINT_SIZE;
306        }
307        if self.core.alpha_to_one != 0 {
308            bits |= Features::ALPHA_TO_ONE;
309        }
310        if self.core.multi_viewport != 0 {
311            bits |= Features::MULTI_VIEWPORTS;
312        }
313        if self.core.sampler_anisotropy != 0 {
314            bits |= Features::SAMPLER_ANISOTROPY;
315        }
316        if self.core.texture_compression_etc2 != 0 {
317            bits |= Features::FORMAT_ETC2;
318        }
319        if self.core.texture_compression_astc_ldr != 0 {
320            bits |= Features::FORMAT_ASTC_LDR;
321        }
322        if self.core.texture_compression_bc != 0 {
323            bits |= Features::FORMAT_BC;
324        }
325        if self.core.occlusion_query_precise != 0 {
326            bits |= Features::PRECISE_OCCLUSION_QUERY;
327        }
328        if self.core.pipeline_statistics_query != 0 {
329            bits |= Features::PIPELINE_STATISTICS_QUERY;
330        }
331        if self.core.vertex_pipeline_stores_and_atomics != 0 {
332            bits |= Features::VERTEX_STORES_AND_ATOMICS;
333        }
334        if self.core.fragment_stores_and_atomics != 0 {
335            bits |= Features::FRAGMENT_STORES_AND_ATOMICS;
336        }
337        if self.core.shader_tessellation_and_geometry_point_size != 0 {
338            bits |= Features::SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE;
339        }
340        if self.core.shader_image_gather_extended != 0 {
341            bits |= Features::SHADER_IMAGE_GATHER_EXTENDED;
342        }
343        if self.core.shader_storage_image_extended_formats != 0 {
344            bits |= Features::SHADER_STORAGE_IMAGE_EXTENDED_FORMATS;
345        }
346        if self.core.shader_storage_image_multisample != 0 {
347            bits |= Features::SHADER_STORAGE_IMAGE_MULTISAMPLE;
348        }
349        if self.core.shader_storage_image_read_without_format != 0 {
350            bits |= Features::SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT;
351        }
352        if self.core.shader_storage_image_write_without_format != 0 {
353            bits |= Features::SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT;
354        }
355        if self.core.shader_uniform_buffer_array_dynamic_indexing != 0 {
356            bits |= Features::SHADER_UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING;
357        }
358        if self.core.shader_sampled_image_array_dynamic_indexing != 0 {
359            bits |= Features::SHADER_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING;
360        }
361        if self.core.shader_storage_buffer_array_dynamic_indexing != 0 {
362            bits |= Features::SHADER_STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING;
363        }
364        if self.core.shader_storage_image_array_dynamic_indexing != 0 {
365            bits |= Features::SHADER_STORAGE_IMAGE_ARRAY_DYNAMIC_INDEXING;
366        }
367        if self.core.shader_clip_distance != 0 {
368            bits |= Features::SHADER_CLIP_DISTANCE;
369        }
370        if self.core.shader_cull_distance != 0 {
371            bits |= Features::SHADER_CULL_DISTANCE;
372        }
373        if self.core.shader_float64 != 0 {
374            bits |= Features::SHADER_FLOAT64;
375        }
376        if self.core.shader_int64 != 0 {
377            bits |= Features::SHADER_INT64;
378        }
379        if self.core.shader_int16 != 0 {
380            bits |= Features::SHADER_INT16;
381        }
382        if self.core.shader_resource_residency != 0 {
383            bits |= Features::SHADER_RESOURCE_RESIDENCY;
384        }
385        if self.core.shader_resource_min_lod != 0 {
386            bits |= Features::SHADER_RESOURCE_MIN_LOD;
387        }
388        if self.core.sparse_binding != 0 {
389            bits |= Features::SPARSE_BINDING;
390        }
391        if self.core.sparse_residency_buffer != 0 {
392            bits |= Features::SPARSE_RESIDENCY_BUFFER;
393        }
394        if self.core.sparse_residency_image2_d != 0 {
395            bits |= Features::SPARSE_RESIDENCY_IMAGE_2D;
396        }
397        if self.core.sparse_residency_image3_d != 0 {
398            bits |= Features::SPARSE_RESIDENCY_IMAGE_3D;
399        }
400        if self.core.sparse_residency2_samples != 0 {
401            bits |= Features::SPARSE_RESIDENCY_2_SAMPLES;
402        }
403        if self.core.sparse_residency4_samples != 0 {
404            bits |= Features::SPARSE_RESIDENCY_4_SAMPLES;
405        }
406        if self.core.sparse_residency8_samples != 0 {
407            bits |= Features::SPARSE_RESIDENCY_8_SAMPLES;
408        }
409        if self.core.sparse_residency16_samples != 0 {
410            bits |= Features::SPARSE_RESIDENCY_16_SAMPLES;
411        }
412        if self.core.sparse_residency_aliased != 0 {
413            bits |= Features::SPARSE_RESIDENCY_ALIASED;
414        }
415        if self.core.variable_multisample_rate != 0 {
416            bits |= Features::VARIABLE_MULTISAMPLE_RATE;
417        }
418        if self.core.inherited_queries != 0 {
419            bits |= Features::INHERITED_QUERIES;
420        }
421
422        if info.supports_extension(vk::AmdNegativeViewportHeightFn::name())
423            || info.supports_extension(vk::KhrMaintenance1Fn::name())
424            || info.api_version() >= Version::V1_1
425        {
426            bits |= Features::NDC_Y_UP;
427        }
428
429        if info.supports_extension(vk::KhrSamplerMirrorClampToEdgeFn::name()) {
430            bits |= Features::SAMPLER_MIRROR_CLAMP_EDGE;
431        }
432
433        if info.supports_extension(vk::ExtSamplerFilterMinmaxFn::name()) {
434            bits |= Features::SAMPLER_REDUCTION;
435        }
436
437        if info.supports_extension(DrawIndirectCount::name()) {
438            bits |= Features::DRAW_INDIRECT_COUNT
439        }
440
441        if info.supports_extension(vk::ExtConservativeRasterizationFn::name()) {
442            bits |= Features::CONSERVATIVE_RASTERIZATION
443        }
444
445        if info.api_version() >= Version::V1_1
446            || (info.supports_extension(vk::KhrGetPhysicalDeviceProperties2Fn::name())
447                && info.supports_extension(vk::KhrExternalMemoryFn::name()))
448        {
449            bits |= Features::EXTERNAL_MEMORY
450        }
451
452        if let Some(ref vulkan_1_2) = self.vulkan_1_2 {
453            if vulkan_1_2.shader_sampled_image_array_non_uniform_indexing != 0 {
454                bits |= Features::SAMPLED_TEXTURE_DESCRIPTOR_INDEXING;
455            }
456            if vulkan_1_2.shader_storage_image_array_non_uniform_indexing != 0 {
457                bits |= Features::STORAGE_TEXTURE_DESCRIPTOR_INDEXING;
458            }
459            if vulkan_1_2.shader_storage_buffer_array_non_uniform_indexing != 0 {
460                bits |= Features::STORAGE_BUFFER_DESCRIPTOR_INDEXING;
461            }
462            if vulkan_1_2.shader_uniform_buffer_array_non_uniform_indexing != 0 {
463                bits |= Features::UNIFORM_BUFFER_DESCRIPTOR_INDEXING;
464            }
465            if vulkan_1_2.runtime_descriptor_array != 0 {
466                bits |= Features::UNSIZED_DESCRIPTOR_ARRAY;
467            }
468            if vulkan_1_2.sampler_mirror_clamp_to_edge != 0 {
469                bits |= Features::SAMPLER_MIRROR_CLAMP_EDGE;
470            }
471            if vulkan_1_2.sampler_filter_minmax != 0 {
472                bits |= Features::SAMPLER_REDUCTION
473            }
474            if vulkan_1_2.draw_indirect_count != 0 {
475                bits |= Features::DRAW_INDIRECT_COUNT
476            }
477        }
478
479        if let Some(ref descriptor_indexing) = self.descriptor_indexing {
480            if descriptor_indexing.shader_sampled_image_array_non_uniform_indexing != 0 {
481                bits |= Features::SAMPLED_TEXTURE_DESCRIPTOR_INDEXING;
482            }
483            if descriptor_indexing.shader_storage_image_array_non_uniform_indexing != 0 {
484                bits |= Features::STORAGE_TEXTURE_DESCRIPTOR_INDEXING;
485            }
486            if descriptor_indexing.shader_storage_buffer_array_non_uniform_indexing != 0 {
487                bits |= Features::STORAGE_BUFFER_DESCRIPTOR_INDEXING;
488            }
489            if descriptor_indexing.shader_uniform_buffer_array_non_uniform_indexing != 0 {
490                bits |= Features::UNIFORM_BUFFER_DESCRIPTOR_INDEXING;
491            }
492            if descriptor_indexing.runtime_descriptor_array != 0 {
493                bits |= Features::UNSIZED_DESCRIPTOR_ARRAY;
494            }
495        }
496
497        if let Some(ref mesh_shader) = self.mesh_shader {
498            if mesh_shader.task_shader != 0 {
499                bits |= Features::TASK_SHADER;
500            }
501            if mesh_shader.mesh_shader != 0 {
502                bits |= Features::MESH_SHADER;
503            }
504        }
505
506        bits
507    }
508}
509
510/// Information gathered about a physical device. Used to
511pub struct PhysicalDeviceInfo {
512    supported_extensions: Vec<vk::ExtensionProperties>,
513    properties: vk::PhysicalDeviceProperties,
514}
515
516impl PhysicalDeviceInfo {
517    fn api_version(&self) -> Version {
518        self.properties.api_version.into()
519    }
520
521    fn supports_extension(&self, extension: &CStr) -> bool {
522        self.supported_extensions
523            .iter()
524            .any(|ep| unsafe { CStr::from_ptr(ep.extension_name.as_ptr()) } == extension)
525    }
526
527    /// Map `requested_features` to the list of Vulkan extension strings required to create the logical device.
528    fn get_required_extensions(&self, requested_features: Features) -> Vec<&'static CStr> {
529        let mut requested_extensions = Vec::new();
530
531        requested_extensions.push(Swapchain::name());
532
533        if self.api_version() < Version::V1_1 {
534            requested_extensions.push(vk::KhrMaintenance1Fn::name());
535            requested_extensions.push(vk::KhrMaintenance2Fn::name());
536        }
537
538        if requested_features.contains(Features::NDC_Y_UP) {
539            // `VK_AMD_negative_viewport_height` is obsoleted by `VK_KHR_maintenance1` and must not be enabled alongside `VK_KHR_maintenance1` or a 1.1+ device.
540            if self.api_version() < Version::V1_1
541                && !self.supports_extension(vk::KhrMaintenance1Fn::name())
542            {
543                requested_extensions.push(vk::AmdNegativeViewportHeightFn::name());
544            }
545        }
546
547        if self.api_version() < Version::V1_2
548            && self.supports_extension(vk::KhrImagelessFramebufferFn::name())
549        {
550            requested_extensions.push(vk::KhrImagelessFramebufferFn::name());
551            requested_extensions.push(vk::KhrImageFormatListFn::name()); // Required for `KhrImagelessFramebufferFn`
552        }
553
554        if self.api_version() < Version::V1_2 {
555            requested_extensions.push(vk::ExtSamplerFilterMinmaxFn::name());
556        }
557
558        if self.api_version() < Version::V1_2
559            && requested_features.intersects(Features::DESCRIPTOR_INDEXING_MASK)
560        {
561            requested_extensions.push(vk::ExtDescriptorIndexingFn::name());
562
563            if self.api_version() < Version::V1_1 {
564                requested_extensions.push(vk::KhrMaintenance3Fn::name());
565            }
566        }
567
568        if self.api_version() < Version::V1_2
569            && requested_features.intersects(Features::SAMPLER_MIRROR_CLAMP_EDGE)
570        {
571            requested_extensions.push(vk::KhrSamplerMirrorClampToEdgeFn::name());
572        }
573
574        if self.api_version() < Version::V1_2
575            && requested_features.contains(Features::SAMPLER_REDUCTION)
576        {
577            requested_extensions.push(vk::ExtSamplerFilterMinmaxFn::name());
578        }
579
580        if requested_features.intersects(Features::MESH_SHADER_MASK) {
581            requested_extensions.push(MeshShader::name());
582        }
583
584        if self.api_version() < Version::V1_2
585            && requested_features.contains(Features::DRAW_INDIRECT_COUNT)
586        {
587            requested_extensions.push(DrawIndirectCount::name());
588        }
589
590        if requested_features.contains(Features::CONSERVATIVE_RASTERIZATION) {
591            requested_extensions.push(vk::ExtConservativeRasterizationFn::name());
592            requested_extensions.push(vk::KhrGetDisplayProperties2Fn::name()); // TODO NOT NEEDED, RIGHT?
593        }
594
595        if self.supports_extension(vk::ExtDisplayControlFn::name()) {
596            requested_extensions.push(vk::ExtDisplayControlFn::name());
597        }
598
599        if requested_features.contains(Features::EXTERNAL_MEMORY) {
600            if self.api_version() < Version::V1_1 {
601                requested_extensions.push(vk::KhrGetPhysicalDeviceProperties2Fn::name());
602                requested_extensions.push(vk::KhrExternalMemoryFn::name());
603
604                // External memory interact with DedicatedAllocation extension, but it is not a strict dependency.
605                requested_extensions.push(vk::KhrGetMemoryRequirements2Fn::name()); // TODO Functions should be added because they are useful
606                requested_extensions.push(vk::KhrDedicatedAllocationFn::name());
607            }
608
609            requested_extensions.push(vk::ExtExternalMemoryHostFn::name());
610            #[cfg(window)]
611            requested_extensions.push(vk::KhrExternalMemoryWin32Fn::name());
612            #[cfg(unix)]
613            {
614                requested_extensions.push(vk::KhrExternalMemoryFdFn::name());
615                requested_extensions.push(vk::ExtExternalMemoryDmaBufFn::name());
616
617                requested_extensions.push(vk::KhrBindMemory2Fn::name());
618
619                requested_extensions.push(vk::KhrImageFormatListFn::name());
620                requested_extensions.push(vk::KhrSamplerYcbcrConversionFn::name());
621                requested_extensions.push(vk::ExtImageDrmFormatModifierFn::name());
622            }
623        }
624        requested_extensions
625    }
626
627    fn load(
628        instance: &Arc<RawInstance>,
629        device: vk::PhysicalDevice,
630    ) -> (Self, PhysicalDeviceFeatures) {
631        let device_properties = unsafe {
632            PhysicalDeviceInfo {
633                supported_extensions: instance
634                    .inner
635                    .enumerate_device_extension_properties(device)
636                    .unwrap(),
637                properties: instance.inner.get_physical_device_properties(device),
638            }
639        };
640
641        let mut features = PhysicalDeviceFeatures::default();
642        features.core = if let Some(ref get_device_properties) =
643            instance.get_physical_device_properties
644        {
645            let core = vk::PhysicalDeviceFeatures::builder().build();
646            let mut features2 = vk::PhysicalDeviceFeatures2KHR::builder()
647                .features(core)
648                .build();
649
650            if device_properties.api_version() >= Version::V1_2 {
651                features.vulkan_1_2 = Some(vk::PhysicalDeviceVulkan12Features::builder().build());
652
653                let mut_ref = features.vulkan_1_2.as_mut().unwrap();
654                mut_ref.p_next = mem::replace(&mut features2.p_next, mut_ref as *mut _ as *mut _);
655            }
656
657            if device_properties.supports_extension(vk::ExtDescriptorIndexingFn::name()) {
658                features.descriptor_indexing =
659                    Some(vk::PhysicalDeviceDescriptorIndexingFeaturesEXT::builder().build());
660
661                let mut_ref = features.descriptor_indexing.as_mut().unwrap();
662                mut_ref.p_next = mem::replace(&mut features2.p_next, mut_ref as *mut _ as *mut _);
663            }
664
665            if device_properties.supports_extension(MeshShader::name()) {
666                features.mesh_shader =
667                    Some(vk::PhysicalDeviceMeshShaderFeaturesNV::builder().build());
668
669                let mut_ref = features.mesh_shader.as_mut().unwrap();
670                mut_ref.p_next = mem::replace(&mut features2.p_next, mut_ref as *mut _ as *mut _);
671            }
672
673            // `VK_KHR_imageless_framebuffer` is promoted to 1.2, but has no changes, so we can keep using the extension unconditionally.
674            if device_properties.supports_extension(vk::KhrImagelessFramebufferFn::name()) {
675                features.imageless_framebuffer =
676                    Some(vk::PhysicalDeviceImagelessFramebufferFeaturesKHR::builder().build());
677
678                let mut_ref = features.imageless_framebuffer.as_mut().unwrap();
679                mut_ref.p_next = mem::replace(&mut features2.p_next, mut_ref as *mut _ as *mut _);
680            }
681
682            match get_device_properties {
683                ExtensionFn::Promoted => {
684                    use ash::version::InstanceV1_1;
685                    unsafe {
686                        instance
687                            .inner
688                            .get_physical_device_features2(device, &mut features2);
689                    }
690                }
691                ExtensionFn::Extension(get_device_properties) => unsafe {
692                    get_device_properties
693                        .get_physical_device_features2_khr(device, &mut features2 as *mut _);
694                },
695            }
696
697            features2.features
698        } else {
699            unsafe { instance.inner.get_physical_device_features(device) }
700        };
701
702        /// # Safety
703        /// `T` must be a struct bigger than `vk::BaseOutStructure`.
704        unsafe fn null_p_next<T>(features: &mut Option<T>) {
705            if let Some(features) = features {
706                // This is technically invalid since `vk::BaseOutStructure` and `T` will probably never have the same size.
707                mem::transmute::<_, &mut vk::BaseOutStructure>(features).p_next = ptr::null_mut();
708            }
709        }
710
711        unsafe {
712            null_p_next(&mut features.vulkan_1_2);
713            null_p_next(&mut features.descriptor_indexing);
714            null_p_next(&mut features.mesh_shader);
715            null_p_next(&mut features.imageless_framebuffer);
716        }
717
718        (device_properties, features)
719    }
720}
721
722pub struct PhysicalDevice {
723    instance: Arc<RawInstance>,
724    pub handle: vk::PhysicalDevice,
725    known_memory_flags: vk::MemoryPropertyFlags,
726    device_info: PhysicalDeviceInfo,
727    device_features: PhysicalDeviceFeatures,
728    available_features: Features,
729}
730
731impl PhysicalDevice {
732    /// # Safety
733    /// `raw_device` must be created from `self` (or from the inner raw handle)
734    /// `raw_device` must be created with `requested_features`
735    pub unsafe fn gpu_from_raw(
736        &self,
737        raw_device: ash::Device,
738        families: &[(&QueueFamily, &[queue::QueuePriority])],
739        requested_features: Features,
740    ) -> Result<adapter::Gpu<Backend>, CreationError> {
741        let enabled_extensions = self.enabled_extensions(requested_features)?;
742        Ok(self.inner_create_gpu(
743            raw_device,
744            true,
745            families,
746            requested_features,
747            enabled_extensions,
748        ))
749    }
750
751    unsafe fn inner_create_gpu(
752        &self,
753        device_raw: ash::Device,
754        handle_is_external: bool,
755        families: &[(&QueueFamily, &[queue::QueuePriority])],
756        requested_features: Features,
757        enabled_extensions: Vec<&CStr>,
758    ) -> adapter::Gpu<Backend> {
759        let valid_ash_memory_types = {
760            let mem_properties = self
761                .instance
762                .inner
763                .get_physical_device_memory_properties(self.handle);
764            mem_properties.memory_types[..mem_properties.memory_type_count as usize]
765                .iter()
766                .enumerate()
767                .fold(0, |u, (i, mem)| {
768                    if self.known_memory_flags.contains(mem.property_flags) {
769                        u | (1 << i)
770                    } else {
771                        u
772                    }
773                })
774        };
775
776        let supports_vulkan12_imageless_framebuffer = self
777            .device_features
778            .vulkan_1_2
779            .map_or(false, |features| features.imageless_framebuffer == vk::TRUE);
780
781        let swapchain_fn = Swapchain::new(&self.instance.inner, &device_raw);
782
783        let mesh_fn = if enabled_extensions.contains(&MeshShader::name()) {
784            Some(ExtensionFn::Extension(MeshShader::new(
785                &self.instance.inner,
786                &device_raw,
787            )))
788        } else {
789            None
790        };
791
792        let indirect_count_fn = if enabled_extensions.contains(&DrawIndirectCount::name()) {
793            Some(ExtensionFn::Extension(DrawIndirectCount::new(
794                &self.instance.inner,
795                &device_raw,
796            )))
797        } else if self.device_info.api_version() >= Version::V1_2 {
798            Some(ExtensionFn::Promoted)
799        } else {
800            None
801        };
802
803        let display_control = if enabled_extensions.contains(&vk::ExtDisplayControlFn::name()) {
804            Some(vk::ExtDisplayControlFn::load(|name| {
805                std::mem::transmute(
806                    self.instance
807                        .inner
808                        .get_device_proc_addr(device_raw.handle(), name.as_ptr()),
809                )
810            }))
811        } else {
812            None
813        };
814
815        let memory_requirements2 =
816            if enabled_extensions.contains(&vk::KhrGetMemoryRequirements2Fn::name()) {
817                Some(ExtensionFn::Extension(
818                    vk::KhrGetMemoryRequirements2Fn::load(|name| {
819                        std::mem::transmute(
820                            self.instance
821                                .inner
822                                .get_device_proc_addr(device_raw.handle(), name.as_ptr()),
823                        )
824                    }),
825                ))
826            } else {
827                None
828            };
829
830        let dedicated_allocation;
831        let external_memory;
832        let external_memory_host;
833
834        #[cfg(unix)]
835        let external_memory_fd;
836
837        #[cfg(any(target_os = "linux", target_os = "android"))]
838        let external_memory_dma_buf;
839
840        #[cfg(any(target_os = "linux", target_os = "android"))]
841        let image_drm_format_modifier;
842
843        #[cfg(windows)]
844        let external_memory_win32;
845
846        if requested_features.contains(Features::EXTERNAL_MEMORY) {
847            if self.device_info.api_version() < Version::V1_1 {
848                external_memory = if enabled_extensions.contains(&vk::KhrExternalMemoryFn::name()) {
849                    Some(ExtensionFn::Extension(()))
850                } else {
851                    None
852                };
853
854                // External memory interact with DedicatedAllocation extension, but it is not a strict dependency.
855                dedicated_allocation =
856                    if enabled_extensions.contains(&vk::KhrDedicatedAllocationFn::name()) {
857                        Some(ExtensionFn::Extension(()))
858                    } else {
859                        None
860                    };
861            } else {
862                external_memory = Some(ExtensionFn::Promoted);
863                dedicated_allocation = Some(ExtensionFn::Promoted);
864            }
865
866            external_memory_host =
867                if enabled_extensions.contains(&vk::ExtExternalMemoryHostFn::name()) {
868                    Some(vk::ExtExternalMemoryHostFn::load(|name| {
869                        std::mem::transmute(
870                            self.instance
871                                .inner
872                                .get_device_proc_addr(device_raw.handle(), name.as_ptr()),
873                        )
874                    }))
875                } else {
876                    None
877                };
878
879            #[cfg(windows)]
880            {
881                external_memory_win32 =
882                    if enabled_extensions.contains(&vk::KhrExternalMemoryWin32Fn::name()) {
883                        Some(vk::KhrExternalMemoryWin32Fn::load(|name| {
884                            std::mem::transmute(
885                                self.instance
886                                    .inner
887                                    .get_device_proc_addr(device_raw.handle(), name.as_ptr()),
888                            )
889                        }))
890                    } else {
891                        None
892                    };
893            }
894            #[cfg(unix)]
895            {
896                external_memory_fd = if enabled_extensions.contains(&ExternalMemoryFd::name()) {
897                    Some(ExternalMemoryFd::new(&self.instance.inner, &device_raw))
898                } else {
899                    None
900                };
901
902                #[cfg(any(target_os = "linux", target_os = "android"))]
903                {
904                    external_memory_dma_buf =
905                        if enabled_extensions.contains(&vk::ExtExternalMemoryDmaBufFn::name()) {
906                            Some(())
907                        } else {
908                            None
909                        };
910
911                    image_drm_format_modifier =
912                        if enabled_extensions.contains(&vk::ExtImageDrmFormatModifierFn::name()) {
913                            Some(vk::ExtImageDrmFormatModifierFn::load(|name| {
914                                std::mem::transmute(
915                                    self.instance
916                                        .inner
917                                        .get_device_proc_addr(device_raw.handle(), name.as_ptr()),
918                                )
919                            }))
920                        } else {
921                            None
922                        };
923                }
924            }
925        } else {
926            dedicated_allocation = None;
927            external_memory = None;
928            external_memory_host = None;
929
930            #[cfg(unix)]
931            {
932                external_memory_fd = None;
933            }
934
935            #[cfg(any(target_os = "linux", target_os = "android"))]
936            {
937                external_memory_dma_buf = None;
938                image_drm_format_modifier = None;
939            }
940
941            #[cfg(windows)]
942            {
943                external_memory_win32 = None;
944            }
945        }
946
947        #[cfg(feature = "naga")]
948        let naga_options = {
949            use naga::back::spv;
950            let capabilities = [
951                spv::Capability::Shader,
952                spv::Capability::Matrix,
953                spv::Capability::InputAttachment,
954                spv::Capability::Sampled1D,
955                spv::Capability::Image1D,
956                spv::Capability::SampledBuffer,
957                spv::Capability::ImageBuffer,
958                spv::Capability::ImageQuery,
959                spv::Capability::DerivativeControl,
960                //TODO: fill out the rest
961            ];
962            let mut flags = spv::WriterFlags::empty();
963            flags.set(spv::WriterFlags::DEBUG, cfg!(debug_assertions));
964            flags.set(
965                spv::WriterFlags::ADJUST_COORDINATE_SPACE,
966                !requested_features.contains(hal::Features::NDC_Y_UP),
967            );
968            spv::Options {
969                lang_version: (1, 0),
970                flags,
971                capabilities: Some(capabilities.iter().cloned().collect()),
972            }
973        };
974
975        let device = Device {
976            shared: Arc::new(RawDevice {
977                raw: device_raw,
978                handle_is_external,
979                features: requested_features,
980                instance: Arc::clone(&self.instance),
981                extension_fns: DeviceExtensionFunctions {
982                    mesh_shaders: mesh_fn,
983                    draw_indirect_count: indirect_count_fn,
984                    display_control,
985                    memory_requirements2: memory_requirements2,
986                    dedicated_allocation: dedicated_allocation,
987                    external_memory,
988                    external_memory_host,
989                    #[cfg(unix)]
990                    external_memory_fd,
991                    #[cfg(windows)]
992                    external_memory_win32,
993                    #[cfg(any(target_os = "linux", target_os = "android"))]
994                    external_memory_dma_buf,
995                    #[cfg(any(target_os = "linux", target_os = "android"))]
996                    image_drm_format_modifier,
997                },
998                flip_y_requires_shift: self.device_info.api_version() >= Version::V1_1
999                    || self
1000                        .device_info
1001                        .supports_extension(vk::KhrMaintenance1Fn::name()),
1002                imageless_framebuffers: supports_vulkan12_imageless_framebuffer
1003                    || self
1004                        .device_info
1005                        .supports_extension(vk::KhrImagelessFramebufferFn::name()),
1006                image_view_usage: self.device_info.api_version() >= Version::V1_1
1007                    || self
1008                        .device_info
1009                        .supports_extension(vk::KhrMaintenance2Fn::name()),
1010                timestamp_period: self.device_info.properties.limits.timestamp_period,
1011            }),
1012            vendor_id: self.device_info.properties.vendor_id,
1013            valid_ash_memory_types,
1014            render_doc: Default::default(),
1015            #[cfg(feature = "naga")]
1016            naga_options,
1017        };
1018
1019        let device_arc = Arc::clone(&device.shared);
1020        let queue_groups = families
1021            .iter()
1022            .map(|&(family, ref priorities)| {
1023                let mut family_raw =
1024                    queue::QueueGroup::new(queue::QueueFamilyId(family.index as usize));
1025                for id in 0..priorities.len() {
1026                    let queue_raw = device_arc.raw.get_device_queue(family.index, id as _);
1027                    family_raw.add_queue(Queue {
1028                        raw: Arc::new(queue_raw),
1029                        device: device_arc.clone(),
1030                        swapchain_fn: swapchain_fn.clone(),
1031                    });
1032                }
1033                family_raw
1034            })
1035            .collect();
1036
1037        adapter::Gpu {
1038            device,
1039            queue_groups,
1040        }
1041    }
1042
1043    pub fn enabled_extensions(
1044        &self,
1045        requested_features: Features,
1046    ) -> Result<Vec<&'static CStr>, CreationError> {
1047        use adapter::PhysicalDevice;
1048
1049        if !self.features().contains(requested_features) {
1050            return Err(CreationError::MissingFeature);
1051        }
1052
1053        let (supported_extensions, unsupported_extensions) = self
1054            .device_info
1055            .get_required_extensions(requested_features)
1056            .iter()
1057            .partition::<Vec<&CStr>, _>(|&&extension| {
1058                self.device_info.supports_extension(extension)
1059            });
1060
1061        if !unsupported_extensions.is_empty() {
1062            warn!("Missing extensions: {:?}", unsupported_extensions);
1063        }
1064
1065        debug!("Supported extensions: {:?}", supported_extensions);
1066
1067        Ok(supported_extensions)
1068    }
1069}
1070
1071pub(crate) fn load_adapter(
1072    instance: &Arc<RawInstance>,
1073    device: vk::PhysicalDevice,
1074) -> adapter::Adapter<Backend> {
1075    let (device_info, device_features) = PhysicalDeviceInfo::load(instance, device);
1076
1077    let info = adapter::AdapterInfo {
1078        name: unsafe {
1079            CStr::from_ptr(device_info.properties.device_name.as_ptr())
1080                .to_str()
1081                .unwrap_or("Unknown")
1082                .to_owned()
1083        },
1084        vendor: device_info.properties.vendor_id as usize,
1085        device: device_info.properties.device_id as usize,
1086        device_type: match device_info.properties.device_type {
1087            ash::vk::PhysicalDeviceType::OTHER => adapter::DeviceType::Other,
1088            ash::vk::PhysicalDeviceType::INTEGRATED_GPU => adapter::DeviceType::IntegratedGpu,
1089            ash::vk::PhysicalDeviceType::DISCRETE_GPU => adapter::DeviceType::DiscreteGpu,
1090            ash::vk::PhysicalDeviceType::VIRTUAL_GPU => adapter::DeviceType::VirtualGpu,
1091            ash::vk::PhysicalDeviceType::CPU => adapter::DeviceType::Cpu,
1092            _ => adapter::DeviceType::Other,
1093        },
1094    };
1095
1096    let available_features = {
1097        let mut bits = device_features.to_hal_features(&device_info);
1098
1099        // see https://github.com/gfx-rs/gfx/issues/1930
1100        let is_windows_intel_dual_src_bug = cfg!(windows)
1101            && device_info.properties.vendor_id == info::intel::VENDOR
1102            && (device_info.properties.device_id & info::intel::DEVICE_KABY_LAKE_MASK
1103                == info::intel::DEVICE_KABY_LAKE_MASK
1104                || device_info.properties.device_id & info::intel::DEVICE_SKY_LAKE_MASK
1105                    == info::intel::DEVICE_SKY_LAKE_MASK);
1106        if is_windows_intel_dual_src_bug {
1107            bits.set(Features::DUAL_SRC_BLENDING, false);
1108        }
1109
1110        bits
1111    };
1112
1113    let physical_device = PhysicalDevice {
1114        instance: instance.clone(),
1115        handle: device,
1116        known_memory_flags: vk::MemoryPropertyFlags::DEVICE_LOCAL
1117            | vk::MemoryPropertyFlags::HOST_VISIBLE
1118            | vk::MemoryPropertyFlags::HOST_COHERENT
1119            | vk::MemoryPropertyFlags::HOST_CACHED
1120            | vk::MemoryPropertyFlags::LAZILY_ALLOCATED,
1121        device_info,
1122        device_features,
1123        available_features,
1124    };
1125
1126    let queue_families = unsafe {
1127        instance
1128            .inner
1129            .get_physical_device_queue_family_properties(device)
1130            .into_iter()
1131            .enumerate()
1132            .map(|(i, properties)| QueueFamily {
1133                properties,
1134                device,
1135                index: i as u32,
1136            })
1137            .collect()
1138    };
1139
1140    adapter::Adapter {
1141        info,
1142        physical_device,
1143        queue_families,
1144    }
1145}
1146
1147impl fmt::Debug for PhysicalDevice {
1148    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1149        f.debug_struct("PhysicalDevice").finish()
1150    }
1151}
1152
1153impl adapter::PhysicalDevice<Backend> for PhysicalDevice {
1154    unsafe fn open(
1155        &self,
1156        families: &[(&QueueFamily, &[queue::QueuePriority])],
1157        requested_features: Features,
1158    ) -> Result<adapter::Gpu<Backend>, CreationError> {
1159        let family_infos = families
1160            .iter()
1161            .map(|&(family, priorities)| {
1162                vk::DeviceQueueCreateInfo::builder()
1163                    .flags(vk::DeviceQueueCreateFlags::empty())
1164                    .queue_family_index(family.index)
1165                    .queue_priorities(priorities)
1166                    .build()
1167            })
1168            .collect::<Vec<_>>();
1169
1170        let enabled_extensions = self.enabled_extensions(requested_features)?;
1171
1172        let supports_vulkan12_imageless_framebuffer = self
1173            .device_features
1174            .vulkan_1_2
1175            .map_or(false, |features| features.imageless_framebuffer == vk::TRUE);
1176
1177        // Create device
1178        let device_raw = {
1179            let str_pointers = enabled_extensions
1180                .iter()
1181                .map(|&s| {
1182                    // Safe because `enabled_extensions` entries have static lifetime.
1183                    s.as_ptr()
1184                })
1185                .collect::<Vec<_>>();
1186
1187            let mut enabled_features =
1188                PhysicalDeviceFeatures::from_extensions_and_requested_features(
1189                    self.device_info.api_version(),
1190                    &enabled_extensions,
1191                    requested_features,
1192                    supports_vulkan12_imageless_framebuffer,
1193                );
1194            let info = vk::DeviceCreateInfo::builder()
1195                .queue_create_infos(&family_infos)
1196                .enabled_extension_names(&str_pointers);
1197            let info = enabled_features.add_to_device_create_builder(info);
1198
1199            match self.instance.inner.create_device(self.handle, &info, None) {
1200                Ok(device) => device,
1201                Err(e) => {
1202                    return Err(match e {
1203                        vk::Result::ERROR_OUT_OF_HOST_MEMORY => {
1204                            CreationError::OutOfMemory(OutOfMemory::Host)
1205                        }
1206                        vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => {
1207                            CreationError::OutOfMemory(OutOfMemory::Device)
1208                        }
1209                        vk::Result::ERROR_INITIALIZATION_FAILED => {
1210                            CreationError::InitializationFailed
1211                        }
1212                        vk::Result::ERROR_DEVICE_LOST => CreationError::DeviceLost,
1213                        vk::Result::ERROR_TOO_MANY_OBJECTS => CreationError::TooManyObjects,
1214                        _ => {
1215                            error!("Unknown device creation error: {:?}", e);
1216                            CreationError::InitializationFailed
1217                        }
1218                    })
1219                }
1220            }
1221        };
1222
1223        Ok(self.inner_create_gpu(
1224            device_raw,
1225            false,
1226            families,
1227            requested_features,
1228            enabled_extensions,
1229        ))
1230    }
1231
1232    fn format_properties(&self, format: Option<format::Format>) -> format::Properties {
1233        let supports_transfer_bits = self
1234            .device_info
1235            .supports_extension(vk::KhrMaintenance1Fn::name());
1236
1237        let supports_sampler_filter_minmax = self
1238            .available_features
1239            .contains(Features::SAMPLER_REDUCTION);
1240
1241        let (properties, drm_format_properties) = unsafe {
1242            match self.instance.get_physical_device_properties {
1243                None => {
1244                    let format_properties =
1245                        self.instance.inner.get_physical_device_format_properties(
1246                            self.handle,
1247                            format.map_or(vk::Format::UNDEFINED, conv::map_format),
1248                        );
1249                    (format_properties, Vec::new())
1250                }
1251                Some(ref extension) => {
1252                    let mut raw_format_modifiers: Vec<vk::DrmFormatModifierPropertiesEXT> = Vec::new();
1253                    let mut drm_format_properties =
1254                        vk::DrmFormatModifierPropertiesListEXT::builder().build();
1255                    let mut format_properties2 = vk::FormatProperties2::builder()
1256                        .push_next(&mut drm_format_properties)
1257                        .build();
1258                    // Ash does not implement the "double call" behaviour for this function, so it is implemented here.
1259                    match extension {
1260                        ExtensionFn::Promoted => {
1261                            use ash::version::InstanceV1_1;
1262                            self.instance.inner.get_physical_device_format_properties2(
1263                                self.handle,
1264                                format.map_or(vk::Format::UNDEFINED, conv::map_format),
1265                                &mut format_properties2,
1266                            );
1267                            raw_format_modifiers.reserve_exact(drm_format_properties.drm_format_modifier_count as usize);
1268                            drm_format_properties.p_drm_format_modifier_properties = raw_format_modifiers.as_mut_ptr();
1269                            self.instance.inner.get_physical_device_format_properties2(
1270                                self.handle,
1271                                format.map_or(vk::Format::UNDEFINED, conv::map_format),
1272                                &mut format_properties2,
1273                            );
1274                            raw_format_modifiers.set_len(drm_format_properties.drm_format_modifier_count as usize);
1275                        }
1276                        ExtensionFn::Extension(extension) => {
1277                            extension.get_physical_device_format_properties2_khr(
1278                                self.handle,
1279                                format.map_or(vk::Format::UNDEFINED, conv::map_format),
1280                                &mut format_properties2,
1281                            );
1282                            raw_format_modifiers.reserve_exact(drm_format_properties.drm_format_modifier_count as usize);
1283                            drm_format_properties.p_drm_format_modifier_properties = raw_format_modifiers.as_mut_ptr();
1284                            extension.get_physical_device_format_properties2_khr(
1285                                self.handle,
1286                                format.map_or(vk::Format::UNDEFINED, conv::map_format),
1287                                &mut format_properties2,
1288                            );
1289                            raw_format_modifiers.set_len(drm_format_properties.drm_format_modifier_count as usize);
1290                        }
1291                    }
1292
1293                    let format_modifiers: Vec<format::DrmFormatProperties> = raw_format_modifiers
1294                        .into_iter()
1295                        .filter_map(|format_modifier_properties| {
1296                            let format_modifier = format::DrmModifier::from(
1297                                format_modifier_properties.drm_format_modifier,
1298                            );
1299                            if let format::DrmModifier::Unrecognized(value) = format_modifier {
1300                                error!("Unrecognized drm format modifier: {:#?}", value);
1301                                None
1302                            } else {
1303                                Some(format::DrmFormatProperties {
1304                                    drm_modifier: format_modifier,
1305                                    plane_count: format_modifier_properties
1306                                        .drm_format_modifier_plane_count,
1307                                    valid_usages: conv::map_image_features(
1308                                        format_modifier_properties
1309                                            .drm_format_modifier_tiling_features,
1310                                        supports_transfer_bits,
1311                                        supports_sampler_filter_minmax,
1312                                    ),
1313                                })
1314                            }
1315                        })
1316                        .collect();
1317                    (format_properties2.format_properties, format_modifiers)
1318                }
1319            }
1320        };
1321
1322        format::Properties {
1323            linear_tiling: conv::map_image_features(
1324                properties.linear_tiling_features,
1325                supports_transfer_bits,
1326                supports_sampler_filter_minmax,
1327            ),
1328            optimal_tiling: conv::map_image_features(
1329                properties.optimal_tiling_features,
1330                supports_transfer_bits,
1331                supports_sampler_filter_minmax,
1332            ),
1333            buffer_features: conv::map_buffer_features(properties.buffer_features),
1334            drm_format_properties,
1335        }
1336    }
1337
1338    fn image_format_properties(
1339        &self,
1340        format: format::Format,
1341        dimensions: u8,
1342        tiling: image::Tiling,
1343        usage: image::Usage,
1344        view_caps: image::ViewCapabilities,
1345    ) -> Option<image::FormatProperties> {
1346        let format_properties = unsafe {
1347            self.instance
1348                .inner
1349                .get_physical_device_image_format_properties(
1350                    self.handle,
1351                    conv::map_format(format),
1352                    match dimensions {
1353                        1 => vk::ImageType::TYPE_1D,
1354                        2 => vk::ImageType::TYPE_2D,
1355                        3 => vk::ImageType::TYPE_3D,
1356                        _ => panic!("Unexpected image dimensionality: {}", dimensions),
1357                    },
1358                    conv::map_tiling(tiling),
1359                    conv::map_image_usage(usage),
1360                    conv::map_view_capabilities(view_caps),
1361                )
1362        };
1363
1364        match format_properties {
1365            Ok(props) => Some(image::FormatProperties {
1366                max_extent: image::Extent {
1367                    width: props.max_extent.width,
1368                    height: props.max_extent.height,
1369                    depth: props.max_extent.depth,
1370                },
1371                max_levels: props.max_mip_levels as _,
1372                max_layers: props.max_array_layers as _,
1373                sample_count_mask: props.sample_counts.as_raw() as _,
1374                max_resource_size: props.max_resource_size as _,
1375            }),
1376            Err(vk::Result::ERROR_FORMAT_NOT_SUPPORTED) => None,
1377            Err(other) => {
1378                error!("Unexpected error in `image_format_properties`: {:?}", other);
1379                None
1380            }
1381        }
1382    }
1383
1384    fn memory_properties(&self) -> adapter::MemoryProperties {
1385        let mem_properties = unsafe {
1386            self.instance
1387                .inner
1388                .get_physical_device_memory_properties(self.handle)
1389        };
1390        let memory_heaps = mem_properties.memory_heaps[..mem_properties.memory_heap_count as usize]
1391            .iter()
1392            .map(|mem| adapter::MemoryHeap {
1393                size: mem.size,
1394                flags: conv::map_vk_memory_heap_flags(mem.flags),
1395            })
1396            .collect();
1397        let memory_types = mem_properties.memory_types[..mem_properties.memory_type_count as usize]
1398            .iter()
1399            .filter_map(|mem| {
1400                if self.known_memory_flags.contains(mem.property_flags) {
1401                    Some(adapter::MemoryType {
1402                        properties: conv::map_vk_memory_properties(mem.property_flags),
1403                        heap_index: mem.heap_index as usize,
1404                    })
1405                } else {
1406                    warn!(
1407                        "Skipping memory type with unknown flags {:?}",
1408                        mem.property_flags
1409                    );
1410                    None
1411                }
1412            })
1413            .collect();
1414
1415        adapter::MemoryProperties {
1416            memory_heaps,
1417            memory_types,
1418        }
1419    }
1420
1421    fn external_buffer_properties(
1422        &self,
1423        usage: hal::buffer::Usage,
1424        sparse: hal::memory::SparseFlags,
1425        external_memory_type: external_memory::ExternalMemoryType,
1426    ) -> external_memory::ExternalMemoryProperties {
1427        let external_memory_type_flags: hal::external_memory::ExternalMemoryTypeFlags =
1428            external_memory_type.into();
1429        let vk_external_memory_type =
1430            vk::ExternalMemoryHandleTypeFlags::from_raw(external_memory_type_flags.bits());
1431
1432        let external_buffer_info = vk::PhysicalDeviceExternalBufferInfo::builder()
1433            .flags(conv::map_buffer_create_flags(sparse))
1434            .usage(conv::map_buffer_usage(usage))
1435            .handle_type(vk_external_memory_type)
1436            .build();
1437
1438        let vk_mem_properties = match self.instance.external_memory_capabilities.as_ref() {
1439            Some(ExtensionFn::Extension(external_memory_capabilities_extension)) => {
1440                let mut external_buffer_properties =
1441                    vk::ExternalBufferProperties::builder().build();
1442                unsafe {
1443                    external_memory_capabilities_extension
1444                        .get_physical_device_external_buffer_properties_khr(
1445                            self.handle,
1446                            &external_buffer_info,
1447                            &mut external_buffer_properties,
1448                        )
1449                };
1450                external_buffer_properties.external_memory_properties
1451            }
1452            Some(ExtensionFn::Promoted) => {
1453                use ash::version::InstanceV1_1;
1454                let mut external_buffer_properties =
1455                    vk::ExternalBufferProperties::builder().build();
1456                unsafe {
1457                    self.instance
1458                        .inner
1459                        .get_physical_device_external_buffer_properties(
1460                            self.handle,
1461                            &external_buffer_info,
1462                            &mut external_buffer_properties,
1463                        )
1464                }
1465                external_buffer_properties.external_memory_properties
1466            }
1467            None => panic!(
1468                "This function rely on `Feature::EXTERNAL_MEMORY`, but the feature is not enabled"
1469            ),
1470        };
1471
1472        let mut external_memory_properties = external_memory::ExternalMemoryProperties::empty();
1473        if vk_mem_properties
1474            .external_memory_features
1475            .contains(vk::ExternalMemoryFeatureFlags::EXPORTABLE)
1476        {
1477            external_memory_properties |= external_memory::ExternalMemoryProperties::EXPORTABLE;
1478        }
1479
1480        if vk_mem_properties
1481            .external_memory_features
1482            .contains(vk::ExternalMemoryFeatureFlags::IMPORTABLE)
1483        {
1484            external_memory_properties |= external_memory::ExternalMemoryProperties::IMPORTABLE;
1485        }
1486
1487        if vk_mem_properties
1488            .export_from_imported_handle_types
1489            .contains(vk_external_memory_type)
1490        {
1491            external_memory_properties |=
1492                external_memory::ExternalMemoryProperties::EXPORTABLE_FROM_IMPORTED;
1493        }
1494
1495        external_memory_properties
1496    }
1497
1498    fn external_image_properties(
1499        &self,
1500        format: format::Format,
1501        dimensions: u8,
1502        tiling: image::Tiling,
1503        usage: image::Usage,
1504        view_caps: image::ViewCapabilities,
1505        external_memory_type: external_memory::ExternalMemoryType,
1506    ) -> Result<external_memory::ExternalMemoryProperties, external_memory::ExternalImagePropertiesError>
1507    {
1508        if self.instance.external_memory_capabilities.is_none() {
1509            panic!(
1510                "This function rely on `Feature::EXTERNAL_MEMORY`, but the feature is not enabled"
1511            );
1512        }
1513
1514        use ash::version::InstanceV1_1;
1515        let external_memory_type_flags: hal::external_memory::ExternalMemoryTypeFlags =
1516            external_memory_type.into();
1517        let vk_external_memory_type =
1518            vk::ExternalMemoryHandleTypeFlags::from_raw(external_memory_type_flags.bits());
1519
1520        let mut external_image_format_info = vk::PhysicalDeviceExternalImageFormatInfo::builder()
1521            .handle_type(vk_external_memory_type)
1522            .build();
1523        let image_format_info = vk::PhysicalDeviceImageFormatInfo2::builder()
1524            .push_next(&mut external_image_format_info)
1525            .format(conv::map_format(format))
1526            .ty(match dimensions {
1527                1 => vk::ImageType::TYPE_1D,
1528                2 => vk::ImageType::TYPE_2D,
1529                3 => vk::ImageType::TYPE_3D,
1530                _ => panic!("Unexpected image dimensionality: {}", dimensions),
1531            })
1532            .tiling(conv::map_tiling(tiling))
1533            .usage(conv::map_image_usage(usage))
1534            .flags(conv::map_view_capabilities(view_caps))
1535            .build();
1536
1537        let mut external_image_format_properties =
1538            vk::ExternalImageFormatProperties::builder().build();
1539        let mut image_format_properties = vk::ImageFormatProperties2::builder()
1540            .push_next(&mut external_image_format_properties)
1541            .build();
1542
1543        match unsafe {
1544            self.instance
1545                .inner
1546                .get_physical_device_image_format_properties2(
1547                    self.handle,
1548                    &image_format_info,
1549                    &mut image_format_properties,
1550                )
1551        } {
1552            Ok(_) => {
1553                let vk_mem_properties = external_image_format_properties.external_memory_properties;
1554
1555                let mut external_memory_properties =
1556                    external_memory::ExternalMemoryProperties::empty();
1557                if vk_mem_properties
1558                    .external_memory_features
1559                    .contains(vk::ExternalMemoryFeatureFlags::EXPORTABLE)
1560                {
1561                    external_memory_properties |=
1562                        external_memory::ExternalMemoryProperties::EXPORTABLE;
1563                }
1564
1565                if vk_mem_properties
1566                    .external_memory_features
1567                    .contains(vk::ExternalMemoryFeatureFlags::IMPORTABLE)
1568                {
1569                    external_memory_properties |=
1570                        external_memory::ExternalMemoryProperties::IMPORTABLE;
1571                }
1572
1573                if vk_mem_properties
1574                    .export_from_imported_handle_types
1575                    .contains(vk_external_memory_type)
1576                {
1577                    external_memory_properties |=
1578                        external_memory::ExternalMemoryProperties::EXPORTABLE_FROM_IMPORTED;
1579                }
1580                Ok(external_memory_properties)
1581            }
1582            Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(OutOfMemory::Host.into()),
1583            Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => Err(OutOfMemory::Device.into()),
1584            Err(vk::Result::ERROR_FORMAT_NOT_SUPPORTED) => {
1585                Err(external_memory::ExternalImagePropertiesError::FormatNotSupported)
1586            }
1587            Err(err) => {
1588                panic!("Unexpected error: {:#?}", err);
1589            }
1590        }
1591    }
1592
1593    fn features(&self) -> Features {
1594        self.available_features
1595    }
1596
1597    fn properties(&self) -> PhysicalDeviceProperties {
1598        let limits = {
1599            let limits = &self.device_info.properties.limits;
1600
1601            let max_group_count = limits.max_compute_work_group_count;
1602            let max_group_size = limits.max_compute_work_group_size;
1603
1604            Limits {
1605                max_image_1d_size: limits.max_image_dimension1_d,
1606                max_image_2d_size: limits.max_image_dimension2_d,
1607                max_image_3d_size: limits.max_image_dimension3_d,
1608                max_image_cube_size: limits.max_image_dimension_cube,
1609                max_image_array_layers: limits.max_image_array_layers as _,
1610                max_texel_elements: limits.max_texel_buffer_elements as _,
1611                max_patch_size: limits.max_tessellation_patch_size as PatchSize,
1612                max_viewports: limits.max_viewports as _,
1613                max_viewport_dimensions: limits.max_viewport_dimensions,
1614                max_framebuffer_extent: image::Extent {
1615                    width: limits.max_framebuffer_width,
1616                    height: limits.max_framebuffer_height,
1617                    depth: limits.max_framebuffer_layers,
1618                },
1619                max_compute_work_group_count: [
1620                    max_group_count[0] as _,
1621                    max_group_count[1] as _,
1622                    max_group_count[2] as _,
1623                ],
1624                max_compute_work_group_size: [
1625                    max_group_size[0] as _,
1626                    max_group_size[1] as _,
1627                    max_group_size[2] as _,
1628                ],
1629                max_vertex_input_attributes: limits.max_vertex_input_attributes as _,
1630                max_vertex_input_bindings: limits.max_vertex_input_bindings as _,
1631                max_vertex_input_attribute_offset: limits.max_vertex_input_attribute_offset as _,
1632                max_vertex_input_binding_stride: limits.max_vertex_input_binding_stride as _,
1633                max_vertex_output_components: limits.max_vertex_output_components as _,
1634                optimal_buffer_copy_offset_alignment: limits.optimal_buffer_copy_offset_alignment
1635                    as _,
1636                optimal_buffer_copy_pitch_alignment: limits.optimal_buffer_copy_row_pitch_alignment
1637                    as _,
1638                min_texel_buffer_offset_alignment: limits.min_texel_buffer_offset_alignment as _,
1639                min_uniform_buffer_offset_alignment: limits.min_uniform_buffer_offset_alignment
1640                    as _,
1641                min_storage_buffer_offset_alignment: limits.min_storage_buffer_offset_alignment
1642                    as _,
1643                framebuffer_color_sample_counts: limits.framebuffer_color_sample_counts.as_raw()
1644                    as _,
1645                framebuffer_depth_sample_counts: limits.framebuffer_depth_sample_counts.as_raw()
1646                    as _,
1647                framebuffer_stencil_sample_counts: limits.framebuffer_stencil_sample_counts.as_raw()
1648                    as _,
1649                timestamp_compute_and_graphics: limits.timestamp_compute_and_graphics != 0,
1650                max_color_attachments: limits.max_color_attachments as _,
1651                buffer_image_granularity: limits.buffer_image_granularity,
1652                non_coherent_atom_size: limits.non_coherent_atom_size as _,
1653                max_sampler_anisotropy: limits.max_sampler_anisotropy,
1654                min_vertex_input_binding_stride_alignment: 1,
1655                max_bound_descriptor_sets: limits.max_bound_descriptor_sets as _,
1656                max_compute_shared_memory_size: limits.max_compute_shared_memory_size as _,
1657                max_compute_work_group_invocations: limits.max_compute_work_group_invocations as _,
1658                descriptor_limits: DescriptorLimits {
1659                    max_per_stage_descriptor_samplers: limits.max_per_stage_descriptor_samplers,
1660                    max_per_stage_descriptor_storage_buffers: limits
1661                        .max_per_stage_descriptor_storage_buffers,
1662                    max_per_stage_descriptor_uniform_buffers: limits
1663                        .max_per_stage_descriptor_uniform_buffers,
1664                    max_per_stage_descriptor_sampled_images: limits
1665                        .max_per_stage_descriptor_sampled_images,
1666                    max_per_stage_descriptor_storage_images: limits
1667                        .max_per_stage_descriptor_storage_images,
1668                    max_per_stage_descriptor_input_attachments: limits
1669                        .max_per_stage_descriptor_input_attachments,
1670                    max_per_stage_resources: limits.max_per_stage_resources,
1671                    max_descriptor_set_samplers: limits.max_descriptor_set_samplers,
1672                    max_descriptor_set_uniform_buffers: limits.max_descriptor_set_uniform_buffers,
1673                    max_descriptor_set_uniform_buffers_dynamic: limits
1674                        .max_descriptor_set_uniform_buffers_dynamic,
1675                    max_descriptor_set_storage_buffers: limits.max_descriptor_set_storage_buffers,
1676                    max_descriptor_set_storage_buffers_dynamic: limits
1677                        .max_descriptor_set_storage_buffers_dynamic,
1678                    max_descriptor_set_sampled_images: limits.max_descriptor_set_sampled_images,
1679                    max_descriptor_set_storage_images: limits.max_descriptor_set_storage_images,
1680                    max_descriptor_set_input_attachments: limits
1681                        .max_descriptor_set_input_attachments,
1682                },
1683                max_draw_indexed_index_value: limits.max_draw_indexed_index_value,
1684                max_draw_indirect_count: limits.max_draw_indirect_count,
1685                max_fragment_combined_output_resources: limits
1686                    .max_fragment_combined_output_resources
1687                    as _,
1688                max_fragment_dual_source_attachments: limits.max_fragment_dual_src_attachments as _,
1689                max_fragment_input_components: limits.max_fragment_input_components as _,
1690                max_fragment_output_attachments: limits.max_fragment_output_attachments as _,
1691                max_framebuffer_layers: limits.max_framebuffer_layers as _,
1692                max_geometry_input_components: limits.max_geometry_input_components as _,
1693                max_geometry_output_components: limits.max_geometry_output_components as _,
1694                max_geometry_output_vertices: limits.max_geometry_output_vertices as _,
1695                max_geometry_shader_invocations: limits.max_geometry_shader_invocations as _,
1696                max_geometry_total_output_components: limits.max_geometry_total_output_components
1697                    as _,
1698                max_memory_allocation_count: limits.max_memory_allocation_count as _,
1699                max_push_constants_size: limits.max_push_constants_size as _,
1700                max_sampler_allocation_count: limits.max_sampler_allocation_count as _,
1701                max_sampler_lod_bias: limits.max_sampler_lod_bias as _,
1702                max_storage_buffer_range: limits.max_storage_buffer_range as _,
1703                max_uniform_buffer_range: limits.max_uniform_buffer_range as _,
1704                min_memory_map_alignment: limits.min_memory_map_alignment,
1705                standard_sample_locations: limits.standard_sample_locations == ash::vk::TRUE,
1706            }
1707        };
1708
1709        let mut descriptor_indexing_capabilities = hal::DescriptorIndexingProperties::default();
1710        let mut mesh_shader_capabilities = hal::MeshShaderProperties::default();
1711        let mut sampler_reduction_capabilities = hal::SamplerReductionProperties::default();
1712        let mut external_memory_limits = hal::ExternalMemoryLimits::default();
1713
1714        if let Some(get_physical_device_properties) =
1715            self.instance.get_physical_device_properties.as_ref()
1716        {
1717            let mut descriptor_indexing_properties =
1718                vk::PhysicalDeviceDescriptorIndexingPropertiesEXT::builder();
1719            let mut mesh_shader_properties = vk::PhysicalDeviceMeshShaderPropertiesNV::builder();
1720            let mut sampler_reduction_properties =
1721                vk::PhysicalDeviceSamplerFilterMinmaxProperties::builder();
1722            let mut memory_host_properties =
1723                vk::PhysicalDeviceExternalMemoryHostPropertiesEXT::builder();
1724
1725            let mut physical_device_properties2 = vk::PhysicalDeviceProperties2::builder()
1726                .push_next(&mut descriptor_indexing_properties)
1727                .push_next(&mut mesh_shader_properties)
1728                .push_next(&mut sampler_reduction_properties)
1729                .push_next(&mut memory_host_properties)
1730                .build();
1731
1732            match get_physical_device_properties {
1733                ExtensionFn::Promoted => {
1734                    use ash::version::InstanceV1_1;
1735                    unsafe {
1736                        self.instance.inner.get_physical_device_properties2(
1737                            self.handle,
1738                            &mut physical_device_properties2,
1739                        );
1740                    }
1741                }
1742                ExtensionFn::Extension(get_physical_device_properties) => unsafe {
1743                    get_physical_device_properties.get_physical_device_properties2_khr(
1744                        self.handle,
1745                        &mut physical_device_properties2,
1746                    );
1747                },
1748            }
1749
1750            descriptor_indexing_capabilities = hal::DescriptorIndexingProperties {
1751                shader_uniform_buffer_array_non_uniform_indexing_native:
1752                    descriptor_indexing_properties
1753                        .shader_uniform_buffer_array_non_uniform_indexing_native
1754                        == vk::TRUE,
1755                shader_sampled_image_array_non_uniform_indexing_native:
1756                    descriptor_indexing_properties
1757                        .shader_sampled_image_array_non_uniform_indexing_native
1758                        == vk::TRUE,
1759                shader_storage_buffer_array_non_uniform_indexing_native:
1760                    descriptor_indexing_properties
1761                        .shader_storage_buffer_array_non_uniform_indexing_native
1762                        == vk::TRUE,
1763                shader_storage_image_array_non_uniform_indexing_native:
1764                    descriptor_indexing_properties
1765                        .shader_storage_image_array_non_uniform_indexing_native
1766                        == vk::TRUE,
1767                shader_input_attachment_array_non_uniform_indexing_native:
1768                    descriptor_indexing_properties
1769                        .shader_input_attachment_array_non_uniform_indexing_native
1770                        == vk::TRUE,
1771                quad_divergent_implicit_lod: descriptor_indexing_properties
1772                    .quad_divergent_implicit_lod
1773                    == vk::TRUE,
1774            };
1775
1776            mesh_shader_capabilities = hal::MeshShaderProperties {
1777                max_draw_mesh_tasks_count: mesh_shader_properties.max_draw_mesh_tasks_count,
1778                max_task_work_group_invocations: mesh_shader_properties
1779                    .max_task_work_group_invocations,
1780                max_task_work_group_size: mesh_shader_properties.max_task_work_group_size,
1781                max_task_total_memory_size: mesh_shader_properties.max_task_total_memory_size,
1782                max_task_output_count: mesh_shader_properties.max_task_output_count,
1783                max_mesh_work_group_invocations: mesh_shader_properties
1784                    .max_mesh_work_group_invocations,
1785                max_mesh_work_group_size: mesh_shader_properties.max_mesh_work_group_size,
1786                max_mesh_total_memory_size: mesh_shader_properties.max_mesh_total_memory_size,
1787                max_mesh_output_vertices: mesh_shader_properties.max_mesh_output_vertices,
1788                max_mesh_output_primitives: mesh_shader_properties.max_mesh_output_primitives,
1789                max_mesh_multiview_view_count: mesh_shader_properties.max_mesh_multiview_view_count,
1790                mesh_output_per_vertex_granularity: mesh_shader_properties
1791                    .mesh_output_per_vertex_granularity,
1792                mesh_output_per_primitive_granularity: mesh_shader_properties
1793                    .mesh_output_per_primitive_granularity,
1794            };
1795
1796            sampler_reduction_capabilities = hal::SamplerReductionProperties {
1797                single_component_formats: sampler_reduction_properties
1798                    .filter_minmax_single_component_formats
1799                    == vk::TRUE,
1800                image_component_mapping: sampler_reduction_properties
1801                    .filter_minmax_image_component_mapping
1802                    == vk::TRUE,
1803            };
1804
1805            external_memory_limits = ExternalMemoryLimits {
1806                min_imported_host_pointer_alignment: memory_host_properties
1807                    .min_imported_host_pointer_alignment,
1808            };
1809        }
1810
1811        PhysicalDeviceProperties {
1812            limits,
1813            descriptor_indexing: descriptor_indexing_capabilities,
1814            mesh_shader: mesh_shader_capabilities,
1815            sampler_reduction: sampler_reduction_capabilities,
1816            performance_caveats: Default::default(),
1817            dynamic_pipeline_states: DynamicStates::all(),
1818            downlevel: DownlevelProperties::all_enabled(),
1819            external_memory_limits,
1820        }
1821    }
1822
1823    fn is_valid_cache(&self, cache: &[u8]) -> bool {
1824        const HEADER_SIZE: usize = 16 + vk::UUID_SIZE;
1825
1826        if cache.len() < HEADER_SIZE {
1827            warn!("Bad cache data length {:?}", cache.len());
1828            return false;
1829        }
1830
1831        let header_len = u32::from_le_bytes([cache[0], cache[1], cache[2], cache[3]]);
1832        let header_version = u32::from_le_bytes([cache[4], cache[5], cache[6], cache[7]]);
1833        let vendor_id = u32::from_le_bytes([cache[8], cache[9], cache[10], cache[11]]);
1834        let device_id = u32::from_le_bytes([cache[12], cache[13], cache[14], cache[15]]);
1835
1836        // header length
1837        if (header_len as usize) < HEADER_SIZE {
1838            warn!("Bad header length {:?}", header_len);
1839            return false;
1840        }
1841
1842        // cache header version
1843        if header_version != vk::PipelineCacheHeaderVersion::ONE.as_raw() as u32 {
1844            warn!("Unsupported cache header version: {:?}", header_version);
1845            return false;
1846        }
1847
1848        // vendor id
1849        if vendor_id != self.device_info.properties.vendor_id {
1850            warn!(
1851                "Vendor ID mismatch. Device: {:?}, cache: {:?}.",
1852                self.device_info.properties.vendor_id, vendor_id,
1853            );
1854            return false;
1855        }
1856
1857        // device id
1858        if device_id != self.device_info.properties.device_id {
1859            warn!(
1860                "Device ID mismatch. Device: {:?}, cache: {:?}.",
1861                self.device_info.properties.device_id, device_id,
1862            );
1863            return false;
1864        }
1865
1866        if self.device_info.properties.pipeline_cache_uuid != cache[16..16 + vk::UUID_SIZE] {
1867            warn!(
1868                "Pipeline cache UUID mismatch. Device: {:?}, cache: {:?}.",
1869                self.device_info.properties.pipeline_cache_uuid,
1870                &cache[16..16 + vk::UUID_SIZE],
1871            );
1872            return false;
1873        }
1874        true
1875    }
1876
1877    unsafe fn enumerate_displays(&self) -> Vec<display::Display<Backend>> {
1878        let display_extension = match self.instance.display {
1879            Some(ref display_extension) => display_extension,
1880            None => {
1881                error!("Direct display feature not supported");
1882                return Vec::new();
1883            }
1884        };
1885
1886        let display_properties =
1887            match display_extension.get_physical_device_display_properties(self.handle) {
1888                Ok(display_properties) => display_properties,
1889                Err(err) => {
1890                    match err {
1891                        vk::Result::ERROR_OUT_OF_HOST_MEMORY
1892                        | vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => error!(
1893                            "Error returned on `get_physical_device_display_properties`: {:#?}",
1894                            err
1895                        ),
1896                        err => error!(
1897                            "Unexpected error on `get_physical_device_display_properties`: {:#?}",
1898                            err
1899                        ),
1900                    }
1901                    return Vec::new();
1902                }
1903            };
1904
1905        let mut displays = Vec::new();
1906        for display_property in display_properties {
1907            let supported_transforms = hal::display::SurfaceTransformFlags::from_bits(
1908                display_property.supported_transforms.as_raw(),
1909            )
1910            .unwrap();
1911            let display_name = if display_property.display_name.is_null() {
1912                None
1913            } else {
1914                Some(
1915                    std::ffi::CStr::from_ptr(display_property.display_name)
1916                        .to_str()
1917                        .unwrap()
1918                        .to_owned(),
1919                )
1920            };
1921
1922            let display_info = display::DisplayInfo {
1923                name: display_name,
1924                physical_dimensions: (
1925                    display_property.physical_dimensions.width,
1926                    display_property.physical_dimensions.height,
1927                )
1928                    .into(),
1929                physical_resolution: (
1930                    display_property.physical_resolution.width,
1931                    display_property.physical_resolution.height,
1932                )
1933                    .into(),
1934                supported_transforms: supported_transforms,
1935                plane_reorder_possible: display_property.plane_reorder_possible == 1,
1936                persistent_content: display_property.persistent_content == 1,
1937            };
1938
1939            let display_modes = match display_extension
1940                .get_display_mode_properties(self.handle, display_property.display)
1941            {
1942                Ok(display_modes) => display_modes,
1943                Err(err) => {
1944                    match err {
1945                        vk::Result::ERROR_OUT_OF_HOST_MEMORY
1946                        | vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => error!(
1947                            "Error returned on `get_display_mode_properties`: {:#?}",
1948                            err
1949                        ),
1950                        err => error!(
1951                            "Unexpected error on `get_display_mode_properties`: {:#?}",
1952                            err
1953                        ),
1954                    }
1955                    return Vec::new();
1956                }
1957            }
1958            .iter()
1959            .map(|display_mode_properties| display::DisplayMode {
1960                handle: native::DisplayMode(display_mode_properties.display_mode),
1961                resolution: (
1962                    display_mode_properties.parameters.visible_region.width,
1963                    display_mode_properties.parameters.visible_region.height,
1964                ),
1965                refresh_rate: display_mode_properties.parameters.refresh_rate,
1966            })
1967            .collect();
1968
1969            let display = display::Display {
1970                handle: native::Display(display_property.display),
1971                info: display_info,
1972                modes: display_modes,
1973            };
1974
1975            displays.push(display);
1976        }
1977        return displays;
1978    }
1979
1980    unsafe fn enumerate_compatible_planes(
1981        &self,
1982        display: &display::Display<Backend>,
1983    ) -> Vec<display::Plane> {
1984        let display_extension = match self.instance.display {
1985            Some(ref display_extension) => display_extension,
1986            None => {
1987                error!("Direct display feature not supported");
1988                return Vec::new();
1989            }
1990        };
1991
1992        match display_extension.get_physical_device_display_plane_properties(self.handle) {
1993            Ok(planes_properties) => {
1994                let mut planes = Vec::new();
1995                for index in 0..planes_properties.len() {
1996                    let compatible_displays = match display_extension
1997                        .get_display_plane_supported_displays(self.handle, index as u32)
1998                    {
1999                        Ok(compatible_displays) => compatible_displays,
2000                        Err(err) => {
2001                            match err {
2002                                vk::Result::ERROR_OUT_OF_HOST_MEMORY | vk::Result::ERROR_OUT_OF_DEVICE_MEMORY =>
2003                                    error!("Error returned on `get_display_plane_supported_displays`: {:#?}",err),
2004                                err=>error!("Unexpected error on `get_display_plane_supported_displays`: {:#?}",err)
2005                            }
2006                            return Vec::new();
2007                        }
2008                    };
2009                    if compatible_displays.contains(&display.handle.0) {
2010                        planes.push(display::Plane {
2011                            handle: index as u32,
2012                            z_index: planes_properties[index].current_stack_index,
2013                        });
2014                    }
2015                }
2016                planes
2017            }
2018            Err(err) => {
2019                match err {
2020                    vk::Result::ERROR_OUT_OF_HOST_MEMORY
2021                    | vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => error!(
2022                        "Error returned on `get_physical_device_display_plane_properties`: {:#?}",
2023                        err
2024                    ),
2025                    err => error!(
2026                        "Unexpected error on `get_physical_device_display_plane_properties`: {:#?}",
2027                        err
2028                    ),
2029                }
2030                Vec::new()
2031            }
2032        }
2033    }
2034
2035    unsafe fn create_display_mode(
2036        &self,
2037        display: &display::Display<Backend>,
2038        resolution: (u32, u32),
2039        refresh_rate: u32,
2040    ) -> Result<display::DisplayMode<Backend>, display::DisplayModeError> {
2041        let display_extension = self.instance.display.as_ref().unwrap();
2042
2043        let display_mode_ci = vk::DisplayModeCreateInfoKHR::builder()
2044            .parameters(vk::DisplayModeParametersKHR {
2045                visible_region: vk::Extent2D {
2046                    width: resolution.0,
2047                    height: resolution.1,
2048                },
2049                refresh_rate: refresh_rate,
2050            })
2051            .build();
2052
2053        match display_extension.create_display_mode(
2054            self.handle,
2055            display.handle.0,
2056            &display_mode_ci,
2057            None,
2058        ) {
2059            Ok(display_mode_handle) => Ok(display::DisplayMode {
2060                handle: native::DisplayMode(display_mode_handle),
2061                resolution: resolution,
2062                refresh_rate: refresh_rate,
2063            }),
2064            Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => return Err(OutOfMemory::Host.into()),
2065            Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => return Err(OutOfMemory::Device.into()),
2066            Err(vk::Result::ERROR_INITIALIZATION_FAILED) => {
2067                return Err(display::DisplayModeError::UnsupportedDisplayMode.into())
2068            }
2069            Err(err) => panic!("Unexpected error on `create_display_mode`: {:#?}", err),
2070        }
2071    }
2072
2073    unsafe fn create_display_plane<'a>(
2074        &self,
2075        display_mode: &'a display::DisplayMode<Backend>,
2076        plane: &'a display::Plane,
2077    ) -> Result<display::DisplayPlane<'a, Backend>, OutOfMemory> {
2078        let display_extension = self.instance.display.as_ref().unwrap();
2079
2080        let display_plane_capabilities = match display_extension.get_display_plane_capabilities(
2081            self.handle,
2082            display_mode.handle.0,
2083            plane.handle,
2084        ) {
2085            Ok(display_plane_capabilities) => display_plane_capabilities,
2086            Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => return Err(OutOfMemory::Host.into()),
2087            Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => return Err(OutOfMemory::Device.into()),
2088            Err(err) => panic!(
2089                "Unexpected error on `get_display_plane_capabilities`: {:#?}",
2090                err
2091            ),
2092        };
2093
2094        let mut supported_alpha_capabilities = Vec::new();
2095        if display_plane_capabilities
2096            .supported_alpha
2097            .contains(vk::DisplayPlaneAlphaFlagsKHR::OPAQUE)
2098        {
2099            supported_alpha_capabilities.push(display::DisplayPlaneAlpha::Opaque);
2100        }
2101        if display_plane_capabilities
2102            .supported_alpha
2103            .contains(vk::DisplayPlaneAlphaFlagsKHR::GLOBAL)
2104        {
2105            supported_alpha_capabilities.push(display::DisplayPlaneAlpha::Global(1.0));
2106        }
2107        if display_plane_capabilities
2108            .supported_alpha
2109            .contains(vk::DisplayPlaneAlphaFlagsKHR::PER_PIXEL)
2110        {
2111            supported_alpha_capabilities.push(display::DisplayPlaneAlpha::PerPixel);
2112        }
2113        if display_plane_capabilities
2114            .supported_alpha
2115            .contains(vk::DisplayPlaneAlphaFlagsKHR::PER_PIXEL_PREMULTIPLIED)
2116        {
2117            supported_alpha_capabilities.push(display::DisplayPlaneAlpha::PerPixelPremultiplied);
2118        }
2119
2120        Ok(display::DisplayPlane {
2121            plane: &plane,
2122            display_mode: &display_mode,
2123            supported_alpha: supported_alpha_capabilities,
2124            src_position: std::ops::Range {
2125                start: (
2126                    display_plane_capabilities.min_src_position.x,
2127                    display_plane_capabilities.min_src_position.x,
2128                )
2129                    .into(),
2130                end: (
2131                    display_plane_capabilities.max_src_position.x,
2132                    display_plane_capabilities.max_src_position.x,
2133                )
2134                    .into(),
2135            },
2136            src_extent: std::ops::Range {
2137                start: (
2138                    display_plane_capabilities.min_src_extent.width,
2139                    display_plane_capabilities.min_src_extent.height,
2140                )
2141                    .into(),
2142                end: (
2143                    display_plane_capabilities.max_src_extent.width,
2144                    display_plane_capabilities.max_src_extent.height,
2145                )
2146                    .into(),
2147            },
2148            dst_position: std::ops::Range {
2149                start: (
2150                    display_plane_capabilities.min_dst_position.x,
2151                    display_plane_capabilities.min_dst_position.x,
2152                )
2153                    .into(),
2154                end: (
2155                    display_plane_capabilities.max_dst_position.x,
2156                    display_plane_capabilities.max_dst_position.x,
2157                )
2158                    .into(),
2159            },
2160            dst_extent: std::ops::Range {
2161                start: (
2162                    display_plane_capabilities.min_dst_extent.width,
2163                    display_plane_capabilities.min_dst_extent.height,
2164                )
2165                    .into(),
2166                end: (
2167                    display_plane_capabilities.max_dst_extent.width,
2168                    display_plane_capabilities.max_dst_extent.height,
2169                )
2170                    .into(),
2171            },
2172        })
2173    }
2174}