use crate::raw::bindings::*;
#[test]
fn test_handle_types_exist() {
let _: VkInstance = std::ptr::null_mut();
let _: VkDevice = std::ptr::null_mut();
let _: VkPhysicalDevice = std::ptr::null_mut();
let _: VkQueue = std::ptr::null_mut();
let _: VkCommandBuffer = std::ptr::null_mut();
}
#[test]
fn test_non_dispatchable_handle_types_exist() {
let _: VkSemaphore = 0u64;
let _: VkFence = 0u64;
let _: VkBuffer = 0u64;
let _: VkImage = 0u64;
let _: VkPipeline = 0u64;
let _: VkSampler = 0u64;
let _: VkDescriptorSet = 0u64;
let _: VkFramebuffer = 0u64;
let _: VkRenderPass = 0u64;
let _: VkCommandPool = 0u64;
let _: VkSwapchainKHR = 0u64;
let _: VkSurfaceKHR = 0u64;
}
#[test]
fn test_base_types_exist() {
let _: VkBool32 = 0u32;
let _: VkFlags = 0u32;
let _: VkFlags64 = 0u64;
let _: VkDeviceSize = 0u64;
let _: VkDeviceAddress = 0u64;
let _: VkSampleMask = 0u32;
}
#[test]
fn test_vk_application_info_struct() {
let info = VkApplicationInfo {
sType: VkStructureType::STRUCTURE_TYPE_APPLICATION_INFO,
pNext: std::ptr::null(),
pApplicationName: std::ptr::null(),
applicationVersion: 0,
pEngineName: std::ptr::null(),
engineVersion: 0,
apiVersion: VK_API_VERSION_1_0,
};
assert_eq!(info.apiVersion, VK_API_VERSION_1_0);
}
#[test]
fn test_vk_instance_create_info_struct() {
let info = VkInstanceCreateInfo {
sType: VkStructureType::STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
pNext: std::ptr::null(),
flags: 0,
pApplicationInfo: std::ptr::null(),
enabledLayerCount: 0,
ppEnabledLayerNames: std::ptr::null(),
enabledExtensionCount: 0,
ppEnabledExtensionNames: std::ptr::null(),
};
assert_eq!(info.enabledLayerCount, 0);
}
#[test]
fn test_struct_default_impls() {
let app_info = VkApplicationInfo::default();
assert!(app_info.pNext.is_null());
assert!(app_info.pApplicationName.is_null());
let create_info = VkInstanceCreateInfo::default();
assert!(create_info.pNext.is_null());
assert_eq!(create_info.enabledLayerCount, 0);
}
#[test]
fn test_vk_result_enum() {
assert_eq!(VkResult::SUCCESS as i32, 0);
assert_eq!(VkResult::NOT_READY as i32, 1);
assert_eq!(VkResult::TIMEOUT as i32, 2);
assert_eq!(VkResult::ERROR_OUT_OF_HOST_MEMORY as i32, -1);
assert_eq!(VkResult::ERROR_OUT_OF_DEVICE_MEMORY as i32, -2);
assert_eq!(VkResult::ERROR_DEVICE_LOST as i32, -4);
}
#[test]
fn test_vk_structure_type_has_extension_values() {
assert_eq!(VkStructureType::STRUCTURE_TYPE_APPLICATION_INFO as i32, 0);
assert_eq!(
VkStructureType::STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR as i32,
1000001000
);
}
#[test]
fn test_vk_make_api_version() {
let version = vk_make_api_version(0, 1, 0, 0);
assert_eq!(version, VK_API_VERSION_1_0);
}
#[test]
fn test_vk_api_version_extraction() {
let version = VK_API_VERSION_1_0;
assert_eq!(vk_api_version_variant(version), 0);
assert_eq!(vk_api_version_major(version), 1);
assert_eq!(vk_api_version_minor(version), 0);
assert_eq!(vk_api_version_patch(version), 0);
}
#[test]
fn test_vk_header_version_exists() {
const _: () = assert!(VK_HEADER_VERSION > 0);
}
#[test]
fn test_version_roundtrip() {
let v = vk_make_api_version(0, 1, 4, 42);
assert_eq!(vk_api_version_variant(v), 0);
assert_eq!(vk_api_version_major(v), 1);
assert_eq!(vk_api_version_minor(v), 4);
assert_eq!(vk_api_version_patch(v), 42);
}
#[test]
fn test_constants_exist() {
const _: () = assert!(VK_MAX_PHYSICAL_DEVICE_NAME_SIZE > 0);
const _: () = assert!(VK_MAX_EXTENSION_NAME_SIZE > 0);
const _: () = assert!(VK_UUID_SIZE > 0);
const _: () = assert!(VK_MAX_MEMORY_TYPES > 0);
const _: () = assert!(VK_MAX_MEMORY_HEAPS > 0);
}
#[test]
fn test_function_pointer_types_exist() {
let _: Option<vkCreateInstance> = None;
let _: Option<vkDestroyInstance> = None;
let _: Option<vkEnumeratePhysicalDevices> = None;
let _: Option<vkCreateDevice> = None;
let _: Option<vkDestroyDevice> = None;
let _: Option<vkGetDeviceProcAddr> = None;
let _: Option<vkGetInstanceProcAddr> = None;
}
#[test]
fn test_function_pointer_signatures_match_spec() {
unsafe extern "system" fn create_instance_stub(
_create_info: *const VkInstanceCreateInfo,
_allocator: *const VkAllocationCallbacks,
_instance: *mut VkInstance,
) -> VkResult {
VkResult::SUCCESS
}
let _f: vkCreateInstance = create_instance_stub;
unsafe extern "system" fn destroy_instance_stub(
_instance: VkInstance,
_allocator: *const VkAllocationCallbacks,
) {
}
let _f: vkDestroyInstance = destroy_instance_stub;
unsafe extern "system" fn enum_phys_stub(
_instance: VkInstance,
_count: *mut u32,
_devices: *mut VkPhysicalDevice,
) -> VkResult {
VkResult::SUCCESS
}
let _f: vkEnumeratePhysicalDevices = enum_phys_stub;
unsafe extern "system" fn enum_version_stub(_version: *mut u32) -> VkResult {
VkResult::SUCCESS
}
let _f: vkEnumerateInstanceVersion = enum_version_stub;
}
#[test]
fn test_dispatch_tables_have_required_fields() {
let entry: VkEntryDispatchTable = unsafe { std::mem::zeroed() };
let _ = entry.vkCreateInstance;
let _ = entry.vkEnumerateInstanceLayerProperties;
let _ = entry.vkEnumerateInstanceExtensionProperties;
let _ = entry.vkEnumerateInstanceVersion;
let inst: VkInstanceDispatchTable = unsafe { std::mem::zeroed() };
let _ = inst.vkDestroyInstance;
let _ = inst.vkEnumeratePhysicalDevices;
let _ = inst.vkGetPhysicalDeviceProperties;
let _ = inst.vkGetPhysicalDeviceMemoryProperties;
let _ = inst.vkGetPhysicalDeviceQueueFamilyProperties;
let _ = inst.vkCreateDevice;
let dev: VkDeviceDispatchTable = unsafe { std::mem::zeroed() };
let _ = dev.vkDestroyDevice;
let _ = dev.vkGetDeviceQueue;
let _ = dev.vkCreateBuffer;
let _ = dev.vkAllocateMemory;
let _ = dev.vkCreateCommandPool;
}
#[test]
fn test_dispatch_tables_exist() {
let _: Option<Box<VkEntryDispatchTable>> = None;
let _: Option<Box<VkInstanceDispatchTable>> = None;
let _: Option<Box<VkDeviceDispatchTable>> = None;
}
#[test]
fn test_extension_structs_exist() {
let _info = VkSwapchainCreateInfoKHR::default();
let _info = VkDebugUtilsMessengerCreateInfoEXT::default();
}
#[test]
fn test_clear_color_value_is_union() {
assert_eq!(
std::mem::size_of::<VkClearColorValue>(),
std::mem::size_of::<[f32; 4]>(),
"VkClearColorValue should be the size of its largest field, not a sum"
);
let mut color = VkClearColorValue::default();
unsafe {
color.float32 = [1.0, 0.0, 0.0, 1.0];
assert_eq!(color.float32[0], 1.0);
}
}
#[test]
fn test_clear_value_is_union() {
let val = VkClearValue::default();
assert!(
std::mem::size_of::<VkClearValue>() <= 16,
"VkClearValue should be at most 16 bytes (4 x f32), got {}",
std::mem::size_of::<VkClearValue>()
);
let _ = val;
}
#[test]
fn test_null_handle() {
assert_eq!(VK_NULL_HANDLE, 0u64);
}
#[test]
fn test_vk_application_info_size_matches_spec() {
#[cfg(target_pointer_width = "64")]
assert_eq!(std::mem::size_of::<VkApplicationInfo>(), 48);
#[cfg(target_pointer_width = "64")]
assert_eq!(std::mem::align_of::<VkApplicationInfo>(), 8);
}
#[test]
fn test_vk_extent_3d_layout() {
assert_eq!(std::mem::size_of::<VkExtent3D>(), 12);
assert_eq!(std::mem::align_of::<VkExtent3D>(), 4);
let e = VkExtent3D {
width: 1024,
height: 768,
depth: 1,
};
assert_eq!(e.width, 1024);
assert_eq!(e.height, 768);
assert_eq!(e.depth, 1);
}
#[test]
fn test_vk_offset_2d_layout() {
assert_eq!(std::mem::size_of::<VkOffset2D>(), 8);
assert_eq!(std::mem::align_of::<VkOffset2D>(), 4);
}
#[test]
fn test_vk_rect_2d_layout() {
assert_eq!(std::mem::size_of::<VkRect2D>(), 16);
}
#[test]
fn test_vk_result_into_result_success() {
use crate::raw::VkResultExt;
assert!(VkResult::SUCCESS.into_result().is_ok());
}
#[test]
fn test_vk_result_into_result_error() {
use crate::raw::VkResultExt;
let err = VkResult::ERROR_OUT_OF_HOST_MEMORY.into_result();
assert!(err.is_err());
assert_eq!(err.unwrap_err(), VkResult::ERROR_OUT_OF_HOST_MEMORY);
}
#[test]
fn test_vk_result_is_success_and_is_error() {
use crate::raw::VkResultExt;
assert!(VkResult::SUCCESS.is_success());
assert!(!VkResult::SUCCESS.is_error());
assert!(!VkResult::ERROR_DEVICE_LOST.is_success());
assert!(VkResult::ERROR_DEVICE_LOST.is_error());
assert!(!VkResult::NOT_READY.is_success());
assert!(!VkResult::NOT_READY.is_error());
}
#[test]
fn test_vk_check_macro_success() {
fn returns_success() -> VkResult {
VkResult::SUCCESS
}
let result = crate::vk_check!(returns_success());
assert!(result.is_ok());
}
#[test]
fn test_vk_check_macro_error() {
fn returns_error() -> VkResult {
VkResult::ERROR_OUT_OF_HOST_MEMORY
}
let result = crate::vk_check!(returns_error());
assert_eq!(result.unwrap_err(), VkResult::ERROR_OUT_OF_HOST_MEMORY);
}
#[test]
fn test_vk_result_implements_error_trait() {
fn returns_box_error() -> Result<(), Box<dyn std::error::Error>> {
use crate::raw::VkResultExt;
VkResult::SUCCESS.into_result()?;
Ok(())
}
assert!(returns_box_error().is_ok());
fn propagates_error() -> Result<(), Box<dyn std::error::Error>> {
use crate::raw::VkResultExt;
VkResult::ERROR_DEVICE_LOST.into_result()?;
Ok(())
}
assert!(propagates_error().is_err());
}
#[test]
fn test_bitmask_flags_combinable() {
let flags: VkBufferUsageFlagBits =
BUFFER_USAGE_TRANSFER_SRC_BIT | BUFFER_USAGE_TRANSFER_DST_BIT;
assert!(flags != 0);
}
#[test]
fn test_generated_bindings_have_zero_todo_lines() {
let path = env!("SPOCK_GENERATED_BINDINGS");
let content = std::fs::read_to_string(path)
.expect("SPOCK_GENERATED_BINDINGS env var should point at the generated bindings file");
let mut offending: Vec<(usize, &str)> = Vec::new();
for (lineno, line) in content.lines().enumerate() {
if line.contains("// TODO:") || line.contains("// FIXME:") {
offending.push((lineno + 1, line.trim()));
}
}
assert!(
offending.is_empty(),
"generated bindings should contain zero TODO/FIXME lines, but found {} \
(this means the macro/type/member generator gave up on translating something \
— fix the generator or add a special case rather than letting the TODO ship). \
First 10 offending lines:\n{}",
offending.len(),
offending
.iter()
.take(10)
.map(|(n, l)| format!(" line {}: {}", n, l))
.collect::<Vec<_>>()
.join("\n")
);
}
#[test]
fn test_vk_header_version_complete_is_usable_const() {
let v = VK_HEADER_VERSION_COMPLETE;
assert_eq!(
v >> 29,
0,
"VK_HEADER_VERSION_COMPLETE variant byte should be 0 for desktop Vulkan, got {}",
v >> 29
);
let patch = v & 0xFFF;
assert_eq!(
patch, VK_HEADER_VERSION,
"patch field of VK_HEADER_VERSION_COMPLETE should equal VK_HEADER_VERSION"
);
let major = (v >> 22) & 0x7F;
assert!(major >= 1, "major version should be >= 1, got {}", major);
}