Trait GlobalHooks

Source
pub trait GlobalHooks: Send + Sync {
    // Provided method
    fn create_instance(
        &self,
        _p_create_info: &InstanceCreateInfo,
        _layer_instance_link: &VkLayerInstanceLink,
        _p_allocator: Option<&AllocationCallbacks>,
        _p_instance: *mut Instance,
    ) -> LayerResult<VkResult<()>> { ... }
}
Expand description

A trait for the layer implementation to provide the implementation of the intercepted global commands.

The global commands are copied here for convenience:

  • vkEnumerateInstanceVersion
  • vkEnumerateInstanceExtensionProperties
  • vkEnumerateInstanceLayerProperties
  • vkCreateInstance

Currently, it is only supported to intercept the vkCreateInstance function.

Provided Methods§

Source

fn create_instance( &self, _p_create_info: &InstanceCreateInfo, _layer_instance_link: &VkLayerInstanceLink, _p_allocator: Option<&AllocationCallbacks>, _p_instance: *mut Instance, ) -> LayerResult<VkResult<()>>

The logic to intercept the vkCreateInstance function.

The implementations should return LayerResult::Unhandled if the layer implementation wants the layer framework to handle the task to call into the next layer, otherwise should return LayerResult::Handled.

This function is usually intercepted if the layer needs to modify the VkInstanceCreateInfo passed to the next layer. Otherwise, Layer::create_instance_info is almost always better. This function is called before Layer::create_instance_info to create the VkInstance.

§Arguments
  • _p_create_info is a pointer to a VkInstanceCreateInfo structure controlling creation of the instance. The VkLayerInstanceLink linked list in the pNext chain is already advanced by the layer framework.
  • _layer_instance_link is the VkLayerInstanceLink linked list node pointing to the next layer.
  • _p_allocator controls host memory allocation as described in the Memory Allocation chapter of the Vulkan spec.
  • _p_instance points a VkInstance handle in which the resulting instance is returned. If the layer implementation wants to handle the call to the next layer, according to the LLP_LAYER_21 requirement, implementations must guarantee that the original pointer should be passed to the lower layers.
§Examples

A layer that always enables the VK_KHR_surface extension.

use ash::vk;
use std::{ffi::CStr, ptr::null};
use vulkan_layer::{GlobalHooks, LayerResult, VkLayerInstanceLink};

struct MyGlobalHooks;

impl GlobalHooks for MyGlobalHooks {
    fn create_instance(
        &self,
        p_create_info: &vk::InstanceCreateInfo,
        layer_instance_link: &VkLayerInstanceLink,
        p_allocator: Option<&vk::AllocationCallbacks>,
        p_instance: *mut vk::Instance,
    ) -> LayerResult<ash::prelude::VkResult<()>> {
        // Clone the input enabled extension names as a Vec.
        let mut enabled_extensions = if p_create_info.enabled_extension_count == 0 {
            vec![]
        } else {
            unsafe {
                std::slice::from_raw_parts(
                    p_create_info.pp_enabled_extension_names,
                    p_create_info.enabled_extension_count as usize,
                )
            }
            .to_vec()
        };
        // Push the VK_KHR_surface extension name only if it doesn't exist.
        if enabled_extensions
            .iter()
            .find(|extension_name| {
                (unsafe { CStr::from_ptr(**extension_name) })
                    == ash::extensions::khr::Win32Surface::name()
            })
            .is_none()
        {
            enabled_extensions.push(ash::extensions::khr::Win32Surface::name().as_ptr());
        }
        // Create a new VkInstanceCreateInfo with the new extensions. The passed in
        // VkInstanceCreateInfo is const, so we have to create another VkInstanceCreateInfo
        // to mutate the field we need to avoid possible undefined behavior in Rust.
        let mut create_info = p_create_info.clone();
        create_info.enabled_extension_count = enabled_extensions.len() as u32;
        create_info.pp_enabled_extension_names = enabled_extensions.as_ptr();
        // Convert p_allocator to a raw pointer that can be directly passed to
        // vkCreateInstance.
        let p_allocator = p_allocator
            .map(|allocator| allocator as *const _)
            .unwrap_or_else(null);
        // Find the vkCreateInstance entry of the next layer.
        let create_instance = unsafe {
            (layer_instance_link.pfnNextGetInstanceProcAddr)(
                vk::Instance::null(),
                c"vkCreateInstance".as_ptr(),
            )
        };
        let create_instance: vk::PFN_vkCreateInstance = match create_instance {
            Some(fp) => unsafe { std::mem::transmute(fp) },
            None => return LayerResult::Handled(Err(vk::Result::ERROR_INITIALIZATION_FAILED)),
        };
        // Call into the vkCreateInstance of the next layer with the original p_instance
        // pointer.
        LayerResult::Handled(
            unsafe { create_instance(&create_info, p_allocator, p_instance) }.result(),
        )
    }
}

Implementors§