Allow Surface to reference an external window object (#848)

* Allow Surface to reference an external window object

This makes the Surface struct generic across a Window
type, so that a surface can own (or reference, if W is
an Arc) an external window object.

This also updates vulkano-win to take advantage of this.
There is no longer a dedicated Window struct in vulkano-win.
Instead, the Surface is simply passed ownership of the
winit::Window.

This fixes #844

* Update examples for new surface API

* Update Changelog

* Remove unnecessary send/sync bounds

* Update swapchain docs for new Surface behavior
This commit is contained in:
Branan Riley 2018-02-13 05:29:36 -08:00 committed by Pierre Krieger
parent aa6ce2f977
commit e9104208c4
13 changed files with 187 additions and 161 deletions

View File

@ -2,6 +2,7 @@
- Changed `ShaderInterfaceMismatchError` to be more verbose.
- Allow depth/stencil images to be used with `AutoCommandBufferBuilder::copy_image_to_buffer()`
- Allow `Surface` to own the window it references.
- Clear value validation for `AutoCommandBufferBuilder::begin_render_pass()`
- Fix occasional truncation of glslang_validator when glsl-to-spirv is rebuilt
- Fix linking against MoltenVK >= 0.19.0

View File

@ -37,12 +37,12 @@ fn main() {
println!("Using device: {} (type: {:?})", physical.name(), physical.ty());
let mut events_loop = winit::EventsLoop::new();
let window = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let mut dimensions;
let queue = physical.queue_families().find(|&q| q.supports_graphics() &&
window.surface().is_supported(q).unwrap_or(false))
surface.is_supported(q).unwrap_or(false))
.expect("couldn't find a graphical queue family");
let device_ext = vulkano::device::DeviceExtensions {
@ -55,14 +55,14 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, mut images) = {
let caps = window.surface().capabilities(physical).expect("failed to get surface capabilities");
let caps = surface.capabilities(physical).expect("failed to get surface capabilities");
dimensions = caps.current_extent.unwrap_or([1024, 768]);
let usage = caps.supported_usage_flags;
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
vulkano::swapchain::Swapchain::new(device.clone(), window.surface().clone(), caps.min_image_count,
vulkano::swapchain::Swapchain::new(device.clone(), surface.clone(), caps.min_image_count,
format, dimensions, 1,
usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
alpha,
@ -149,7 +149,7 @@ fn main() {
previous_frame_end.cleanup_finished();
if recreate_swapchain {
dimensions = window.surface().capabilities(physical)
dimensions = surface.capabilities(physical)
.expect("failed to get surface capabilities")
.current_extent.unwrap_or([1024, 768]);

View File

@ -73,7 +73,7 @@ fn main() {
.next()
.expect("no graphics device");
let mut events_loop = winit::EventsLoop::new();
let window = winit::WindowBuilder::new()
let surface = winit::WindowBuilder::new()
.with_decorations(false)
.with_title("particle storm")
.build_vk_surface(&events_loop, instance.clone())
@ -81,7 +81,7 @@ fn main() {
let (graphics_device, mut queues) = {
let graphical_queue_family = physical
.queue_families()
.find(|&q| q.supports_graphics() && window.surface().is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.expect("couldn't find a graphic queue family");
let device_ext = DeviceExtensions {
khr_swapchain: true,
@ -97,7 +97,7 @@ fn main() {
let graphics_queue = queues.next().unwrap();
let (swapchain, images) = {
let caps = window.surface()
let caps = surface
.capabilities(graphics_device.physical_device())
.expect("failure to get surface capabilities");
let format = caps.supported_formats[0].0;
@ -107,7 +107,7 @@ fn main() {
Swapchain::new(
graphics_device.clone(),
window.surface().clone(),
surface.clone(),
caps.min_image_count,
format,
dimensions,

View File

@ -38,12 +38,12 @@ fn main() {
println!("Using device: {} (type: {:?})", physical.name(), physical.ty());
let mut events_loop = winit::EventsLoop::new();
let window = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let mut dimensions;
let queue = physical.queue_families().find(|&q| q.supports_graphics() &&
window.surface().is_supported(q).unwrap_or(false))
surface.is_supported(q).unwrap_or(false))
.expect("couldn't find a graphical queue family");
let device_ext = vulkano::device::DeviceExtensions {
@ -57,7 +57,7 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, mut images) = {
let caps = window.surface().capabilities(physical).expect("failed to get surface capabilities");
let caps = surface.capabilities(physical).expect("failed to get surface capabilities");
dimensions = caps.current_extent.unwrap_or([1024, 768]);
@ -65,7 +65,7 @@ fn main() {
let format = caps.supported_formats[0].0;
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
vulkano::swapchain::Swapchain::new(device.clone(), window.surface().clone(), caps.min_image_count, format, dimensions, 1,
vulkano::swapchain::Swapchain::new(device.clone(), surface.clone(), caps.min_image_count, format, dimensions, 1,
usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
alpha,
vulkano::swapchain::PresentMode::Fifo, true, None).expect("failed to create swapchain")
@ -143,7 +143,7 @@ fn main() {
if recreate_swapchain {
dimensions = window.surface().capabilities(physical)
dimensions = surface.capabilities(physical)
.expect("failed to get surface capabilities")
.current_extent.unwrap_or([1024, 768]);

View File

@ -102,10 +102,10 @@ fn main() {
// ever get an error about `build_vk_surface` being undefined in one of your projects, this
// probably means that you forgot to import this trait.
//
// This returns a `vulkano_win::Window` object that contains both a cross-platform winit
// This returns a `vulkano::swapchain::Surface` object that contains both a cross-platform winit
// window and a cross-platform Vulkan surface that represents the surface of the window.
let mut events_loop = winit::EventsLoop::new();
let window = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
// The next step is to choose which GPU queue will execute our draw commands.
//
@ -119,7 +119,7 @@ fn main() {
// We have to choose which queues to use early on, because we will need this info very soon.
let queue = physical.queue_families().find(|&q| {
// We take the first queue that supports drawing to our window.
q.supports_graphics() && window.surface().is_supported(q).unwrap_or(false)
q.supports_graphics() && surface.is_supported(q).unwrap_or(false)
}).expect("couldn't find a graphical queue family");
// Now initializing the device. This is probably the most important object of Vulkan.
@ -166,7 +166,7 @@ fn main() {
let (mut swapchain, mut images) = {
// Querying the capabilities of the surface. When we create the swapchain we can only
// pass values that are allowed by the capabilities.
let caps = window.surface().capabilities(physical)
let caps = surface.capabilities(physical)
.expect("failed to get surface capabilities");
dimensions = caps.current_extent.unwrap_or([1024, 768]);
@ -183,7 +183,7 @@ fn main() {
let format = caps.supported_formats[0].0;
// Please take a look at the docs for the meaning of the parameters we didn't mention.
Swapchain::new(device.clone(), window.surface().clone(), caps.min_image_count, format,
Swapchain::new(device.clone(), surface.clone(), caps.min_image_count, format,
dimensions, 1, caps.supported_usage_flags, &queue,
SurfaceTransform::Identity, alpha, PresentMode::Fifo, true,
None).expect("failed to create swapchain")
@ -337,7 +337,7 @@ void main() {
// If the swapchain needs to be recreated, recreate it
if recreate_swapchain {
// Get the new dimensions for the viewport/framebuffers.
dimensions = window.surface().capabilities(physical)
dimensions = surface.capabilities(physical)
.expect("failed to get surface capabilities")
.current_extent.unwrap();

View File

@ -55,36 +55,14 @@ pub fn required_extensions() -> InstanceExtensions {
pub trait VkSurfaceBuild {
fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc<Instance>)
-> Result<Window, CreationError>;
-> Result<Arc<Surface<winit::Window>>, CreationError>;
}
impl VkSurfaceBuild for WindowBuilder {
fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc<Instance>)
-> Result<Window, CreationError> {
-> Result<Arc<Surface<winit::Window>>, CreationError> {
let window = self.build(events_loop)?;
let surface = unsafe { winit_to_surface(instance, &window) }?;
Ok(Window {
window: window,
surface: surface,
})
}
}
pub struct Window {
window: winit::Window,
surface: Arc<Surface>,
}
impl Window {
#[inline]
pub fn window(&self) -> &winit::Window {
&self.window
}
#[inline]
pub fn surface(&self) -> &Arc<Surface> {
&self.surface
Ok(unsafe { winit_to_surface(instance, window) }?)
}
}
@ -137,46 +115,52 @@ impl From<WindowCreationError> for CreationError {
}
#[cfg(target_os = "android")]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: &winit::Window)
-> Result<Arc<Surface>, SurfaceCreationError> {
unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window)
-> Result<Arc<Surface<winit::Window>>, SurfaceCreationError> {
use winit::os::android::WindowExt;
Surface::from_anativewindow(instance, win.get_native_window())
Surface::from_anativewindow(instance, win.get_native_window(), win)
}
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: &winit::Window)
-> Result<Arc<Surface>, SurfaceCreationError> {
unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window)
-> Result<Arc<Surface<winit::Window>>, SurfaceCreationError> {
use winit::os::unix::WindowExt;
match (win.get_wayland_display(), win.get_wayland_surface()) {
(Some(display), Some(surface)) => Surface::from_wayland(instance, display, surface),
(Some(display), Some(surface)) => Surface::from_wayland(instance,
display,
surface,
win),
_ => {
// No wayland display found, check if we can use xlib.
// If not, we use xcb.
if instance.loaded_extensions().khr_xlib_surface {
Surface::from_xlib(instance,
win.get_xlib_display().unwrap(),
win.get_xlib_window().unwrap() as _)
win.get_xlib_window().unwrap() as _,
win)
} else {
Surface::from_xcb(instance,
win.get_xcb_connection().unwrap(),
win.get_xlib_window().unwrap() as _)
win.get_xlib_window().unwrap() as _,
win)
}
},
}
}
#[cfg(target_os = "windows")]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: &winit::Window)
-> Result<Arc<Surface>, SurfaceCreationError> {
unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window)
-> Result<Arc<Surface<winit::Window>>, SurfaceCreationError> {
use winit::os::windows::WindowExt;
Surface::from_hwnd(instance,
ptr::null() as *const (), // FIXME
win.get_hwnd())
win.get_hwnd(),
win)
}
#[cfg(target_os = "macos")]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: &winit::Window)
-> Result<Arc<Surface>, SurfaceCreationError> {
unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window)
-> Result<Arc<Surface<winit::Window>>, SurfaceCreationError> {
use winit::os::macos::WindowExt;
let wnd: cocoa_id = mem::transmute(win.get_nswindow());
@ -193,5 +177,5 @@ unsafe fn winit_to_surface(instance: Arc<Instance>, win: &winit::Window)
view.setLayer(mem::transmute(layer.0)); // Bombs here with out of memory
view.setWantsLayer(YES);
Surface::from_macos_moltenvk(instance, win.get_nsview() as *const ())
Surface::from_macos_moltenvk(instance, win.get_nsview() as *const (), win)
}

View File

@ -90,7 +90,7 @@ impl<'a> SubmitPresentBuilder<'a> {
/// - The swapchains and semaphores must all belong to the same device.
///
#[inline]
pub unsafe fn add_swapchain(&mut self, swapchain: &'a Swapchain, image_num: u32,
pub unsafe fn add_swapchain<W>(&mut self, swapchain: &'a Swapchain<W>, image_num: u32,
present_region: Option<&'a PresentRegion>) {
debug_assert!(image_num < swapchain.num_images());

View File

@ -41,18 +41,18 @@ use OomError;
/// the screen. Once an image has been presented, it can no longer be used unless it is acquired
/// again.
// TODO: #[derive(Debug)]
pub struct SwapchainImage {
swapchain: Arc<Swapchain>,
pub struct SwapchainImage<W> {
swapchain: Arc<Swapchain<W>>,
image_offset: usize,
view: UnsafeImageView,
}
impl SwapchainImage {
impl<W> SwapchainImage<W> {
/// Builds a `SwapchainImage` from raw components.
///
/// This is an internal method that you shouldn't call.
pub unsafe fn from_raw(swapchain: Arc<Swapchain>, id: usize)
-> Result<Arc<SwapchainImage>, OomError> {
pub unsafe fn from_raw(swapchain: Arc<Swapchain<W>>, id: usize)
-> Result<Arc<SwapchainImage<W>>, OomError> {
let image = swapchain.raw_image(id).unwrap();
let view = UnsafeImageView::raw(&image.image, ViewType::Dim2d, 0 .. 1, 0 .. 1)?;
@ -74,7 +74,7 @@ impl SwapchainImage {
/// Returns the swapchain this image belongs to.
#[inline]
pub fn swapchain(&self) -> &Arc<Swapchain> {
pub fn swapchain(&self) -> &Arc<Swapchain<W>> {
&self.swapchain
}
@ -84,7 +84,7 @@ impl SwapchainImage {
}
}
unsafe impl ImageAccess for SwapchainImage {
unsafe impl<W> ImageAccess for SwapchainImage<W> {
#[inline]
fn inner(&self) -> ImageInner {
self.my_image()
@ -131,21 +131,21 @@ unsafe impl ImageAccess for SwapchainImage {
}
}
unsafe impl ImageClearValue<<Format as FormatDesc>::ClearValue> for SwapchainImage {
unsafe impl<W> ImageClearValue<<Format as FormatDesc>::ClearValue> for SwapchainImage<W> {
#[inline]
fn decode(&self, value: <Format as FormatDesc>::ClearValue) -> Option<ClearValue> {
Some(self.swapchain.format().decode_clear_value(value))
}
}
unsafe impl<P> ImageContent<P> for SwapchainImage {
unsafe impl<P,W> ImageContent<P> for SwapchainImage<W> {
#[inline]
fn matches_format(&self) -> bool {
true // FIXME:
}
}
unsafe impl ImageViewAccess for SwapchainImage {
unsafe impl<W> ImageViewAccess for SwapchainImage<W> {
#[inline]
fn parent(&self) -> &ImageAccess {
self

View File

@ -47,8 +47,10 @@
//! Trying to use one of these functions without enabling the proper extension will result in an
//! error.
//!
//! **Note that the `Surface` object is unsafe**. It is your responsibility to keep the window
//! alive for at least as long as the surface exists.
//! **Note that the `Surface` object is potentially unsafe**. It is your responsibility to
//! keep the window alive for at least as long as the surface exists. In many cases Surface
//! may be able to do this for you, if you pass it ownership of your Window (or a
//! reference-counting container for it).
//!
//! ### Example
//!
@ -71,11 +73,17 @@
//! }
//! };
//!
//! # fn build_window() -> *const u32 { ptr::null() }
//! # use std::sync::Arc;
//! # struct Window(*const u32);
//! # impl Window {
//! # fn hwnd(&self) -> *const u32 { self.0 }
//! # }
//! #
//! # fn build_window() -> Arc<Window> { Arc::new(Window(ptr::null())) }
//! let window = build_window(); // Third-party function, not provided by vulkano
//! let _surface = unsafe {
//! let hinstance: *const () = ptr::null(); // Windows-specific object
//! Surface::from_hwnd(instance.clone(), hinstance, window).unwrap()
//! Surface::from_hwnd(instance.clone(), hinstance, window.hwnd(), Arc::clone(&window)).unwrap()
//! };
//! ```
//!
@ -129,7 +137,7 @@
//! # use vulkano::device::Device;
//! # use vulkano::swapchain::Surface;
//! # use std::cmp::{max, min};
//! # fn choose_caps(device: Arc<Device>, surface: Arc<Surface>) -> Result<(), Box<std::error::Error>> {
//! # fn choose_caps(device: Arc<Device>, surface: Arc<Surface<()>>) -> Result<(), Box<std::error::Error>> {
//! let caps = surface.capabilities(device.physical_device())?;
//!
//! // Use the current window size or some fixed resolution.
@ -157,7 +165,7 @@
//! # use vulkano::format::Format;
//! # use vulkano::swapchain::{Surface, Swapchain, SurfaceTransform, PresentMode, CompositeAlpha};
//! # fn create_swapchain(
//! # device: Arc<Device>, surface: Arc<Surface>, present_queue: Arc<Queue>,
//! # device: Arc<Device>, surface: Arc<Surface<()>>, present_queue: Arc<Queue>,
//! # buffers_count: u32, format: Format, dimensions: [u32; 2],
//! # surface_transform: SurfaceTransform, composite_alpha: CompositeAlpha, present_mode: PresentMode
//! # ) -> Result<(), Box<std::error::Error>> {
@ -248,7 +256,7 @@
//! use vulkano::sync::GpuFuture;
//!
//! // let mut swapchain = Swapchain::new(...);
//! # let mut swapchain: (::std::sync::Arc<::vulkano::swapchain::Swapchain>, _) = return;
//! # let mut swapchain: (::std::sync::Arc<::vulkano::swapchain::Swapchain<()>>, _) = return;
//! # let queue: ::std::sync::Arc<::vulkano::device::Queue> = return;
//! let mut recreate_swapchain = false;
//!

View File

@ -20,7 +20,7 @@ pub struct PresentRegion {
impl PresentRegion {
/// Returns true if this present region is compatible with swapchain.
pub fn is_compatible_with(&self, swapchain: &Swapchain) -> bool {
pub fn is_compatible_with<W>(&self, swapchain: &Swapchain<W>) -> bool {
self.rectangles
.iter()
.all(|rect| rect.is_compatible_with(swapchain))
@ -42,7 +42,7 @@ pub struct RectangleLayer {
impl RectangleLayer {
/// Returns true if this rectangle layer is compatible with swapchain.
pub fn is_compatible_with(&self, swapchain: &Swapchain) -> bool {
pub fn is_compatible_with<W>(&self, swapchain: &Swapchain<W>) -> bool {
// FIXME negative offset is not disallowed by spec, but semantically should not be possible
debug_assert!(self.offset[0] >= 0);
debug_assert!(self.offset[1] >= 0);

View File

@ -35,7 +35,8 @@ use vk;
/// Represents a surface on the screen.
///
/// Creating a `Surface` is platform-specific.
pub struct Surface {
pub struct Surface<W> {
window: W,
instance: Arc<Instance>,
surface: vk::SurfaceKHR,
@ -44,13 +45,16 @@ pub struct Surface {
has_swapchain: AtomicBool,
}
impl Surface {
impl<W> Surface<W> {
/// Creates a `Surface` given the raw handler.
///
/// Be careful when using it
///
pub unsafe fn from_raw_surface(instance: Arc<Instance>, surface: vk::SurfaceKHR) -> Surface {
pub unsafe fn from_raw_surface(instance: Arc<Instance>, surface: vk::SurfaceKHR,
win: W)
-> Surface<W> {
Surface {
window: win,
instance: instance,
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -65,7 +69,7 @@ impl Surface {
/// - Panics if `plane` doesn't support the display of `display_mode`.
///
pub fn from_display_mode(display_mode: &DisplayMode, plane: &DisplayPlane)
-> Result<Arc<Surface>, SurfaceCreationError> {
-> Result<Arc<Surface<()>>, SurfaceCreationError> {
if !display_mode
.display()
.physical_device()
@ -110,6 +114,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: (),
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -123,9 +128,11 @@ impl Surface {
/// # Safety
///
/// The caller must ensure that the `hinstance` and the `hwnd` are both correct and stay
/// alive for the entire lifetime of the surface.
pub unsafe fn from_hwnd<T, U>(instance: Arc<Instance>, hinstance: *const T, hwnd: *const U)
-> Result<Arc<Surface>, SurfaceCreationError> {
/// alive for the entire lifetime of the surface. The `win` parameter can be used to ensure this.
pub unsafe fn from_hwnd<T, U>(instance: Arc<Instance>, hinstance: *const T, hwnd: *const U,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().khr_win32_surface {
@ -150,6 +157,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -163,9 +171,10 @@ impl Surface {
/// # Safety
///
/// The caller must ensure that the `connection` and the `window` are both correct and stay
/// alive for the entire lifetime of the surface.
pub unsafe fn from_xcb<C>(instance: Arc<Instance>, connection: *const C, window: u32)
-> Result<Arc<Surface>, SurfaceCreationError> {
/// alive for the entire lifetime of the surface. The `win` parameter can be used to ensure this.
pub unsafe fn from_xcb<C>(instance: Arc<Instance>, connection: *const C, window: u32,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().khr_xcb_surface {
@ -190,6 +199,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -203,9 +213,10 @@ impl Surface {
/// # Safety
///
/// The caller must ensure that the `display` and the `window` are both correct and stay
/// alive for the entire lifetime of the surface.
pub unsafe fn from_xlib<D>(instance: Arc<Instance>, display: *const D, window: c_ulong)
-> Result<Arc<Surface>, SurfaceCreationError> {
/// alive for the entire lifetime of the surface. The `win` parameter can be used to ensure this.
pub unsafe fn from_xlib<D>(instance: Arc<Instance>, display: *const D, window: c_ulong,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().khr_xlib_surface {
@ -230,6 +241,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -243,10 +255,11 @@ impl Surface {
/// # Safety
///
/// The caller must ensure that the `display` and the `surface` are both correct and stay
/// alive for the entire lifetime of the surface.
/// alive for the entire lifetime of the surface. The `win` parameter can be used to ensure this.
pub unsafe fn from_wayland<D, S>(instance: Arc<Instance>, display: *const D,
surface: *const S)
-> Result<Arc<Surface>, SurfaceCreationError> {
surface: *const S,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().khr_wayland_surface {
@ -271,6 +284,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -285,9 +299,11 @@ impl Surface {
/// # Safety
///
/// The caller must ensure that the `connection` and the `surface` are both correct and stay
/// alive for the entire lifetime of the surface.
pub unsafe fn from_mir<C, S>(instance: Arc<Instance>, connection: *const C, surface: *const S)
-> Result<Arc<Surface>, SurfaceCreationError> {
/// alive for the entire lifetime of the surface. The `win` parameter can be used to ensure this.
pub unsafe fn from_mir<C, S>(instance: Arc<Instance>, connection: *const C,
surface: *const S,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().khr_mir_surface {
@ -312,6 +328,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -323,9 +340,10 @@ impl Surface {
/// # Safety
///
/// The caller must ensure that the `window` is correct and stays alive for the entire
/// lifetime of the surface.
pub unsafe fn from_anativewindow<T>(instance: Arc<Instance>, window: *const T)
-> Result<Arc<Surface>, SurfaceCreationError> {
/// lifetime of the surface. The `win` parameter can be used to ensure this.
pub unsafe fn from_anativewindow<T>(instance: Arc<Instance>, window: *const T,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().khr_android_surface {
@ -349,6 +367,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -360,10 +379,11 @@ impl Surface {
/// # Safety
///
/// - The caller must ensure that the `view` is correct and stays alive for the entire
/// lifetime of the surface.
/// lifetime of the surface. The win parameter can be used to ensure this.
/// - The `UIView` must be backed by a `CALayer` instance of type `CAMetalLayer`.
pub unsafe fn from_ios_moltenvk<T>(instance: Arc<Instance>, view: *const T)
-> Result<Arc<Surface>, SurfaceCreationError> {
pub unsafe fn from_ios_moltenvk<T>(instance: Arc<Instance>, view: *const T,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().mvk_ios_surface {
@ -387,6 +407,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -398,10 +419,11 @@ impl Surface {
/// # Safety
///
/// - The caller must ensure that the `view` is correct and stays alive for the entire
/// lifetime of the surface.
/// lifetime of the surface. The `win` parameter can be used to ensure this.
/// - The `NSView` must be backed by a `CALayer` instance of type `CAMetalLayer`.
pub unsafe fn from_macos_moltenvk<T>(instance: Arc<Instance>, view: *const T)
-> Result<Arc<Surface>, SurfaceCreationError> {
pub unsafe fn from_macos_moltenvk<T>(instance: Arc<Instance>, view: *const T,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().mvk_macos_surface {
@ -425,6 +447,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -436,9 +459,10 @@ impl Surface {
/// # Safety
///
/// The caller must ensure that the `window` is correct and stays alive for the entire
/// lifetime of the surface.
pub unsafe fn from_vi_surface<T>(instance: Arc<Instance>, window: *const T)
-> Result<Arc<Surface>, SurfaceCreationError> {
/// lifetime of the surface. The `win` parameter can be used to ensure this.
pub unsafe fn from_vi_surface<T>(instance: Arc<Instance>, window: *const T,
win: W)
-> Result<Arc<Surface<W>>, SurfaceCreationError> {
let vk = instance.pointers();
if !instance.loaded_extensions().nn_vi_surface {
@ -462,6 +486,7 @@ impl Surface {
};
Ok(Arc::new(Surface {
window: win,
instance: instance.clone(),
surface: surface,
has_swapchain: AtomicBool::new(false),
@ -574,6 +599,12 @@ impl Surface {
}
}
#[inline]
pub fn window(&self) -> &W {
&self.window
}
/// Returns the instance this surface was created with.
#[inline]
pub fn instance(&self) -> &Arc<Instance> {
@ -581,14 +612,14 @@ impl Surface {
}
}
unsafe impl SurfaceSwapchainLock for Surface {
unsafe impl <W> SurfaceSwapchainLock for Surface<W> {
#[inline]
fn flag(&self) -> &AtomicBool {
&self.has_swapchain
}
}
unsafe impl VulkanObject for Surface {
unsafe impl <W> VulkanObject for Surface<W> {
type Object = vk::SurfaceKHR;
const TYPE: vk::DebugReportObjectTypeEXT = vk::DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT;
@ -599,14 +630,14 @@ unsafe impl VulkanObject for Surface {
}
}
impl fmt::Debug for Surface {
impl <W> fmt::Debug for Surface<W> {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "<Vulkan surface {:?}>", self.surface)
}
}
impl Drop for Surface {
impl <W> Drop for Surface<W> {
#[inline]
fn drop(&mut self) {
unsafe {
@ -737,7 +768,7 @@ mod tests {
#[test]
fn khr_win32_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_hwnd(instance, ptr::null::<u8>(), ptr::null::<u8>()) } {
match unsafe { Surface::from_hwnd(instance, ptr::null::<u8>(), ptr::null::<u8>(), ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
@ -746,7 +777,7 @@ mod tests {
#[test]
fn khr_xcb_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_xcb(instance, ptr::null::<u8>(), 0) } {
match unsafe { Surface::from_xcb(instance, ptr::null::<u8>(), 0, ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
@ -755,7 +786,7 @@ mod tests {
#[test]
fn khr_xlib_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_xlib(instance, ptr::null::<u8>(), 0) } {
match unsafe { Surface::from_xlib(instance, ptr::null::<u8>(), 0, ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
@ -764,7 +795,9 @@ mod tests {
#[test]
fn khr_wayland_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_wayland(instance, ptr::null::<u8>(), ptr::null::<u8>()) } {
match unsafe {
Surface::from_wayland(instance, ptr::null::<u8>(), ptr::null::<u8>(), ())
} {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
@ -773,7 +806,7 @@ mod tests {
#[test]
fn khr_mir_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_mir(instance, ptr::null::<u8>(), ptr::null::<u8>()) } {
match unsafe { Surface::from_mir(instance, ptr::null::<u8>(), ptr::null::<u8>(), ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
@ -782,7 +815,7 @@ mod tests {
#[test]
fn khr_android_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_anativewindow(instance, ptr::null::<u8>()) } {
match unsafe { Surface::from_anativewindow(instance, ptr::null::<u8>(), ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}

View File

@ -66,8 +66,8 @@ use vk;
///
/// If you try to draw on an image without acquiring it first, the execution will block. (TODO
/// behavior may change).
pub fn acquire_next_image(swapchain: Arc<Swapchain>, timeout: Option<Duration>)
-> Result<(usize, SwapchainAcquireFuture), AcquireError> {
pub fn acquire_next_image<W>(swapchain: Arc<Swapchain<W>>, timeout: Option<Duration>)
-> Result<(usize, SwapchainAcquireFuture<W>), AcquireError> {
let semaphore = Semaphore::from_pool(swapchain.device.clone())?;
let fence = Fence::from_pool(swapchain.device.clone())?;
@ -101,8 +101,8 @@ pub fn acquire_next_image(swapchain: Arc<Swapchain>, timeout: Option<Duration>)
///
/// The actual behavior depends on the present mode that you passed when creating the
/// swapchain.
pub fn present<F>(swapchain: Arc<Swapchain>, before: F, queue: Arc<Queue>, index: usize)
-> PresentFuture<F>
pub fn present<F, W>(swapchain: Arc<Swapchain<W>>, before: F, queue: Arc<Queue>, index: usize)
-> PresentFuture<F,W>
where F: GpuFuture
{
assert!(index < swapchain.images.len());
@ -131,9 +131,9 @@ pub fn present<F>(swapchain: Arc<Swapchain>, before: F, queue: Arc<Queue>, index
/// This is just an optimizaion hint, as the vulkan driver is free to ignore the given present region.
///
/// If `VK_KHR_incremental_present` is not enabled on the device, the parameter will be ignored.
pub fn present_incremental<F>(swapchain: Arc<Swapchain>, before: F, queue: Arc<Queue>,
pub fn present_incremental<F, W>(swapchain: Arc<Swapchain<W>>, before: F, queue: Arc<Queue>,
index: usize, present_region: PresentRegion)
-> PresentFuture<F>
-> PresentFuture<F, W>
where F: GpuFuture
{
assert!(index < swapchain.images.len());
@ -157,11 +157,11 @@ pub fn present_incremental<F>(swapchain: Arc<Swapchain>, before: F, queue: Arc<Q
}
/// Contains the swapping system and the images that can be shown on a surface.
pub struct Swapchain {
pub struct Swapchain<W> {
// The Vulkan device this swapchain was created with.
device: Arc<Device>,
// The surface, which we need to keep alive.
surface: Arc<Surface>,
surface: Arc<Surface<W>>,
// The swapchain object.
swapchain: vk::SwapchainKHR,
@ -196,7 +196,7 @@ struct ImageEntry {
undefined_layout: AtomicBool,
}
impl Swapchain {
impl <W> Swapchain<W> {
/// Builds a new swapchain. Allocates images who content can be made visible on a surface.
///
/// See also the `Surface::get_capabilities` function which returns the values that are
@ -222,11 +222,11 @@ impl Swapchain {
// TODO: isn't it unsafe to take the surface through an Arc when it comes to vulkano-win?
#[inline]
pub fn new<F, S>(
device: Arc<Device>, surface: Arc<Surface>, num_images: u32, format: F,
device: Arc<Device>, surface: Arc<Surface<W>>, num_images: u32, format: F,
dimensions: [u32; 2], layers: u32, usage: ImageUsage, sharing: S,
transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode, clipped: bool,
old_swapchain: Option<&Arc<Swapchain>>)
-> Result<(Arc<Swapchain>, Vec<Arc<SwapchainImage>>), SwapchainCreationError>
old_swapchain: Option<&Arc<Swapchain<W>>>)
-> Result<(Arc<Swapchain<W>>, Vec<Arc<SwapchainImage<W>>>), SwapchainCreationError>
where F: FormatDesc,
S: Into<SharingMode>
{
@ -249,7 +249,7 @@ impl Swapchain {
/// Recreates the swapchain with new dimensions.
pub fn recreate_with_dimension(
&self, dimensions: [u32; 2])
-> Result<(Arc<Swapchain>, Vec<Arc<SwapchainImage>>), SwapchainCreationError> {
-> Result<(Arc<Swapchain<W>>, Vec<Arc<SwapchainImage<W>>>), SwapchainCreationError> {
Swapchain::new_inner(self.device.clone(),
self.surface.clone(),
self.num_images,
@ -266,11 +266,11 @@ impl Swapchain {
Some(self))
}
fn new_inner(device: Arc<Device>, surface: Arc<Surface>, num_images: u32, format: Format,
fn new_inner(device: Arc<Device>, surface: Arc<Surface<W>>, num_images: u32, format: Format,
color_space: ColorSpace, dimensions: [u32; 2], layers: u32, usage: ImageUsage,
sharing: SharingMode, transform: SurfaceTransform, alpha: CompositeAlpha,
mode: PresentMode, clipped: bool, old_swapchain: Option<&Swapchain>)
-> Result<(Arc<Swapchain>, Vec<Arc<SwapchainImage>>), SwapchainCreationError> {
mode: PresentMode, clipped: bool, old_swapchain: Option<&Swapchain<W>>)
-> Result<(Arc<Swapchain<W>>, Vec<Arc<SwapchainImage<W>>>), SwapchainCreationError> {
assert_eq!(device.instance().internal_object(),
surface.instance().internal_object());
@ -557,7 +557,7 @@ impl Swapchain {
}
}
unsafe impl VulkanObject for Swapchain {
unsafe impl<W> VulkanObject for Swapchain<W> {
type Object = vk::SwapchainKHR;
const TYPE: vk::DebugReportObjectTypeEXT = vk::DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT;
@ -568,20 +568,20 @@ unsafe impl VulkanObject for Swapchain {
}
}
unsafe impl DeviceOwned for Swapchain {
unsafe impl<W> DeviceOwned for Swapchain<W> {
fn device(&self) -> &Arc<Device> {
&self.device
}
}
impl fmt::Debug for Swapchain {
impl<W> fmt::Debug for Swapchain<W> {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "<Vulkan swapchain {:?}>", self.swapchain)
}
}
impl Drop for Swapchain {
impl<W> Drop for Swapchain<W> {
#[inline]
fn drop(&mut self) {
unsafe {
@ -748,8 +748,8 @@ impl From<CapabilitiesError> for SwapchainCreationError {
/// Represents the moment when the GPU will have access to a swapchain image.
#[must_use]
pub struct SwapchainAcquireFuture {
swapchain: Arc<Swapchain>,
pub struct SwapchainAcquireFuture<W> {
swapchain: Arc<Swapchain<W>>,
image_id: usize,
// Semaphore that is signalled when the acquire is complete. Empty if the acquire has already
// happened.
@ -760,7 +760,7 @@ pub struct SwapchainAcquireFuture {
finished: AtomicBool,
}
impl SwapchainAcquireFuture {
impl<W> SwapchainAcquireFuture<W> {
/// Returns the index of the image in the list of images returned when creating the swapchain.
#[inline]
pub fn image_id(&self) -> usize {
@ -769,12 +769,12 @@ impl SwapchainAcquireFuture {
/// Returns the corresponding swapchain.
#[inline]
pub fn swapchain(&self) -> &Arc<Swapchain> {
pub fn swapchain(&self) -> &Arc<Swapchain<W>> {
&self.swapchain
}
}
unsafe impl GpuFuture for SwapchainAcquireFuture {
unsafe impl<W> GpuFuture for SwapchainAcquireFuture<W> {
#[inline]
fn cleanup_finished(&mut self) {
}
@ -845,14 +845,14 @@ unsafe impl GpuFuture for SwapchainAcquireFuture {
}
}
unsafe impl DeviceOwned for SwapchainAcquireFuture {
unsafe impl<W> DeviceOwned for SwapchainAcquireFuture<W> {
#[inline]
fn device(&self) -> &Arc<Device> {
&self.swapchain.device
}
}
impl Drop for SwapchainAcquireFuture {
impl<W> Drop for SwapchainAcquireFuture<W> {
fn drop(&mut self) {
if !*self.finished.get_mut() {
if let Some(ref fence) = self.fence {
@ -950,12 +950,12 @@ impl From<Error> for AcquireError {
/// Represents a swapchain image being presented on the screen.
#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"]
pub struct PresentFuture<P>
pub struct PresentFuture<P, W>
where P: GpuFuture
{
previous: P,
queue: Arc<Queue>,
swapchain: Arc<Swapchain>,
swapchain: Arc<Swapchain<W>>,
image_id: usize,
present_region: Option<PresentRegion>,
// True if `flush()` has been called on the future, which means that the present command has
@ -966,7 +966,7 @@ pub struct PresentFuture<P>
finished: AtomicBool,
}
impl<P> PresentFuture<P>
impl<P, W> PresentFuture<P, W>
where P: GpuFuture
{
/// Returns the index of the image in the list of images returned when creating the swapchain.
@ -977,12 +977,12 @@ impl<P> PresentFuture<P>
/// Returns the corresponding swapchain.
#[inline]
pub fn swapchain(&self) -> &Arc<Swapchain> {
pub fn swapchain(&self) -> &Arc<Swapchain<W>> {
&self.swapchain
}
}
unsafe impl<P> GpuFuture for PresentFuture<P>
unsafe impl<P, W> GpuFuture for PresentFuture<P, W>
where P: GpuFuture
{
#[inline]
@ -1113,7 +1113,7 @@ unsafe impl<P> GpuFuture for PresentFuture<P>
}
}
unsafe impl<P> DeviceOwned for PresentFuture<P>
unsafe impl<P, W> DeviceOwned for PresentFuture<P, W>
where P: GpuFuture
{
#[inline]
@ -1122,7 +1122,7 @@ unsafe impl<P> DeviceOwned for PresentFuture<P>
}
}
impl<P> Drop for PresentFuture<P>
impl<P, W> Drop for PresentFuture<P, W>
where P: GpuFuture
{
fn drop(&mut self) {
@ -1156,7 +1156,7 @@ pub struct AcquiredImage {
/// - The semaphore and/or the fence must be kept alive until it is signaled.
/// - The swapchain must not have been replaced by being passed as the old swapchain when creating
/// a new one.
pub unsafe fn acquire_next_image_raw(swapchain: &Swapchain, timeout: Option<Duration>,
pub unsafe fn acquire_next_image_raw<W>(swapchain: &Swapchain<W>, timeout: Option<Duration>,
semaphore: Option<&Semaphore>, fence: Option<&Fence>)
-> Result<AcquiredImage, AcquireError> {
let vk = swapchain.device.pointers();

View File

@ -236,9 +236,9 @@ pub unsafe trait GpuFuture: DeviceOwned {
///
/// > **Note**: This is just a shortcut for the `Swapchain::present()` function.
#[inline]
fn then_swapchain_present(self, queue: Arc<Queue>, swapchain: Arc<Swapchain>,
fn then_swapchain_present<W>(self, queue: Arc<Queue>, swapchain: Arc<Swapchain<W>>,
image_index: usize)
-> PresentFuture<Self>
-> PresentFuture<Self,W>
where Self: Sized
{
swapchain::present(swapchain, self, queue, image_index)
@ -248,9 +248,9 @@ pub unsafe trait GpuFuture: DeviceOwned {
///
/// > **Note**: This is just a shortcut for the `Swapchain::present_incremental()` function.
#[inline]
fn then_swapchain_present_incremental(self, queue: Arc<Queue>, swapchain: Arc<Swapchain>,
fn then_swapchain_present_incremental<W>(self, queue: Arc<Queue>, swapchain: Arc<Swapchain<W>>,
image_index: usize, present_region: PresentRegion)
-> PresentFuture<Self>
-> PresentFuture<Self,W>
where Self: Sized
{
swapchain::present_incremental(swapchain, self, queue, image_index, present_region)