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:
vkEnumerateInstanceVersionvkEnumerateInstanceExtensionPropertiesvkEnumerateInstanceLayerPropertiesvkCreateInstance
Currently, it is only supported to intercept the vkCreateInstance function.
Provided Methods§
Sourcefn create_instance(
&self,
_p_create_info: &InstanceCreateInfo,
_layer_instance_link: &VkLayerInstanceLink,
_p_allocator: Option<&AllocationCallbacks>,
_p_instance: *mut Instance,
) -> LayerResult<VkResult<()>>
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_infois a pointer to a VkInstanceCreateInfo structure controlling creation of the instance. TheVkLayerInstanceLinklinked list in thepNextchain is already advanced by the layer framework._layer_instance_linkis theVkLayerInstanceLinklinked list node pointing to the next layer._p_allocatorcontrols host memory allocation as described in the Memory Allocation chapter of the Vulkan spec._p_instancepoints 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 theLLP_LAYER_21requirement, 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(),
)
}
}