declared ICD api
authorJacob Lifshay <programmerjake@gmail.com>
Wed, 26 Sep 2018 03:36:28 +0000 (20:36 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Wed, 26 Sep 2018 03:36:28 +0000 (20:36 -0700)
.gitignore
Cargo.toml [new file with mode: 0644]
vulkan-driver/Cargo.toml [new file with mode: 0644]
vulkan-driver/build.rs [new file with mode: 0644]
vulkan-driver/src/api.rs [new file with mode: 0644]
vulkan-driver/src/lib.rs [new file with mode: 0644]
vulkan-driver/vulkan-wrapper.h [new file with mode: 0644]

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 100644 (file)
@@ -0,0 +1,2 @@
+/target
+/Cargo.lock
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..6b0d8e8
--- /dev/null
@@ -0,0 +1,2 @@
+[workspace]
+members = ["vulkan-driver"]
diff --git a/vulkan-driver/Cargo.toml b/vulkan-driver/Cargo.toml
new file mode 100644 (file)
index 0000000..7a85b74
--- /dev/null
@@ -0,0 +1,14 @@
+[package]
+name = "vulkan-driver"
+version = "0.1.0"
+authors = ["Jacob Lifshay <programmerjake@gmail.com>"]
+
+[lib]
+crate-type = ["cdylib"]
+
+[target.'cfg(unix)'.dependencies]
+xcb = "0.8"
+
+[build-dependencies]
+bindgen = "0.40"
+regex = "1"
diff --git a/vulkan-driver/build.rs b/vulkan-driver/build.rs
new file mode 100644 (file)
index 0000000..4aa46c5
--- /dev/null
@@ -0,0 +1,83 @@
+extern crate bindgen;
+extern crate regex;
+use std::env;
+use std::fs;
+use std::io;
+use std::path::PathBuf;
+
+fn detect_vulkan_calling_convention() -> io::Result<String> {
+    let code = bindgen::builder()
+        .header_contents(
+            "vulkan_detect.h",
+            r#"#include <vulkan/vk_platform.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+VKAPI_ATTR void VKAPI_CALL detect_fn();
+
+#ifdef __cplusplus
+}
+#endif
+"#,
+        ).clang_arg("-target")
+        .clang_arg(env::var("TARGET").unwrap())
+        .clang_arg("-I../external/Vulkan-Headers/include")
+        .whitelist_function("detect_fn")
+        .generate()
+        .map_err(|_| io::Error::new(io::ErrorKind::Other, "generate() failed"))?
+        .to_string();
+    if let Some(captures) = regex::Regex::new(r#"extern "([^"]+)""#)
+        .unwrap()
+        .captures(&code)
+    {
+        Ok(captures[1].to_owned())
+    } else {
+        eprintln!("code:\n{}", code);
+        Err(io::Error::new(io::ErrorKind::Other, "regex not found"))
+    }
+}
+
+fn main() -> io::Result<()> {
+    println!("cargo:rerun-if-changed=vulkan-wrapper.h");
+    println!("cargo:rerun-if-changed=../external/Vulkan-Headers/include");
+    let vulkan_calling_convention = detect_vulkan_calling_convention()?;
+    let match_calling_convention_regex = regex::Regex::new(r#"extern "([^"]+)""#).unwrap();
+    let builder = bindgen::builder()
+        .header("vulkan-wrapper.h")
+        .clang_arg("-target")
+        .clang_arg(env::var("TARGET").unwrap())
+        .clang_arg("-I../external/Vulkan-Headers/include")
+        .prepend_enum_name(false)
+        .layout_tests(false)
+        .whitelist_var("VK_.*")
+        .whitelist_var("ICD_LOADER_MAGIC")
+        .whitelist_type("Vk.*")
+        .whitelist_type("PFN_.*")
+        .blacklist_type("^xcb_.*")
+        .derive_debug(false)
+        .ignore_functions()
+        .constified_enum(".*");
+    let mut code = builder
+        .generate()
+        .map_err(|_| io::Error::new(io::ErrorKind::Other, "generate() failed"))?
+        .to_string();
+    code = match_calling_convention_regex
+        .replace_all(&code, |captures: &regex::Captures| {
+            if captures[1] == vulkan_calling_convention {
+                r#"extern "system""#
+            } else {
+                let _ = fs::write(
+                    PathBuf::from(env::var("OUT_DIR").unwrap()).join("vulkan-types.rs"),
+                    &code,
+                );
+                eprintln!("vulkan_calling_convention: {:?}", vulkan_calling_convention);
+                panic!("unhandled non-vulkan calling convention");
+            }
+        }).into_owned();
+    fs::write(
+        PathBuf::from(env::var("OUT_DIR").unwrap()).join("vulkan-types.rs"),
+        code,
+    )?;
+    Ok(())
+}
diff --git a/vulkan-driver/src/api.rs b/vulkan-driver/src/api.rs
new file mode 100644 (file)
index 0000000..ac2fce9
--- /dev/null
@@ -0,0 +1,7 @@
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#[cfg(unix)]
+use xcb::ffi::{xcb_connection_t, xcb_visualid_t, xcb_window_t};
+include!(concat!(env!("OUT_DIR"), "/vulkan-types.rs"));
diff --git a/vulkan-driver/src/lib.rs b/vulkan-driver/src/lib.rs
new file mode 100644 (file)
index 0000000..2b256a3
--- /dev/null
@@ -0,0 +1,97 @@
+#[cfg(unix)]
+extern crate xcb;
+mod api;
+use std::ffi::CStr;
+use std::os::raw::c_char;
+
+#[no_mangle]
+pub extern "system" fn vk_icdGetInstanceProcAddr(
+    instance: api::VkInstance,
+    name: *const c_char,
+) -> api::PFN_vkVoidFunction {
+    unimplemented!()
+}
+
+// note that if the following fails, then you may be encountering bindgen issue #1402
+// https://github.com/rust-lang-nursery/rust-bindgen/issues/1402
+#[allow(dead_code)]
+const ASSERT_TYPE_VK_ICD_GET_INSTANCE_PROC_ADDR: api::PFN_vkGetInstanceProcAddr =
+    Some(vk_icdGetInstanceProcAddr);
+
+const ICD_VERSION: u32 = 5;
+
+#[no_mangle]
+pub extern "system" fn vk_icdNegotiateLoaderICDInterfaceVersion(
+    supported_version: &mut u32,
+) -> api::VkResult {
+    if *supported_version > ICD_VERSION {
+        *supported_version = ICD_VERSION;
+    }
+    api::VK_SUCCESS
+}
+
+#[no_mangle]
+pub extern "system" fn vk_icdGetPhysicalDeviceProcAddr(
+    instance: api::VkInstance,
+    name: *const c_char,
+) -> api::PFN_vkVoidFunction {
+    match unsafe { CStr::from_ptr(name) }.to_str().ok()? {
+        "vkCreateDevice"
+        | "vkCreateDisplayModeKHR"
+        | "vkEnumerateDeviceExtensionProperties"
+        | "vkEnumerateDeviceLayerProperties"
+        | "vkGetDisplayModeProperties2KHR"
+        | "vkGetDisplayModePropertiesKHR"
+        | "vkGetDisplayPlaneCapabilities2KHR"
+        | "vkGetDisplayPlaneCapabilitiesKHR"
+        | "vkGetDisplayPlaneSupportedDisplaysKHR"
+        | "vkGetPhysicalDeviceDisplayPlaneProperties2KHR"
+        | "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"
+        | "vkGetPhysicalDeviceDisplayProperties2KHR"
+        | "vkGetPhysicalDeviceDisplayPropertiesKHR"
+        | "vkGetPhysicalDeviceExternalBufferProperties"
+        | "vkGetPhysicalDeviceExternalBufferPropertiesKHR"
+        | "vkGetPhysicalDeviceExternalFenceProperties"
+        | "vkGetPhysicalDeviceExternalFencePropertiesKHR"
+        | "vkGetPhysicalDeviceExternalImageFormatPropertiesNV"
+        | "vkGetPhysicalDeviceExternalSemaphoreProperties"
+        | "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"
+        | "vkGetPhysicalDeviceFeatures"
+        | "vkGetPhysicalDeviceFeatures2"
+        | "vkGetPhysicalDeviceFeatures2KHR"
+        | "vkGetPhysicalDeviceFormatProperties"
+        | "vkGetPhysicalDeviceFormatProperties2"
+        | "vkGetPhysicalDeviceFormatProperties2KHR"
+        | "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX"
+        | "vkGetPhysicalDeviceImageFormatProperties"
+        | "vkGetPhysicalDeviceImageFormatProperties2"
+        | "vkGetPhysicalDeviceImageFormatProperties2KHR"
+        | "vkGetPhysicalDeviceMemoryProperties"
+        | "vkGetPhysicalDeviceMemoryProperties2"
+        | "vkGetPhysicalDeviceMemoryProperties2KHR"
+        | "vkGetPhysicalDeviceMultisamplePropertiesEXT"
+        | "vkGetPhysicalDevicePresentRectanglesKHR"
+        | "vkGetPhysicalDeviceProperties"
+        | "vkGetPhysicalDeviceProperties2"
+        | "vkGetPhysicalDeviceProperties2KHR"
+        | "vkGetPhysicalDeviceQueueFamilyProperties"
+        | "vkGetPhysicalDeviceQueueFamilyProperties2"
+        | "vkGetPhysicalDeviceQueueFamilyProperties2KHR"
+        | "vkGetPhysicalDeviceSparseImageFormatProperties"
+        | "vkGetPhysicalDeviceSparseImageFormatProperties2"
+        | "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"
+        | "vkGetPhysicalDeviceSurfaceCapabilities2EXT"
+        | "vkGetPhysicalDeviceSurfaceCapabilities2KHR"
+        | "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"
+        | "vkGetPhysicalDeviceSurfaceFormats2KHR"
+        | "vkGetPhysicalDeviceSurfaceFormatsKHR"
+        | "vkGetPhysicalDeviceSurfacePresentModesKHR"
+        | "vkGetPhysicalDeviceSurfaceSupportKHR"
+        | "vkGetPhysicalDeviceXcbPresentationSupportKHR"
+        | "vkReleaseDisplayEXT" => vk_icdGetInstanceProcAddr(instance, name),
+        _ => None,
+    }
+}
+
+#[cfg(test)]
+mod tests {}
diff --git a/vulkan-driver/vulkan-wrapper.h b/vulkan-driver/vulkan-wrapper.h
new file mode 100644 (file)
index 0000000..9e95fbd
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdint.h>
+#ifdef __ANDROID__
+#error not supported on Android; need to fix ABI
+#endif
+#define VK_NO_PROTOTYPES
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_icd.h>
+#ifdef __unix
+typedef struct xcb_connection_t xcb_connection_t;
+typedef uint32_t xcb_visualid_t;
+typedef uint32_t xcb_window_t;
+#include <vulkan/vulkan_xcb.h>
+#endif
+#undef VK_NO_PROTOTYPES