Trait InstanceInfo

Source
pub trait InstanceInfo: Send + Sync {
    type HooksType: InstanceHooks;
    type HooksRefType<'a>: Deref<Target = Self::HooksType> + 'a
       where Self: 'a;

    // Required methods
    fn hooked_commands() -> &'static [VulkanCommand];
    fn hooks(&self) -> Self::HooksRefType<'_>;
}
Expand description

A trait for the layer implementation to provide metadata of InstanceHooks for the layer framework.

This trait serves as the container of the InstanceHooks type and provides the list of intercepted Vulkan instance functions (global commands not included) for the layer framework. This trait and InstanceHooks can be implemented by the same type. Avoid returning either Vulkan device functions or global commands.

This trait can also be automatically implemented with the help of the auto_instanceinfo_impl attribute macro.

§Examples

A layer that needs to intercept the vkCreateWin32SurfaceKHR function.

use ash::{prelude::VkResult, vk};
use vulkan_layer::{
    InstanceHooks, InstanceInfo, LayerResult, LayerVulkanCommand as VulkanCommand,
};

struct MyLayerInstanceHooks;

impl InstanceHooks for MyLayerInstanceHooks {
    fn create_win32_surface_khr(
        &self,
        _p_create_info: &vk::Win32SurfaceCreateInfoKHR,
        _p_allocator: Option<&vk::AllocationCallbacks>,
    ) -> LayerResult<VkResult<vk::SurfaceKHR>> {
        LayerResult::Unhandled
    }
}

impl InstanceInfo for MyLayerInstanceHooks {
    type HooksType = Self;
    type HooksRefType<'a> = &'a Self;

    fn hooked_commands() -> &'static [VulkanCommand] {
        &[VulkanCommand::CreateWin32SurfaceKhr]
    }

    fn hooks(&self) -> Self::HooksRefType<'_> {
        self
    }
}

Required Associated Types§

Source

type HooksType: InstanceHooks

The underlying InstanceHooks type that implements the core logic to intercept Vulkan instance functions apart from global commands.

If a type implements both this trait and the InstanceHooks trait simultaneously, InstanceInfo::HooksType can be set to Self.

Source

type HooksRefType<'a>: Deref<Target = Self::HooksType> + 'a where Self: 'a

A type that can be dereferencing to InstanceInfo::HooksType. Usually &InstanceInfo::HooksType.

This extra associated type allows the layer implementation to use a smart pointer like Arc or MutexGuard to hold the reference.

§Examples

A layer implementation that returns a Arc.

struct MyLayerInstanceInfo(Arc<MyLayerInstanceHooks>);

impl InstanceInfo for MyLayerInstanceInfo {
    type HooksType = MyLayerInstanceHooks;
    type HooksRefType<'a> = Arc<MyLayerInstanceHooks>;

    // Other required methods omitted.

    fn hooks(&self) -> Self::HooksRefType<'_> {
        Arc::clone(&self.0)
    }
}

Required Methods§

Source

fn hooked_commands() -> &'static [VulkanCommand]

Returns a slice of Vulkan instance functions (global commands not included) that the layer implementation needs to intercept.

This function should normally return the methods implemented by the associated InstanceHooks type. If the layer implementation needs to decide the function to intercept dynamically at runtime, use the Layer::hooked_instance_commands method to override the list of intercepted instance functions.

Avoid returning unexpected commands(i.e. Vulkan device functions or global commands). Otherwise, those commands may or may not be intercepted.

For Vulkan commands that have multiple names, e.g. vkGetPhysicalDeviceProperties2 and vkGetPhysicalDeviceProperties2KHR, only the shortest name should be used(VulkanCommand::GetPhysicalDeviceProperties2 in this example). The layer framework automatically wires both entries to the layer implementation.

§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,
                }),
        )
    }
}
Source

fn hooks(&self) -> Self::HooksRefType<'_>

Returns the reference of the InstanceInfo::HooksType.

The layer framework uses the returned value to call into the layer implementation of intercepted commands.

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 InstanceInfo for StubInstanceInfo

Source§

impl<T: TestLayerMock> InstanceInfo for MockInstanceInfo<T>

Available on crate feature _test only.
Source§

type HooksType = MockInstanceHooks

Source§

type HooksRefType<'a> = MutexGuard<'a, MockInstanceHooks>