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#[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
36unsafe impl Send for PhysicalDeviceFeatures {}
38unsafe impl Sync for PhysicalDeviceFeatures {}
39
40impl PhysicalDeviceFeatures {
41 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 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 let features = requested_features;
75 PhysicalDeviceFeatures {
76 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 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
510pub 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 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 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()); }
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()); }
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 requested_extensions.push(vk::KhrGetMemoryRequirements2Fn::name()); 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 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 unsafe fn null_p_next<T>(features: &mut Option<T>) {
705 if let Some(features) = features {
706 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 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 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 ];
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 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 let device_raw = {
1179 let str_pointers = enabled_extensions
1180 .iter()
1181 .map(|&s| {
1182 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 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 if (header_len as usize) < HEADER_SIZE {
1838 warn!("Bad header length {:?}", header_len);
1839 return false;
1840 }
1841
1842 if header_version != vk::PipelineCacheHeaderVersion::ONE.as_raw() as u32 {
1844 warn!("Unsupported cache header version: {:?}", header_version);
1845 return false;
1846 }
1847
1848 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 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}