diff --git a/.gitignore b/.gitignore index 87ec7b9..9d0e23b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,4 @@ /target/ -native/test -native/test.o native/vulkan -src/original.rs **/*.rs.bk Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 9ab61c6..53a1a22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.0" authors = ["Dzmitry Malyshau "] [lib] -name = "vulkan" -crate-type = ["dylib"] +name = "portability" +crate-type = ["staticlib"] [dependencies] gfx_core = { path = "../gfx/src/core" } -gfx_backend_vulkan = { path = "../gfx/src/backend/vulkan" } +gfx_backend_vulkan = { path = "../gfx/src/backend/vulkan", features = ["portable"] } diff --git a/Makefile b/Makefile index 5fd9592..2c672f6 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,33 @@ +CC=gcc +CFLAGS= +DEPS= +LDFLAGS=-lpthread -ldl -lm + HEADER=native/vulkan/vulkan.h -BINDING=src/original.rs -TARGET=native/test -OBJECTS=native/test.o -OUTPUT_DIR=target/debug -OUTPUT=${OUTPUT_DIR}/libvulkan.a +BINDING=target/vulkan.rs +NATIVE_DIR=target/native +TARGET=$(NATIVE_DIR)/test +OBJECTS=$(NATIVE_DIR)/test.o +LIBRARY=target/debug/libportability.a -all: ${TARGET} +all: $(TARGET) -${BINDING}: ${HEADER} - bindgen --no-layout-tests --rustfmt-bindings ${HEADER} -o ${BINDING} +$(BINDING): $(HEADER) + bindgen --no-layout-tests --rustfmt-bindings $(HEADER) -o $(BINDING) -portability: ${BINDING} +$(LIBRARY): $(BINDING) src/*.rs cargo build + mkdir -p target/native -${TARGET}: portability ${OBJECTS} - gcc -o ${TARGET} -L${OUTPUT_DIR} -lvulkan ${OBJECTS} +$(NATIVE_DIR)/%.o: native/%.c $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) -run: ${TARGET} - ${TARGET} +$(TARGET): $(LIBRARY) $(OBJECTS) + $(CC) -o $(TARGET) $(LDFLAGS) $(OBJECTS) $(LIBRARY) + +run: $(TARGET) + $(TARGET) clean: - rm -f ${OBJECTS} ${TARGET} ${BINDING} + rm -f $(OBJECTS) $(TARGET) $(BINDING) + cargo clean diff --git a/native/test.c b/native/test.c index 3a01c94..7670b8a 100644 --- a/native/test.c +++ b/native/test.c @@ -1,31 +1,33 @@ #include "vulkan/vulkan.h" +#include #include -#include int main() { + printf("starting the portability test\n"); + VkInstanceCreateInfo inst_info = {}; inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - inst_info.pNext = NULL; - inst_info.flags = 0; - inst_info.pApplicationInfo = NULL; - inst_info.enabledExtensionCount = 0; - inst_info.ppEnabledExtensionNames = NULL; - inst_info.enabledLayerCount = 0; - inst_info.ppEnabledLayerNames = NULL; - VkInstance inst; + VkInstance instance; VkResult res; - res = vkCreateInstance(&inst_info, NULL, &inst); + res = vkCreateInstance(&inst_info, NULL, &instance); if (res == VK_ERROR_INCOMPATIBLE_DRIVER) { printf("cannot find a compatible Vulkan ICD\n"); - exit(-1); + return -1; } else if (res) { printf("unknown error\n"); - exit(-1); + return -1; } - vkDestroyInstance(inst, NULL); + uint32_t gpu_count = 1; + VkPhysicalDevice physical_devices[1] = {}; + res = vkEnumeratePhysicalDevices(instance, &gpu_count, physical_devices); + printf("\tvkEnumeratePhysicalDevices: res=%d count=%d\n", res, gpu_count); + assert(!res && gpu_count); + vkDestroyInstance(instance, NULL); + + printf("done.\n"); return 0; } diff --git a/src/handle.rs b/src/handle.rs new file mode 100644 index 0000000..4df54df --- /dev/null +++ b/src/handle.rs @@ -0,0 +1,53 @@ +use std::{fmt, ops}; +use std::marker::PhantomData; + + +#[repr(C)] +pub struct Handle { + pointer: *mut u8, + marker: PhantomData, +} + +impl Handle { + pub fn new(value: T) -> Self { + Handle { + pointer: Box::into_raw(Box::new(value)) as _, + marker: PhantomData, + } + } + + pub fn unwrap(self) -> Box { + unsafe { Box::from_raw(self.pointer as _) } + } +} + +impl Clone for Handle { + fn clone(&self) -> Self { + Handle { + pointer: self.pointer, + marker: PhantomData, + } + } +} + +impl Copy for Handle {} + +impl ops::Deref for Handle { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*(self.pointer as *mut _) } + } +} + +impl ops::DerefMut for Handle { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut*(self.pointer as *mut _) } + } +} + +impl fmt::Debug for Handle { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + //TODO + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index c3f43d4..7a490bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,13 @@ extern crate gfx_core as core; extern crate gfx_backend_vulkan as back; +mod handle; + +use std::{cmp, slice}; +use core::Instance; +use back::Backend as B; +use handle::Handle; + /* automatically generated by rust-bindgen */ pub const VULKAN_H_: ::std::os::raw::c_uint = 1; @@ -451,36 +458,9 @@ pub type VkBool32 = u32; pub type VkDeviceSize = u64; pub type VkSampleMask = u32; -pub type VkInstance = *mut u8; +pub type VkInstance = Handle; +pub type VkPhysicalDevice = Handle<::Adapter>; -#[no_mangle] -pub extern fn vkCreateInstance( - _pCreateInfo: *const VkInstanceCreateInfo, - _pAllocator: *const VkAllocationCallbacks, - pInstance: *mut VkInstance, -) -> VkResult { - let instance = back::Instance::create("portability", 1); - let pointer = Box::into_raw(Box::new(instance)); - unsafe { *pInstance = pointer as *mut _ }; - return VkResult::VK_SUCCESS; -} - -#[no_mangle] -pub extern fn vkDestroyInstance( - instance: VkInstance, - _pAllocator: *const VkAllocationCallbacks, -) { - let _instance = unsafe { Box::from_raw(instance as *mut _) }; - //let it drop -} - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct VkPhysicalDevice_T { - _unused: [u8; 0], -} -pub type VkPhysicalDevice = *mut VkPhysicalDevice_T; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct VkDevice_T { @@ -3472,23 +3452,7 @@ pub struct VkDrawIndirectCommand { impl Clone for VkDrawIndirectCommand { fn clone(&self) -> Self { *self } } -pub type PFN_vkCreateInstance = - ::std::option::Option VkResult>; -pub type PFN_vkDestroyInstance = - ::std::option::Option; -pub type PFN_vkEnumeratePhysicalDevices = - ::std::option::Option VkResult>; + pub type PFN_vkGetPhysicalDeviceFeatures = ::std::option::Option; -extern "C" { - pub fn vkEnumeratePhysicalDevices(instance: VkInstance, - pPhysicalDeviceCount: *mut u32, - pPhysicalDevices: *mut VkPhysicalDevice) - -> VkResult; + +#[no_mangle] +pub extern fn vkCreateInstance( + _pCreateInfo: *const VkInstanceCreateInfo, + _pAllocator: *const VkAllocationCallbacks, + pInstance: *mut VkInstance, +) -> VkResult { + let instance = back::Instance::create("portability", 1); + unsafe { *pInstance = Handle::new(instance) }; + VkResult::VK_SUCCESS } + +#[no_mangle] +pub extern fn vkDestroyInstance( + instance: VkInstance, + _pAllocator: *const VkAllocationCallbacks, +) { + instance.unwrap(); + //let it drop +} + +#[no_mangle] +pub extern fn vkEnumeratePhysicalDevices( + instance: VkInstance, + pPhysicalDeviceCount: *mut u32, + pPhysicalDevices: *mut VkPhysicalDevice, +) -> VkResult { + let adapters = instance.enumerate_adapters(); + let output = unsafe { slice::from_raw_parts_mut(pPhysicalDevices, *pPhysicalDeviceCount as _) }; + let count = cmp::min(adapters.len(), output.len()); + + for (out, adapter) in output.iter_mut().zip(adapters.into_iter()) { + *out = Handle::new(adapter); + } + + unsafe { *pPhysicalDeviceCount = count as _ }; + VkResult::VK_SUCCESS +} + extern "C" { pub fn vkGetPhysicalDeviceFeatures(physicalDevice: VkPhysicalDevice, pFeatures: