diff --git a/Changelog.md b/Changelog.md index 2f72e646..59aa054c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `VK_KHR_get_display_properties2` instance extension (#932) - Added `VK_EXT_metal_objects` device extension (#942) - Added `VK_AMD_anti_lag` device extension (#943) +- Added `VK_KHR_pipeline_binary` device extension (#944) ## [0.38.0] - 2024-04-01 diff --git a/ash/src/extensions/khr/mod.rs b/ash/src/extensions/khr/mod.rs index cd15e02e..d2967768 100644 --- a/ash/src/extensions/khr/mod.rs +++ b/ash/src/extensions/khr/mod.rs @@ -30,6 +30,7 @@ pub mod maintenance4; pub mod maintenance5; pub mod maintenance6; pub mod performance_query; +pub mod pipeline_binary; pub mod pipeline_executable_properties; pub mod present_wait; pub mod push_descriptor; diff --git a/ash/src/extensions/khr/pipeline_binary.rs b/ash/src/extensions/khr/pipeline_binary.rs new file mode 100644 index 00000000..70afabda --- /dev/null +++ b/ash/src/extensions/khr/pipeline_binary.rs @@ -0,0 +1,94 @@ +//! + +use crate::prelude::*; +use crate::vk; +use crate::RawPtr as _; +use alloc::vec::Vec; +use core::ffi; +use core::mem; + +impl crate::khr::pipeline_binary::Device { + /// + #[inline] + #[doc(alias = "vkCreatePipelineBinariesKHR")] + pub unsafe fn create_pipeline_binaries( + &self, + create_info: &vk::PipelineBinaryCreateInfoKHR<'_>, + allocation_callbacks: Option<&vk::AllocationCallbacks<'_>>, + binaries: &mut vk::PipelineBinaryHandlesInfoKHR<'_>, + ) -> VkResult<()> { + (self.fp.create_pipeline_binaries_khr)( + self.handle, + create_info, + allocation_callbacks.as_raw_ptr(), + binaries, + ) + .result() + } + + /// + #[inline] + #[doc(alias = "vkDestroyPipelineBinaryKHR")] + pub unsafe fn destroy_pipeline_binary( + &self, + pipeline_binary: vk::PipelineBinaryKHR, + allocation_callbacks: Option<&vk::AllocationCallbacks<'_>>, + ) { + (self.fp.destroy_pipeline_binary_khr)( + self.handle, + pipeline_binary, + allocation_callbacks.as_raw_ptr(), + ) + } + + /// + #[inline] + #[doc(alias = "vkGetPipelineKeyKHR")] + pub unsafe fn get_pipeline_key( + &self, + pipeline_create_info: Option<&vk::PipelineCreateInfoKHR<'_>>, + ) -> VkResult> { + let mut pipeline_key = mem::MaybeUninit::uninit(); + (self.fp.get_pipeline_key_khr)( + self.handle, + pipeline_create_info.as_raw_ptr(), + pipeline_key.as_mut_ptr(), + ) + .assume_init_on_success(pipeline_key) + } + + /// + #[inline] + #[doc(alias = "vkGetPipelineBinaryDataKHR")] + pub unsafe fn get_pipeline_binary_data( + &self, + info: &vk::PipelineBinaryDataInfoKHR<'_>, + pipeline_binary_key: &mut vk::PipelineBinaryKeyKHR<'_>, + ) -> VkResult> { + read_into_uninitialized_binary_vector(|count, data| { + (self.fp.get_pipeline_binary_data_khr)( + self.handle, + info, + pipeline_binary_key, + count, + data, + ) + }) + } + + /// + #[inline] + #[doc(alias = "vkReleaseCapturedPipelineDataKHR")] + pub unsafe fn release_captured_pipeline_data( + &self, + info: &vk::ReleaseCapturedPipelineDataInfoKHR<'_>, + allocation_callbacks: Option<&vk::AllocationCallbacks<'_>>, + ) -> VkResult<()> { + (self.fp.release_captured_pipeline_data_khr)( + self.handle, + info, + allocation_callbacks.as_raw_ptr(), + ) + .result() + } +} diff --git a/ash/src/prelude.rs b/ash/src/prelude.rs index 1341960f..b974e61b 100644 --- a/ash/src/prelude.rs +++ b/ash/src/prelude.rs @@ -1,5 +1,6 @@ use alloc::vec::Vec; use core::convert::TryInto; +use core::ffi; use core::mem; use core::ptr; @@ -43,7 +44,7 @@ impl vk::Result { /// /// [`vkEnumerateInstanceExtensionProperties`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceExtensionProperties.html pub(crate) unsafe fn read_into_uninitialized_vector, T>( - f: impl Fn(&mut N, *mut T) -> vk::Result, + mut f: impl FnMut(&mut N, *mut T) -> vk::Result, ) -> VkResult> where >::Error: core::fmt::Debug, @@ -64,6 +65,29 @@ where } } +/// Calls `f` twice until it does not return [`vk::Result::ERROR_NOT_ENOUGH_SPACE_KHR`], ensuring all +/// available binary data has been read into the vector. +/// +/// The first call happens with a [`Vec`] of size `4096`. If this is not adequate, `f` is supposed +/// to return [`vk::Result::ERROR_NOT_ENOUGH_SPACE_KHR`] while also updating `count` to the desired +/// number of elements, allowing us to try again. +/// +/// See for example [`vkGetPipelineBinaryDataKHR`]. +/// +/// [`vkGetPipelineBinaryDataKHR`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPipelineBinaryDataKHR.html +pub(crate) unsafe fn read_into_uninitialized_binary_vector( + mut f: impl FnMut(&mut usize, *mut ffi::c_void) -> vk::Result, +) -> VkResult> { + let mut count = 4096; + let mut data = Vec::::with_capacity(count); + let err_code = f(&mut count, data.as_mut_ptr().cast()); + if err_code != vk::Result::ERROR_NOT_ENOUGH_SPACE_KHR { + return err_code.set_vec_len_on_success(data, count); + } + // XXX: The implementation should not return NOT_ENOUGH_SPACE again + f(&mut count, data.as_mut_ptr().cast()).set_vec_len_on_success(data, count) +} + /// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore, ensuring all /// available data has been read into the vector. /// @@ -81,7 +105,7 @@ pub(crate) unsafe fn read_into_defaulted_vector< N: Copy + Default + TryInto, T: Default + Clone, >( - f: impl Fn(&mut N, *mut T) -> vk::Result, + mut f: impl FnMut(&mut N, *mut T) -> vk::Result, ) -> VkResult> where >::Error: core::fmt::Debug,