ash/extensions/khr/
device_group.rs

1#[cfg(doc)]
2use super::Swapchain;
3use crate::prelude::*;
4use crate::vk;
5use crate::{Device, Entry, Instance};
6use std::ffi::CStr;
7use std::mem;
8
9/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_device_group.html>
10#[derive(Clone)]
11pub struct DeviceGroup {
12    handle: vk::Device,
13    fp: vk::KhrDeviceGroupFn,
14}
15
16impl DeviceGroup {
17    /// # Warning
18    /// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called:
19    /// - [`Self::get_physical_device_present_rectangles()`]
20    ///
21    /// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the
22    /// above [`Instance`] function is called. This will be solved in the next breaking `ash`
23    /// release: <https://github.com/ash-rs/ash/issues/727>.
24    pub fn new(instance: &Instance, device: &Device) -> Self {
25        let handle = device.handle();
26        let fp = vk::KhrDeviceGroupFn::load(|name| unsafe {
27            mem::transmute(instance.get_device_proc_addr(handle, name.as_ptr()))
28        });
29        Self { handle, fp }
30    }
31
32    /// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra
33    /// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be
34    /// loaded instead of always panicking. See also [`Self::new()`] for more details.
35    ///
36    /// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the
37    /// [`Instance`] function.
38    pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self {
39        let fp = vk::KhrDeviceGroupFn::load(|name| unsafe {
40            mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
41        });
42        Self { handle: device, fp }
43    }
44
45    /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceGroupPeerMemoryFeaturesKHR.html>
46    #[inline]
47    pub unsafe fn get_device_group_peer_memory_features(
48        &self,
49        heap_index: u32,
50        local_device_index: u32,
51        remote_device_index: u32,
52    ) -> vk::PeerMemoryFeatureFlags {
53        let mut peer_memory_features = mem::zeroed();
54        (self.fp.get_device_group_peer_memory_features_khr)(
55            self.handle,
56            heap_index,
57            local_device_index,
58            remote_device_index,
59            &mut peer_memory_features,
60        );
61        peer_memory_features
62    }
63
64    /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetDeviceMaskKHR.html>
65    #[inline]
66    pub unsafe fn cmd_set_device_mask(&self, command_buffer: vk::CommandBuffer, device_mask: u32) {
67        (self.fp.cmd_set_device_mask_khr)(command_buffer, device_mask)
68    }
69
70    /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdDispatchBaseKHR.html>
71    #[inline]
72    pub unsafe fn cmd_dispatch_base(
73        &self,
74        command_buffer: vk::CommandBuffer,
75        base_group: (u32, u32, u32),
76        group_count: (u32, u32, u32),
77    ) {
78        (self.fp.cmd_dispatch_base_khr)(
79            command_buffer,
80            base_group.0,
81            base_group.1,
82            base_group.2,
83            group_count.0,
84            group_count.1,
85            group_count.2,
86        )
87    }
88
89    /// Requires [`VK_KHR_surface`] to be enabled.
90    ///
91    /// Also available as [`Swapchain::get_device_group_present_capabilities()`] since [Vulkan 1.1].
92    ///
93    /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceGroupPresentCapabilitiesKHR.html>
94    ///
95    /// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html
96    /// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html
97    #[inline]
98    pub unsafe fn get_device_group_present_capabilities(
99        &self,
100        device_group_present_capabilities: &mut vk::DeviceGroupPresentCapabilitiesKHR,
101    ) -> VkResult<()> {
102        (self.fp.get_device_group_present_capabilities_khr)(
103            self.handle,
104            device_group_present_capabilities,
105        )
106        .result()
107    }
108
109    /// Requires [`VK_KHR_surface`] to be enabled.
110    ///
111    /// Also available as [`Swapchain::get_device_group_surface_present_modes()`] since [Vulkan 1.1].
112    ///
113    /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceGroupSurfacePresentModesKHR.html>
114    ///
115    /// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html
116    /// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html
117    #[inline]
118    pub unsafe fn get_device_group_surface_present_modes(
119        &self,
120        surface: vk::SurfaceKHR,
121    ) -> VkResult<vk::DeviceGroupPresentModeFlagsKHR> {
122        let mut modes = mem::zeroed();
123        (self.fp.get_device_group_surface_present_modes_khr)(self.handle, surface, &mut modes)
124            .result_with_success(modes)
125    }
126
127    /// Requires [`VK_KHR_surface`] to be enabled.
128    ///
129    /// Also available as [`Swapchain::get_physical_device_present_rectangles()`] since [Vulkan 1.1].
130    ///
131    /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetPhysicalDevicePresentRectanglesKHR.html>
132    ///
133    /// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html
134    /// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html
135    ///
136    /// # Warning
137    ///
138    /// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`].
139    #[inline]
140    pub unsafe fn get_physical_device_present_rectangles(
141        &self,
142        physical_device: vk::PhysicalDevice,
143        surface: vk::SurfaceKHR,
144    ) -> VkResult<Vec<vk::Rect2D>> {
145        read_into_uninitialized_vector(|count, data| {
146            (self.fp.get_physical_device_present_rectangles_khr)(
147                physical_device,
148                surface,
149                count,
150                data,
151            )
152        })
153    }
154
155    /// On success, returns the next image's index and whether the swapchain is suboptimal for the surface.
156    ///
157    /// Requires [`VK_KHR_swapchain`] to be enabled.
158    ///
159    /// Also available as [`Swapchain::acquire_next_image2()`] since [Vulkan 1.1].
160    ///
161    /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkAcquireNextImage2KHR.html>
162    ///
163    /// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html
164    /// [`VK_KHR_swapchain`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_swapchain.html
165    #[inline]
166    pub unsafe fn acquire_next_image2(
167        &self,
168        acquire_info: &vk::AcquireNextImageInfoKHR,
169    ) -> VkResult<(u32, bool)> {
170        let mut index = 0;
171        let err_code = (self.fp.acquire_next_image2_khr)(self.handle, acquire_info, &mut index);
172        match err_code {
173            vk::Result::SUCCESS => Ok((index, false)),
174            vk::Result::SUBOPTIMAL_KHR => Ok((index, true)),
175            _ => Err(err_code),
176        }
177    }
178
179    #[inline]
180    pub const fn name() -> &'static CStr {
181        vk::KhrDeviceGroupFn::name()
182    }
183
184    #[inline]
185    pub fn fp(&self) -> &vk::KhrDeviceGroupFn {
186        &self.fp
187    }
188
189    #[inline]
190    pub fn device(&self) -> vk::Device {
191        self.handle
192    }
193}