pub trait Layer:
Sync
+ Default
+ 'static {
type GlobalHooksInfo: GlobalHooksInfo;
type InstanceInfo: InstanceInfo;
type DeviceInfo: DeviceInfo;
type InstanceInfoContainer: Borrow<Self::InstanceInfo> + Sync + Send;
type DeviceInfoContainer: Borrow<Self::DeviceInfo> + Sync + Send;
// Required methods
fn manifest() -> LayerManifest;
fn global_instance() -> impl Deref<Target = Global<Self>> + 'static;
fn global_hooks_info(&self) -> &Self::GlobalHooksInfo;
fn create_instance_info(
&self,
create_info: &InstanceCreateInfo,
allocator: Option<&AllocationCallbacks>,
instance: Arc<Instance>,
next_get_instance_proc_addr: PFN_vkGetInstanceProcAddr,
) -> Self::InstanceInfoContainer;
fn create_device_info(
&self,
physical_device: PhysicalDevice,
create_info: &DeviceCreateInfo,
allocator: Option<&AllocationCallbacks>,
device: Arc<Device>,
next_get_device_proc_addr: PFN_vkGetDeviceProcAddr,
) -> Self::DeviceInfoContainer;
// Provided methods
fn global_hooks(
&self,
) -> <Self::GlobalHooksInfo as GlobalHooksInfo>::HooksRefType<'_> { ... }
fn hooked_instance_commands(
&self,
_instance_info: &Self::InstanceInfo,
) -> Box<dyn Iterator<Item = VulkanCommand>> { ... }
fn hooked_device_commands(
&self,
_instance_info: &Self::InstanceInfo,
_device_info: Option<&Self::DeviceInfo>,
) -> Box<dyn Iterator<Item = VulkanCommand>> { ... }
}Expand description
The Layer trait provides all layer implementation information for the layer framework.
The type that implements Layer provides the following functionalities:
- Global initialization for the layer.
- The factory of
LayerManifest,InstanceInfo, andDeviceInfo. - The container of
GlobalHooksInfo. - Providing the storage of
Global. - Overriding the intercepted Vulkan commands at runtime.
§Initialization
The layer implementation can rely on Layer::default to perform the global initialization. e.g.
initialize the logger.
The layer framework guarantees that Layer::default is only called once when
Global::default is called, and won’t be called anywhere else. The layer framework doesn’t
call Global::default to initialize. Instead, Layer::global_instance is called instead on
every Vulkan function entry when the global singleton is needed, and the layer implementation is
expected to lazily create the static Global singleton with Global::default in
Layer::global_instance. Therefore, if the layer implementation can guarantee that
Global::default is called once during the lifetime of the whole process, it is also
guaranteed that Layer::default is called once during the lifetime of the whole process. Note
that it may be difficult to realize such guarantee, because the Vulkan loader my load and unload
the layer library multiple times, and the application my load and unload the Vulkan loader
multiple times.
Layer::default must not call into any Global methods and any Vulkan commands exported by
the Vulkan loader to avoid an endless recursion.
§Global clean up
It is recommended that the implementor of the Layer trait should have a no-op drop if all
VkInstance intercepted by the layer is destroyed. If so, Global has a no-op drop when all
VkInstance is destroyed. If the Layer implementor is always
trivially-destructible1, it’s great.
It is guaranteed that when Global::drop is called, Layer::drop is called exactly once.
However, as a dynamic link library that may be loaded and unloaded to/from the process multiple
times, there is no easy way to guarantee that Global::drop is called on every unload. In
additoon, in Rust, static items do not call drop at the end of the program2. We
can’t expect drop to be called on dynamic link library unload as well. Therefore, we should
avoid using Layer::drop to do clean-up to avoid resource leak.
If it is really necessary to store some not trivially-destructible types(note that all Rust
std::collections are not trivially-destructible) in side the type that implements Layer,
the following techniques may be helpful.
One way to test if a type T leaks heap memory is to run Miri tests with std::mem::forget.
#[derive(Default)]
struct TriviallyDestructible;
#[derive(Default)]
struct NotTriviallyDestructible(Box<u32>);
// This passes the Miri test, so TriviallyDestructible won't leak heap memory if drop is not
// called.
{
let x: TriviallyDestructible = Default::default();
std::mem::forget(x);
}
// This fails the Miri test, so NotTriviallyDestructible will leak heap memory if drop is not
// called.
{
let x: NotTriviallyDestructible = Default::default();
std::mem::forget(x);
}The drop of Rust std::collections is not no-op even if the collection is empty, so avoid
using them directly in the type that implements Layer.
The drop of std::sync::Weak is not no-op even if all strong references to the underlying
object don’t exist, so we should avoid using it to construct a type that needs a no-op drop.
The drop of Option::None is no-op even if the underlying T is not trivially destructible,
and the drop of Mutex is no-op if the drop of the wrapped T is no-op.
Therefore Mutex<Option<T>> is a good basic block to build a type that needs a no-op drop.
§Examples
A simple layer that prints “Hello from the Rust Vulkan layer!” to stdout on every
vkCreateDevice.
use ash::{self, vk};
use once_cell::sync::Lazy;
use std::sync::Arc;
use vulkan_layer::{
Global, Layer, LayerManifest, StubDeviceInfo, StubGlobalHooks, StubInstanceInfo,
};
#[derive(Default)]
struct MyLayer(StubGlobalHooks);
impl Layer for MyLayer {
type GlobalHooksInfo = StubGlobalHooks;
type InstanceInfo = StubInstanceInfo;
type DeviceInfo = StubDeviceInfo;
type InstanceInfoContainer = StubInstanceInfo;
type DeviceInfoContainer = StubDeviceInfo;
fn global_instance() -> impl std::ops::Deref<Target = Global<Self>> + 'static {
static GLOBAL: Lazy<Global<MyLayer>> = Lazy::new(Default::default);
&*GLOBAL
}
fn manifest() -> LayerManifest {
let mut manifest = LayerManifest::default();
manifest.name = "VK_LAYER_VENDOR_rust_example";
manifest.spec_version = vk::API_VERSION_1_1;
manifest
}
fn global_hooks_info(&self) -> &Self::GlobalHooksInfo {
&self.0
}
fn create_instance_info(
&self,
_: &vk::InstanceCreateInfo,
_: Option<&vk::AllocationCallbacks>,
_: Arc<ash::Instance>,
_next_get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr,
) -> Self::InstanceInfoContainer {
Default::default()
}
fn create_device_info(
&self,
_: vk::PhysicalDevice,
_: &vk::DeviceCreateInfo,
_: Option<&vk::AllocationCallbacks>,
_: Arc<ash::Device>,
_next_get_device_proc_addr: vk::PFN_vkGetDeviceProcAddr,
) -> Self::DeviceInfoContainer {
println!("Hello from the Rust Vulkan layer!");
Default::default()
}
}A layer that initializes the logging infrastructure with env_logger.
use ash::{self, vk};
use log::info;
use once_cell::sync::Lazy;
use std::sync::Arc;
use vulkan_layer::{
Global, Layer, LayerManifest, StubDeviceInfo, StubGlobalHooks, StubInstanceInfo,
};
struct MyLayer(StubGlobalHooks);
impl Default for MyLayer {
fn default() -> Self {
env_logger::init();
Self(Default::default())
}
}
impl Layer for MyLayer {
type GlobalHooksInfo = StubGlobalHooks;
type InstanceInfo = StubInstanceInfo;
type DeviceInfo = StubDeviceInfo;
type InstanceInfoContainer = StubInstanceInfo;
type DeviceInfoContainer = StubDeviceInfo;
fn global_instance() -> impl std::ops::Deref<Target = Global<Self>> + 'static {
static GLOBAL: Lazy<Global<MyLayer>> = Lazy::new(Default::default);
&*GLOBAL
}
fn manifest() -> LayerManifest {
let mut manifest = LayerManifest::default();
manifest.name = "VK_LAYER_VENDOR_rust_example";
manifest.spec_version = vk::API_VERSION_1_1;
manifest
}
fn global_hooks_info(&self) -> &Self::GlobalHooksInfo {
&self.0
}
fn create_instance_info(
&self,
_: &vk::InstanceCreateInfo,
_: Option<&vk::AllocationCallbacks>,
_: Arc<ash::Instance>,
_next_get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr,
) -> Self::InstanceInfoContainer {
Default::default()
}
fn create_device_info(
&self,
_: vk::PhysicalDevice,
_: &vk::DeviceCreateInfo,
_: Option<&vk::AllocationCallbacks>,
_: Arc<ash::Device>,
_next_get_device_proc_addr: vk::PFN_vkGetDeviceProcAddr,
) -> Self::DeviceInfoContainer {
info!("Hello from the Rust Vulkan layer!");
Default::default()
}
}This term is borrowed from C++: if the type itself doesn’t have a destructor and the types of all fields are trivially destructible, this type is trivially destructible. Rust has
std::mem::needs_drop, but this function doesn’t have a strong guarantee. ↩https://doc.rust-lang.org/reference/items/static-items.html#:~:text=Static%20items%20do%20not%20call%20drop%20at%20the%20end%20of%20the%20program. ↩
Required Associated Types§
Sourcetype GlobalHooksInfo: GlobalHooksInfo
type GlobalHooksInfo: GlobalHooksInfo
The type that provides information about interception of global commands.
If the layer implementation is not interested in intercepting any
global commands,
StubGlobalHooks can be used.
Sourcetype InstanceInfo: InstanceInfo
type InstanceInfo: InstanceInfo
The type that provides information about interception of Vulkan instance functions, global commands not included.
If the layer implementation is not interested in intercepting any
Vulkan instance functions
(global commands
not included), StubInstanceInfo can be used.
Sourcetype DeviceInfo: DeviceInfo
type DeviceInfo: DeviceInfo
The type that provides information about interception of Vulkan device functions.
If the layer implementation is not interested in intercepting any
Vulkan device functions,
StubDeviceInfo can be used.
Sourcetype InstanceInfoContainer: Borrow<Self::InstanceInfo> + Sync + Send
type InstanceInfoContainer: Borrow<Self::InstanceInfo> + Sync + Send
The type that holds a Layer::InstanceInfo type. Usually just Self::InstanceInfo.
This extra associated type allows the layer to use a smart pointer like Arc or Box
to hold the Layer::InstanceInfo.
§Examples
Use Arc to hold the Layer::InstanceInfo.
use ash::vk;
use once_cell::sync::Lazy;
use std::sync::Arc;
use vulkan_layer::{
Global, Layer, LayerManifest, StubDeviceInfo, StubGlobalHooks, StubInstanceInfo,
};
#[derive(Default)]
struct MyLayer(StubGlobalHooks);
impl Layer for MyLayer {
type InstanceInfo = StubInstanceInfo;
type InstanceInfoContainer = Arc<StubInstanceInfo>;
fn create_instance_info(
&self,
_: &vk::InstanceCreateInfo,
_: Option<&vk::AllocationCallbacks>,
_: Arc<ash::Instance>,
_next_get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr,
) -> Self::InstanceInfoContainer {
Arc::default()
}
// Unrelated required items are omitted.
}Sourcetype DeviceInfoContainer: Borrow<Self::DeviceInfo> + Sync + Send
type DeviceInfoContainer: Borrow<Self::DeviceInfo> + Sync + Send
The type that holds a Layer::DeviceInfo type. Usually just Self::DeviceInfo.
This extra associated type allows the layer to use a smart pointer like Arc to hold the
Layer::DeviceInfo.
§Examples
Use Arc to hold the Layer::DeviceInfo.
use ash::vk;
use once_cell::sync::Lazy;
use std::sync::Arc;
use vulkan_layer::{
Global, Layer, LayerManifest, StubDeviceInfo, StubGlobalHooks, StubInstanceInfo,
};
#[derive(Default)]
struct MyLayer(StubGlobalHooks);
impl Layer for MyLayer {
type DeviceInfo = StubDeviceInfo;
type DeviceInfoContainer = Arc<StubDeviceInfo>;
fn create_device_info(
&self,
_: vk::PhysicalDevice,
_: &vk::DeviceCreateInfo,
_: Option<&vk::AllocationCallbacks>,
_: Arc<ash::Device>,
_next_get_device_proc_addr: vk::PFN_vkGetDeviceProcAddr,
) -> Self::DeviceInfoContainer {
Arc::default()
}
// Unrelated required items are omitted.
}Required Methods§
Sourcefn manifest() -> LayerManifest
fn manifest() -> LayerManifest
Returns the layer manifest to the layer framework.
Implementors should always return the same value during the lifetime of the process, and
must match the manifest json file with the layer. Implementors should avoid calling into any
Global methods because this function can be called to implement Vulkan introspection
queries before any VkInstance is created.
The layer framework will use this value to:
- Implement Vulkan introspection queries,
including
vkEnumerateInstanceLayerProperties,vkEnumerateDeviceLayerProperties,vkEnumerateInstanceExtensionPropertiesandvkEnumerateDeviceExtensionProperties. - Remove the layer device extensions from
VkDeviceCreateInfo::ppEnabledExtensionNamesinvkCreateDeviceif present.
Sourcefn global_instance() -> impl Deref<Target = Global<Self>> + 'static
fn global_instance() -> impl Deref<Target = Global<Self>> + 'static
Provide the reference to the global singleton of Global.
Implementors must always return the reference pointing to the same Global object.
Implementors can use LazyLock, OnceLock,
or Lazy from the once_cell crate to implement. Implementors should use
Global::default to create the Global object. More information on initialization can
be found here.
§Examples
Use Lazy provided by the once_cell crate to implement.
use ash::{self, vk};
use once_cell::sync::Lazy;
use std::sync::Arc;
use vulkan_layer::{
Global, Layer, LayerManifest, StubDeviceInfo, StubGlobalHooks, StubInstanceInfo,
};
#[derive(Default)]
struct MyLayer(StubGlobalHooks);
impl Layer for MyLayer {
fn global_instance() -> impl std::ops::Deref<Target = Global<Self>> + 'static {
static GLOBAL: Lazy<Global<MyLayer>> = Lazy::new(Default::default);
&*GLOBAL
}
// Unrelated required items are omitted.
}Sourcefn global_hooks_info(&self) -> &Self::GlobalHooksInfo
fn global_hooks_info(&self) -> &Self::GlobalHooksInfo
Returns a reference of the underlying GlobalHooksInfo object.
Sourcefn create_instance_info(
&self,
create_info: &InstanceCreateInfo,
allocator: Option<&AllocationCallbacks>,
instance: Arc<Instance>,
next_get_instance_proc_addr: PFN_vkGetInstanceProcAddr,
) -> Self::InstanceInfoContainer
fn create_instance_info( &self, create_info: &InstanceCreateInfo, allocator: Option<&AllocationCallbacks>, instance: Arc<Instance>, next_get_instance_proc_addr: PFN_vkGetInstanceProcAddr, ) -> Self::InstanceInfoContainer
The factory method for the InstanceInfo type.
This function is called by the layer framework in vkCreateInstance, after the
vkCreateInstance of the next layer returns with success.
§Arguments
create_infois a pointer to a VkInstanceCreateInfo structure controlling creation of the instance. TheVkLayerInstanceLinklinked list in thepNextchain is already advanced by the layer framework. This is the originalVkInstanceCreateInfopassed in by the application or the previous layer(except the advancedVkLayerInstanceLinklinked list), even if the layer implementation passes a differentVkInstanceCreateInfoto the next layer inGlobalHooks::create_instance.allocatorcontrols host memory allocation as described in the Memory Allocation chapter of the Vulkan spec.instancecontains the loaded instance dispatch table of the next layer. The layer implementation can just clone thisArcif it is needed to keep the instance dispatch table.next_get_instance_proc_addris thevkGetInstanceProcAddrfunction pointer of the next layer obtained from theVkLayerInstanceLinklinked list.
Sourcefn create_device_info(
&self,
physical_device: PhysicalDevice,
create_info: &DeviceCreateInfo,
allocator: Option<&AllocationCallbacks>,
device: Arc<Device>,
next_get_device_proc_addr: PFN_vkGetDeviceProcAddr,
) -> Self::DeviceInfoContainer
fn create_device_info( &self, physical_device: PhysicalDevice, create_info: &DeviceCreateInfo, allocator: Option<&AllocationCallbacks>, device: Arc<Device>, next_get_device_proc_addr: PFN_vkGetDeviceProcAddr, ) -> Self::DeviceInfoContainer
The factory method for the DeviceInfo type.
This function is called by the layer framework in vkCreateDevice, after the
vkCreateDevice of the next layer returns with success.
§Arguments
physical_deviceis one of the device handles returned from a call tovkEnumeratePhysicalDevicesthat is passed tovkCreateDeviceby the application or the previous layer.create_infois a pointer to aVkDeviceCreateInfostructure containing information about how to create the device. TheVkLayerDeviceLinklinked list in thepNextchain is already advanced by the layer framework. This is the originalVkDeviceCreateInfopassed in by the application or the previous layer(except the advancedVkLayerDeviceLinklinked list), even if the layer implementation passes a differentVkDeviceCreateInfoto the next layer inInstanceHooks::create_device.allocatorcontrols host memory allocation as described in the Memory Allocation chapter of the Vulkan spec.devicecontains the loaded device dispatch table of the next layer. The layer implementation can just clone thisArcif it is needed to keep the device dispatch table.next_get_device_proc_addris thevkGetDeviceProcAddrfunction pointer of the next layer obtained from theVkLayerDeviceLinklinked list.
Provided Methods§
Sourcefn global_hooks(
&self,
) -> <Self::GlobalHooksInfo as GlobalHooksInfo>::HooksRefType<'_>
fn global_hooks( &self, ) -> <Self::GlobalHooksInfo as GlobalHooksInfo>::HooksRefType<'_>
Returns a reference of the underlying GlobalHooks object.
The layer framework relies on this function to obtain GlobalHooks, and implementors
should avoid overriding this method.
Sourcefn hooked_instance_commands(
&self,
_instance_info: &Self::InstanceInfo,
) -> Box<dyn Iterator<Item = VulkanCommand>>
fn hooked_instance_commands( &self, _instance_info: &Self::InstanceInfo, ) -> Box<dyn Iterator<Item = VulkanCommand>>
Returns an iterator of Vulkan instance functions (global commands not included) that the layer implementation needs to intercept.
This function allows the layer implementation to decide the commands to intercept
dynamically after the VkInstance is created. By default it just returns all commands
returned by InstanceInfo::hooked_commands.
§Arguments
_instance_infois the relevant instance.
§Examples
A layer that intercepts vkDestroySurfaceKHR only if the VK_KHR_win32_surface extension
is enabled.
use ash::vk;
use once_cell::sync::Lazy;
use std::{ffi::CStr, sync::Arc};
use vulkan_layer::{
Global, InstanceHooks, InstanceInfo, Layer, LayerManifest, LayerResult,
LayerVulkanCommand as VulkanCommand, StubDeviceInfo, StubGlobalHooks,
};
struct MyLayerInstanceInfo {
is_win32_surface_enabled: bool,
}
impl InstanceHooks for MyLayerInstanceInfo {
fn destroy_surface_khr(
&self,
_surface: vk::SurfaceKHR,
_p_allocator: Option<&vk::AllocationCallbacks>,
) -> LayerResult<()> {
LayerResult::Unhandled
}
}
impl InstanceInfo for MyLayerInstanceInfo {
type HooksType = Self;
type HooksRefType<'a> = &'a Self;
fn hooked_commands() -> &'static [VulkanCommand] {
&[VulkanCommand::DestroySurfaceKhr]
}
fn hooks(&self) -> Self::HooksRefType<'_> {
self
}
}
#[derive(Default)]
struct MyLayer(StubGlobalHooks);
impl Layer for MyLayer {
// ...
type InstanceInfo = MyLayerInstanceInfo;
type InstanceInfoContainer = MyLayerInstanceInfo;
fn create_instance_info(
&self,
create_info: &vk::InstanceCreateInfo,
_: Option<&vk::AllocationCallbacks>,
_: Arc<ash::Instance>,
_next_get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr,
) -> Self::InstanceInfoContainer {
let enabled_extensions = if create_info.enabled_extension_count > 0 {
unsafe {
std::slice::from_raw_parts(
create_info.pp_enabled_extension_names,
create_info.enabled_extension_count as usize,
)
}
} else {
&[]
};
let is_win32_surface_enabled = enabled_extensions
.iter()
.find(|extension_name| {
(unsafe { CStr::from_ptr(**extension_name) })
== ash::extensions::khr::Win32Surface::name()
})
.is_some();
MyLayerInstanceInfo {
is_win32_surface_enabled,
}
}
fn hooked_instance_commands(
&self,
instance_info: &Self::InstanceInfo,
) -> Box<dyn Iterator<Item = VulkanCommand>> {
let should_hook_destroy_surface = instance_info.is_win32_surface_enabled;
Box::new(
Self::InstanceInfo::hooked_commands()
.iter()
.cloned()
.filter(move |command| match command {
VulkanCommand::DestroySurfaceKhr => should_hook_destroy_surface,
_ => true,
}),
)
}
}Sourcefn hooked_device_commands(
&self,
_instance_info: &Self::InstanceInfo,
_device_info: Option<&Self::DeviceInfo>,
) -> Box<dyn Iterator<Item = VulkanCommand>>
fn hooked_device_commands( &self, _instance_info: &Self::InstanceInfo, _device_info: Option<&Self::DeviceInfo>, ) -> Box<dyn Iterator<Item = VulkanCommand>>
Returns an iterator of Vulkan device functions that the layer implementation needs to intercept.
This function allows the layer implementation to decide the commands to intercept
dynamically after the VkInstance or VkDevice is created. By default it just returns all
commands returned by DeviceInfo::hooked_commands.
Arguments
_instance_infois the relevant instance._device_infois an optional relevant device. If_device_infoisNone, the layer framework is querying all possible intercepted device functions to implementvkGetInstanceProcAddrwith thepNameparameter referring to a device functions, i.e. implementations must guarantee that the returned commands with aNone_device_infois the superset of all possible_device_info. Otherwise, the application that just uses the function pointers returned byvkGetInstanceProcAddrmay skip the current layer.
§Examples
A layer that intercepts the vkCreateImage only if the ASTC LDR feature is enabled.
use ash::{self, prelude::VkResult, vk};
use once_cell::sync::Lazy;
use std::sync::Arc;
use vulkan_layer::{
DeviceHooks, DeviceInfo, Global, Layer, LayerManifest, LayerResult,
LayerVulkanCommand as VulkanCommand, StubGlobalHooks, StubInstanceInfo,
VulkanBaseInStructChain,
};
struct MyLayerDeviceInfo {
is_astc_enabled: bool,
}
impl DeviceHooks for MyLayerDeviceInfo {
fn create_image(
&self,
create_info: &vk::ImageCreateInfo,
_p_allocator: Option<&vk::AllocationCallbacks>,
) -> LayerResult<VkResult<vk::Image>> {
if create_info.format == vk::Format::ASTC_4X4_UNORM_BLOCK {
println!("ASTC 4x4 UNORM image created.");
}
LayerResult::Unhandled
}
}
impl DeviceInfo for MyLayerDeviceInfo {
type HooksType = Self;
type HooksRefType<'a> = &'a Self;
fn hooked_commands() -> &'static [VulkanCommand] {
&[VulkanCommand::CreateImage]
}
fn hooks(&self) -> Self::HooksRefType<'_> {
self
}
}
#[derive(Default)]
struct MyLayer(StubGlobalHooks);
impl Layer for MyLayer {
// ...
type DeviceInfo = MyLayerDeviceInfo;
type DeviceInfoContainer = MyLayerDeviceInfo;
fn create_device_info(
&self,
_: vk::PhysicalDevice,
create_info: &vk::DeviceCreateInfo,
_: Option<&vk::AllocationCallbacks>,
_: Arc<ash::Device>,
_next_get_device_proc_addr: vk::PFN_vkGetDeviceProcAddr,
) -> Self::DeviceInfoContainer {
let mut p_next_chain: VulkanBaseInStructChain =
unsafe { (create_info.p_next as *const vk::BaseInStructure).as_ref() }.into();
let is_astc_enabled = p_next_chain
.find_map(|p_next| {
let p_next = p_next as *const vk::BaseInStructure;
unsafe {
ash::match_in_struct!(match p_next {
features2 @ vk::PhysicalDeviceFeatures2 => {
Some(&features2.features)
}
_ => {
None
}
})
}
})
.or_else(|| unsafe { create_info.p_enabled_features.as_ref() })
.map(|features| features.texture_compression_astc_ldr == vk::TRUE)
.unwrap_or(false);
MyLayerDeviceInfo { is_astc_enabled }
}
fn hooked_device_commands(
&self,
_instance_info: &Self::InstanceInfo,
device_info: Option<&Self::DeviceInfo>,
) -> Box<dyn Iterator<Item = VulkanCommand>> {
let should_hook_create_image = device_info
.map(|device_info| device_info.is_astc_enabled)
// Always hook the vkCreateImage function in the function pointers returned by
// vkGetInstanceProcAddr: we don't know if the to-be-created VkDevice will be
// created with the ASTC feature enabled.
.unwrap_or(true);
Box::new(
Self::DeviceInfo::hooked_commands()
.iter()
.cloned()
.filter(move |command| match command {
VulkanCommand::CreateImage => should_hook_create_image,
_ => true,
}),
)
}
}Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementors§
Source§impl<T: TestLayerTag> Layer for TestLayer<T>
Available on crate feature _test only.
impl<T: TestLayerTag> Layer for TestLayer<T>
_test only.