diff --git a/Changelog.md b/Changelog.md index e8394a7ca..8f2b30182 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `VK_EXT_display_control` display extension (#934) - Added `VK_EXT_metal_objects` device extension (#942) - Added `VK_AMD_anti_lag` device extension (#943) +- Added `VK_KHR_pipeline_binary` device extension (#944) - Added `VK_KHR_video_queue`, `VK_KHR_video_encode_queue`, and `VK_KHR_video_decode_queue` device extensions (#965) - Added (typically vendor-suffixed) aliases for global constants (#1018) diff --git a/ash/src/extensions/khr/mod.rs b/ash/src/extensions/khr/mod.rs index b5313cdb2..4218623cc 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 000000000..29a46aadc --- /dev/null +++ b/ash/src/extensions/khr/pipeline_binary.rs @@ -0,0 +1,89 @@ +//! + +use crate::read_into_uninitialized_binary_vector; +use crate::vk; +use crate::RawPtr as _; +use crate::VkResult; +use alloc::vec::Vec; + +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.to_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.to_raw_ptr(), + ) + } + + /// + #[inline] + #[doc(alias = "vkGetPipelineKeyKHR")] + pub unsafe fn get_pipeline_key( + &self, + pipeline_create_info: Option<&vk::PipelineCreateInfoKHR<'_>>, + pipeline_key: &mut vk::PipelineBinaryKeyKHR<'_>, + ) -> VkResult<()> { + (self.fp.get_pipeline_key_khr)(self.handle, pipeline_create_info.to_raw_ptr(), pipeline_key) + .result() + } + + /// + #[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.to_raw_ptr(), + ) + .result() + } +} diff --git a/ash/src/lib.rs b/ash/src/lib.rs index c9964045f..2ee30275b 100644 --- a/ash/src/lib.rs +++ b/ash/src/lib.rs @@ -57,6 +57,7 @@ extern crate alloc; use alloc::vec::Vec; use core::convert::TryInto; +use core::ffi; use core::mem; use core::ptr; @@ -242,13 +243,13 @@ 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 +/// 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://docs.vulkan.org/refpages/latest/refpages/source/vkEnumerateInstanceExtensionProperties.html +/// [`vkEnumerateInstanceExtensionProperties()`]: https://docs.vulkan.org/refpages/latest/refpages/source/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, @@ -269,6 +270,41 @@ where } } +/// Calls `f` at most 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 capacity `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. +/// +/// This function is _not_ designed to be used with [`vk::Result::INCOMPLETE`], see +/// [`read_into_uninitialized_vector()`] instead. +/// +/// See for example [`vkGetPipelineBinaryDataKHR()`], where the new return code was first introduced. +/// +/// [`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 data = Vec::::with_capacity(4096); + let mut count = data.capacity(); + let mut err_code = f(&mut count, data.as_mut_ptr().cast()); + if err_code == vk::Result::ERROR_NOT_ENOUGH_SPACE_KHR { + debug_assert!( + count > data.capacity(), + "Implementation should have updated the value to be higher than the initial request" + ); + data.reserve(count); + err_code = f(&mut count, data.as_mut_ptr().cast()); + debug_assert_ne!( + err_code, + vk::Result::ERROR_NOT_ENOUGH_SPACE_KHR, + "Updated count was still not adequate" + ); + } + err_code.set_vec_len_on_success(data, count) +} + #[test] fn trybuild() { let t = trybuild::TestCases::new();