blob: 54de7a9cc5525d97dea29a435b3ae4f21dcccb22 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use derivative::Derivative;
use fuchsia_zircon::sys::zx_handle_t;
use std::{
ffi::CStr,
mem::{self, MaybeUninit},
os::raw::c_char,
ptr,
};
use vk_sys as vk;
macro_rules! ptrs {(
$struct_name:ident,
{ $($name:ident => ($($param_n:ident: $param_ty:ty),*) -> $ret:ty,)+ }) => {
#[allow(non_snake_case)]
pub struct $struct_name {
$(
pub $name: extern "system" fn($($param_ty),*) -> $ret,
)+
}
impl $struct_name {
pub fn load<F>(mut f: F) -> $struct_name
where F: FnMut(&CStr) -> *const ::std::ffi::c_void
{
#[allow(non_snake_case)]
$struct_name {
$(
$name: unsafe {
extern "system" fn $name($(_: $param_ty),*) {
panic!("function pointer `{}` not loaded", stringify!($name))
}
let name = ::std::ffi::CStr::from_bytes_with_nul_unchecked(
concat!("vk", stringify!($name), "\0").as_bytes());
let val = f(name);
if val.is_null() {
::std::mem::transmute($name as *const ())
} else {
::std::mem::transmute(val)
}
},
)+
}
}
$(
#[inline]
#[allow(non_snake_case)]
#[allow(clippy::missing_safety_doc)] // TODO(fxbug.dev/99063)
pub unsafe fn $name(&self $(, $param_n: $param_ty)*) -> $ret {
let ptr = self.$name;
ptr($($param_n),*)
}
)+
}
impl ::std::fmt::Debug for $struct_name {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.debug_struct(stringify!($struct_name)).finish()
}
}
};
}
// TODO: Remove buffer collection bindings when they are upstream.
pub type BufferCollectionFUCHSIA = u64;
pub type BufferCollectionFUCHSIAX = u64;
// VK_FUCHSIA_imagepipe_surface
pub const STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA: u32 = 1000214000;
// VK_FUCHSIA_external_memory
pub const STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA: u32 = 1000364000;
pub const STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA: u32 = 1000364001;
pub const STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA: u32 = 1000364002;
// VK_FUCHSIA_external_semaphore
pub const STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA: u32 = 1000365000;
pub const STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA: u32 = 1000365001;
// VK_FUCHSIA_buffer_collection
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA: u32 = 1000366000;
pub const STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA: u32 = 1000366001;
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA: u32 = 1000366002;
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA: u32 = 1000366003;
pub const STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA: u32 = 1000366004;
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA: u32 = 1000366005;
pub const STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA: u32 = 1000366006;
pub const STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA: u32 = 1000366007;
pub const STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA: u32 = 1000366008;
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA: u32 = 1000366009;
// VK_FUCHSIA_buffer_collection_x
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIAX: u32 = 1000367000;
pub const STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIAX: u32 = 1000367004;
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIAX: u32 = 1000367005;
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIAX: u32 = 1000367006;
pub const STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIAX: u32 = 1000367007;
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIAX: u32 = 1000367008;
pub const STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIAX: u32 = 1000367009;
pub const STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIAX: u32 = 1000367010;
pub const STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES2_FUCHSIAX: u32 = 1000367011;
pub const STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIAX: u32 = 1000367012;
pub const IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA: u32 = 1;
pub const IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA: u32 = 2;
pub const IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA: u32 = 4;
pub const IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA: u32 = 8;
pub const IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA: u32 = 16;
pub const IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIAX: u32 = 1;
pub const IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIAX: u32 = 2;
pub const IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIAX: u32 = 4;
pub const IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIAX: u32 = 8;
pub const IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIAX: u32 = 16;
pub const EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA: u32 = 128;
pub const EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA: u32 = 2048;
pub const OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA: u32 = 1000366000;
pub const OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIAX: u32 = 1000367002;
pub type ImageFormatConstraintsFlagsFUCHSIA = vk::Flags;
pub type ImageConstraintsInfoFlagsFUCHSIA = vk::Flags;
// VK_FUCHSIA_imagepipe_surface
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct ImagePipeSurfaceCreateInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub flags: u32,
pub imagePipeHandle: zx_handle_t,
}
// VK_FUCHSIA_external_memory
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct ImportMemoryZirconHandleInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub handleType: u32,
pub handle: zx_handle_t,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct MemoryZirconHandlePropertiesFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null_mut()"))]
pub pNext: *mut ::std::os::raw::c_void,
pub memoryTypeBits: u32,
}
// VK_FUCHSIA_external_semaphore
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct ImportSemaphoreZirconHandleInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub semaphore: vk::Semaphore,
pub flags: u32,
pub handleType: u32,
pub zirconHandle: zx_handle_t,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct SemaphoreGetZirconHandleInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub semaphore: vk::Semaphore,
pub handleType: u32,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct MemoryGetZirconHandleInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub memory: vk::DeviceMemory,
pub handleType: u32,
}
// VK_FUCHSIA_buffer_collection
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct BufferCollectionCreateInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub collectionToken: u32,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct BufferCollectionImageCreateInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub collection: BufferCollectionFUCHSIA,
pub index: u32,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct BufferCollectionConstraintsInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub minBufferCount: u32,
pub maxBufferCount: u32,
pub minBufferCountForCamping: u32,
pub minBufferCountForDedicatedSlack: u32,
pub minBufferCountForSharedSlack: u32,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Default)]
pub struct BufferConstraintsInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
#[derivative(Default(value = "unsafe { MaybeUninit::zeroed().assume_init() }"))]
pub createInfo: vk::BufferCreateInfo,
pub requiredFormatFeatures: vk::FormatFeatureFlags,
pub bufferCollectionConstraints: BufferCollectionConstraintsInfoFUCHSIA,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Default)]
pub struct BufferCollectionBufferCreateInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub collection: BufferCollectionFUCHSIA,
pub index: u32,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct SysmemColorSpaceFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub colorSpace: u32,
}
// VK_FUCHSIA_buffer_collection_x
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct SysmemColorSpaceFUCHSIAX {
#[derivative(Default(value = "STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIAX"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub colorSpace: u32,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Default)]
pub struct BufferCollectionPropertiesFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub memoryTypeBits: u32,
pub bufferCount: u32,
pub createInfoIndex: u32,
pub sysmemPixelFormat: u64,
pub formatFeatures: vk::FormatFeatureFlags,
pub sysmemColorSpaceIndex: SysmemColorSpaceFUCHSIA,
#[derivative(Default(value = "unsafe { MaybeUninit::zeroed().assume_init() }"))]
pub samplerYcbcrConversionComponents: vk::ComponentMapping,
pub suggestedYcbcrModel: u32,
pub suggestedYcbcrRange: u32,
pub suggestedXChromaOffset: u32,
pub suggestedYChromaOffset: u32,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Default)]
pub struct ImageFormatConstraintsInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
#[derivative(Default(value = "unsafe { MaybeUninit::zeroed().assume_init() }"))]
pub imageCreateInfo: vk::ImageCreateInfo,
pub requiredFormatFeatures: vk::FormatFeatureFlags,
pub flags: ImageFormatConstraintsFlagsFUCHSIA,
pub sysmemPixelFormat: u64,
pub colorSpaceCount: u32,
#[derivative(Default(value = "ptr::null()"))]
pub pColorSpaces: *const SysmemColorSpaceFUCHSIA,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Derivative)]
#[derivative(Default)]
pub struct ImageConstraintsInfoFUCHSIA {
#[derivative(Default(value = "STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA"))]
pub sType: vk::StructureType,
#[derivative(Default(value = "ptr::null()"))]
pub pNext: *const ::std::os::raw::c_void,
pub formatConstraintsCount: u32,
#[derivative(Default(value = "ptr::null()"))]
pub pFormatConstraints: *const ImageFormatConstraintsInfoFUCHSIA,
pub bufferCollectionConstraints: BufferCollectionConstraintsInfoFUCHSIA,
pub flags: ImageConstraintsInfoFlagsFUCHSIA,
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Debug, Copy, Clone)]
pub struct ImageConstraintsInfoFUCHSIAX {
pub sType: vk::StructureType,
pub __bindgen_padding_0: [u8; 4usize],
pub pNext: *const ::std::os::raw::c_void,
pub createInfoCount: u32,
pub __bindgen_padding_1: [u8; 4usize],
pub pCreateInfos: *const vk::ImageCreateInfo,
pub pFormatConstraints: *const ImageFormatConstraintsInfoFUCHSIAX,
pub minBufferCount: u32,
pub maxBufferCount: u32,
pub minBufferCountForCamping: u32,
pub minBufferCountForDedicatedSlack: u32,
pub minBufferCountForSharedSlack: u32,
pub flags: vk::Flags,
}
impl Default for ImageConstraintsInfoFUCHSIAX {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Debug, Copy, Clone)]
pub struct BufferConstraintsInfoFUCHSIAX {
pub sType: vk::StructureType,
pub pNext: *const ::std::os::raw::c_void,
pub pBufferCreateInfo: *const vk::BufferCreateInfo,
pub requiredFormatFeatures: vk::FormatFeatureFlags,
pub minCount: u32,
}
impl Default for BufferConstraintsInfoFUCHSIAX {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Debug, Copy, Clone)]
pub struct BufferCollectionPropertiesFUCHSIAX {
pub sType: vk::StructureType,
pub pNext: *mut ::std::os::raw::c_void,
pub memoryTypeBits: u32,
pub count: u32,
}
impl Default for BufferCollectionPropertiesFUCHSIAX {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
pub struct BufferCollectionProperties2FUCHSIAX {
pub sType: vk::StructureType,
pub pNext: *mut ::std::os::raw::c_void,
pub memoryTypeBits: u32,
pub bufferCount: u32,
pub createInfoIndex: u32,
pub sysmemFormat: u64,
pub formatFeatures: vk::FormatFeatureFlags,
pub colorSpace: SysmemColorSpaceFUCHSIAX,
pub samplerYcbcrConversionComponents: vk::ComponentMapping,
pub suggestedYcbcrModel: u32,
pub suggestedYcbcrRange: u32,
pub suggestedXChromaOffset: u32,
pub suggestedYChromaOffset: u32,
}
impl Default for BufferCollectionProperties2FUCHSIAX {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Debug, Copy, Clone)]
pub struct ImageFormatConstraintsInfoFUCHSIAX {
pub sType: vk::StructureType,
pub __bindgen_padding_0: [u8; 4usize],
pub pNext: *const ::std::os::raw::c_void,
pub requiredFormatFeatures: vk::FormatFeatureFlags,
pub flags: vk::Flags,
pub sysmemFormat: u64,
pub colorSpaceCount: u32,
pub __bindgen_padding_1: [u8; 4usize],
pub pColorSpaces: *const SysmemColorSpaceFUCHSIAX,
}
impl Default for ImageFormatConstraintsInfoFUCHSIAX {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
ptrs!(FuchsiaExtensionPointers, {
// VK_FUCHSIA_external_memory
GetMemoryZirconHandleFUCHSIA => (
device: vk::Device,
pGetZirconHandleInfo: *const MemoryGetZirconHandleInfoFUCHSIA,
pZirconHandle: *mut zx_handle_t
) -> vk::Result,
GetMemoryZirconHandlePropertiesFUCHSIA => (
device: vk::Device,
handleType: u32,
zirconHandle: zx_handle_t,
pMemoryZirconHandleProperties: *mut MemoryZirconHandlePropertiesFUCHSIA
) -> vk::Result,
// VK_FUCHSIA_external_semaphore
ImportSemaphoreZirconHandleFUCHSIA => (
device: vk::Device,
pImportSemaphoreZirconHandleInfo: *const ImportSemaphoreZirconHandleInfoFUCHSIA
) -> vk::Result,
GetSemaphoreZirconHandleFUCHSIA => (
device: vk::Device,
pGetZirconHandleInfo: *const SemaphoreGetZirconHandleInfoFUCHSIA,
pZirconHandle: *mut zx_handle_t
) -> vk::Result,
// VK_FUCHSIA_buffer_collection
CreateBufferCollectionFUCHSIA => (
device: vk::Device,
pImportInfo: *const BufferCollectionCreateInfoFUCHSIA,
pAllocator: *const vk::AllocationCallbacks,
pCollection: *mut BufferCollectionFUCHSIA) -> vk::Result,
SetBufferCollectionImageConstraintsFUCHSIA => (
device: vk::Device,
collection: BufferCollectionFUCHSIA,
pImageConstraintsInfo: *const ImageConstraintsInfoFUCHSIA) -> vk::Result,
SetBufferCollectionBufferConstraintsFUCHSIA => (
device: vk::Device,
collection: BufferCollectionFUCHSIA,
pBufferConstraintsInfo: *const BufferConstraintsInfoFUCHSIA
) -> vk::Result,
DestroyBufferCollectionFUCHSIA => (
device: vk::Device,
collection: BufferCollectionFUCHSIA,
pAllocator: *const vk::AllocationCallbacks
) -> (),
GetBufferCollectionPropertiesFUCHSIA => (
device: vk::Device,
collection: BufferCollectionFUCHSIA,
pProperties: *mut BufferCollectionPropertiesFUCHSIA
) -> vk::Result,
// VK_FUCHSIA_buffer_collection_x
CreateBufferCollectionFUCHSIAX => (
device: vk::Device,
pImportInfo: *const BufferCollectionCreateInfoFUCHSIA,
pAllocator: *const vk::AllocationCallbacks,
pCollection: *mut BufferCollectionFUCHSIA) -> vk::Result,
SetBufferCollectionConstraintsFUCHSIAX => (
device: vk::Device,
collection: BufferCollectionFUCHSIAX,
pImageInfo: *const vk::ImageCreateInfo) -> vk::Result,
SetBufferCollectionImageConstraintsFUCHSIAX => (
device: vk::Device,
collection: BufferCollectionFUCHSIAX,
pImageConstraintsInfo: *const ImageConstraintsInfoFUCHSIAX) -> vk::Result,
SetBufferCollectionBufferConstraintsFUCHSIAX => (
device: vk::Device,
collection: BufferCollectionFUCHSIAX,
pBufferConstraintsInfo: *const BufferConstraintsInfoFUCHSIAX) -> vk::Result,
DestroyBufferCollectionFUCHSIAX => (
device: vk::Device,
collection: BufferCollectionFUCHSIAX,
pAllocator: *const vk::AllocationCallbacks) -> (),
GetBufferCollectionPropertiesFUCHSIAX => (
device: vk::Device,
collection: BufferCollectionFUCHSIAX,
pProperties: *mut BufferCollectionPropertiesFUCHSIAX) -> vk::Result,
GetBufferCollectionProperties2FUCHSIAX => (
device: vk::Device,
collection: BufferCollectionFUCHSIAX,
pProperties: *mut BufferCollectionProperties2FUCHSIAX) -> vk::Result,
});
#[link(name = "vulkan")]
extern "C" {
fn vkGetInstanceProcAddr(
instance: vk::Instance,
pName: *const c_char,
) -> vk::PFN_vkVoidFunction;
}
pub fn entry_points() -> vk::EntryPoints {
vk::EntryPoints::load(|name| unsafe { mem::transmute(vkGetInstanceProcAddr(0, name.as_ptr())) })
}
pub fn instance_pointers(instance: vk::Instance) -> vk::InstancePointers {
vk::InstancePointers::load(|name| unsafe {
mem::transmute(vkGetInstanceProcAddr(instance, name.as_ptr()))
})
}
pub fn device_pointers(vk_i: &vk::InstancePointers, device: vk::Device) -> vk::DevicePointers {
vk::DevicePointers::load(|name| unsafe {
vk_i.GetDeviceProcAddr(device, name.as_ptr()) as *const _
})
}
#[cfg(test)]
pub(crate) mod tests {
use std::{ffi::CStr, mem::MaybeUninit, os::raw::c_char, ptr};
use vk_sys as vk;
macro_rules! cstr {
( $bytes:expr ) => {
CStr::from_bytes_with_nul($bytes).expect("CStr must end with '\\0'")
};
}
macro_rules! vulkan_version {
( $major:expr, $minor:expr, $patch:expr ) => {
($major as u32) << 22 | ($minor as u32) << 12 | ($patch as u32)
};
}
unsafe fn init<T>(f: impl FnOnce(*mut T)) -> T {
let mut value = MaybeUninit::uninit();
f(value.as_mut_ptr());
value.assume_init()
}
fn create_vk_instance() -> vk::Instance {
let entry_points = super::entry_points();
let mut instance: vk::Instance = 0;
let create_instance_result = unsafe {
entry_points.CreateInstance(
&vk::InstanceCreateInfo {
sType: vk::STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
pApplicationInfo: &vk::ApplicationInfo {
sType: vk::STRUCTURE_TYPE_APPLICATION_INFO,
pNext: ptr::null(),
pApplicationName: cstr!(b"fuchsia-vulkan unit test\0").as_ptr(),
applicationVersion: 0,
pEngineName: ptr::null(),
engineVersion: 0,
apiVersion: vulkan_version!(1, 1, 0),
},
enabledLayerCount: 0,
ppEnabledLayerNames: ptr::null(),
enabledExtensionCount: 0,
ppEnabledExtensionNames: ptr::null(),
},
ptr::null(),
&mut instance as *mut vk::Instance,
)
};
assert!(create_instance_result == vk::SUCCESS);
instance
}
fn destroy_vk_instance(instance: vk::Instance) {
let vk_i = super::instance_pointers(instance);
unsafe {
vk_i.DestroyInstance(instance, ptr::null());
}
}
fn get_vk_physical_device(instance: vk::Instance) -> Option<vk::PhysicalDevice> {
let vk_i = super::instance_pointers(instance);
let physical_devices = {
let mut len = unsafe {
init(|ptr| {
vk_i.EnumeratePhysicalDevices(instance, ptr, ptr::null_mut());
})
};
let mut physical_devices: Vec<vk::PhysicalDevice> = Vec::with_capacity(len as usize);
unsafe {
let enumerate_result = vk_i.EnumeratePhysicalDevices(
instance,
&mut len,
physical_devices.as_mut_ptr(),
);
assert!(enumerate_result == vk::SUCCESS);
physical_devices.set_len(len as usize);
}
physical_devices
};
match physical_devices.get(0) {
Some(val) => Some(*val),
None => {
println!("cannot create physical device");
None
}
}
}
fn physical_device_supports_extension(
instance: vk::Instance,
extension_names: &Vec<*const c_char>,
) -> bool {
let vk_i = super::instance_pointers(instance);
let physical_device = match get_vk_physical_device(instance) {
Some(val) => val,
None => return false,
};
let mut extension_len = unsafe {
init(|ptr| {
let result = vk_i.EnumerateDeviceExtensionProperties(
physical_device,
ptr::null(),
ptr,
ptr::null_mut(),
);
assert!(result == vk::SUCCESS);
})
};
let mut extensions: Vec<vk::ExtensionProperties> =
Vec::with_capacity(extension_len as usize);
unsafe {
let result = vk_i.EnumerateDeviceExtensionProperties(
physical_device,
ptr::null(),
&mut extension_len,
extensions.as_mut_ptr(),
);
assert!(result == vk::SUCCESS);
extensions.set_len(extension_len as usize);
}
for expected_extension_name in extension_names {
match extensions.iter().find(|&p| unsafe {
CStr::from_ptr(*expected_extension_name)
== CStr::from_ptr(&p.extensionName as *const c_char)
}) {
None => return false,
_ => {}
}
}
true
}
fn create_vk_device(
instance: vk::Instance,
extension_names: Vec<*const c_char>,
) -> Option<vk::Device> {
let vk_i = super::instance_pointers(instance);
let physical_device = match get_vk_physical_device(instance) {
Some(val) => val,
None => return None,
};
let mut queue_family_count = unsafe {
init(|ptr| {
vk_i.GetPhysicalDeviceQueueFamilyProperties(physical_device, ptr, ptr::null_mut())
})
};
let mut queue_family_properties = Vec::with_capacity(queue_family_count as usize);
unsafe {
vk_i.GetPhysicalDeviceQueueFamilyProperties(
physical_device,
&mut queue_family_count,
queue_family_properties.as_mut_ptr(),
);
queue_family_properties.set_len(queue_family_count as usize);
}
if queue_family_count == 0 {
println!("no queue family available!");
return None;
}
let queue_priority: f32 = 1.0;
let queue_create_info = vk::DeviceQueueCreateInfo {
sType: vk::STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
queueFamilyIndex: 0,
queueCount: 1,
pQueuePriorities: &queue_priority as *const f32,
};
let device = unsafe {
init(|ptr| {
let create_device_result = vk_i.CreateDevice(
physical_device,
&vk::DeviceCreateInfo {
sType: vk::STRUCTURE_TYPE_DEVICE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
queueCreateInfoCount: 1,
pQueueCreateInfos: &queue_create_info as *const _,
enabledLayerCount: 0,
ppEnabledLayerNames: ptr::null(),
enabledExtensionCount: extension_names.len() as u32,
ppEnabledExtensionNames: extension_names.as_ptr(),
pEnabledFeatures: ptr::null(),
},
ptr::null(),
ptr,
);
assert!(create_device_result == vk::SUCCESS);
})
};
Some(device)
}
fn destroy_vk_device(instance: vk::Instance, device: vk::Device) {
let vk_i = super::instance_pointers(instance);
let vk_d = super::device_pointers(&vk_i, device);
unsafe {
vk_d.DestroyDevice(device, ptr::null());
}
}
#[test]
fn can_create_vk_instance() {
let instance = create_vk_instance();
assert!(instance != 0);
}
#[test]
fn can_create_vk_device() {
let instance = create_vk_instance();
let device = create_vk_device(instance, vec![]);
assert!(device.is_some());
destroy_vk_device(instance, device.unwrap());
destroy_vk_instance(instance);
}
macro_rules! assert_fn_valid {
($fn:expr) => {
assert!($fn as *const i8 != ptr::null(), "function {:?} not found", stringify!($fn));
};
}
#[test]
fn fuchsia_buffer_collection_function_valid() {
let instance = create_vk_instance();
let extension_names = vec![cstr!(b"VK_FUCHSIA_buffer_collection\0").as_ptr()];
if !physical_device_supports_extension(instance, &extension_names) {
println!("extension {:?} not supported, test skipped.", extension_names);
return;
}
let device = create_vk_device(instance, extension_names).unwrap();
let vk_i = super::instance_pointers(instance);
let vk_ext = super::FuchsiaExtensionPointers::load(|name| unsafe {
vk_i.GetDeviceProcAddr(device, name.as_ptr()) as *const _
});
assert_fn_valid!(vk_ext.CreateBufferCollectionFUCHSIA);
assert_fn_valid!(vk_ext.SetBufferCollectionImageConstraintsFUCHSIA);
assert_fn_valid!(vk_ext.SetBufferCollectionBufferConstraintsFUCHSIA);
assert_fn_valid!(vk_ext.DestroyBufferCollectionFUCHSIA);
assert_fn_valid!(vk_ext.GetBufferCollectionPropertiesFUCHSIA);
destroy_vk_device(instance, device);
destroy_vk_instance(instance);
}
#[test]
fn fuchsia_buffer_collection_x_function_valid() {
let instance = create_vk_instance();
let extension_names = vec![cstr!(b"VK_FUCHSIA_buffer_collection_x\0").as_ptr()];
if !physical_device_supports_extension(instance, &extension_names) {
println!("extension {:?} not supported, test skipped.", extension_names);
return;
}
let device = create_vk_device(instance, extension_names).unwrap();
let vk_i = super::instance_pointers(instance);
let vk_ext = super::FuchsiaExtensionPointers::load(|name| unsafe {
vk_i.GetDeviceProcAddr(device, name.as_ptr()) as *const _
});
assert_fn_valid!(vk_ext.CreateBufferCollectionFUCHSIAX);
assert_fn_valid!(vk_ext.SetBufferCollectionConstraintsFUCHSIAX);
assert_fn_valid!(vk_ext.SetBufferCollectionImageConstraintsFUCHSIAX);
assert_fn_valid!(vk_ext.SetBufferCollectionBufferConstraintsFUCHSIAX);
assert_fn_valid!(vk_ext.DestroyBufferCollectionFUCHSIAX);
assert_fn_valid!(vk_ext.GetBufferCollectionPropertiesFUCHSIAX);
assert_fn_valid!(vk_ext.GetBufferCollectionProperties2FUCHSIAX);
destroy_vk_device(instance, device);
destroy_vk_instance(instance);
}
#[test]
fn fuchsia_external_memory_function_valid() {
let instance = create_vk_instance();
let extension_names = vec![cstr!(b"VK_FUCHSIA_external_memory\0").as_ptr()];
if !physical_device_supports_extension(instance, &extension_names) {
println!("extension {:?} not supported, test skipped.", extension_names);
return;
}
let device = create_vk_device(instance, extension_names).unwrap();
let vk_i = super::instance_pointers(instance);
let vk_ext = super::FuchsiaExtensionPointers::load(|name| unsafe {
vk_i.GetDeviceProcAddr(device, name.as_ptr()) as *const _
});
assert_fn_valid!(vk_ext.GetMemoryZirconHandleFUCHSIA);
assert_fn_valid!(vk_ext.GetMemoryZirconHandlePropertiesFUCHSIA);
destroy_vk_device(instance, device);
destroy_vk_instance(instance);
}
#[test]
fn fuchsia_external_semaphore_function_valid() {
let instance = create_vk_instance();
let extension_names = vec![cstr!(b"VK_FUCHSIA_external_semaphore\0").as_ptr()];
if !physical_device_supports_extension(instance, &extension_names) {
println!("extension {:?} not supported, test skipped.", extension_names);
return;
}
let device = create_vk_device(instance, extension_names).unwrap();
let vk_i = super::instance_pointers(instance);
let vk_ext = super::FuchsiaExtensionPointers::load(|name| unsafe {
vk_i.GetDeviceProcAddr(device, name.as_ptr()) as *const _
});
assert_fn_valid!(vk_ext.ImportSemaphoreZirconHandleFUCHSIA);
assert_fn_valid!(vk_ext.GetSemaphoreZirconHandleFUCHSIA);
destroy_vk_device(instance, device);
destroy_vk_instance(instance);
}
}