working on implementing shader compiler
authorJacob Lifshay <programmerjake@gmail.com>
Wed, 7 Nov 2018 08:28:04 +0000 (00:28 -0800)
committerJacob Lifshay <programmerjake@gmail.com>
Wed, 7 Nov 2018 08:28:04 +0000 (00:28 -0800)
12 files changed:
Cargo.toml
shader-compiler/Cargo.toml [new file with mode: 0644]
shader-compiler/src/lib.rs [new file with mode: 0644]
spirv-parser-generator/src/generate.rs
vulkan-driver/Cargo.toml
vulkan-driver/src/api_impl.rs
vulkan-driver/src/descriptor_set.rs
vulkan-driver/src/handle.rs
vulkan-driver/src/lib.rs
vulkan-driver/src/pipeline.rs [new file with mode: 0644]
vulkan-driver/src/shm.rs
vulkan-driver/src/util.rs [new file with mode: 0644]

index 0b509346759e9314d7e8ab903ab844acb1a648e1..bf2dd6f6e343d8aaed1352718a96354c9e64684d 100644 (file)
@@ -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 (file)
index 0000000..1bbfcf7
--- /dev/null
@@ -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 <programmerjake@gmail.com>"]
+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 (file)
index 0000000..f2d976e
--- /dev/null
@@ -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;
index dd836a3542530e45be7b1f21a3cfab636cf3c48d..a2d2c4f648bc2b489e1e08788f2bf41549001d47 100644 (file)
@@ -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),*);})?;
             }
         }
index ac2666dbdeba1cd4b38678d6992398990eff08c2..28d4ef73f643d21ba908527a0c8bca4e4c69040e 100644 (file)
@@ -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"]}
index 61685161fac3420e2bf9d86a388d1c60a48c3498..41836c28644e5a8332a46966fa408a3bba25936d 100644 (file)
@@ -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::<api::VkInstance>::new(Instance {
             physical_device: OwnedHandle::new(PhysicalDevice {
@@ -3336,10 +3095,7 @@ pub unsafe fn enumerate_helper<T, Item, I: IntoIterator<Item = Item>, 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<api::VkPhysicalDevice>,
+    _physical_device: SharedHandle<api::VkPhysicalDevice>,
     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::<u32>());
     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::<api::VkShaderModule>::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::<pipeline::GraphicsPipeline>(
+        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::<pipeline::ComputePipeline>(
+        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::<api::VkPipelineLayout>::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<Option<DescriptorLayout>> = (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,
             );
index 5de5f0d33240a8fe1eb615ccececca4be8b27dbe..fe55a16022fbe3b693960dd992fc4daad951bd42 100644 (file)
@@ -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 {
index 33b31ad96540dab0ee539b9d15ce26f50517304a..c5ea31702168d50eb7bee1636e74f1b2ab96ee3d 100644 (file)
@@ -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<T: Handle>(NonNull<T::Value>);
 
+impl<T: Handle> Copy for SharedHandle<T> {}
+
 impl<T: Handle> Clone for SharedHandle<T> {
     fn clone(&self) -> Self {
         SharedHandle(self.0)
@@ -224,7 +227,7 @@ impl<T: Handle> SharedHandle<T> {
     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<T::Value> {
@@ -369,8 +372,6 @@ pub type VkPipelineCache = NondispatchableHandle<PipelineCache>;
 
 impl HandleAllocFree for VkPipelineCache {}
 
-pub struct PipelineLayout {}
-
 pub type VkPipelineLayout = NondispatchableHandle<PipelineLayout>;
 
 impl HandleAllocFree for VkPipelineLayout {}
@@ -379,8 +380,6 @@ pub type VkRenderPass = NondispatchableHandle<RenderPass>;
 
 impl HandleAllocFree for VkRenderPass {}
 
-pub struct Pipeline {}
-
 pub type VkPipeline = NondispatchableHandle<Pipeline>;
 
 impl HandleAllocFree for VkPipeline {}
index b920b61c9fbad5db55364e1e928bc882f575bb59..8cea073fa4807fcdabb8f63a71832556a4361fe9 100644 (file)
@@ -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 (file)
index 0000000..89826b0
--- /dev/null
@@ -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<api::VkPushConstantRange>,
+    pub descriptor_set_layouts: Vec<SharedHandle<api::VkDescriptorSetLayout>>,
+}
+
+pub trait GenericPipeline: fmt::Debug + Sync + 'static {}
+
+pub trait GenericPipelineSized: GenericPipeline + Sized {
+    type PipelineCreateInfo;
+    unsafe fn create(
+        device: SharedHandle<api::VkDevice>,
+        pipeline_cache: Option<SharedHandle<api::VkPipelineCache>>,
+        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<api::VkDevice>,
+        _pipeline_cache: Option<SharedHandle<api::VkPipelineCache>>,
+        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<api::VkDevice>,
+        _pipeline_cache: Option<SharedHandle<api::VkPipelineCache>>,
+        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<T: GenericPipelineSized>(
+    device: SharedHandle<api::VkDevice>,
+    pipeline_cache: Option<SharedHandle<api::VkPipelineCache>>,
+    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::<api::VkPipeline>::new(
+            T::create(device, pipeline_cache, create_info).to_pipeline(),
+        )
+        .take();
+    }
+    api::VK_SUCCESS
+}
index 05980cd3f64279483c484122a3c761c964709a44..efe51ed9791ae7c80b951c5fd3335038ae4f158f 100644 (file)
@@ -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 (file)
index 0000000..321f394
--- /dev/null
@@ -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;
+    }
+}