vulk_ext/vkx/
physical_device.rs

1use super::*;
2
3#[derive(Debug)]
4pub struct PhysicalDevice {
5    physical_device: vk::PhysicalDevice,
6    pub properties: vk::PhysicalDeviceProperties,
7    pub queue_family_properties: Vec<vk::QueueFamilyProperties>,
8    pub memory_properties: vk::PhysicalDeviceMemoryProperties,
9    pub descriptor_buffer_properties_ext: vk::PhysicalDeviceDescriptorBufferPropertiesEXT,
10    pub mesh_shader_properties_ext: vk::PhysicalDeviceMeshShaderPropertiesEXT,
11    pub subgroup_properties: vk::PhysicalDeviceSubgroupProperties,
12    pub acceleration_structure_properties: vk::PhysicalDeviceAccelerationStructurePropertiesKHR,
13    pub raytracing_pipeline_properties: vk::PhysicalDeviceRayTracingPipelinePropertiesKHR,
14}
15
16impl PhysicalDevice {
17    pub unsafe fn create(instance: &Instance) -> Result<Self> {
18        // Find physical devices.
19        let physical_devices = vulk::read_to_vec(
20            |count, ptr| instance.enumerate_physical_devices(count, ptr),
21            None,
22        )?;
23
24        // Pick a physical device.
25        let physical_device = physical_devices
26            .into_iter()
27            .find(|&physical_device| {
28                let mut props2: vk::PhysicalDeviceProperties2 = zeroed();
29                props2.s_type = vk::StructureType::PhysicalDeviceProperties2;
30                instance.get_physical_device_properties2(physical_device, &mut props2);
31                let props = props2.properties;
32                let device_name = std::ffi::CStr::from_ptr(props.device_name.as_ptr());
33                let device_name = device_name.to_string_lossy();
34                let discrete_gpu = props.device_type == vk::PhysicalDeviceType::DiscreteGpu;
35                let nvidia_gpu = device_name.contains("NVIDIA");
36                discrete_gpu == nvidia_gpu
37            })
38            .context("Failed to find compatible physical device")?;
39
40        // Physical device properties.
41        let mut as_props: vk::PhysicalDeviceAccelerationStructurePropertiesKHR = zeroed();
42        as_props.s_type = vk::StructureType::PhysicalDeviceAccelerationStructurePropertiesKHR;
43        let mut rtp_props: vk::PhysicalDeviceRayTracingPipelinePropertiesKHR = zeroed();
44        rtp_props.s_type = vk::StructureType::PhysicalDeviceRayTracingPipelinePropertiesKHR;
45        rtp_props.p_next = addr_of_mut!(as_props).cast();
46        let mut sg_props: vk::PhysicalDeviceSubgroupProperties = zeroed();
47        sg_props.s_type = vk::StructureType::PhysicalDeviceSubgroupProperties;
48        sg_props.p_next = addr_of_mut!(rtp_props).cast();
49        let mut ms_props: vk::PhysicalDeviceMeshShaderPropertiesEXT = zeroed();
50        ms_props.s_type = vk::StructureType::PhysicalDeviceMeshShaderPropertiesEXT;
51        ms_props.p_next = addr_of_mut!(sg_props).cast();
52        let mut db_props: vk::PhysicalDeviceDescriptorBufferPropertiesEXT = zeroed();
53        db_props.s_type = vk::StructureType::PhysicalDeviceDescriptorBufferPropertiesEXT;
54        db_props.p_next = addr_of_mut!(ms_props).cast();
55        let mut props2 = vk::PhysicalDeviceProperties2 {
56            s_type: vk::StructureType::PhysicalDeviceProperties2,
57            p_next: addr_of_mut!(db_props).cast(),
58            properties: zeroed(),
59        };
60        instance.get_physical_device_properties2(physical_device, &mut props2);
61
62        // Queue family properties.
63        let qf_props = {
64            let qf_props2 = vulk::read_to_vec(
65                |a, b| {
66                    instance.get_physical_device_queue_family_properties2(physical_device, a, b);
67                    Ok(())
68                },
69                Some(vk::StructureType::QueueFamilyProperties2),
70            )?;
71            qf_props2
72                .into_iter()
73                .map(|qf_prop| qf_prop.queue_family_properties)
74                .collect()
75        };
76
77        // Memory properties.
78        let mem_props = {
79            let mut mem_props2 = vk::PhysicalDeviceMemoryProperties2 {
80                s_type: vk::StructureType::PhysicalDeviceMemoryProperties2,
81                p_next: null_mut(),
82                memory_properties: zeroed(),
83            };
84            instance.get_physical_device_memory_properties2(physical_device, &mut mem_props2);
85            mem_props2.memory_properties
86        };
87
88        // Post-validation.
89        descriptor::validate_descriptor_sizes(&db_props)?;
90
91        Ok(Self {
92            physical_device,
93            properties: props2.properties,
94            queue_family_properties: qf_props,
95            memory_properties: mem_props,
96            descriptor_buffer_properties_ext: db_props,
97            mesh_shader_properties_ext: ms_props,
98            subgroup_properties: sg_props,
99            acceleration_structure_properties: as_props,
100            raytracing_pipeline_properties: rtp_props,
101        })
102    }
103
104    #[must_use]
105    pub fn handle(&self) -> vk::PhysicalDevice {
106        self.physical_device
107    }
108}