diff --git a/examples/src/bin/texture.rs b/examples/src/bin/texture.rs index 81a6a86..22ee781 100644 --- a/examples/src/bin/texture.rs +++ b/examples/src/bin/texture.rs @@ -22,7 +22,7 @@ struct Vertex { fn main() { unsafe { - let base: ExampleBase = ExampleBase::new(1920, 1080); + let base = ExampleBase::new(1920, 1080); let renderpass_attachments = [vk::AttachmentDescription { format: base.surface_format.format, diff --git a/examples/src/lib.rs b/examples/src/lib.rs index 6dc0de6..6d37596 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -9,15 +9,15 @@ extern crate winapi; use ash::vk; use std::default::Default; -use ash::entry::Entry; -use ash::instance::Instance; +use ash::Entry; +use ash::Instance; +use ash::Device; +pub use ash::version::{FunctionPointers, V1_0, InstanceV1_0, DeviceV1_0}; use ash::extensions::{Swapchain, XlibSurface, Surface, DebugReport, Win32Surface}; -use ash::device::Device; use std::ptr; use std::ffi::{CStr, CString}; use std::ops::Drop; -pub use ash::instance::{V1_0, InstanceV1_0}; -pub use ash::device::DeviceV1_0; +use ash::entry::EntryExt; // Simple offset_of macro akin to C++ offsetof #[macro_export] @@ -33,7 +33,7 @@ macro_rules! offset_of{ } } -pub fn record_submit_commandbuffer, vk::CommandBuffer)>(device: &Device, +pub fn record_submit_commandbuffer(device: &D, command_buffer: vk::CommandBuffer, submit_queue: vk::Queue, wait_mask: &[vk::PipelineStageFlags], @@ -592,6 +592,7 @@ impl ExampleBase { } } } + impl Drop for ExampleBase { fn drop(&mut self) { unsafe { diff --git a/src/device.rs b/src/device.rs index 6724f43..a53f05c 100644 --- a/src/device.rs +++ b/src/device.rs @@ -4,14 +4,11 @@ use std::mem; use vk; use ::RawPtr; -use instance::{VkVersion, V1_0}; +use version::{FunctionPointers, V1_0, DeviceFpV1_0}; // unsafe impl Sync for Device {} // unsafe impl Send for Device {} -pub struct DeviceFpV1_0 { - pub device_fn: vk::DeviceFnV1_0, -} pub trait DeviceV1_0 { fn handle(&self) -> vk::Device; @@ -751,7 +748,7 @@ pub trait DeviceV1_0 { } #[derive(Clone)] -pub struct Device { +pub struct Device { handle: vk::Device, device_fn: V::DeviceFp, } @@ -766,7 +763,7 @@ impl DeviceV1_0 for Device { } } -impl Device { +impl Device { pub fn handle(&self) -> vk::Device { self.handle } diff --git a/src/entry.rs b/src/entry.rs index ea0234e..e07ecd3 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -2,12 +2,12 @@ use prelude::*; use std::mem; use std::ptr; use vk; -use instance::{Instance, V1_0, InstanceFpV1_0}; +use instance::Instance; use shared_library::dynamic_library::DynamicLibrary; use std::path::Path; use ::RawPtr; use std::marker::PhantomData; -use instance::VkVersion; +use version::{FunctionPointers, V1_0, InstanceFpV1_0, InstanceLoader}; #[cfg(windows)] fn get_path() -> &'static Path { @@ -29,11 +29,10 @@ lazy_static!{ } #[derive(Clone)] -pub struct Entry { +pub struct Entry { static_fn: vk::StaticFn, entry_fn: vk::EntryFn, - _v: PhantomData - + _v: PhantomData, } #[derive(Debug)] @@ -48,12 +47,39 @@ pub enum InstanceError { LoadError(Vec<&'static str>), VkError(vk::Result), } - -impl Entry{ +pub trait EntryExt { + fn load_vulkan() -> Result, LoadingError> { + let static_fn = match *VK_LIB { + Ok(ref lib) => { + let static_fn = vk::StaticFn::load(|name| unsafe { + let name = name.to_str().unwrap(); + let f = match lib.symbol(name) { + Ok(s) => s, + Err(_) => ptr::null(), + }; + f + }).map_err(|err| LoadingError::StaticLoadError(err))?; + Ok(static_fn) + } + Err(ref err) => Err(LoadingError::LibraryLoadError(err.clone())), + }?; + let entry_fn = vk::EntryFn::load(|name| unsafe { + mem::transmute(static_fn.get_instance_proc_addr(vk::Instance::null(), name.as_ptr())) + }).map_err(|err| LoadingError::EntryLoadError(err))?; + Ok(Entry { + static_fn: static_fn, + entry_fn: entry_fn, + _v: PhantomData, + }) + } +} +impl EntryExt for Entry {} +impl Entry {} +impl Entry { pub fn create_instance(&self, create_info: &vk::InstanceCreateInfo, allocation_callbacks: Option<&vk::AllocationCallbacks>) - -> Result, InstanceError> { + -> Result, InstanceError> { unsafe { let mut instance: vk::Instance = mem::uninitialized(); let err_code = self.entry_fn.create_instance(create_info, @@ -62,14 +88,10 @@ impl Entry{ if err_code != vk::Result::Success { return Err(InstanceError::VkError(err_code)); } - let instance_fn = vk::InstanceFnV1_0::load(|name| { - mem::transmute(self.static_fn.get_instance_proc_addr(instance, name.as_ptr())) - }).map_err(|err| InstanceError::LoadError(err))?; - Ok(Instance::from_raw(instance, InstanceFpV1_0 { instance_fn: instance_fn })) + let instance_fp = V::InstanceFp::load(&self.static_fn, instance).map_err(|err| InstanceError::LoadError(err))?; + Ok(Instance::from_raw(instance, instance_fp)) } } -} -impl Entry { pub fn load_vulkan() -> Result, LoadingError> { let static_fn = match *VK_LIB { Ok(ref lib) => { @@ -91,7 +113,7 @@ impl Entry { Ok(Entry { static_fn: static_fn, entry_fn: entry_fn, - _v: PhantomData + _v: PhantomData, }) } diff --git a/src/extensions/debug_report.rs b/src/extensions/debug_report.rs index 95e6c54..6a39949 100644 --- a/src/extensions/debug_report.rs +++ b/src/extensions/debug_report.rs @@ -5,7 +5,7 @@ use entry::Entry; use vk; use std::ffi::CStr; use ::RawPtr; -use instance::{V1_0, InstanceV1_0}; +use version::{V1_0, InstanceFpV1_0}; #[derive(Clone)] pub struct DebugReport { diff --git a/src/extensions/surface.rs b/src/extensions/surface.rs index 8642898..ba8d2e1 100644 --- a/src/extensions/surface.rs +++ b/src/extensions/surface.rs @@ -7,7 +7,7 @@ use entry::Entry; use vk; use std::ffi::CStr; use ::RawPtr; -use instance::{V1_0, InstanceV1_0}; +use version::{V1_0}; #[derive(Clone)] pub struct Surface { diff --git a/src/extensions/swapchain.rs b/src/extensions/swapchain.rs index dc182e1..cfc3c84 100644 --- a/src/extensions/swapchain.rs +++ b/src/extensions/swapchain.rs @@ -6,7 +6,8 @@ use device::Device; use vk; use std::ffi::CStr; use ::RawPtr; -use instance::{V1_0, InstanceV1_0}; +use instance::InstanceV1_0; +use version::{V1_0}; #[derive(Clone)] pub struct Swapchain { diff --git a/src/extensions/win32_surface.rs b/src/extensions/win32_surface.rs index f232599..cd58bd9 100644 --- a/src/extensions/win32_surface.rs +++ b/src/extensions/win32_surface.rs @@ -6,7 +6,8 @@ use entry::Entry; use vk; use std::ffi::CStr; use ::RawPtr; -use instance::{V1_0, InstanceV1_0}; +use instance::InstanceV1_0; +use version::{V1_0}; #[derive(Clone)] pub struct Win32Surface { diff --git a/src/extensions/xlib_surface.rs b/src/extensions/xlib_surface.rs index 4615db1..c1e84c6 100644 --- a/src/extensions/xlib_surface.rs +++ b/src/extensions/xlib_surface.rs @@ -6,7 +6,8 @@ use entry::Entry; use vk; use std::ffi::CStr; use ::RawPtr; -use instance::{V1_0, InstanceV1_0}; +use instance::InstanceV1_0; +use version::{V1_0}; #[derive(Clone)] pub struct XlibSurface { @@ -15,7 +16,9 @@ pub struct XlibSurface { } impl XlibSurface { - pub fn new(entry: &Entry, instance: &Instance) -> Result> { + pub fn new(entry: &Entry, + instance: &Instance) + -> Result> { let surface_fn = vk::XlibSurfaceFn::load(|name| { unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) diff --git a/src/instance.rs b/src/instance.rs index ff8db39..eadcb67 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -3,8 +3,11 @@ use prelude::*; use std::ptr; use std::mem; use vk; -use device::{Device, DeviceFpV1_0}; +use device::Device; use ::RawPtr; +use version::{FunctionPointers, V1_0, InstanceFpV1_0, DeviceFpV1_0}; +use version::{InstanceLoader, DeviceLoader}; + #[derive(Debug)] pub enum DeviceError { @@ -12,25 +15,9 @@ pub enum DeviceError { VkError(vk::Result), } -pub trait VkVersion { - type InstanceFp; - type DeviceFp; -} - -#[warn(non_camel_case_types)] -pub struct V1_0; -impl VkVersion for V1_0 { - type InstanceFp = InstanceFpV1_0; - type DeviceFp = DeviceFpV1_0; -} - -#[warn(non_camel_case_types)] -pub struct InstanceFpV1_0 { - pub instance_fn: vk::InstanceFnV1_0, -} #[derive(Clone)] -pub struct Instance { +pub struct Instance { handle: vk::Instance, instance_fp: V::InstanceFp, } @@ -44,7 +31,7 @@ impl InstanceV1_0 for Instance { &self.instance_fp.instance_fn } } -impl Instance { +impl Instance { pub fn handle(&self) -> vk::Instance { self.handle } @@ -57,14 +44,15 @@ impl Instance { } } -impl Instance { +impl Instance { pub unsafe fn create_device(&self, physical_device: vk::PhysicalDevice, create_info: &vk::DeviceCreateInfo, allocation_callbacks: Option<&vk::AllocationCallbacks>) - -> Result, DeviceError> { + -> Result, DeviceError> { let mut device: vk::Device = mem::uninitialized(); - let err_code = self.fp_v1_0() + let err_code = self.instance_fp + .fp_v1_0() .create_device(physical_device, create_info, allocation_callbacks.as_raw_ptr(), @@ -72,10 +60,8 @@ impl Instance { if err_code != vk::Result::Success { return Err(DeviceError::VkError(err_code)); } - let device_fn = vk::DeviceFnV1_0::load(|name| { - mem::transmute(self.fp_v1_0().get_device_proc_addr(device, name.as_ptr())) - }).map_err(|err| DeviceError::LoadError(err))?; - Ok(Device::from_raw(device, DeviceFpV1_0 { device_fn: device_fn })) + let device_fn = V::DeviceFp::load(self.instance_fp.fp_v1_0(), device).map_err(|err| DeviceError::LoadError(err))?; + Ok(Device::from_raw(device, device_fn)) } } diff --git a/src/lib.rs b/src/lib.rs index f05b512..43e295f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,18 @@ extern crate shared_library; #[macro_use] extern crate lazy_static; -pub mod instance; -pub mod device; +pub use instance::Instance; +pub use device::Device; +pub use entry::Entry; + +mod instance; +mod device; pub mod entry; pub mod prelude; pub mod vk; pub mod allocator; pub mod extensions; +pub mod version; pub trait RawPtr{ fn as_raw_ptr(&self) -> *const T; diff --git a/src/version.rs b/src/version.rs new file mode 100644 index 0000000..fe15d8d --- /dev/null +++ b/src/version.rs @@ -0,0 +1,64 @@ +use vk; +pub use instance::InstanceV1_0; +pub use device::DeviceV1_0; +use entry::EntryExt; +use std::mem; +pub trait FunctionPointers { + type InstanceFp: InstanceLoader; + type DeviceFp: DeviceLoader; +} + +#[allow(non_camel_case_types)] +pub struct V1_0; +impl FunctionPointers for V1_0 { + type InstanceFp = InstanceFpV1_0; + type DeviceFp = DeviceFpV1_0; +} + +#[allow(non_camel_case_types)] +pub struct InstanceFpV1_0 { + pub instance_fn: vk::InstanceFnV1_0, +} + +pub trait InstanceLoader: Sized { + fn fp_v1_0(&self) -> &vk::InstanceFnV1_0; + unsafe fn load(static_fn: &vk::StaticFn, + instance: vk::Instance) + -> Result>; +} + +pub trait DeviceLoader: Sized { + unsafe fn load(instance_fn: &vk::InstanceFnV1_0, + device: vk::Device) + -> Result>; +} + +impl DeviceLoader for DeviceFpV1_0 { + unsafe fn load(instance_fn: &vk::InstanceFnV1_0, + device: vk::Device) + -> Result> { + let device_fn = vk::DeviceFnV1_0::load(|name| { + mem::transmute(instance_fn.get_device_proc_addr(device, name.as_ptr())) + })?; + Ok(DeviceFpV1_0 { device_fn: device_fn }) + } +} + +impl InstanceLoader for InstanceFpV1_0 { + fn fp_v1_0(&self) -> &vk::InstanceFnV1_0{ + &self.instance_fn + } + unsafe fn load(static_fn: &vk::StaticFn, + instance: vk::Instance) + -> Result> { + let instance_fn = vk::InstanceFnV1_0::load(|name| { + mem::transmute(static_fn.get_instance_proc_addr(instance, name.as_ptr())) + })?; + Ok(InstanceFpV1_0 { instance_fn: instance_fn }) + } +} + +#[allow(non_camel_case_types)] +pub struct DeviceFpV1_0 { + pub device_fn: vk::DeviceFnV1_0, +}