Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extensions: Remove read_into_defaulted_vector() to let caller pass pNext #966

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `VK_EXT_metal_objects` device extension (#942)
- Added `VK_AMD_anti_lag` device extension (#943)

### Changed

- Enable passing mutable arrays of `pNext`-initialized structs for these remaining extension functions: (#966)
- `VK_EXT_tooling_info`: `get_physical_device_tool_properties()`;
- `VK_KHR_cooperative_matrix`: `get_physical_device_cooperative_matrix_properties()`;
- `VK_KHR_pipeline_executable_properties`:
- `get_pipeline_executable_internal_representations()`;
- `get_pipeline_executable_properties()`;
- `get_pipeline_executable_statistics()`.
The expected length of this array can be queried with the respective `*_len()` variant of these functions.

## [0.38.0] - 2024-04-01

With over two years of collecting breaking changes (since the `0.37.0` release in March 2022), April 2024 marks the next breaking release of `ash`. This release introduces an overhaul of all Vulkan structures, restructures modules around extensions, and separates extension wrappers between `Instance` and `Device` functions. The crate contains all bindings defined by the latest `1.3.281` Vulkan specification, and many old and new extensions have received a hand-written extension wrapper. For a full overview of all individual changes, see the list at the end of this post.
Expand Down
38 changes: 33 additions & 5 deletions ash/src/extensions/ext/tooling_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,45 @@

use crate::prelude::*;
use crate::vk;
use alloc::vec::Vec;
use core::mem;
use core::ptr;

impl crate::ext::tooling_info::Instance {
/// Retrieve the number of elements to pass to [`get_physical_device_tool_properties()`][Self::get_physical_device_tool_properties()]
#[inline]
pub unsafe fn get_physical_device_tool_properties_len(
&self,
physical_device: vk::PhysicalDevice,
) -> VkResult<usize> {
let mut count = mem::MaybeUninit::uninit();
(self.fp.get_physical_device_tool_properties_ext)(
physical_device,
count.as_mut_ptr(),
ptr::null_mut(),
)
.assume_init_on_success(count)
.map(|c| c as usize)
}

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPhysicalDeviceToolPropertiesEXT.html>
///
/// Call [`get_physical_device_tool_properties_len()`][Self::get_physical_device_tool_properties_len()] to query the number of elements to pass to `out`.
/// Be sure to [`Default::default()`]-initialize these elements and optionally set their `p_next` pointer.
#[inline]
#[doc(alias = "vkGetPhysicalDeviceToolPropertiesEXT")]
pub unsafe fn get_physical_device_tool_properties(
&self,
physical_device: vk::PhysicalDevice,
) -> VkResult<Vec<vk::PhysicalDeviceToolPropertiesEXT<'_>>> {
read_into_defaulted_vector(|count, data| {
(self.fp.get_physical_device_tool_properties_ext)(physical_device, count, data)
})
out: &mut [vk::PhysicalDeviceToolPropertiesEXT<'_>],
) -> VkResult<()> {
let mut count = out.len() as u32;
(self.fp.get_physical_device_tool_properties_ext)(
physical_device,
&mut count,
out.as_mut_ptr(),
)
.result()?;
assert_eq!(count as usize, out.len());
Ok(())
}
}
47 changes: 36 additions & 11 deletions ash/src/extensions/khr/cooperative_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,48 @@

use crate::prelude::*;
use crate::vk;
use alloc::vec::Vec;
use core::mem;
use core::ptr;

impl crate::khr::cooperative_matrix::Instance {
/// Retrieve the number of elements to pass to [`get_physical_device_cooperative_matrix_properties()`][Self::get_physical_device_cooperative_matrix_properties()]
#[inline]
pub unsafe fn get_physical_device_cooperative_matrix_properties_len(
&self,
physical_device: vk::PhysicalDevice,
) -> VkResult<usize> {
let mut count = mem::MaybeUninit::uninit();
(self
.fp
.get_physical_device_cooperative_matrix_properties_khr)(
physical_device,
count.as_mut_ptr(),
ptr::null_mut(),
)
.assume_init_on_success(count)
.map(|c| c as usize)
}

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR.html>
///
/// Call [`get_physical_device_cooperative_matrix_properties_len()`][Self::get_physical_device_cooperative_matrix_properties_len()] to query the number of elements to pass to `out`.
/// Be sure to [`Default::default()`]-initialize these elements and optionally set their `p_next` pointer.
#[inline]
pub unsafe fn get_physical_device_cooperative_matrix_properties(
&self,
physical_device: vk::PhysicalDevice,
) -> VkResult<Vec<vk::CooperativeMatrixPropertiesKHR<'_>>> {
read_into_defaulted_vector(|count, data| {
(self
.fp
.get_physical_device_cooperative_matrix_properties_khr)(
physical_device,
count,
data,
)
})
out: &mut [vk::CooperativeMatrixPropertiesKHR<'_>],
) -> VkResult<()> {
let mut count = out.len() as u32;
(self
.fp
.get_physical_device_cooperative_matrix_properties_khr)(
physical_device,
&mut count,
out.as_mut_ptr(),
)
.result()?;
assert_eq!(count as usize, out.len());
Ok(())
}
}
129 changes: 101 additions & 28 deletions ash/src/extensions/khr/pipeline_executable_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,127 @@

use crate::prelude::*;
use crate::vk;
use alloc::vec::Vec;
use core::mem;
use core::ptr;

impl crate::khr::pipeline_executable_properties::Device {
/// Retrieve the number of elements to pass to [`get_pipeline_executable_internal_representations()`][Self::get_pipeline_executable_internal_representations()]
#[inline]
pub unsafe fn get_pipeline_executable_internal_representations_len(
&self,
executable_info: &vk::PipelineExecutableInfoKHR<'_>,
) -> VkResult<usize> {
let mut count = mem::MaybeUninit::uninit();
(self.fp.get_pipeline_executable_internal_representations_khr)(
self.handle,
executable_info,
count.as_mut_ptr(),
ptr::null_mut(),
)
.assume_init_on_success(count)
.map(|c| c as usize)
}

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPipelineExecutableInternalRepresentationsKHR.html>
///
/// Call [`get_pipeline_executable_internal_representations_len()`][Self::get_pipeline_executable_internal_representations_len()] to query the number of elements to pass to `out`.
/// Be sure to [`Default::default()`]-initialize these elements and optionally set their `p_next` pointer.
#[inline]
#[doc(alias = "vkGetPipelineExecutableInternalRepresentationsKHR")]
pub unsafe fn get_pipeline_executable_internal_representations(
&self,
executable_info: &vk::PipelineExecutableInfoKHR<'_>,
) -> VkResult<Vec<vk::PipelineExecutableInternalRepresentationKHR<'_>>> {
read_into_defaulted_vector(|count, data| {
(self.fp.get_pipeline_executable_internal_representations_khr)(
self.handle,
executable_info,
count,
data,
)
})
out: &mut [vk::PipelineExecutableInternalRepresentationKHR<'_>],
) -> VkResult<()> {
let mut count = out.len() as u32;
(self.fp.get_pipeline_executable_internal_representations_khr)(
self.handle,
executable_info,
&mut count,
out.as_mut_ptr(),
)
.result()?;
assert_eq!(count as usize, out.len());
Ok(())
}

/// Retrieve the number of elements to pass to [`get_pipeline_executable_properties()`][Self::get_pipeline_executable_properties()]
#[inline]
pub unsafe fn get_pipeline_executable_properties_len(
&self,
pipeline_info: &vk::PipelineInfoKHR<'_>,
) -> VkResult<usize> {
let mut count = mem::MaybeUninit::uninit();
(self.fp.get_pipeline_executable_properties_khr)(
self.handle,
pipeline_info,
count.as_mut_ptr(),
ptr::null_mut(),
)
.assume_init_on_success(count)
.map(|c| c as usize)
}

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPipelineExecutablePropertiesKHR.html>
///
/// Call [`get_pipeline_executable_properties_len()`][Self::get_pipeline_executable_properties_len()] to query the number of elements to pass to `out`.
/// Be sure to [`Default::default()`]-initialize these elements and optionally set their `p_next` pointer.
#[inline]
#[doc(alias = "vkGetPipelineExecutablePropertiesKHR")]
pub unsafe fn get_pipeline_executable_properties(
&self,
pipeline_info: &vk::PipelineInfoKHR<'_>,
) -> VkResult<Vec<vk::PipelineExecutablePropertiesKHR<'_>>> {
read_into_defaulted_vector(|count, data| {
(self.fp.get_pipeline_executable_properties_khr)(
self.handle,
pipeline_info,
count,
data,
)
})
out: &mut [vk::PipelineExecutablePropertiesKHR<'_>],
) -> VkResult<()> {
let mut count = out.len() as u32;
(self.fp.get_pipeline_executable_properties_khr)(
self.handle,
pipeline_info,
&mut count,
out.as_mut_ptr(),
)
.result()?;
assert_eq!(count as usize, out.len());
Ok(())
}

/// Retrieve the number of elements to pass to [`get_pipeline_executable_statistics()`][Self::get_pipeline_executable_statistics()]
#[inline]
pub unsafe fn get_pipeline_executable_statistics_len(
&self,
executable_info: &vk::PipelineExecutableInfoKHR<'_>,
) -> VkResult<usize> {
let mut count = mem::MaybeUninit::uninit();
(self.fp.get_pipeline_executable_statistics_khr)(
self.handle,
executable_info,
count.as_mut_ptr(),
ptr::null_mut(),
)
.assume_init_on_success(count)
.map(|c| c as usize)
}

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPipelineExecutableStatisticsKHR.html>
///
/// Call [`get_pipeline_executable_statistics_len()`][Self::get_pipeline_executable_statistics_len()] to query the number of elements to pass to `out`.
/// Be sure to [`Default::default()`]-initialize these elements and optionally set their `p_next` pointer.
#[inline]
#[doc(alias = "vkGetPipelineExecutableStatisticsKHR")]
pub unsafe fn get_pipeline_executable_statistics(
&self,
executable_info: &vk::PipelineExecutableInfoKHR<'_>,
) -> VkResult<Vec<vk::PipelineExecutableStatisticKHR<'_>>> {
read_into_defaulted_vector(|count, data| {
(self.fp.get_pipeline_executable_statistics_khr)(
self.handle,
executable_info,
count,
data,
)
})
out: &mut [vk::PipelineExecutableStatisticKHR<'_>],
) -> VkResult<()> {
let mut count = out.len() as u32;
(self.fp.get_pipeline_executable_statistics_khr)(
self.handle,
executable_info,
&mut count,
out.as_mut_ptr(),
)
.result()?;
assert_eq!(count as usize, out.len());
Ok(())
}
}
37 changes: 0 additions & 37 deletions ash/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,43 +64,6 @@ where
}
}

/// 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`][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://registry.khronos.org/vulkan/specs/1.3-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: core::fmt::Debug,
{
loop {
let mut count = N::default();
f(&mut count, ptr::null_mut()).result()?;
let mut data = alloc::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 {
break err_code.set_vec_len_on_success(
data,
count.try_into().expect("`N` failed to convert to `usize`"),
);
}
}
}

#[cfg(feature = "debug")]
pub(crate) fn debug_flags<Value: Into<u64> + Copy>(
f: &mut core::fmt::Formatter<'_>,
Expand Down
Loading