[0.37-stable] extensions: Provide new_from_instance() fallback for Instance functions ()

extensions: Provide `new_from_instance()` fallback for `Instance` functions

This is a minimal, semver-compatible backport of  to the
`0.37-stable` branch, warning Ash users of the problem outlined below
while the issue is properly being solved in the next breaking Ash
release (by separating `Instance` and `Device` functions in the
generator to avert this problem entirely while also always providing
optimal `Device`-specific functions for extension wrappers that are
currently already loading _everything_ via `Instance` to forgo the
problem).

As discovered and detailed in  a few extension wrappers were loading
and calling `Instance` functions via `Device` and
`get_device_proc_addr()` which is [defined] to only return non-`NULL`
function pointers for `Device` functions.  Those wrapper functions will
always call into Ash's panicking NULL-stub functions as the desired
`Instance` function could not be loaded.

Deprecate the `new()` functions for extension wrappers that were doing
this, while pointing the reader to `new_from_instance()` and explaining
in the docs what function will always `panic!()` when the struct was
loaded using `new()` instead.

This function always takes a raw `vk::Device` directly to fill `handle`
(rather than `ash::Device` to retrieve `handle()` from), allowing users
to pass `vk::Device::null()` when they do intend to load this extension
wrapper just for calling the `Instance` function.

[defined]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetDeviceProcAddr.html#_description
This commit is contained in:
Marijn Suijten 2023-05-06 21:07:08 +02:00 committed by GitHub
parent a2d17fe5ba
commit 81cf86eb44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 95 additions and 8 deletions

