ash: Repeatedly call enumeration functions when INCOMPLETE is returned

This commit is contained in:
Marijn Suijten 2021-08-07 10:38:01 +02:00 committed by Benjamin Saunders
parent c6842949de
commit 6fa57a4269
10 changed files with 196 additions and 345 deletions

View file

@ -1638,24 +1638,14 @@ impl Device {
&self,
pipeline_cache: vk::PipelineCache,
) -> VkResult<Vec<u8>> {
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<u8> = 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 = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkMergePipelineCaches.html>"]
@ -2107,21 +2097,16 @@ impl Device {
&self,
image: vk::Image,
) -> Vec<vk::SparseImageMemoryRequirements> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
self.device_fn_1_0.get_image_sparse_memory_requirements(
self.handle(),
image,
&mut count,
ptr::null_mut(),
count,
data,
);
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
vk::Result::SUCCESS
})
// The closure always returns SUCCESS
.unwrap()
}
}

View file

@ -123,16 +123,10 @@ impl<L> EntryCustom<L> {
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkEnumerateInstanceLayerProperties.html>"]
pub fn enumerate_instance_layer_properties(&self) -> VkResult<Vec<vk::LayerProperties>> {
unsafe {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
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)
.enumerate_instance_layer_properties(count, data)
})
}
}
@ -141,18 +135,10 @@ impl<L> EntryCustom<L> {
&self,
) -> VkResult<Vec<vk::ExtensionProperties>> {
unsafe {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
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)
.enumerate_instance_extension_properties(ptr::null(), count, data)
})
}
}

View file

@ -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<Vec<vk::PresentModeKHR>> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
self.full_screen_exclusive_fn
.get_physical_device_surface_present_modes2_ext(
physical_device,
surface_info,
&mut count,
ptr::null_mut(),
count,
data,
)
.result()?;
let mut present_modes = Vec::<vk::PresentModeKHR>::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)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkReleaseFullScreenExclusiveModeEXT.html>"]

View file

