From 6fa57a42698f01d284f9f4a30c1e1a29a9e7fb20 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Sat, 7 Aug 2021 10:38:01 +0200 Subject: [PATCH] ash: Repeatedly call enumeration functions when INCOMPLETE is returned --- ash/src/device.rs | 47 +++---- ash/src/entry.rs | 30 ++--- .../extensions/ext/full_screen_exclusive.rs | 30 ++--- ash/src/extensions/ext/tooling_info.rs | 15 +-- ash/src/extensions/khr/display.rs | 83 +++--------- .../khr/pipeline_executable_properties.rs | 81 +++--------- ash/src/extensions/khr/surface.rs | 50 +++----- ash/src/extensions/khr/swapchain.rs | 19 +-- ash/src/instance.rs | 118 ++++++------------ ash/src/prelude.rs | 68 ++++++++++ 10 files changed, 196 insertions(+), 345 deletions(-) diff --git a/ash/src/device.rs b/ash/src/device.rs index e49004e..87c53c7 100644 --- a/ash/src/device.rs +++ b/ash/src/device.rs @@ -1638,24 +1638,14 @@ impl Device { &self, pipeline_cache: vk::PipelineCache, ) -> VkResult> { - let mut data_size: usize = 0; - self.device_fn_1_0 - .get_pipeline_cache_data( + read_into_uninitialized_vector(|count, data| { + self.device_fn_1_0.get_pipeline_cache_data( self.handle(), pipeline_cache, - &mut data_size, - ptr::null_mut(), + count, + data as _, ) - .result()?; - let mut data: Vec = Vec::with_capacity(data_size); - let err_code = self.device_fn_1_0.get_pipeline_cache_data( - self.handle(), - pipeline_cache, - &mut data_size, - data.as_mut_ptr() as _, - ); - data.set_len(data_size); - err_code.result_with_success(data) + }) } #[doc = ""] @@ -2107,21 +2097,16 @@ impl Device { &self, image: vk::Image, ) -> Vec { - let mut count = 0; - self.device_fn_1_0.get_image_sparse_memory_requirements( - self.handle(), - image, - &mut count, - ptr::null_mut(), - ); - let mut data = Vec::with_capacity(count as usize); - self.device_fn_1_0.get_image_sparse_memory_requirements( - self.handle(), - image, - &mut count, - data.as_mut_ptr(), - ); - data.set_len(count as usize); - data + read_into_uninitialized_vector(|count, data| { + self.device_fn_1_0.get_image_sparse_memory_requirements( + self.handle(), + image, + count, + data, + ); + vk::Result::SUCCESS + }) + // The closure always returns SUCCESS + .unwrap() } } diff --git a/ash/src/entry.rs b/ash/src/entry.rs index c7009d5..280076b 100644 --- a/ash/src/entry.rs +++ b/ash/src/entry.rs @@ -123,16 +123,10 @@ impl EntryCustom { #[doc = ""] pub fn enumerate_instance_layer_properties(&self) -> VkResult> { unsafe { - let mut count = 0; - self.entry_fn_1_0 - .enumerate_instance_layer_properties(&mut count, ptr::null_mut()) - .result()?; - let mut v = Vec::with_capacity(count as usize); - let err_code = self - .entry_fn_1_0 - .enumerate_instance_layer_properties(&mut count, v.as_mut_ptr()); - v.set_len(count as usize); - err_code.result_with_success(v) + read_into_uninitialized_vector(|count, data| { + self.entry_fn_1_0 + .enumerate_instance_layer_properties(count, data) + }) } } @@ -141,18 +135,10 @@ impl EntryCustom { &self, ) -> VkResult> { unsafe { - let mut count = 0; - self.entry_fn_1_0 - .enumerate_instance_extension_properties(ptr::null(), &mut count, ptr::null_mut()) - .result()?; - let mut data = Vec::with_capacity(count as usize); - let err_code = self.entry_fn_1_0.enumerate_instance_extension_properties( - ptr::null(), - &mut count, - data.as_mut_ptr(), - ); - data.set_len(count as usize); - err_code.result_with_success(data) + read_into_uninitialized_vector(|count, data| { + self.entry_fn_1_0 + .enumerate_instance_extension_properties(ptr::null(), count, data) + }) } } diff --git a/ash/src/extensions/ext/full_screen_exclusive.rs b/ash/src/extensions/ext/full_screen_exclusive.rs index 8957117..59d546d 100644 --- a/ash/src/extensions/ext/full_screen_exclusive.rs +++ b/ash/src/extensions/ext/full_screen_exclusive.rs @@ -3,7 +3,6 @@ use crate::vk; use crate::{Device, Instance}; use std::ffi::CStr; use std::mem; -use std::ptr; #[derive(Clone)] pub struct FullScreenExclusive { @@ -42,26 +41,15 @@ impl FullScreenExclusive { physical_device: vk::PhysicalDevice, surface_info: &vk::PhysicalDeviceSurfaceInfo2KHR, ) -> VkResult> { - let mut count = 0; - self.full_screen_exclusive_fn - .get_physical_device_surface_present_modes2_ext( - physical_device, - surface_info, - &mut count, - ptr::null_mut(), - ) - .result()?; - let mut present_modes = Vec::::with_capacity(count as usize); - let err_code = self - .full_screen_exclusive_fn - .get_physical_device_surface_present_modes2_ext( - physical_device, - surface_info, - &mut count, - present_modes.as_mut_ptr(), - ); - present_modes.set_len(count as usize); - err_code.result_with_success(present_modes) + read_into_uninitialized_vector(|count, data| { + self.full_screen_exclusive_fn + .get_physical_device_surface_present_modes2_ext( + physical_device, + surface_info, + count, + data, + ) + }) } #[doc = ""] diff --git a/ash/src/extensions/ext/tooling_info.rs b/ash/src/extensions/ext/tooling_info.rs index bf2dd60..563afae 100644 --- a/ash/src/extensions/ext/tooling_info.rs +++ b/ash/src/extensions/ext/tooling_info.rs @@ -3,7 +3,6 @@ use crate::vk; use crate::{EntryCustom, Instance}; use std::ffi::CStr; use std::mem; -use std::ptr; #[derive(Clone)] pub struct ToolingInfo { @@ -31,16 +30,10 @@ impl ToolingInfo { &self, physical_device: vk::PhysicalDevice, ) -> VkResult> { - let mut count = 0; - self.tooling_info_fn - .get_physical_device_tool_properties_ext(physical_device, &mut count, ptr::null_mut()) - .result()?; - let mut v = Vec::with_capacity(count as usize); - let err_code = self - .tooling_info_fn - .get_physical_device_tool_properties_ext(physical_device, &mut count, v.as_mut_ptr()); - v.set_len(count as usize); - err_code.result_with_success(v) + read_into_uninitialized_vector(|count, data| { + self.tooling_info_fn + .get_physical_device_tool_properties_ext(physical_device, count, data) + }) } pub fn fp(&self) -> &vk::ExtToolingInfoFn { diff --git a/ash/src/extensions/khr/display.rs b/ash/src/extensions/khr/display.rs index f963077..4ae8a34 100755 --- a/ash/src/extensions/khr/display.rs +++ b/ash/src/extensions/khr/display.rs @@ -4,7 +4,6 @@ use crate::RawPtr; use crate::{EntryCustom, Instance}; use std::ffi::CStr; use std::mem; -use std::ptr; #[derive(Clone)] pub struct Display { @@ -32,22 +31,10 @@ impl Display { &self, physical_device: vk::PhysicalDevice, ) -> VkResult> { - let mut count = 0; - self.display_fn - .get_physical_device_display_properties_khr( - physical_device, - &mut count, - ptr::null_mut(), - ) - .result()?; - let mut v = Vec::with_capacity(count as usize); - let err_code = self.display_fn.get_physical_device_display_properties_khr( - physical_device, - &mut count, - v.as_mut_ptr(), - ); - v.set_len(count as usize); - err_code.result_with_success(v) + read_into_uninitialized_vector(|count, data| { + self.display_fn + .get_physical_device_display_properties_khr(physical_device, count, data) + }) } #[doc = ""] @@ -55,27 +42,10 @@ impl Display { &self, physical_device: vk::PhysicalDevice, ) -> VkResult> { - let mut count = 0; - let err_code = self - .display_fn - .get_physical_device_display_plane_properties_khr( - physical_device, - &mut count, - ptr::null_mut(), - ); - if err_code != vk::Result::SUCCESS { - return Err(err_code); - } - let mut v = Vec::with_capacity(count as usize); - let err_code = self - .display_fn - .get_physical_device_display_plane_properties_khr( - physical_device, - &mut count, - v.as_mut_ptr(), - ); - v.set_len(count as usize); - err_code.result_with_success(v) + read_into_uninitialized_vector(|count, data| { + self.display_fn + .get_physical_device_display_plane_properties_khr(physical_device, count, data) + }) } #[doc = ""] @@ -84,24 +54,14 @@ impl Display { physical_device: vk::PhysicalDevice, plane_index: u32, ) -> VkResult> { - let mut count = 0; - self.display_fn - .get_display_plane_supported_displays_khr( + read_into_uninitialized_vector(|count, data| { + self.display_fn.get_display_plane_supported_displays_khr( physical_device, plane_index, - &mut count, - ptr::null_mut(), + count, + data, ) - .result()?; - let mut v = Vec::with_capacity(count as usize); - let err_code = self.display_fn.get_display_plane_supported_displays_khr( - physical_device, - plane_index, - &mut count, - v.as_mut_ptr(), - ); - v.set_len(count as usize); - err_code.result_with_success(v) + }) } #[doc = ""] @@ -110,19 +70,10 @@ impl Display { physical_device: vk::PhysicalDevice, display: vk::DisplayKHR, ) -> VkResult> { - let mut count = 0; - self.display_fn - .get_display_mode_properties_khr(physical_device, display, &mut count, ptr::null_mut()) - .result()?; - let mut v = Vec::with_capacity(count as usize); - let err_code = self.display_fn.get_display_mode_properties_khr( - physical_device, - display, - &mut count, - v.as_mut_ptr(), - ); - v.set_len(count as usize); - err_code.result_with_success(v) + read_into_uninitialized_vector(|count, data| { + self.display_fn + .get_display_mode_properties_khr(physical_device, display, count, data) + }) } #[doc = ""] diff --git a/ash/src/extensions/khr/pipeline_executable_properties.rs b/ash/src/extensions/khr/pipeline_executable_properties.rs index 4dcc7b9..fd85a76 100644 --- a/ash/src/extensions/khr/pipeline_executable_properties.rs +++ b/ash/src/extensions/khr/pipeline_executable_properties.rs @@ -3,7 +3,6 @@ use crate::vk; use crate::{EntryCustom, Instance}; use std::ffi::CStr; use std::mem; -use std::ptr; #[derive(Clone)] pub struct PipelineExecutableProperties { @@ -33,27 +32,15 @@ impl PipelineExecutableProperties { device: vk::Device, executable_info: &vk::PipelineExecutableInfoKHR, ) -> VkResult> { - let mut count = 0; - let err_code = self - .pipeline_executable_properties_fn - .get_pipeline_executable_internal_representations_khr( - device, - executable_info, - &mut count, - ptr::null_mut(), - ); - if err_code != vk::Result::SUCCESS { - return Err(err_code); - } - let mut v: Vec<_> = vec![Default::default(); count as usize]; - self.pipeline_executable_properties_fn - .get_pipeline_executable_internal_representations_khr( - device, - executable_info, - &mut count, - v.as_mut_ptr(), - ) - .result_with_success(v) + read_into_defaulted_vector(|count, data| { + self.pipeline_executable_properties_fn + .get_pipeline_executable_internal_representations_khr( + device, + executable_info, + count, + data, + ) + }) } #[doc = ""] @@ -62,27 +49,10 @@ impl PipelineExecutableProperties { device: vk::Device, pipeline_info: &vk::PipelineInfoKHR, ) -> VkResult> { - let mut count = 0; - let err_code = self - .pipeline_executable_properties_fn - .get_pipeline_executable_properties_khr( - device, - pipeline_info, - &mut count, - ptr::null_mut(), - ); - if err_code != vk::Result::SUCCESS { - return Err(err_code); - } - let mut v: Vec<_> = vec![Default::default(); count as usize]; - self.pipeline_executable_properties_fn - .get_pipeline_executable_properties_khr( - device, - pipeline_info, - &mut count, - v.as_mut_ptr(), - ) - .result_with_success(v) + read_into_defaulted_vector(|count, data| { + self.pipeline_executable_properties_fn + .get_pipeline_executable_properties_khr(device, pipeline_info, count, data) + }) } #[doc = ""] @@ -91,27 +61,10 @@ impl PipelineExecutableProperties { device: vk::Device, executable_info: &vk::PipelineExecutableInfoKHR, ) -> VkResult> { - let mut count = 0; - let err_code = self - .pipeline_executable_properties_fn - .get_pipeline_executable_statistics_khr( - device, - executable_info, - &mut count, - ptr::null_mut(), - ); - if err_code != vk::Result::SUCCESS { - return Err(err_code); - } - let mut v: Vec<_> = vec![Default::default(); count as usize]; - self.pipeline_executable_properties_fn - .get_pipeline_executable_statistics_khr( - device, - executable_info, - &mut count, - v.as_mut_ptr(), - ) - .result_with_success(v) + read_into_defaulted_vector(|count, data| { + self.pipeline_executable_properties_fn + .get_pipeline_executable_statistics_khr(device, executable_info, count, data) + }) } pub fn fp(&self) -> &vk::KhrPipelineExecutablePropertiesFn { diff --git a/ash/src/extensions/khr/surface.rs b/ash/src/extensions/khr/surface.rs index b0fd698..3c19d22 100755 --- a/ash/src/extensions/khr/surface.rs +++ b/ash/src/extensions/khr/surface.rs @@ -4,7 +4,6 @@ use crate::RawPtr; use crate::{EntryCustom, Instance}; use std::ffi::CStr; use std::mem; -use std::ptr; #[derive(Clone)] pub struct Surface { @@ -51,26 +50,15 @@ impl Surface { physical_device: vk::PhysicalDevice, surface: vk::SurfaceKHR, ) -> VkResult> { - let mut count = 0; - self.surface_fn - .get_physical_device_surface_present_modes_khr( - physical_device, - surface, - &mut count, - ptr::null_mut(), - ) - .result()?; - let mut v = Vec::with_capacity(count as usize); - let err_code = self - .surface_fn - .get_physical_device_surface_present_modes_khr( - physical_device, - surface, - &mut count, - v.as_mut_ptr(), - ); - v.set_len(count as usize); - err_code.result_with_success(v) + read_into_uninitialized_vector(|count, data| { + self.surface_fn + .get_physical_device_surface_present_modes_khr( + physical_device, + surface, + count, + data, + ) + }) } #[doc = ""] @@ -95,24 +83,14 @@ impl Surface { physical_device: vk::PhysicalDevice, surface: vk::SurfaceKHR, ) -> VkResult> { - let mut count = 0; - self.surface_fn - .get_physical_device_surface_formats_khr( + read_into_uninitialized_vector(|count, data| { + self.surface_fn.get_physical_device_surface_formats_khr( physical_device, surface, - &mut count, - ptr::null_mut(), + count, + data, ) - .result()?; - let mut v = Vec::with_capacity(count as usize); - let err_code = self.surface_fn.get_physical_device_surface_formats_khr( - physical_device, - surface, - &mut count, - v.as_mut_ptr(), - ); - v.set_len(count as usize); - err_code.result_with_success(v) + }) } #[doc = ""] diff --git a/ash/src/extensions/khr/swapchain.rs b/ash/src/extensions/khr/swapchain.rs index 5e59dc2..9fa86a6 100755 --- a/ash/src/extensions/khr/swapchain.rs +++ b/ash/src/extensions/khr/swapchain.rs @@ -4,7 +4,6 @@ use crate::RawPtr; use crate::{Device, Instance}; use std::ffi::CStr; use std::mem; -use std::ptr; #[derive(Clone)] pub struct Swapchain { @@ -102,20 +101,10 @@ impl Swapchain { &self, swapchain: vk::SwapchainKHR, ) -> VkResult> { - let mut count = 0; - self.swapchain_fn - .get_swapchain_images_khr(self.handle, swapchain, &mut count, ptr::null_mut()) - .result()?; - - let mut v = Vec::with_capacity(count as usize); - let err_code = self.swapchain_fn.get_swapchain_images_khr( - self.handle, - swapchain, - &mut count, - v.as_mut_ptr(), - ); - v.set_len(count as usize); - err_code.result_with_success(v) + read_into_uninitialized_vector(|count, data| { + self.swapchain_fn + .get_swapchain_images_khr(self.handle, swapchain, count, data) + }) } pub fn fp(&self) -> &vk::KhrSwapchainFn { diff --git a/ash/src/instance.rs b/ash/src/instance.rs index 9a3c78f..8328594 100644 --- a/ash/src/instance.rs +++ b/ash/src/instance.rs @@ -348,22 +348,13 @@ impl Instance { &self, physical_device: vk::PhysicalDevice, ) -> Vec { - let mut queue_count = 0; - self.instance_fn_1_0 - .get_physical_device_queue_family_properties( - physical_device, - &mut queue_count, - ptr::null_mut(), - ); - let mut queue_families_vec = Vec::with_capacity(queue_count as usize); - self.instance_fn_1_0 - .get_physical_device_queue_family_properties( - physical_device, - &mut queue_count, - queue_families_vec.as_mut_ptr(), - ); - queue_families_vec.set_len(queue_count as usize); - queue_families_vec + read_into_uninitialized_vector(|count, data| { + self.instance_fn_1_0 + .get_physical_device_queue_family_properties(physical_device, count, data); + vk::Result::SUCCESS + }) + // The closure always returns SUCCESS + .unwrap() } #[doc = ""] @@ -379,18 +370,10 @@ impl Instance { #[doc = ""] pub unsafe fn enumerate_physical_devices(&self) -> VkResult> { - let mut count = 0; - self.instance_fn_1_0 - .enumerate_physical_devices(self.handle(), &mut count, ptr::null_mut()) - .result()?; - let mut physical_devices = Vec::::with_capacity(count as usize); - let err_code = self.instance_fn_1_0.enumerate_physical_devices( - self.handle(), - &mut count, - physical_devices.as_mut_ptr(), - ); - physical_devices.set_len(count as usize); - err_code.result_with_success(physical_devices) + read_into_uninitialized_vector(|count, data| { + self.instance_fn_1_0 + .enumerate_physical_devices(self.handle(), count, data) + }) } #[doc = ""] @@ -398,19 +381,14 @@ impl Instance { &self, device: vk::PhysicalDevice, ) -> VkResult> { - let mut count = 0; - self.instance_fn_1_0 - .enumerate_device_extension_properties(device, ptr::null(), &mut count, ptr::null_mut()) - .result()?; - let mut data = Vec::with_capacity(count as usize); - let err_code = self.instance_fn_1_0.enumerate_device_extension_properties( - device, - ptr::null(), - &mut count, - data.as_mut_ptr(), - ); - data.set_len(count as usize); - err_code.result_with_success(data) + read_into_uninitialized_vector(|count, data| { + self.instance_fn_1_0.enumerate_device_extension_properties( + device, + ptr::null(), + count, + data, + ) + }) } #[doc = ""] @@ -418,18 +396,10 @@ impl Instance { &self, device: vk::PhysicalDevice, ) -> VkResult> { - let mut count = 0; - self.instance_fn_1_0 - .enumerate_device_layer_properties(device, &mut count, ptr::null_mut()) - .result()?; - let mut data = Vec::with_capacity(count as usize); - let err_code = self.instance_fn_1_0.enumerate_device_layer_properties( - device, - &mut count, - data.as_mut_ptr(), - ); - data.set_len(count as usize); - err_code.result_with_success(data) + read_into_uninitialized_vector(|count, data| { + self.instance_fn_1_0 + .enumerate_device_layer_properties(device, count, data) + }) } #[doc = ""] @@ -442,31 +412,21 @@ impl Instance { usage: vk::ImageUsageFlags, tiling: vk::ImageTiling, ) -> Vec { - let mut count = 0; - self.instance_fn_1_0 - .get_physical_device_sparse_image_format_properties( - physical_device, - format, - typ, - samples, - usage, - tiling, - &mut count, - ptr::null_mut(), - ); - let mut data = Vec::with_capacity(count as usize); - self.instance_fn_1_0 - .get_physical_device_sparse_image_format_properties( - physical_device, - format, - typ, - samples, - usage, - tiling, - &mut count, - data.as_mut_ptr(), - ); - data.set_len(count as usize); - data + read_into_uninitialized_vector(|count, data| { + self.instance_fn_1_0 + .get_physical_device_sparse_image_format_properties( + physical_device, + format, + typ, + samples, + usage, + tiling, + count, + data, + ); + vk::Result::SUCCESS + }) + // The closure always returns SUCCESS + .unwrap() } } diff --git a/ash/src/prelude.rs b/ash/src/prelude.rs index 112b0d4..45a909a 100644 --- a/ash/src/prelude.rs +++ b/ash/src/prelude.rs @@ -1,3 +1,5 @@ +use std::convert::TryInto; + use crate::vk; pub type VkResult = Result; @@ -19,3 +21,69 @@ impl vk::Result { } } } + +/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, +/// ensuring all available data has been read into the vector. +/// +/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available +/// items may change between calls; [`vk::Result::INCOMPLETE`] is returned when the count +/// increased (and the vector is not large enough after querying the initial size), +/// requiring Ash to try again. +/// +/// [`vkEnumerateInstanceExtensionProperties`]: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkEnumerateInstanceExtensionProperties.html +pub(crate) unsafe fn read_into_uninitialized_vector, T>( + f: impl Fn(&mut N, *mut T) -> vk::Result, +) -> VkResult> +where + >::Error: std::fmt::Debug, +{ + loop { + let mut count = N::default(); + f(&mut count, std::ptr::null_mut()).result()?; + let mut data = + Vec::with_capacity(count.try_into().expect("`N` failed to convert to `usize`")); + + let err_code = f(&mut count, data.as_mut_ptr()); + if err_code != vk::Result::INCOMPLETE { + data.set_len(count.try_into().expect("`N` failed to convert to `usize`")); + break err_code.result_with_success(data); + } + } +} + +/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, +/// ensuring all available data has been read into the vector. +/// +/// Items in the target vector are [`default()`][`Default::default()`]-initialized which +/// is required for [`vk::BaseOutStructure`]-like structs where [`vk::BaseOutStructure::s_type`] +/// needs to be a valid type and [`vk::BaseOutStructure::p_next`] a valid or +/// [`null`][`std::ptr::null_mut()`] pointer. +/// +/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available +/// items may change between calls; [`vk::Result::INCOMPLETE`] is returned when the count +/// increased (and the vector is not large enough after querying the initial size), +/// requiring Ash to try again. +/// +/// [`vkEnumerateInstanceExtensionProperties`]: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkEnumerateInstanceExtensionProperties.html +pub(crate) unsafe fn read_into_defaulted_vector< + N: Copy + Default + TryInto, + T: Default + Clone, +>( + f: impl Fn(&mut N, *mut T) -> vk::Result, +) -> VkResult> +where + >::Error: std::fmt::Debug, +{ + loop { + let mut count = N::default(); + f(&mut count, std::ptr::null_mut()).result()?; + let mut data = + vec![Default::default(); count.try_into().expect("`N` failed to convert to `usize`")]; + + let err_code = f(&mut count, data.as_mut_ptr()); + if err_code != vk::Result::INCOMPLETE { + data.set_len(count.try_into().expect("`N` failed to convert to `usize`")); + break err_code.result_with_success(data); + } + } +}