-
Notifications
You must be signed in to change notification settings - Fork 229
extensions/khr: Add VK_KHR_pipeline_binary extension #944
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| //! <https://docs.vulkan.org/refpages/latest/refpages/source/VK_KHR_pipeline_binary.html> | ||
|
|
||
| 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 { | ||
| /// <https://docs.vulkan.org/refpages/latest/refpages/source/vkCreatePipelineBinariesKHR.html> | ||
| #[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() | ||
| } | ||
|
|
||
| /// <https://docs.vulkan.org/refpages/latest/refpages/source/vkDestroyPipelineBinaryKHR.html> | ||
| #[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(), | ||
| ) | ||
| } | ||
|
|
||
| /// <https://docs.vulkan.org/refpages/latest/refpages/source/vkGetPipelineKeyKHR.html> | ||
| #[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() | ||
| } | ||
|
|
||
| /// <https://docs.vulkan.org/refpages/latest/refpages/source/vkGetPipelineBinaryDataKHR.html> | ||
| #[inline] | ||
| #[doc(alias = "vkGetPipelineBinaryDataKHR")] | ||
| pub unsafe fn get_pipeline_binary_data( | ||
| &self, | ||
| info: &vk::PipelineBinaryDataInfoKHR<'_>, | ||
| pipeline_binary_key: &mut vk::PipelineBinaryKeyKHR<'_>, | ||
| ) -> VkResult<Vec<u8>> { | ||
| read_into_uninitialized_binary_vector(|count, data| { | ||
| (self.fp.get_pipeline_binary_data_khr)( | ||
| self.handle, | ||
| info, | ||
| pipeline_binary_key, | ||
| count, | ||
| data, | ||
| ) | ||
| }) | ||
| } | ||
|
|
||
| /// <https://docs.vulkan.org/refpages/latest/refpages/source/vkReleaseCapturedPipelineDataKHR.html> | ||
| #[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() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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<N: Copy + Default + TryInto<usize>, T>( | ||
| f: impl Fn(&mut N, *mut T) -> vk::Result, | ||
| mut f: impl FnMut(&mut N, *mut T) -> vk::Result, | ||
| ) -> VkResult<Vec<T>> | ||
| where | ||
| <N as TryInto<usize>>::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<Vec<u8>> { | ||
| let mut data = Vec::<u8>::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); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: We don't expect to reallocate this any further, so |
||
| 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(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really a blocker, but I'd like to see some sort of reference for why we think 4KiB in particular makes sense here rather than, say, 128B, or 1MiB.