diff --git a/.travis.yml b/.travis.yml index 24098b12..171f454f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,8 +21,11 @@ addons: script: - cargo test -v --manifest-path glsl-to-spirv/Cargo.toml - cargo test -v --manifest-path vulkano-shaders/Cargo.toml - # We run the main build with `-j 1` or we have a chance to reach travis' memory limit - - cargo test --lib --no-run -j 1 -v --manifest-path vulkano/Cargo.toml # TODO: remove `--lib` when it works + # We run the projects that depend on vulkano with `-j 1` or we have a + # chance to reach travis' memory limit + - cargo test -j 1 --manifest-path vulkano-win/Cargo.toml + - cargo test --no-run -j 1 -v --manifest-path vulkano/Cargo.toml + #- cargo build -j 1 --manifest-path examples/Cargo.toml after_success: - | diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 00000000..a9d37c56 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 00000000..897a5b3a --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "examples" +version = "0.1.0" +authors = ["Pierre Krieger "] +build = "build.rs" + +[dependencies] +vulkano = { path = "../vulkano" } +vulkano-win = { path = "../vulkano-win" } +cgmath = "0.7.0" +image = "0.6.1" +winit = { git = "https://github.com/tomaka/winit" } + +[build-dependencies] +vk-sys = { path = "../vk-sys" } +vulkano-shaders = { path = "../vulkano-shaders" } diff --git a/examples/build.rs b/examples/build.rs new file mode 100644 index 00000000..37d1adfd --- /dev/null +++ b/examples/build.rs @@ -0,0 +1,13 @@ +extern crate vulkano_shaders; + +fn main() { + // building the shaders used in the examples + vulkano_shaders::build_glsl_shaders([ + ("src/bin/triangle_vs.glsl", vulkano_shaders::ShaderType::Vertex), + ("src/bin/triangle_fs.glsl", vulkano_shaders::ShaderType::Fragment), + ("src/bin/teapot_vs.glsl", vulkano_shaders::ShaderType::Vertex), + ("src/bin/teapot_fs.glsl", vulkano_shaders::ShaderType::Fragment), + ("src/bin/image_vs.glsl", vulkano_shaders::ShaderType::Vertex), + ("src/bin/image_fs.glsl", vulkano_shaders::ShaderType::Fragment), + ].iter().cloned()); +} diff --git a/vulkano/examples/image.rs b/examples/src/bin/image.rs similarity index 98% rename from vulkano/examples/image.rs rename to examples/src/bin/image.rs index aec8aded..1f1f5e0d 100644 --- a/vulkano/examples/image.rs +++ b/examples/src/bin/image.rs @@ -97,9 +97,9 @@ fn main() { } - mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/image_vs.glsl")} } + mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/image_vs.glsl")} } let vs = vs::Shader::load(&device).expect("failed to create shader module"); - mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/image_fs.glsl")} } + mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/image_fs.glsl")} } let fs = fs::Shader::load(&device).expect("failed to create shader module"); mod renderpass { diff --git a/vulkano/examples/image_fs.glsl b/examples/src/bin/image_fs.glsl similarity index 100% rename from vulkano/examples/image_fs.glsl rename to examples/src/bin/image_fs.glsl diff --git a/vulkano/examples/image_img.png b/examples/src/bin/image_img.png similarity index 100% rename from vulkano/examples/image_img.png rename to examples/src/bin/image_img.png diff --git a/vulkano/examples/image_vs.glsl b/examples/src/bin/image_vs.glsl similarity index 100% rename from vulkano/examples/image_vs.glsl rename to examples/src/bin/image_vs.glsl diff --git a/vulkano/examples/teapot.rs b/examples/src/bin/teapot.rs similarity index 93% rename from vulkano/examples/teapot.rs rename to examples/src/bin/teapot.rs index 9b3f008c..a13bbeec 100644 --- a/vulkano/examples/teapot.rs +++ b/examples/src/bin/teapot.rs @@ -7,6 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. +extern crate examples; extern crate cgmath; extern crate winit; @@ -16,9 +17,6 @@ use winit::os::windows::WindowExt; #[macro_use] extern crate vulkano; -#[path = "support/teapot.rs"] -mod teapot; - use std::ffi::OsStr; use std::os::windows::ffi::OsStrExt; use std::mem; @@ -26,8 +24,8 @@ use std::ptr; use std::sync::Arc; use std::time::Duration; -mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/teapot_vs.glsl")} } -mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/teapot_fs.glsl")} } +mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/teapot_vs.glsl")} } +mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/teapot_fs.glsl")} } fn main() { // The start of this example is exactly the same as `triangle`. You should read the @@ -84,37 +82,37 @@ fn main() { let depth_buffer = vulkano::image::attachment::AttachmentImage::transient(&device, images[0].dimensions(), vulkano::format::D16Unorm).unwrap(); let vertex_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer - ::array(&device, teapot::VERTICES.len(), + ::array(&device, examples::VERTICES.len(), &vulkano::buffer::Usage::all(), Some(queue.family())) .expect("failed to create buffer"); { let mut mapping = vertex_buffer.write(Duration::new(0, 0)).unwrap(); - for (o, i) in mapping.iter_mut().zip(teapot::VERTICES.iter()) { + for (o, i) in mapping.iter_mut().zip(examples::VERTICES.iter()) { *o = *i; } } let normals_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer - ::array(&device, teapot::NORMALS.len(), + ::array(&device, examples::NORMALS.len(), &vulkano::buffer::Usage::all(), Some(queue.family())) .expect("failed to create buffer"); { let mut mapping = normals_buffer.write(Duration::new(0, 0)).unwrap(); - for (o, i) in mapping.iter_mut().zip(teapot::NORMALS.iter()) { + for (o, i) in mapping.iter_mut().zip(examples::NORMALS.iter()) { *o = *i; } } let index_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer - ::array(&device, teapot::INDICES.len(), + ::array(&device, examples::INDICES.len(), &vulkano::buffer::Usage::all(), Some(queue.family())) .expect("failed to create buffer"); { let mut mapping = index_buffer.write(Duration::new(0, 0)).unwrap(); - for (o, i) in mapping.iter_mut().zip(teapot::INDICES.iter()) { + for (o, i) in mapping.iter_mut().zip(examples::INDICES.iter()) { *o = *i; } } diff --git a/vulkano/examples/teapot_fs.glsl b/examples/src/bin/teapot_fs.glsl similarity index 100% rename from vulkano/examples/teapot_fs.glsl rename to examples/src/bin/teapot_fs.glsl diff --git a/vulkano/examples/teapot_vs.glsl b/examples/src/bin/teapot_vs.glsl similarity index 100% rename from vulkano/examples/teapot_vs.glsl rename to examples/src/bin/teapot_vs.glsl diff --git a/vulkano/examples/triangle.rs b/examples/src/bin/triangle.rs similarity index 98% rename from vulkano/examples/triangle.rs rename to examples/src/bin/triangle.rs index bbb4abff..570ee834 100644 --- a/vulkano/examples/triangle.rs +++ b/examples/src/bin/triangle.rs @@ -146,9 +146,9 @@ fn main() { // can now use to load the shader. // // Because of some restrictions with the `include!` macro, we need to use a module. - mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/triangle_vs.glsl")} } + mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/triangle_vs.glsl")} } let vs = vs::Shader::load(&device).expect("failed to create shader module"); - mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/examples/triangle_fs.glsl")} } + mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/triangle_fs.glsl")} } let fs = fs::Shader::load(&device).expect("failed to create shader module"); // At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL diff --git a/vulkano/examples/triangle_fs.glsl b/examples/src/bin/triangle_fs.glsl similarity index 100% rename from vulkano/examples/triangle_fs.glsl rename to examples/src/bin/triangle_fs.glsl diff --git a/vulkano/examples/triangle_vs.glsl b/examples/src/bin/triangle_vs.glsl similarity index 100% rename from vulkano/examples/triangle_vs.glsl rename to examples/src/bin/triangle_vs.glsl diff --git a/vulkano/examples/support/teapot.rs b/examples/src/lib.rs similarity index 99% rename from vulkano/examples/support/teapot.rs rename to examples/src/lib.rs index 3c5a4bc6..de3c3d0f 100644 --- a/vulkano/examples/support/teapot.rs +++ b/examples/src/lib.rs @@ -7,6 +7,9 @@ // notice may not be copied, modified, or distributed except // according to those terms. +#[macro_use] +extern crate vulkano; + #[derive(Copy, Clone)] pub struct Vertex { position: (f32, f32, f32) diff --git a/vulkano-win/.gitignore b/vulkano-win/.gitignore new file mode 100644 index 00000000..a9d37c56 --- /dev/null +++ b/vulkano-win/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/vulkano-win/Cargo.toml b/vulkano-win/Cargo.toml new file mode 100644 index 00000000..c12c236f --- /dev/null +++ b/vulkano-win/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "vulkano-win" +version = "0.1.0" +authors = ["Pierre Krieger "] + +[dependencies] +vulkano = { version = "0.1", path = "../vulkano" } +winit = { git = "https://github.com/tomaka/winit" } diff --git a/vulkano-win/src/lib.rs b/vulkano-win/src/lib.rs new file mode 100644 index 00000000..0c23bd4a --- /dev/null +++ b/vulkano-win/src/lib.rs @@ -0,0 +1,135 @@ +extern crate vulkano; +extern crate winit; + +use std::error; +use std::fmt; +use std::ptr; +use std::sync::Arc; + +use vulkano::instance::Instance; +use vulkano::instance::InstanceExtensions; +use vulkano::swapchain::Surface; +use vulkano::swapchain::SurfaceCreationError; +use winit::WindowBuilder; +use winit::CreationError as WindowCreationError; + +pub fn required_instances() -> InstanceExtensions { + let ideal = InstanceExtensions { + khr_xlib_surface: true, + khr_xcb_surface: true, + khr_wayland_surface: true, + khr_mir_surface: true, + khr_android_surface: true, + khr_win32_surface: true, + .. InstanceExtensions::none() + }; + + let supported = InstanceExtensions::supported_by_core(); + supported.intersection(&ideal) +} + +pub trait VkSurfaceBuild { + fn build_vk_surface(self, instance: &Arc) -> Result; +} + +impl VkSurfaceBuild for WindowBuilder { + fn build_vk_surface(self, instance: &Arc) -> Result { + let window = try!(self.build()); + let surface = try!(unsafe { winit_to_surface(instance, &window) }); + + Ok(Window { + window: window, + surface: surface, + }) + } +} + +pub struct Window { + window: winit::Window, + surface: Arc, +} + +impl Window { + #[inline] + pub fn window(&self) -> &winit::Window { + &self.window + } + + #[inline] + pub fn surface(&self) -> &Arc { + &self.surface + } +} + +/// Error that can happen when creating a window. +#[derive(Debug)] +pub enum CreationError { + /// Error when creating the surface. + SurfaceCreationError(SurfaceCreationError), + /// Error when creating the window. + WindowCreationError(WindowCreationError), +} + +impl error::Error for CreationError { + #[inline] + fn description(&self) -> &str { + match *self { + CreationError::SurfaceCreationError(_) => "error while creating the surface", + CreationError::WindowCreationError(_) => "error while creating the window", + } + } + + #[inline] + fn cause(&self) -> Option<&error::Error> { + match *self { + CreationError::SurfaceCreationError(ref err) => Some(err), + CreationError::WindowCreationError(ref err) => Some(err), + } + } +} + +impl fmt::Display for CreationError { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(fmt, "{}", error::Error::description(self)) + } +} + +impl From for CreationError { + #[inline] + fn from(err: SurfaceCreationError) -> CreationError { + CreationError::SurfaceCreationError(err) + } +} + +impl From for CreationError { + #[inline] + fn from(err: WindowCreationError) -> CreationError { + CreationError::WindowCreationError(err) + } +} + +#[cfg(target_os = "android")] +unsafe fn winit_to_surface(instance: &Arc, win: &winit::Window) + -> Result, SurfaceCreationError> +{ + use winit::os::android::WindowExt; + Surface::from_anativewindow(instance, win.get_native_window()) +} + +#[cfg(all(unix, not(target_os = "android")))] +unsafe fn winit_to_surface(instance: &Arc, win: &winit::Window) + -> Result, SurfaceCreationError> +{ + use winit::os::unix::WindowExt; + Surface::from_xlib(instance, window.get_xlib_display().unwrap(), + window.get_xlib_window().unwrap()) +} + +#[cfg(windows)] +unsafe fn winit_to_surface(instance: &Arc, win: &winit::Window) + -> Result, SurfaceCreationError> +{ + use winit::os::windows::WindowExt; + Surface::from_hwnd(instance, ptr::null() as *const () /* FIXME */, win.get_hwnd()) +} diff --git a/vulkano/Cargo.toml b/vulkano/Cargo.toml index f6ba472a..187f0627 100644 --- a/vulkano/Cargo.toml +++ b/vulkano/Cargo.toml @@ -14,9 +14,3 @@ lazy_static = "0.1.15" [build-dependencies] vk-sys = { path = "../vk-sys" } -vulkano-shaders = { path = "../vulkano-shaders" } - -[dev-dependencies] -cgmath = "0.7.0" -image = "0.6.1" -winit = { git = "https://github.com/tomaka/winit" } diff --git a/vulkano/build.rs b/vulkano/build.rs index 495ee63d..671403cb 100644 --- a/vulkano/build.rs +++ b/vulkano/build.rs @@ -1,4 +1,3 @@ -extern crate vulkano_shaders; extern crate vk_sys; use std::env; @@ -14,14 +13,4 @@ fn main() { let mut file_output = File::create(&dest.join("vk_bindings.rs")).unwrap(); vk_sys::write_bindings(&mut file_output).unwrap(); - - // building the shaders used in the examples - vulkano_shaders::build_glsl_shaders([ - ("examples/triangle_vs.glsl", vulkano_shaders::ShaderType::Vertex), - ("examples/triangle_fs.glsl", vulkano_shaders::ShaderType::Fragment), - ("examples/teapot_vs.glsl", vulkano_shaders::ShaderType::Vertex), - ("examples/teapot_fs.glsl", vulkano_shaders::ShaderType::Fragment), - ("examples/image_vs.glsl", vulkano_shaders::ShaderType::Vertex), - ("examples/image_fs.glsl", vulkano_shaders::ShaderType::Fragment), - ].iter().cloned()); } diff --git a/vulkano/src/instance/extensions.rs b/vulkano/src/instance/extensions.rs index d63e636e..fc779b6a 100644 --- a/vulkano/src/instance/extensions.rs +++ b/vulkano/src/instance/extensions.rs @@ -41,6 +41,16 @@ macro_rules! extensions { $(if self.$ext { data.push(CString::new(&$s[..]).unwrap()); })* data } + + /// Returns the intersection of this list and another list. + #[inline] + pub fn intersection(&self, other: &$sname) -> $sname { + $sname { + $( + $ext: self.$ext && other.$ext, + )* + } + } } ); }