View file

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] - ReleaseDate
### Changed
- `VK_KHR_device_group_creation`: Replaced `device()` with `instance()` (via deprecation) because it is returning `vk::Instance` (#744)
### Added
- Added `VK_EXT_pipeline_properties` device extension (#622)
@ -14,6 +18,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `VK_KHR_performance_query` device extension (#726)
- Added `VK_EXT_shader_object` device extension (#732)
- Added missing `Device::get_device_queue2()` wrapper (#736)
- Added with `new_with_instance()` on the following extensions to allow loading the listed `Instance` functions: (#744)
- `VK_KHR_swapchain`: `get_physical_device_present_rectangles()`
- `VK_KHR_device_group`: `get_physical_device_present_rectangles()`
- `VK_EXT_full_screen_exclusive`: `get_physical_device_surface_present_modes2()`
- Exposed `FramebufferCreateInfoBuilder::attachment_count()` builder for `vk::FramebufferCreateFlags::IMAGELESS` (#747)
## [0.37.2] - 2022-01-11
@ -52,7 +60,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `VK_EXT_extended_dynamic_state3` device extension (#671)
- Added `VK_EXT_descriptor_buffer` instance extension (#679)
### Fixed
- `VK_KHR_ray_tracing_pipeline`: Set the buffer length in `get_ray_tracing_capture_replay_shader_group_handles` so it no longer always returns an empty `Vec` (#658)
@ -296,7 +303,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### 0.29.0
- -Breaking-: Removed Display impl for flags. The Debug impl now reports flags by name.
- _Breaking_: Removed Display impl for flags. The Debug impl now reports flags by name.
- Functions now have a doc comment that links to the Vulkan spec
- Entry has a new method called `try_enumerate_instance_version` which can be used in a 1.0 context.
- The generator now uses `BTreeMap` for better diffs.
@ -305,9 +312,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Switched to a new [changelog](https://keepachangelog.com/en/1.0.0/) format
- Fixed a build issue on ARM.
- -Breaking- Arrays are now passed by reference.
- _Breaking_: Arrays are now passed by reference.
- Builders are now marked as `#[transparent]`.
- -Breaking- Renamed `.next(..)` to `push_next`. `push_next` is only available on structs that are passed directly. Additionally `push_next` only accepts structs that can be inserted into the pointer chain. Read the readme for more information.
- _Breaking_: Renamed `.next(..)` to `push_next`. `push_next` is only available on structs that are passed directly. Additionally `push_next` only accepts structs that can be inserted into the pointer chain. Read the readme for more information.
- New -experimental- extensions. Those do not follow the semver rules and can be removed at any time.
- Added `AmdGpaInterface` extension.
@ -372,7 +379,7 @@ flags: vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER_BIT,
- `map_memory` now returns a void ptr
- `ash::util::Align` is a helper struct that
can write to aligned memory.
can write to aligned memory.
[Unreleased]: https://github.com/MaikKlein/ash/compare/0.37.2...HEAD
[0.37.2]: https://github.com/MaikKlein/ash/releases/tag/0.37.2

View file

@ -1,9 +1,10 @@
use crate::prelude::*;
use crate::vk;
use crate::{Device, Instance};
use crate::{Device, Entry, Instance};
use std::ffi::CStr;
use std::mem;
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_EXT_full_screen_exclusive.html>
#[derive(Clone)]
pub struct FullScreenExclusive {
handle: vk::Device,
@ -11,6 +12,13 @@ pub struct FullScreenExclusive {
}
impl FullScreenExclusive {
/// # Warning
/// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called:
/// - [`Self::get_physical_device_surface_present_modes2()`]
///
/// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the
/// above [`Instance`] function is called. This will be solved in the next breaking `ash`
/// release: <https://github.com/ash-rs/ash/issues/727>.
pub fn new(instance: &Instance, device: &Device) -> Self {
let handle = device.handle();
let fp = vk::ExtFullScreenExclusiveFn::load(|name| unsafe {
@ -19,6 +27,19 @@ impl FullScreenExclusive {
Self { handle, fp }
}
/// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra
/// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be
/// loaded instead of always panicking. See also [`Self::new()`] for more details.
///
/// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the
/// [`Instance`] function.
pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self {
let fp = vk::ExtFullScreenExclusiveFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
Self { handle: device, fp }
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkAcquireFullScreenExclusiveModeEXT.html>
#[inline]
pub unsafe fn acquire_full_screen_exclusive_mode(
@ -29,6 +50,10 @@ impl FullScreenExclusive {
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetPhysicalDeviceSurfacePresentModes2EXT.html>
///
/// # Warning
///
/// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`].
#[inline]
pub unsafe fn get_physical_device_surface_present_modes2(
&self,

View file

@ -2,7 +2,7 @@
use super::Swapchain;
use crate::prelude::*;
use crate::vk;
use crate::{Device, Instance};
use crate::{Device, Entry, Instance};
use std::ffi::CStr;
use std::mem;
@ -14,6 +14,13 @@ pub struct DeviceGroup {
}
impl DeviceGroup {
/// # Warning
/// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called:
/// - [`Self::get_physical_device_present_rectangles()`]
///
/// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the
/// above [`Instance`] function is called. This will be solved in the next breaking `ash`
/// release: <https://github.com/ash-rs/ash/issues/727>.
pub fn new(instance: &Instance, device: &Device) -> Self {
let handle = device.handle();
let fp = vk::KhrDeviceGroupFn::load(|name| unsafe {
@ -22,6 +29,19 @@ impl DeviceGroup {
Self { handle, fp }
}
/// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra
/// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be
/// loaded instead of always panicking. See also [`Self::new()`] for more details.
///
/// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the
/// [`Instance`] function.
pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self {
let fp = vk::KhrDeviceGroupFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
Self { handle: device, fp }
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceGroupPeerMemoryFeaturesKHR.html>
#[inline]
pub unsafe fn get_device_group_peer_memory_features(
@ -112,6 +132,10 @@ impl DeviceGroup {
///
/// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html
/// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html
///
/// # Warning
///
/// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`].
#[inline]
pub unsafe fn get_physical_device_present_rectangles(
&self,

View file

@ -59,8 +59,14 @@ impl DeviceGroupCreation {
&self.fp
}
#[deprecated = "typo: this function is called `device()`, but returns an `Instance`."]
#[inline]
pub fn device(&self) -> vk::Instance {
self.handle
}
#[inline]
pub fn instance(&self) -> vk::Instance {
self.handle
}
}

View file

@ -3,10 +3,11 @@ use super::DeviceGroup;
use crate::prelude::*;
use crate::vk;
use crate::RawPtr;
use crate::{Device, Instance};
use crate::{Device, Entry, Instance};
use std::ffi::CStr;
use std::mem;
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_swapchain.html>
#[derive(Clone)]
pub struct Swapchain {
handle: vk::Device,
@ -14,6 +15,13 @@ pub struct Swapchain {
}
impl Swapchain {
/// # Warning
/// [`Instance`] functions cannot be loaded from a [`Device`] and will always panic when called:
/// - [`Self::get_physical_device_present_rectangles()`]
///
/// Load this struct using an [`Instance`] instead via [`Self::new_from_instance()`] if the
/// above [`Instance`] function is called. This will be solved in the next breaking `ash`
/// release: <https://github.com/ash-rs/ash/issues/727>.
pub fn new(instance: &Instance, device: &Device) -> Self {
let handle = device.handle();
let fp = vk::KhrSwapchainFn::load(|name| unsafe {
@ -22,6 +30,19 @@ impl Swapchain {
Self { handle, fp }
}
/// Loads all functions on the [`Instance`] instead of [`Device`]. This incurs an extra
/// dispatch table for [`Device`] functions but also allows the [`Instance`] function to be
/// loaded instead of always panicking. See also [`Self::new()`] for more details.
///
/// It is okay to pass [`vk::Device::null()`] when this struct is only used to call the
/// [`Instance`] function.
pub fn new_from_instance(entry: &Entry, instance: &Instance, device: vk::Device) -> Self {
let fp = vk::KhrSwapchainFn::load(|name| unsafe {
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
});
Self { handle: device, fp }
}
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateSwapchainKHR.html>
#[inline]
pub unsafe fn create_swapchain(
@ -153,6 +174,10 @@ impl Swapchain {
///
/// [Vulkan 1.1]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_VERSION_1_1.html
/// [`VK_KHR_surface`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_surface.html
///
/// # Warning
///
/// Function will always panic unless this struct is loaded via [`Self::new_from_instance()`].
#[inline]
pub unsafe fn get_physical_device_present_rectangles(
&self,