From b596b0e6047816bc03e5478bb95cafcd09f7316e Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 7 Nov 2018 00:28:04 -0800 Subject: [PATCH] working on implementing shader compiler --- Cargo.toml | 1 + shader-compiler/Cargo.toml | 14 + shader-compiler/src/lib.rs | 6 + spirv-parser-generator/src/generate.rs | 2 +- vulkan-driver/Cargo.toml | 1 + vulkan-driver/src/api_impl.rs | 412 ++++++------------------- vulkan-driver/src/descriptor_set.rs | 17 +- vulkan-driver/src/handle.rs | 9 +- vulkan-driver/src/lib.rs | 5 + vulkan-driver/src/pipeline.rs | 107 +++++++ vulkan-driver/src/shm.rs | 4 +- vulkan-driver/src/util.rs | 265 ++++++++++++++++ 12 files changed, 511 insertions(+), 332 deletions(-) create mode 100644 shader-compiler/Cargo.toml create mode 100644 shader-compiler/src/lib.rs create mode 100644 vulkan-driver/src/pipeline.rs create mode 100644 vulkan-driver/src/util.rs diff --git a/Cargo.toml b/Cargo.toml index 0b50934..bf2dd6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ # Copyright 2018 Jacob Lifshay [workspace] members = [ + "shader-compiler", "shader-compiler-backend", "shader-compiler-backend-llvm-7", "spirv-parser", diff --git a/shader-compiler/Cargo.toml b/shader-compiler/Cargo.toml new file mode 100644 index 0000000..1bbfcf7 --- /dev/null +++ b/shader-compiler/Cargo.toml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# Copyright 2018 Jacob Lifshay +[package] +name = "shader-compiler" +version = "0.1.0" +authors = ["Jacob Lifshay "] +license = "LGPL-2.1-or-later" + +[lib] +crate-type = ["rlib"] + +[dependencies] +shader-compiler-backend = {path = "../shader-compiler-backend"} +spirv-parser = {path = "../spirv-parser"} diff --git a/shader-compiler/src/lib.rs b/shader-compiler/src/lib.rs new file mode 100644 index 0000000..f2d976e --- /dev/null +++ b/shader-compiler/src/lib.rs @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright 2018 Jacob Lifshay + +#[macro_use] +extern crate shader_compiler_backend; +extern crate spirv_parser; diff --git a/spirv-parser-generator/src/generate.rs b/spirv-parser-generator/src/generate.rs index dd836a3..a2d2c4f 100644 --- a/spirv-parser-generator/src/generate.rs +++ b/spirv-parser-generator/src/generate.rs @@ -763,7 +763,7 @@ pub(crate) fn generate( } ast::OperandKind::Composite { kind, bases } => { let kind = new_id(kind, CamelCase); - let bases = bases.into_iter().map(|base| new_id(base, CamelCase)); + let bases = bases.iter().map(|base| new_id(base, CamelCase)); writeln!(&mut out, "{}", quote!{pub type #kind = (#(#bases),*);})?; } } diff --git a/vulkan-driver/Cargo.toml b/vulkan-driver/Cargo.toml index ac2666d..28d4ef7 100644 --- a/vulkan-driver/Cargo.toml +++ b/vulkan-driver/Cargo.toml @@ -16,6 +16,7 @@ uuid = {version = "0.7", features = ["v5"]} sys-info = "0.5" shader-compiler-backend = {path = "../shader-compiler-backend"} shader-compiler-backend-llvm-7 = {path = "../shader-compiler-backend-llvm-7"} +spirv-parser = {path = "../spirv-parser"} [target.'cfg(unix)'.dependencies] xcb = {version = "0.8", features = ["shm"]} diff --git a/vulkan-driver/src/api_impl.rs b/vulkan-driver/src/api_impl.rs index 6168516..41836c2 100644 --- a/vulkan-driver/src/api_impl.rs +++ b/vulkan-driver/src/api_impl.rs @@ -21,6 +21,7 @@ use image::{ ComponentMapping, Image, ImageMemory, ImageMultisampleCount, ImageProperties, ImageView, ImageViewType, SupportedTilings, }; +use pipeline::{self, PipelineLayout}; use render_pass::RenderPass; use sampler; use sampler::Sampler; @@ -35,252 +36,14 @@ use std::ptr::null; use std::ptr::null_mut; #[cfg(target_os = "linux")] use std::ptr::NonNull; -use std::slice; use std::str::FromStr; use swapchain::SurfacePlatform; use sys_info; +use util; use uuid; #[cfg(target_os = "linux")] use xcb; -/// structure types the driver should know about -fn is_supported_structure_type(v: api::VkStructureType) -> bool { - #[cfg(target_os = "linux")] - { - #[cfg_attr(feature = "cargo-clippy", allow(clippy::single_match))] - match v { - api::VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR => return true, - _ => {} - } - } - match v { - api::VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR - | api::VK_STRUCTURE_TYPE_APPLICATION_INFO - | api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO - | api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO - | api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO - | api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO - | api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR - | api::VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO - | api::VK_STRUCTURE_TYPE_BIND_SPARSE_INFO - | api::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO - | api::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER - | api::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 - | api::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO - | api::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO - | api::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO - | api::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO - | api::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO - | api::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET - | api::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO - | api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO - | api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO - | api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT - | api::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO - | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO - | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR - | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR - | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO - | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO - | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR - | api::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 - | api::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO - | api::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO - | api::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES - | api::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES - | api::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES - | api::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO - | api::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES - | api::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 - | api::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO - | api::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 - | api::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER - | api::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 - | api::VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO - | api::VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 - | api::VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR - | api::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO - | api::VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE - | api::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO - | api::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO - | api::VK_STRUCTURE_TYPE_MEMORY_BARRIER - | api::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO - | api::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS - | api::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR - | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES - | api::VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR - | api::VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO - | api::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO - | api::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 - | api::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO - | api::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO - | api::VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO - | api::VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO - | api::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO - | api::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO - | api::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES - | api::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO - | api::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO - | api::VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 - | api::VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 - | api::VK_STRUCTURE_TYPE_SUBMIT_INFO - | api::VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR - | api::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR - | api::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET => true, - _ => false, - } -} - -fn verify_structure_type_is_supported(v: api::VkStructureType) { - assert!( - is_supported_structure_type(v), - "missing structure type in is_supported_structure_type: {:?}", - v - ); -} - -unsafe fn parse_next_chain_const( - root: *const api::VkBaseInStructure, - expected_root_struct_type: api::VkStructureType, - expected_child_structs: &[(api::VkStructureType, *mut *const api::VkBaseInStructure)], -) { - verify_structure_type_is_supported(expected_root_struct_type); - let root = &*root; - assert_eq!(root.sType, expected_root_struct_type); - for &(child_struct_type, child_struct) in expected_child_structs.iter() { - verify_structure_type_is_supported(child_struct_type); - *child_struct = null(); - } - let mut child = root.pNext as *const api::VkBaseInStructure; - while !child.is_null() { - let child_ref = &*child; - let search_for_type = child_ref.sType; - let mut found = false; - for &(child_struct_type, child_struct) in expected_child_structs.iter() { - if child_struct_type == search_for_type { - assert!( - (*child_struct).is_null(), - "duplicate struct type in pNext chain: {:?}", - search_for_type - ); - *child_struct = child; - found = true; - break; - } - } - assert!( - found || !is_supported_structure_type(search_for_type), - "unexpected struct type in pNext chain: {:?}", - search_for_type - ); - child = child_ref.pNext as *const _; - } -} - -unsafe fn parse_next_chain_mut( - root: *mut api::VkBaseOutStructure, - expected_root_struct_type: api::VkStructureType, - expected_child_structs: &[(api::VkStructureType, *mut *mut api::VkBaseOutStructure)], -) { - parse_next_chain_const( - root as *const api::VkBaseInStructure, - expected_root_struct_type, - &*(expected_child_structs as *const [(u32, *mut *mut api::VkBaseOutStructure)] - as *const [(u32, *mut *const api::VkBaseInStructure)]), - ) -} - -macro_rules! parse_next_chain_const { - { - $root:expr, - root = $root_type:expr, - $($name:ident: $var_type:ty = $struct_type:expr,)* - } => { - $(let mut $name: *const $var_type = null();)* - parse_next_chain_const( - $root as *const _ as *const api::VkBaseInStructure, - $root_type, - &[$(($struct_type, &mut $name as *mut *const $var_type as *mut *const api::VkBaseInStructure)),*] - ); - }; -} - -macro_rules! parse_next_chain_mut { - { - $root:expr, - root = $root_type:expr, - $($name:ident: $var_type:ty = $struct_type:expr,)* - } => { - $(let mut $name: *mut $var_type = null_mut();)* - parse_next_chain_mut( - $root as *mut _ as *mut api::VkBaseOutStructure, - $root_type, - &[$(($struct_type, &mut $name as *mut *mut $var_type as *mut *mut api::VkBaseOutStructure)),*] - ); - }; -} - -fn copy_str_to_char_array(dest: &mut [c_char], src: &str) { - #![cfg_attr(feature = "cargo-clippy", allow(clippy::int_plus_one))] - assert!(dest.len() >= src.len() + 1); - let src = src.as_bytes(); - for i in 0..src.len() { - dest[i] = src[i] as c_char; - } - for v in dest.iter_mut().skip(src.len()) { - *v = 0; - } -} - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Enum)] #[repr(u32)] #[allow(non_camel_case_types)] @@ -490,7 +253,7 @@ impl Extension { extensionName: [0; api::VK_MAX_EXTENSION_NAME_SIZE as usize], specVersion: self.get_spec_version(), }; - copy_str_to_char_array(&mut retval.extensionName, self.get_name()); + util::copy_str_to_char_array(&mut retval.extensionName, self.get_name()); retval } pub fn get_scope(self) -> ExtensionScope { @@ -1564,19 +1327,17 @@ impl Device { return Err(api::VK_ERROR_LAYER_NOT_PRESENT); } let mut enabled_extensions = physical_device.enabled_extensions; - if create_info.enabledExtensionCount != 0 { - for &extension_name in slice::from_raw_parts( - create_info.ppEnabledExtensionNames, - create_info.enabledExtensionCount as usize, - ) { - let extension: Extension = CStr::from_ptr(extension_name) - .to_str() - .map_err(|_| api::VK_ERROR_EXTENSION_NOT_PRESENT)? - .parse() - .map_err(|_| api::VK_ERROR_EXTENSION_NOT_PRESENT)?; - assert_eq!(extension.get_scope(), ExtensionScope::Device); - enabled_extensions[extension] = true; - } + for &extension_name in util::to_slice( + create_info.ppEnabledExtensionNames, + create_info.enabledExtensionCount as usize, + ) { + let extension: Extension = CStr::from_ptr(extension_name) + .to_str() + .map_err(|_| api::VK_ERROR_EXTENSION_NOT_PRESENT)? + .parse() + .map_err(|_| api::VK_ERROR_EXTENSION_NOT_PRESENT)?; + assert_eq!(extension.get_scope(), ExtensionScope::Device); + enabled_extensions[extension] = true; } for extension in enabled_extensions .iter() @@ -1644,7 +1405,7 @@ impl Device { return Err(api::VK_ERROR_FEATURE_NOT_PRESENT); } assert_ne!(create_info.queueCreateInfoCount, 0); - let queue_create_infos = slice::from_raw_parts( + let queue_create_infos = util::to_slice( create_info.pQueueCreateInfos, create_info.queueCreateInfoCount as usize, ); @@ -1667,7 +1428,7 @@ impl Device { assert_eq!(flags & api::VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT, 0); assert!(queue_family_index < QUEUE_FAMILY_COUNT); assert!(queue_count <= QUEUE_COUNTS[queue_family_index as usize]); - let queue_priorities = slice::from_raw_parts(queue_priorities, queue_count as usize); + let queue_priorities = util::to_slice(queue_priorities, queue_count as usize); for &queue_priority in queue_priorities { assert!(queue_priority >= 0.0 && queue_priority <= 1.0); } @@ -3176,19 +2937,17 @@ impl Instance { return Err(api::VK_ERROR_LAYER_NOT_PRESENT); } let mut enabled_extensions = Extensions::create_empty(); - if create_info.enabledExtensionCount != 0 { - for &extension_name in slice::from_raw_parts( - create_info.ppEnabledExtensionNames, - create_info.enabledExtensionCount as usize, - ) { - let extension: Extension = CStr::from_ptr(extension_name) - .to_str() - .map_err(|_| api::VK_ERROR_EXTENSION_NOT_PRESENT)? - .parse() - .map_err(|_| api::VK_ERROR_EXTENSION_NOT_PRESENT)?; - assert_eq!(extension.get_scope(), ExtensionScope::Instance); - enabled_extensions[extension] = true; - } + for &extension_name in util::to_slice( + create_info.ppEnabledExtensionNames, + create_info.enabledExtensionCount as usize, + ) { + let extension: Extension = CStr::from_ptr(extension_name) + .to_str() + .map_err(|_| api::VK_ERROR_EXTENSION_NOT_PRESENT)? + .parse() + .map_err(|_| api::VK_ERROR_EXTENSION_NOT_PRESENT)?; + assert_eq!(extension.get_scope(), ExtensionScope::Instance); + enabled_extensions[extension] = true; } for extension in enabled_extensions .iter() @@ -3215,7 +2974,7 @@ impl Instance { Ok(info) => system_memory_size = info.total * 1024, } let mut device_name = [0; api::VK_MAX_PHYSICAL_DEVICE_NAME_SIZE as usize]; - copy_str_to_char_array(&mut device_name, KAZAN_DEVICE_NAME); + util::copy_str_to_char_array(&mut device_name, KAZAN_DEVICE_NAME); #[cfg_attr(feature = "cargo-clippy", allow(clippy::needless_update))] let retval = OwnedHandle::::new(Instance { physical_device: OwnedHandle::new(PhysicalDevice { @@ -3336,10 +3095,7 @@ pub unsafe fn enumerate_helper, AF: FnMut( let mut api_values = if api_values.is_null() { None } else { - Some(slice::from_raw_parts_mut( - api_values, - *api_value_count as usize, - )) + Some(util::to_slice_mut(api_values, *api_value_count as usize)) }; let mut final_count = 0; for value in values { @@ -3473,7 +3229,7 @@ pub unsafe extern "system" fn vkGetPhysicalDeviceProperties( } unsafe fn get_physical_device_queue_family_properties( - _physical_device: &SharedHandle, + _physical_device: SharedHandle, queue_family_properties: &mut api::VkQueueFamilyProperties2, queue_count: u32, ) { @@ -3512,7 +3268,7 @@ pub unsafe extern "system" fn vkGetPhysicalDeviceQueueFamilyProperties( queueFamilyProperties: mem::zeroed(), }; get_physical_device_queue_family_properties( - &SharedHandle::from(physical_device).unwrap(), + SharedHandle::from(physical_device).unwrap(), &mut queue_family_properties2, count, ); @@ -4189,7 +3945,7 @@ pub unsafe extern "system" fn vkCreateShaderModule( assert_eq!(U32_BYTE_COUNT, mem::size_of::()); assert_eq!(create_info.codeSize % U32_BYTE_COUNT, 0); assert_ne!(create_info.codeSize, 0); - let code = slice::from_raw_parts(create_info.pCode, create_info.codeSize / U32_BYTE_COUNT); + let code = util::to_slice(create_info.pCode, create_info.codeSize / U32_BYTE_COUNT); *shader_module = OwnedHandle::::new(ShaderModule { code: code.to_owned(), }) @@ -4247,54 +4003,87 @@ pub unsafe extern "system" fn vkMergePipelineCaches( #[allow(non_snake_case)] pub unsafe extern "system" fn vkCreateGraphicsPipelines( - _device: api::VkDevice, - _pipelineCache: api::VkPipelineCache, - _createInfoCount: u32, - _pCreateInfos: *const api::VkGraphicsPipelineCreateInfo, - _pAllocator: *const api::VkAllocationCallbacks, - _pPipelines: *mut api::VkPipeline, + device: api::VkDevice, + pipeline_cache: api::VkPipelineCache, + create_info_count: u32, + create_infos: *const api::VkGraphicsPipelineCreateInfo, + _allocator: *const api::VkAllocationCallbacks, + pipelines: *mut api::VkPipeline, ) -> api::VkResult { - unimplemented!() + pipeline::create_pipelines::( + SharedHandle::from(device).unwrap(), + SharedHandle::from(pipeline_cache), + util::to_slice(create_infos, create_info_count as usize), + util::to_slice_mut(pipelines, create_info_count as usize), + ) } #[allow(non_snake_case)] pub unsafe extern "system" fn vkCreateComputePipelines( - _device: api::VkDevice, - _pipelineCache: api::VkPipelineCache, - _createInfoCount: u32, - _pCreateInfos: *const api::VkComputePipelineCreateInfo, - _pAllocator: *const api::VkAllocationCallbacks, - _pPipelines: *mut api::VkPipeline, + device: api::VkDevice, + pipeline_cache: api::VkPipelineCache, + create_info_count: u32, + create_infos: *const api::VkComputePipelineCreateInfo, + _allocator: *const api::VkAllocationCallbacks, + pipelines: *mut api::VkPipeline, ) -> api::VkResult { - unimplemented!() + pipeline::create_pipelines::( + SharedHandle::from(device).unwrap(), + SharedHandle::from(pipeline_cache), + util::to_slice(create_infos, create_info_count as usize), + util::to_slice_mut(pipelines, create_info_count as usize), + ) } #[allow(non_snake_case)] pub unsafe extern "system" fn vkDestroyPipeline( _device: api::VkDevice, - _pipeline: api::VkPipeline, - _pAllocator: *const api::VkAllocationCallbacks, + pipeline: api::VkPipeline, + _allocator: *const api::VkAllocationCallbacks, ) { - unimplemented!() + OwnedHandle::from(pipeline); } #[allow(non_snake_case)] pub unsafe extern "system" fn vkCreatePipelineLayout( _device: api::VkDevice, - _pCreateInfo: *const api::VkPipelineLayoutCreateInfo, - _pAllocator: *const api::VkAllocationCallbacks, - _pPipelineLayout: *mut api::VkPipelineLayout, + create_info: *const api::VkPipelineLayoutCreateInfo, + _allocator: *const api::VkAllocationCallbacks, + pipeline_layout: *mut api::VkPipelineLayout, ) -> api::VkResult { - unimplemented!() + parse_next_chain_const!{ + create_info, + root = api::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + } + let create_info = &*create_info; + let set_layouts = util::to_slice(create_info.pSetLayouts, create_info.setLayoutCount as usize); + let push_constant_ranges = util::to_slice( + create_info.pPushConstantRanges, + create_info.pushConstantRangeCount as usize, + ); + *pipeline_layout = OwnedHandle::::new(PipelineLayout { + push_constants_size: push_constant_ranges + .iter() + .map(|v| v.size as usize + v.offset as usize) + .max() + .unwrap_or(0), + push_constant_ranges: push_constant_ranges.into(), + descriptor_set_layouts: set_layouts + .iter() + .map(|v| SharedHandle::from(*v).unwrap()) + .collect(), + }) + .take(); + api::VK_SUCCESS } #[allow(non_snake_case)] pub unsafe extern "system" fn vkDestroyPipelineLayout( _device: api::VkDevice, - _pipelineLayout: api::VkPipelineLayout, - _pAllocator: *const api::VkAllocationCallbacks, + pipeline_layout: api::VkPipelineLayout, + _allocator: *const api::VkAllocationCallbacks, ) { - unimplemented!() + OwnedHandle::from(pipeline_layout); } #[allow(non_snake_case)] @@ -4362,10 +4151,7 @@ pub unsafe extern "system" fn vkCreateDescriptorSetLayout( root = api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, } let create_info = &*create_info; - let bindings = match create_info.bindingCount { - 0 => &[], - binding_count => slice::from_raw_parts(create_info.pBindings, binding_count as usize), - }; + let bindings = util::to_slice(create_info.pBindings, create_info.bindingCount as usize); let max_binding = bindings.iter().map(|v| v.binding).max().unwrap_or(0) as usize; let mut bindings_map: Vec> = (0..=max_binding).map(|_| None).collect(); for binding in bindings { @@ -4440,8 +4226,8 @@ pub unsafe extern "system" fn vkAllocateDescriptorSets( let allocate_info = &*allocate_info; let mut descriptor_pool = MutHandle::from(allocate_info.descriptorPool).unwrap(); let descriptor_sets = - slice::from_raw_parts_mut(descriptor_sets, allocate_info.descriptorSetCount as usize); - let descriptor_set_layouts = slice::from_raw_parts( + util::to_slice_mut(descriptor_sets, allocate_info.descriptorSetCount as usize); + let descriptor_set_layouts = util::to_slice( allocate_info.pSetLayouts, allocate_info.descriptorSetCount as usize, ); @@ -4469,7 +4255,7 @@ pub unsafe extern "system" fn vkFreeDescriptorSets( descriptor_sets: *const api::VkDescriptorSet, ) -> api::VkResult { let mut descriptor_pool = MutHandle::from(descriptor_pool).unwrap(); - let descriptor_sets = slice::from_raw_parts(descriptor_sets, descriptor_set_count as usize); + let descriptor_sets = util::to_slice(descriptor_sets, descriptor_set_count as usize); descriptor_pool.free(descriptor_sets); api::VK_SUCCESS } @@ -4482,10 +4268,8 @@ pub unsafe extern "system" fn vkUpdateDescriptorSets( descriptor_copy_count: u32, descriptor_copies: *const api::VkCopyDescriptorSet, ) { - let descriptor_writes = - slice::from_raw_parts(descriptor_writes, descriptor_write_count as usize); - let descriptor_copies = - slice::from_raw_parts(descriptor_copies, descriptor_copy_count as usize); + let descriptor_writes = util::to_slice(descriptor_writes, descriptor_write_count as usize); + let descriptor_copies = util::to_slice(descriptor_copies, descriptor_copy_count as usize); for descriptor_write in descriptor_writes { parse_next_chain_const!{ descriptor_write, @@ -5119,7 +4903,7 @@ pub unsafe extern "system" fn vkBindBufferMemory2( bind_infos: *const api::VkBindBufferMemoryInfo, ) -> api::VkResult { assert_ne!(bind_info_count, 0); - let bind_infos = slice::from_raw_parts(bind_infos, bind_info_count as usize); + let bind_infos = util::to_slice(bind_infos, bind_info_count as usize); for bind_info in bind_infos { parse_next_chain_const!{ bind_info, @@ -5157,7 +4941,7 @@ pub unsafe extern "system" fn vkBindImageMemory2( bind_infos: *const api::VkBindImageMemoryInfo, ) -> api::VkResult { assert_ne!(bind_info_count, 0); - let bind_infos = slice::from_raw_parts(bind_infos, bind_info_count as usize); + let bind_infos = util::to_slice(bind_infos, bind_info_count as usize); for bind_info in bind_infos { parse_next_chain_const!{ bind_info, @@ -5492,7 +5276,7 @@ pub unsafe extern "system" fn vkGetPhysicalDeviceQueueFamilyProperties2( QUEUE_COUNTS.iter(), |queue_family_properties, &count| { get_physical_device_queue_family_properties( - &SharedHandle::from(physical_device).unwrap(), + SharedHandle::from(physical_device).unwrap(), queue_family_properties, count, ); diff --git a/vulkan-driver/src/descriptor_set.rs b/vulkan-driver/src/descriptor_set.rs index 5de5f0d..fe55a16 100644 --- a/vulkan-driver/src/descriptor_set.rs +++ b/vulkan-driver/src/descriptor_set.rs @@ -7,7 +7,7 @@ use handle::OwnedHandle; use handle::SharedHandle; use image; use std::ops; -use std::slice; +use util; #[derive(Debug)] pub enum DescriptorLayout { @@ -110,7 +110,7 @@ impl DescriptorLayout { None } else { let immutable_samplers = - slice::from_raw_parts(v.pImmutableSamplers, v.descriptorCount as usize); + util::to_slice(v.pImmutableSamplers, v.descriptorCount as usize); Some( immutable_samplers .iter() @@ -282,15 +282,12 @@ impl<'a> DescriptorWriteArg<'a> { | api::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE | api::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT => { assert!(!v.pImageInfo.is_null()); - DescriptorWriteArg::Image(slice::from_raw_parts( - v.pImageInfo, - v.descriptorCount as usize, - )) + DescriptorWriteArg::Image(util::to_slice(v.pImageInfo, v.descriptorCount as usize)) } api::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER | api::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER => { assert!(!v.pTexelBufferView.is_null()); - DescriptorWriteArg::TexelBuffer(slice::from_raw_parts( + DescriptorWriteArg::TexelBuffer(util::to_slice( v.pTexelBufferView, v.descriptorCount as usize, )) @@ -300,7 +297,7 @@ impl<'a> DescriptorWriteArg<'a> { | api::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC | api::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC => { assert!(!v.pBufferInfo.is_null()); - DescriptorWriteArg::Buffer(slice::from_raw_parts( + DescriptorWriteArg::Buffer(util::to_slice( v.pBufferInfo, v.descriptorCount as usize, )) @@ -396,7 +393,7 @@ impl Descriptor { let immutable_samplers = if let Some(immutable_samplers) = immutable_samplers { assert_eq!(immutable_samplers.len(), *count); for (element, sampler) in elements.iter_mut().zip(immutable_samplers.iter()) { - *element = Some(sampler.clone()); + *element = Some(*sampler); } true } else { @@ -420,7 +417,7 @@ impl Descriptor { let immutable_samplers = if let Some(immutable_samplers) = immutable_samplers { assert_eq!(immutable_samplers.len(), *count); for (element, sampler) in elements.iter_mut().zip(immutable_samplers.iter()) { - element.sampler = Some(sampler.clone()); + element.sampler = Some(*sampler); } true } else { diff --git a/vulkan-driver/src/handle.rs b/vulkan-driver/src/handle.rs index 33b31ad..c5ea317 100644 --- a/vulkan-driver/src/handle.rs +++ b/vulkan-driver/src/handle.rs @@ -6,6 +6,7 @@ use buffer::{Buffer, BufferView}; use descriptor_set::{DescriptorPool, DescriptorSet, DescriptorSetLayout}; use device_memory::DeviceMemory; use image::{Image, ImageView}; +use pipeline::{Pipeline, PipelineLayout}; use render_pass::RenderPass; use sampler::Sampler; use sampler::SamplerYcbcrConversion; @@ -210,6 +211,8 @@ where #[repr(transparent)] pub struct SharedHandle(NonNull); +impl Copy for SharedHandle {} + impl Clone for SharedHandle { fn clone(&self) -> Self { SharedHandle(self.0) @@ -224,7 +227,7 @@ impl SharedHandle { pub unsafe fn take(self) -> T { T::new(Some(self.0)) } - pub unsafe fn get_handle(&self) -> T { + pub unsafe fn get_handle(self) -> T { T::new(Some(self.0)) } pub fn into_nonnull(self) -> NonNull { @@ -369,8 +372,6 @@ pub type VkPipelineCache = NondispatchableHandle; impl HandleAllocFree for VkPipelineCache {} -pub struct PipelineLayout {} - pub type VkPipelineLayout = NondispatchableHandle; impl HandleAllocFree for VkPipelineLayout {} @@ -379,8 +380,6 @@ pub type VkRenderPass = NondispatchableHandle; impl HandleAllocFree for VkRenderPass {} -pub struct Pipeline {} - pub type VkPipeline = NondispatchableHandle; impl HandleAllocFree for VkPipeline {} diff --git a/vulkan-driver/src/lib.rs b/vulkan-driver/src/lib.rs index b920b61..8cea073 100644 --- a/vulkan-driver/src/lib.rs +++ b/vulkan-driver/src/lib.rs @@ -8,10 +8,14 @@ extern crate errno; #[cfg(target_os = "linux")] extern crate libc; extern crate shader_compiler_backend; +extern crate shader_compiler_backend_llvm_7; +extern crate spirv_parser; extern crate sys_info; extern crate uuid; #[cfg(target_os = "linux")] extern crate xcb; +#[macro_use] +mod util; mod api; mod api_impl; mod buffer; @@ -19,6 +23,7 @@ mod descriptor_set; mod device_memory; mod handle; mod image; +mod pipeline; mod render_pass; mod sampler; mod shader_module; diff --git a/vulkan-driver/src/pipeline.rs b/vulkan-driver/src/pipeline.rs new file mode 100644 index 0000000..89826b0 --- /dev/null +++ b/vulkan-driver/src/pipeline.rs @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright 2018 Jacob Lifshay + +use api; +use handle::{OwnedHandle, SharedHandle}; +use std::fmt; +use std::ops::Deref; + +#[derive(Debug)] +pub struct PipelineLayout { + pub push_constants_size: usize, + pub push_constant_ranges: Vec, + pub descriptor_set_layouts: Vec>, +} + +pub trait GenericPipeline: fmt::Debug + Sync + 'static {} + +pub trait GenericPipelineSized: GenericPipeline + Sized { + type PipelineCreateInfo; + unsafe fn create( + device: SharedHandle, + pipeline_cache: Option>, + create_info: &Self::PipelineCreateInfo, + ) -> Self; + fn to_pipeline(self) -> Pipeline; +} + +#[derive(Debug)] +pub struct ComputePipeline {} + +impl GenericPipeline for ComputePipeline {} + +impl GenericPipelineSized for ComputePipeline { + type PipelineCreateInfo = api::VkComputePipelineCreateInfo; + unsafe fn create( + _device: SharedHandle, + _pipeline_cache: Option>, + create_info: &api::VkComputePipelineCreateInfo, + ) -> Self { + parse_next_chain_const!{ + create_info, + root = api::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + } + if (create_info.flags & api::VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT) != 0 { + unimplemented!(); + } + unimplemented!() + } + fn to_pipeline(self) -> Pipeline { + Pipeline::Compute(self) + } +} + +#[derive(Debug)] +pub struct GraphicsPipeline {} + +impl GenericPipeline for GraphicsPipeline {} + +impl GenericPipelineSized for GraphicsPipeline { + type PipelineCreateInfo = api::VkGraphicsPipelineCreateInfo; + unsafe fn create( + _device: SharedHandle, + _pipeline_cache: Option>, + create_info: &api::VkGraphicsPipelineCreateInfo, + ) -> Self { + parse_next_chain_const!{ + create_info, + root = api::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + } + unimplemented!() + } + fn to_pipeline(self) -> Pipeline { + Pipeline::Graphics(self) + } +} + +#[derive(Debug)] +pub enum Pipeline { + Compute(ComputePipeline), + Graphics(GraphicsPipeline), +} + +impl Deref for Pipeline { + type Target = dyn GenericPipeline; + fn deref(&self) -> &dyn GenericPipeline { + match self { + Pipeline::Compute(v) => v, + Pipeline::Graphics(v) => v, + } + } +} + +pub unsafe fn create_pipelines( + device: SharedHandle, + pipeline_cache: Option>, + create_infos: &[T::PipelineCreateInfo], + pipelines: &mut [api::VkPipeline], +) -> api::VkResult { + assert_eq!(create_infos.len(), pipelines.len()); + for (pipeline, create_info) in pipelines.iter_mut().zip(create_infos.iter()) { + *pipeline = OwnedHandle::::new( + T::create(device, pipeline_cache, create_info).to_pipeline(), + ) + .take(); + } + api::VK_SUCCESS +} diff --git a/vulkan-driver/src/shm.rs b/vulkan-driver/src/shm.rs index 05980cd..efe51ed 100644 --- a/vulkan-driver/src/shm.rs +++ b/vulkan-driver/src/shm.rs @@ -7,7 +7,7 @@ use std::ops::Deref; use std::ops::DerefMut; use std::os::raw::c_int; use std::ptr::null_mut; -use std::slice; +use util; #[derive(Debug)] #[allow(dead_code)] @@ -73,7 +73,7 @@ pub struct MappedSharedMemorySegment { impl MappedSharedMemorySegment { unsafe fn get(&self) -> *mut [u8] { - slice::from_raw_parts_mut(self.memory, self.size) + util::to_slice_mut(self.memory, self.size) } } diff --git a/vulkan-driver/src/util.rs b/vulkan-driver/src/util.rs new file mode 100644 index 0000000..321f394 --- /dev/null +++ b/vulkan-driver/src/util.rs @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright 2018 Jacob Lifshay + +use api; +use std::os::raw::c_char; +use std::ptr::null; +use std::slice; + +/// like `std::util::to_slice` except that the pointer can be null when the length is zero +pub unsafe fn to_slice<'a, T>(p: *const T, len: usize) -> &'a [T] { + if len == 0 { + &[] + } else { + assert!(!p.is_null()); + slice::from_raw_parts(p, len) + } +} + +/// like `std::util::to_slice_mut` except that the pointer can be null when the length is zero +pub unsafe fn to_slice_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] { + if len == 0 { + &mut [] + } else { + assert!(!p.is_null()); + slice::from_raw_parts_mut(p, len) + } +} + +/// structure types the driver should know about +pub fn is_supported_structure_type(v: api::VkStructureType) -> bool { + #[cfg(target_os = "linux")] + { + #[cfg_attr(feature = "cargo-clippy", allow(clippy::single_match))] + match v { + api::VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR => return true, + _ => {} + } + } + match v { + api::VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR + | api::VK_STRUCTURE_TYPE_APPLICATION_INFO + | api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO + | api::VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO + | api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO + | api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO + | api::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR + | api::VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO + | api::VK_STRUCTURE_TYPE_BIND_SPARSE_INFO + | api::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO + | api::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER + | api::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 + | api::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO + | api::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO + | api::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO + | api::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO + | api::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO + | api::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET + | api::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO + | api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO + | api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO + | api::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT + | api::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO + | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO + | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR + | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR + | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO + | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO + | api::VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR + | api::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 + | api::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO + | api::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO + | api::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES + | api::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES + | api::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES + | api::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO + | api::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES + | api::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 + | api::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO + | api::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 + | api::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER + | api::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 + | api::VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO + | api::VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 + | api::VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR + | api::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO + | api::VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE + | api::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO + | api::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO + | api::VK_STRUCTURE_TYPE_MEMORY_BARRIER + | api::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO + | api::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS + | api::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR + | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES + | api::VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR + | api::VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO + | api::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO + | api::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 + | api::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO + | api::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO + | api::VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO + | api::VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO + | api::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO + | api::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO + | api::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES + | api::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO + | api::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO + | api::VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 + | api::VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 + | api::VK_STRUCTURE_TYPE_SUBMIT_INFO + | api::VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR + | api::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR + | api::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET => true, + _ => false, + } +} + +pub fn verify_structure_type_is_supported(v: api::VkStructureType) { + assert!( + is_supported_structure_type(v), + "missing structure type in is_supported_structure_type: {:?}", + v + ); +} + +pub unsafe fn parse_next_chain_const( + root: *const api::VkBaseInStructure, + expected_root_struct_type: api::VkStructureType, + expected_child_structs: &[(api::VkStructureType, *mut *const api::VkBaseInStructure)], +) { + verify_structure_type_is_supported(expected_root_struct_type); + let root = &*root; + assert_eq!(root.sType, expected_root_struct_type); + for &(child_struct_type, child_struct) in expected_child_structs.iter() { + verify_structure_type_is_supported(child_struct_type); + *child_struct = null(); + } + let mut child = root.pNext as *const api::VkBaseInStructure; + while !child.is_null() { + let child_ref = &*child; + let search_for_type = child_ref.sType; + let mut found = false; + for &(child_struct_type, child_struct) in expected_child_structs.iter() { + if child_struct_type == search_for_type { + assert!( + (*child_struct).is_null(), + "duplicate struct type in pNext chain: {:?}", + search_for_type + ); + *child_struct = child; + found = true; + break; + } + } + assert!( + found || !is_supported_structure_type(search_for_type), + "unexpected struct type in pNext chain: {:?}", + search_for_type + ); + child = child_ref.pNext as *const _; + } +} + +pub unsafe fn parse_next_chain_mut( + root: *mut api::VkBaseOutStructure, + expected_root_struct_type: api::VkStructureType, + expected_child_structs: &[(api::VkStructureType, *mut *mut api::VkBaseOutStructure)], +) { + parse_next_chain_const( + root as *const api::VkBaseInStructure, + expected_root_struct_type, + &*(expected_child_structs as *const [(u32, *mut *mut api::VkBaseOutStructure)] + as *const [(u32, *mut *const api::VkBaseInStructure)]), + ) +} + +macro_rules! parse_next_chain_const { + { + $root:expr, + root = $root_type:expr, + $($name:ident: $var_type:ty = $struct_type:expr,)* + } => { + $(let mut $name: *const $var_type = ::std::ptr::null();)* + ::util::parse_next_chain_const( + $root as *const _ as *const ::api::VkBaseInStructure, + $root_type, + &[$(($struct_type, &mut $name as *mut *const $var_type as *mut *const ::api::VkBaseInStructure)),*] + ); + }; +} + +macro_rules! parse_next_chain_mut { + { + $root:expr, + root = $root_type:expr, + $($name:ident: $var_type:ty = $struct_type:expr,)* + } => { + $(let mut $name: *mut $var_type = ::std::ptr::null_mut();)* + ::util::parse_next_chain_mut( + $root as *mut _ as *mut ::api::VkBaseOutStructure, + $root_type, + &[$(($struct_type, &mut $name as *mut *mut $var_type as *mut *mut ::api::VkBaseOutStructure)),*] + ); + }; +} + +pub fn copy_str_to_char_array(dest: &mut [c_char], src: &str) { + #![cfg_attr(feature = "cargo-clippy", allow(clippy::int_plus_one))] + assert!(dest.len() >= src.len() + 1); + let src = src.as_bytes(); + for i in 0..src.len() { + dest[i] = src[i] as c_char; + } + for v in dest.iter_mut().skip(src.len()) { + *v = 0; + } +} -- 2.30.2