@ -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<Vec<vk::PhysicalDeviceToolPropertiesEXT>> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
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)
.get_physical_device_tool_properties_ext(physical_device, count, data)
})
}
pub fn fp(&self) -> &vk::ExtToolingInfoFn {

View file

@ -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<Vec<vk::DisplayPropertiesKHR>> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
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)
.get_physical_device_display_properties_khr(physical_device, count, data)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetPhysicalDeviceDisplayPlanePropertiesKHR.html>"]
@ -55,27 +42,10 @@ impl Display {
&self,
physical_device: vk::PhysicalDevice,
) -> VkResult<Vec<vk::DisplayPlanePropertiesKHR>> {
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 = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetDisplayPlaneSupportedDisplaysKHR.html>"]
@ -84,24 +54,14 @@ impl Display {
physical_device: vk::PhysicalDevice,
plane_index: u32,
) -> VkResult<Vec<vk::DisplayKHR>> {
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 = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetDisplayModePropertiesKHR.html>"]
@ -110,19 +70,10 @@ impl Display {
physical_device: vk::PhysicalDevice,
display: vk::DisplayKHR,
) -> VkResult<Vec<vk::DisplayModePropertiesKHR>> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
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)
.get_display_mode_properties_khr(physical_device, display, count, data)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCreateDisplayModeKHR.html>"]

View file

@ -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<Vec<vk::PipelineExecutableInternalRepresentationKHR>> {
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];
read_into_defaulted_vector(|count, data| {
self.pipeline_executable_properties_fn
.get_pipeline_executable_internal_representations_khr(
device,
executable_info,
&mut count,
v.as_mut_ptr(),
count,
data,
)
.result_with_success(v)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetPipelineExecutablePropertiesKHR.html>"]
@ -62,27 +49,10 @@ impl PipelineExecutableProperties {
device: vk::Device,
pipeline_info: &vk::PipelineInfoKHR,
) -> VkResult<Vec<vk::PipelineExecutablePropertiesKHR>> {
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];
read_into_defaulted_vector(|count, data| {
self.pipeline_executable_properties_fn
.get_pipeline_executable_properties_khr(
device,
pipeline_info,
&mut count,
v.as_mut_ptr(),
)
.result_with_success(v)
.get_pipeline_executable_properties_khr(device, pipeline_info, count, data)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetPipelineExecutableStatisticsKHR.html>"]
@ -91,27 +61,10 @@ impl PipelineExecutableProperties {
device: vk::Device,
executable_info: &vk::PipelineExecutableInfoKHR,
) -> VkResult<Vec<vk::PipelineExecutableStatisticKHR>> {
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];
read_into_defaulted_vector(|count, data| {
self.pipeline_executable_properties_fn
.get_pipeline_executable_statistics_khr(
device,
executable_info,
&mut count,
v.as_mut_ptr(),
)
.result_with_success(v)
.get_pipeline_executable_statistics_khr(device, executable_info, count, data)
})
}
pub fn fp(&self) -> &vk::KhrPipelineExecutablePropertiesFn {

View file

@ -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<Vec<vk::PresentModeKHR>> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
self.surface_fn
.get_physical_device_surface_present_modes_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_present_modes_khr(
physical_device,
surface,
&mut count,
v.as_mut_ptr(),
);
v.set_len(count as usize);
err_code.result_with_success(v)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetPhysicalDeviceSurfaceCapabilitiesKHR.html>"]
@ -95,24 +83,14 @@ impl Surface {
physical_device: vk::PhysicalDevice,
surface: vk::SurfaceKHR,
) -> VkResult<Vec<vk::SurfaceFormatKHR>> {
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 = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkDestroySurfaceKHR.html>"]

View file

@ -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<Vec<vk::Image>> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
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)
.get_swapchain_images_khr(self.handle, swapchain, count, data)
})
}
pub fn fp(&self) -> &vk::KhrSwapchainFn {

View file

@ -348,22 +348,13 @@ impl Instance {
&self,
physical_device: vk::PhysicalDevice,
) -> Vec<vk::QueueFamilyProperties> {
let mut queue_count = 0;
read_into_uninitialized_vector(|count, data| {
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
.get_physical_device_queue_family_properties(physical_device, count, data);
vk::Result::SUCCESS
})
// The closure always returns SUCCESS
.unwrap()
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetPhysicalDeviceFeatures.html>"]
@ -379,18 +370,10 @@ impl Instance {
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkEnumeratePhysicalDevices.html>"]
pub unsafe fn enumerate_physical_devices(&self) -> VkResult<Vec<vk::PhysicalDevice>> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
self.instance_fn_1_0
.enumerate_physical_devices(self.handle(), &mut count, ptr::null_mut())
.result()?;
let mut physical_devices = Vec::<vk::PhysicalDevice>::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)
.enumerate_physical_devices(self.handle(), count, data)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkEnumerateDeviceExtensionProperties.html>"]
@ -398,19 +381,14 @@ impl Instance {
&self,
device: vk::PhysicalDevice,
) -> VkResult<Vec<vk::ExtensionProperties>> {
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(
read_into_uninitialized_vector(|count, data| {
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)
count,
data,
)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkEnumerateDeviceLayerProperties.html>"]
@ -418,18 +396,10 @@ impl Instance {
&self,
device: vk::PhysicalDevice,
) -> VkResult<Vec<vk::LayerProperties>> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
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)
.enumerate_device_layer_properties(device, count, data)
})
}
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetPhysicalDeviceSparseImageFormatProperties.html>"]
@ -442,7 +412,7 @@ impl Instance {
usage: vk::ImageUsageFlags,
tiling: vk::ImageTiling,
) -> Vec<vk::SparseImageFormatProperties> {
let mut count = 0;
read_into_uninitialized_vector(|count, data| {
self.instance_fn_1_0
.get_physical_device_sparse_image_format_properties(
physical_device,
@ -451,22 +421,12 @@ impl Instance {
samples,
usage,
tiling,
&mut count,
ptr::null_mut(),
count,
data,
);
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
vk::Result::SUCCESS
})
// The closure always returns SUCCESS
.unwrap()
}
}

View file

@ -1,3 +1,5 @@
use std::convert::TryInto;
use crate::vk;
pub type VkResult<T> = Result<T, vk::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<N: Copy + Default + TryInto<usize>, T>(
f: impl Fn(&mut N, *mut T) -> vk::Result,
) -> VkResult<Vec<T>>
where
<N as TryInto<usize>>::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<usize>,
T: Default + Clone,
>(
f: impl Fn(&mut N, *mut T) -> vk::Result,
) -> VkResult<Vec<T>>
where
<N as TryInto<usize>>::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);
}
}
}