Add SwapchainCreateInfo, various related changes (#1832)

This commit is contained in:
Rua 2022-02-20 10:55:34 +01:00 committed by GitHub
parent 7f14f6ff7a
commit 645faa4530
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 3696 additions and 2747 deletions

View File

@ -33,7 +33,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -68,7 +70,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -101,20 +103,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
// Vertex Buffer Pool
@ -159,7 +174,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -207,11 +222,13 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};

View File

@ -18,7 +18,9 @@ use vulkano::instance::{Instance, InstanceCreateInfo};
use vulkano::pipeline::graphics::viewport::ViewportState;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -49,7 +51,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -81,20 +83,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
mod vs {
@ -133,7 +148,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -153,8 +168,8 @@ fn main() {
.build(device.clone())
.unwrap();
let mut width = swapchain.dimensions()[0];
let mut height = swapchain.dimensions()[1];
let mut width = swapchain.image_extent()[0];
let mut height = swapchain.image_extent()[1];
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone());
let mut recreate_swapchain = false;
@ -177,17 +192,18 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
width = dimensions[0];
height = dimensions[1];
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
width = swapchain.image_extent()[0];
height = swapchain.image_extent()[1];
framebuffers = window_size_dependent_setup(&new_images, render_pass.clone());
recreate_swapchain = false;
}

View File

@ -38,7 +38,7 @@ use vulkano::image::view::ImageView;
use vulkano::image::ImageUsage;
use vulkano::instance::{Instance, InstanceCreateInfo};
use vulkano::swapchain;
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
@ -72,7 +72,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -104,20 +104,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, mut images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (swapchain, images) = Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
let (swapchain, images) = Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap();
let images = images
.into_iter()
.map(|image| ImageView::new(image.clone()).unwrap())
@ -126,7 +139,7 @@ fn main() {
};
// Here is the basic initialization for the deferred system.
let mut frame_system = FrameSystem::new(queue.clone(), swapchain.format());
let mut frame_system = FrameSystem::new(queue.clone(), swapchain.image_format());
let triangle_draw_system =
TriangleDrawSystem::new(queue.clone(), frame_system.deferred_subpass());
@ -150,13 +163,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let new_images = new_images
.into_iter()
.map(|image| ImageView::new(image.clone()).unwrap())

View File

@ -35,7 +35,7 @@ use vulkano::{
},
render_pass::{Framebuffer, RenderPass, Subpass},
sampler::{Filter, Sampler, SamplerAddressMode},
swapchain::{AcquireError, Swapchain, SwapchainCreationError},
swapchain::{AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError},
sync::{now, FlushError, GpuFuture, PipelineStages, Semaphore},
};
#[cfg(target_os = "linux")]
@ -233,11 +233,13 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
@ -395,7 +397,7 @@ fn vk_setup(
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.filter(|(p, _)| p.properties().driver_uuid.unwrap() == display.driver_uuid().unwrap())
@ -433,20 +435,33 @@ fn vk_setup(
let queue = queues.next().unwrap();
let (swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
@ -480,7 +495,7 @@ fn vk_setup(
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},

View File

@ -27,7 +27,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -58,7 +60,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -90,20 +92,31 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device.surface_capabilities(&surface, Default::default()).unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[repr(C)]
@ -144,7 +157,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -304,13 +317,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -28,7 +28,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -59,7 +61,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -91,20 +93,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[repr(C)]
@ -145,7 +160,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -238,13 +253,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -37,7 +37,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -65,7 +67,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -97,20 +99,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[repr(C)]
@ -151,7 +166,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -246,13 +261,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -47,7 +47,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{ComputePipeline, GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -85,7 +87,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -118,20 +120,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
mod vs {
@ -231,7 +246,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -279,11 +294,13 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};

View File

@ -31,7 +31,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -81,7 +83,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -114,20 +116,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
// We now create a buffer that will store the shape of our triangle.
@ -229,7 +244,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -283,11 +298,13 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};

View File

@ -74,7 +74,7 @@ Usage:
Space: Toggle between Mandelbrot and Julia
Enter: Randomize color palette
Equals/Minus: Increase/Decrease max iterations
F: Toggle fullscreen
F: Toggle full-screen
Right mouse: Stop movement in Julia (mouse position determines c)
Esc: Quit\
"
@ -175,9 +175,9 @@ Usage:
if self.input_state.randomize_palette {
self.fractal_pipeline.randomize_palette();
}
// Toggle fullscreen
if self.input_state.toggle_fullscreen {
renderer.toggle_fullscreen()
// Toggle full-screen
if self.input_state.toggle_full_screen {
renderer.toggle_full_screen()
}
}
@ -211,7 +211,7 @@ struct InputState {
pub increase_iterations: bool,
pub decrease_iterations: bool,
pub randomize_palette: bool,
pub toggle_fullscreen: bool,
pub toggle_full_screen: bool,
pub toggle_julia: bool,
pub toggle_c: bool,
pub should_quit: bool,
@ -230,7 +230,7 @@ impl InputState {
increase_iterations: false,
decrease_iterations: false,
randomize_palette: false,
toggle_fullscreen: false,
toggle_full_screen: false,
toggle_julia: false,
toggle_c: false,
should_quit: false,
@ -250,7 +250,7 @@ impl InputState {
fn reset(&mut self) {
*self = InputState {
scroll_delta: 0.0,
toggle_fullscreen: false,
toggle_full_screen: false,
toggle_julia: false,
toggle_c: false,
randomize_palette: false,
@ -284,7 +284,7 @@ impl InputState {
VirtualKeyCode::A => self.pan_left = state_is_pressed(input.state),
VirtualKeyCode::S => self.pan_down = state_is_pressed(input.state),
VirtualKeyCode::D => self.pan_right = state_is_pressed(input.state),
VirtualKeyCode::F => self.toggle_fullscreen = state_is_pressed(input.state),
VirtualKeyCode::F => self.toggle_full_screen = state_is_pressed(input.state),
VirtualKeyCode::Return => self.randomize_palette = state_is_pressed(input.state),
VirtualKeyCode::Equals => self.increase_iterations = state_is_pressed(input.state),
VirtualKeyCode::Minus => self.decrease_iterations = state_is_pressed(input.state),

View File

@ -25,8 +25,7 @@ use vulkano::image::{
use vulkano::instance::InstanceExtensions;
use vulkano::instance::{Instance, InstanceCreateInfo};
use vulkano::swapchain::{
AcquireError, ColorSpace, FullscreenExclusive, PresentMode, Surface, SurfaceTransform,
Swapchain, SwapchainCreationError,
AcquireError, PresentMode, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{FlushError, GpuFuture};
use vulkano::{swapchain, sync};
@ -67,7 +66,7 @@ pub struct Renderer {
device: Arc<Device>,
surface: Arc<Surface<Window>>,
queue: Arc<Queue>,
swap_chain: Arc<Swapchain<Window>>,
swapchain: Arc<Swapchain<Window>>,
image_index: usize,
final_views: Vec<FinalImageView>,
/// Image view that is to be rendered with our pipeline.
@ -76,7 +75,7 @@ pub struct Renderer {
recreate_swapchain: bool,
previous_frame_end: Option<Box<dyn GpuFuture>>,
render_passes: RenderPasses,
is_fullscreen: bool,
is_full_screen: bool,
}
impl Renderer {
@ -120,11 +119,10 @@ impl Renderer {
// Create device
let (device, queue) = Self::create_device(physical_device, surface.clone());
// Create swap chain & frame(s) to which we'll render
let (swap_chain, final_images) = Self::create_swap_chain(
let (swapchain, final_images) = Self::create_swapchain(
surface.clone(),
physical_device,
device.clone(),
queue.clone(),
if opts.v_sync {
PresentMode::Fifo
} else {
@ -132,7 +130,7 @@ impl Renderer {
},
);
let previous_frame_end = Some(sync::now(device.clone()).boxed());
let is_fullscreen = swap_chain.surface().window().fullscreen().is_some();
let is_full_screen = swapchain.surface().window().fullscreen().is_some();
let image_format = final_images.first().unwrap().format();
let render_passes = RenderPasses {
place_over_frame: RenderPassPlaceOverFrame::new(queue.clone(), image_format),
@ -143,14 +141,14 @@ impl Renderer {
device,
surface,
queue,
swap_chain,
swapchain,
image_index: 0,
final_views: final_images,
interim_image_views: HashMap::new(),
previous_frame_end,
recreate_swapchain: false,
render_passes,
is_fullscreen,
is_full_screen,
}
}
@ -161,7 +159,7 @@ impl Renderer {
) -> (Arc<Device>, Arc<Queue>) {
let queue_family = physical_device
.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.unwrap();
// Add device extensions based on needs,
@ -191,37 +189,46 @@ impl Renderer {
}
/// Creates swapchain and swapchain images
fn create_swap_chain(
fn create_swapchain(
surface: Arc<Surface<Window>>,
physical: PhysicalDevice,
device: Arc<Device>,
queue: Arc<Queue>,
present_mode: PresentMode,
) -> (Arc<Swapchain<Window>>, Vec<FinalImageView>) {
let caps = surface.capabilities(physical).unwrap();
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (swap_chain, images) = Swapchain::start(device, surface)
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(alpha)
.transform(SurfaceTransform::Identity)
.present_mode(present_mode)
.fullscreen_exclusive(FullscreenExclusive::Default)
.clipped(true)
.color_space(ColorSpace::SrgbNonLinear)
.layers(1)
.build()
let surface_capabilities = physical
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
let image_extent = surface.window().inner_size().into();
let (swapchain, images) = Swapchain::new(
device,
surface,
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent,
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
present_mode,
..Default::default()
},
)
.unwrap();
let images = images
.into_iter()
.map(|image| ImageView::new(image).unwrap())
.collect::<Vec<_>>();
(swap_chain, images)
(swapchain, images)
}
/// Return default image format for images (swapchain format may differ)
@ -334,10 +341,10 @@ impl Renderer {
self.interim_image_views.remove(&key);
}
/// Toggles fullscreen view
pub fn toggle_fullscreen(&mut self) {
self.is_fullscreen = !self.is_fullscreen;
self.window().set_fullscreen(if self.is_fullscreen {
/// Toggles full-screen view
pub fn toggle_full_screen(&mut self) {
self.is_full_screen = !self.is_full_screen;
self.window().set_fullscreen(if self.is_full_screen {
Some(Fullscreen::Borderless(self.window().current_monitor()))
} else {
None
@ -367,7 +374,7 @@ impl Renderer {
// Acquire next image in the swapchain
let (image_num, suboptimal, acquire_future) =
match swapchain::acquire_next_image(self.swap_chain.clone(), None) {
match swapchain::acquire_next_image(self.swapchain.clone(), None) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
self.recreate_swapchain = true;
@ -388,11 +395,7 @@ impl Renderer {
/// Finishes render by presenting the swapchain
pub(crate) fn finish_frame(&mut self, after_future: Box<dyn GpuFuture>) {
let future = after_future
.then_swapchain_present(
self.queue.clone(),
self.swap_chain.clone(),
self.image_index,
)
.then_swapchain_present(self.queue.clone(), self.swapchain.clone(), self.image_index)
.then_signal_fence_and_flush();
match future {
Ok(future) => {
@ -418,21 +421,19 @@ impl Renderer {
/// Swapchain is recreated when resized. Interim image views that should follow swapchain
/// are also recreated
fn recreate_swapchain_and_views(&mut self) {
let dimensions: [u32; 2] = self.window().inner_size().into();
let (new_swapchain, new_images) =
match self.swap_chain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => {
println!(
"{}",
SwapchainCreationError::UnsupportedDimensions.to_string()
);
return;
}
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match self.swapchain.recreate(SwapchainCreateInfo {
image_extent: self.window().inner_size().into(),
..self.swapchain.create_info()
}) {
Ok(r) => r,
Err(e @ SwapchainCreationError::ImageExtentNotSupported { .. }) => {
println!("{}", e);
return;
}
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
self.swap_chain = new_swapchain;
self.swapchain = new_swapchain;
let new_images = new_images
.into_iter()
.map(|image| ImageView::new(image).unwrap())

View File

@ -30,7 +30,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{self, AcquireError, Surface, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::ElementState;
@ -67,7 +69,7 @@ fn main() {
let window_id = surface.window().id();
// Find the device and a queue.
// TODO: it is assumed the device, queue, and surface caps are the same for all windows
// TODO: it is assumed the device, queue, and surface surface_capabilities are the same for all windows
let (device, queue, surface_caps) = {
let device_extensions = DeviceExtensions {
@ -78,7 +80,9 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| {
q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false)
})
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -111,30 +115,40 @@ fn main() {
(
device,
queues.next().unwrap(),
surface.capabilities(physical_device).unwrap(),
physical_device
.surface_capabilities(&surface, Default::default())
.unwrap(),
)
};
// The swapchain and framebuffer images for this perticular window
let (swapchain, images) = {
let composite_alpha = surface_caps
.supported_composite_alpha
.iter()
.next()
.unwrap();
let format = surface_caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let image_format = Some(
device
.physical_device()
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(surface_caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_caps.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_caps
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[repr(C)]
@ -203,7 +217,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -280,18 +294,27 @@ fn main() {
.iter()
.next()
.unwrap();
let format = surface_caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let image_format = Some(
device
.physical_device()
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(surface_caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_caps.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha,
..Default::default()
},
)
.unwrap()
};
window_surfaces.insert(
@ -326,13 +349,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if *recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
*swapchain = new_swapchain;
*framebuffers =

View File

@ -24,7 +24,8 @@ use vulkano::{
Instance, InstanceCreateInfo, InstanceExtensions,
},
swapchain::{
ColorSpace, FullscreenExclusive, PresentMode, Surface, SurfaceTransform, Swapchain,
ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceTransform, Swapchain,
SwapchainCreateInfo,
},
Version,
};
@ -165,36 +166,48 @@ impl VulkanoContext {
}
/// Creates swapchain and swapchain images
pub(crate) fn create_swap_chain(
pub(crate) fn create_swapchain(
&self,
surface: Arc<Surface<Window>>,
queue: Arc<Queue>,
present_mode: PresentMode,
) -> (Arc<Swapchain<Window>>, Vec<FinalImageView>) {
let caps = surface.capabilities(self.device.physical_device()).unwrap();
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (swap_chain, images) = Swapchain::start(self.device.clone(), surface)
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(alpha)
.transform(SurfaceTransform::Identity)
.present_mode(present_mode)
.fullscreen_exclusive(FullscreenExclusive::Default)
.clipped(true)
.color_space(ColorSpace::SrgbNonLinear)
.layers(1)
.build()
let surface_capabilities = self
.device
.physical_device()
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
self.device
.physical_device()
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
let image_extent = surface.window().inner_size().into();
let (swapchain, images) = Swapchain::new(
self.device.clone(),
surface,
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent,
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
present_mode,
..Default::default()
},
)
.unwrap();
let images = images
.into_iter()
.map(|image| ImageView::new(image).unwrap())
.collect::<Vec<_>>();
(swap_chain, images)
(swapchain, images)
}
pub fn device_name(&self) -> &str {

View File

@ -9,15 +9,17 @@
use std::sync::Arc;
use vulkano::{
device::Queue,
device::{DeviceOwned, Queue},
format::Format,
image::{view::ImageView, ImageAccess, ImageViewAbstract},
swapchain,
swapchain::{AcquireError, PresentMode, Surface, Swapchain, SwapchainCreationError},
swapchain::{
AcquireError, PresentMode, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
},
sync,
sync::{FlushError, GpuFuture},
};
use vulkano_win::create_vk_surface_from_handle;
use vulkano_win::create_surface_from_handle;
use winit::window::Window;
use crate::vulkano_context::{DeviceImageView, FinalImageView, VulkanoContext};
@ -28,7 +30,7 @@ use vulkano::image::{ImageCreateFlags, ImageDimensions, ImageUsage, StorageImage
pub struct VulkanoWindow {
surface: Arc<Surface<Window>>,
graphics_queue: Arc<Queue>,
swap_chain: Arc<Swapchain<Window>>,
swapchain: Arc<Swapchain<Window>>,
final_views: Vec<FinalImageView>,
/// Image view that is to be rendered with our pipeline.
/// (bool refers to whether it should get resized with swapchain resize)
@ -51,11 +53,10 @@ impl VulkanoWindow {
vsync: bool,
) -> VulkanoWindow {
// Create rendering surface from window
let surface = create_vk_surface_from_handle(window, vulkano_context.instance()).unwrap();
let surface = create_surface_from_handle(window, vulkano_context.instance()).unwrap();
// Create swap chain & frame(s) to which we'll render
let (swap_chain, final_views) = vulkano_context.create_swap_chain(
let (swapchain, final_views) = vulkano_context.create_swapchain(
surface.clone(),
vulkano_context.graphics_queue(),
if vsync {
PresentMode::Fifo
} else {
@ -68,7 +69,7 @@ impl VulkanoWindow {
VulkanoWindow {
surface,
graphics_queue: vulkano_context.graphics_queue(),
swap_chain,
swapchain,
final_views,
image_views: HashMap::default(),
recreate_swapchain: false,
@ -186,7 +187,7 @@ impl VulkanoWindow {
// Acquire next image in the swapchain
let (image_num, suboptimal, acquire_future) =
match swapchain::acquire_next_image(self.swap_chain.clone(), None) {
match swapchain::acquire_next_image(self.swapchain.clone(), None) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
self.recreate_swapchain = true;
@ -210,7 +211,7 @@ impl VulkanoWindow {
let future = after_future
.then_swapchain_present(
self.graphics_queue.clone(),
self.swap_chain.clone(),
self.swapchain.clone(),
self.image_index,
)
.then_signal_fence_and_flush();
@ -239,21 +240,19 @@ impl VulkanoWindow {
/// Recreates swapchain images and image views that should follow swap chain image size
fn recreate_swapchain_and_views(&mut self) {
let dimensions: [u32; 2] = self.window().inner_size().into();
let (new_swapchain, new_images) =
match self.swap_chain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => {
println!(
"{}",
SwapchainCreationError::UnsupportedDimensions.to_string()
);
return;
}
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match self.swapchain.recreate(SwapchainCreateInfo {
image_extent: self.window().inner_size().into(),
..self.swapchain.create_info()
}) {
Ok(r) => r,
Err(e @ SwapchainCreationError::ImageExtentNotSupported { .. }) => {
println!("{}", e);
return;
}
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
self.swap_chain = new_swapchain;
self.swapchain = new_swapchain;
let new_images = new_images
.into_iter()
.map(|image| ImageView::new(image).unwrap())

View File

@ -27,7 +27,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::GraphicsPipeline;
use vulkano::query::{QueryControlFlags, QueryPool, QueryResultFlags, QueryType};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -55,7 +57,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -87,19 +89,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[repr(C)]
@ -225,7 +241,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
},
depth: {
@ -284,13 +300,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -28,7 +28,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -57,7 +59,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -89,20 +91,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[repr(C)]
@ -143,7 +158,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -228,13 +243,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -37,7 +37,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::shader::ShaderModule;
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -74,7 +76,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -106,20 +108,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
let render_pass = vulkano::single_pass_renderpass!(
@ -128,7 +143,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -226,13 +241,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -31,7 +31,9 @@ use vulkano::pipeline::layout::PipelineLayout;
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -62,7 +64,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -101,20 +103,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[repr(C)]
@ -205,7 +220,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -357,13 +372,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -29,7 +29,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::shader::ShaderModule;
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -60,7 +62,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -91,23 +93,35 @@ fn main() {
.unwrap();
let queue = queues.next().unwrap();
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let format = caps.supported_formats[0].0;
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
let vertices = VERTICES.iter().cloned();
@ -133,7 +147,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
},
depth: {
@ -175,11 +189,13 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
@ -204,7 +220,8 @@ fn main() {
// note: this teapot was meant for OpenGL where the origin is at the lower left
// instead the origin is at the upper left in Vulkan, so we reverse the Y axis
let aspect_ratio = dimensions[0] as f32 / dimensions[1] as f32;
let aspect_ratio =
swapchain.image_extent()[0] as f32 / swapchain.image_extent()[1] as f32;
let proj = cgmath::perspective(
Rad(std::f32::consts::FRAC_PI_2),
aspect_ratio,

View File

@ -33,7 +33,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -162,7 +164,7 @@ fn main() {
.filter(|&p| p.supported_features().is_superset_of(&features))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -195,20 +197,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[derive(Default, Debug, Clone)]
@ -267,7 +282,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -329,13 +344,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -33,7 +33,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::sampler::Sampler;
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
@ -63,7 +65,7 @@ fn main() {
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
.filter_map(|p| {
p.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.find(|&q| q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false))
.map(|q| (p, q))
})
.min_by_key(|(p, _)| match p.properties().device_type {
@ -95,20 +97,33 @@ fn main() {
let queue = queues.next().unwrap();
let (mut swapchain, images) = {
let caps = surface.capabilities(physical_device).unwrap();
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions: [u32; 2] = surface.window().inner_size().into();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
#[repr(C)]
@ -149,7 +164,7 @@ fn main() {
color: {
load: Clear,
store: Store,
format: swapchain.format(),
format: swapchain.image_format(),
samples: 1,
}
},
@ -246,13 +261,14 @@ fn main() {
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};
swapchain = new_swapchain;
framebuffers =

View File

@ -29,7 +29,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::swapchain::{
self, AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
@ -103,7 +105,7 @@ fn main() {
// We select a queue family that supports graphics operations. When drawing to
// a window surface, as we do in this example, we also need to check that queues
// in this queue family are capable of presenting images to the surface.
q.supports_graphics() && surface.is_supported(q).unwrap_or(false)
q.supports_graphics() && q.supports_surface(&surface).unwrap_or(false)
})
// The code here searches for the first queue family that is suitable. If none is
// found, `None` is returned to `filter_map`, which disqualifies this physical
@ -175,37 +177,56 @@ fn main() {
let (mut swapchain, 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 = surface.capabilities(physical_device).unwrap();
// The alpha mode indicates how the alpha value of the final image will behave. For example,
// you can choose whether the window will be opaque or transparent.
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
let surface_capabilities = physical_device
.surface_capabilities(&surface, Default::default())
.unwrap();
// Choosing the internal format that the images will have.
let format = caps.supported_formats[0].0;
// The dimensions of the window, only used to initially setup the swapchain.
// NOTE:
// On some drivers the swapchain dimensions are specified by `caps.current_extent` and the
// swapchain size must use these dimensions.
// These dimensions are always the same as the window dimensions.
//
// However, other drivers don't specify a value, i.e. `caps.current_extent` is `None`
// These drivers will allow anything, but the only sensible value is the window dimensions.
//
// Both of these cases need the swapchain to use the window dimensions, so we just use that.
let dimensions: [u32; 2] = surface.window().inner_size().into();
let image_format = Some(
physical_device
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0,
);
// Please take a look at the docs for the meaning of the parameters we didn't mention.
Swapchain::start(device.clone(), surface.clone())
.num_images(caps.min_image_count)
.format(format)
.dimensions(dimensions)
.usage(ImageUsage::color_attachment())
.sharing_mode(&queue)
.composite_alpha(composite_alpha)
.build()
.unwrap()
Swapchain::new(
device.clone(),
surface.clone(),
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count,
image_format,
// The dimensions of the window, only used to initially setup the swapchain.
// NOTE:
// On some drivers the swapchain dimensions are specified by
// `surface_capabilities.current_extent` and the swapchain size must use these
// dimensions.
// These dimensions are always the same as the window dimensions.
//
// However, other drivers don't specify a value, i.e.
// `surface_capabilities.current_extent` is `None`. These drivers will allow
// anything, but the only sensible value is the window
// dimensions.
//
// Both of these cases need the swapchain to use the window dimensions, so we just
// use that.
image_extent: surface.window().inner_size().into(),
image_usage: ImageUsage::color_attachment(),
// The alpha mode indicates how the alpha value of the final image will behave. For
// example, you can choose whether the window will be opaque or transparent.
composite_alpha: surface_capabilities
.supported_composite_alpha
.iter()
.next()
.unwrap(),
..Default::default()
},
)
.unwrap()
};
// We now create a buffer that will store the shape of our triangle.
@ -301,7 +322,7 @@ fn main() {
// be one of the types of the `vulkano::format` module (or alternatively one
// of your structs that implements the `FormatDesc` trait). Here we use the
// same format as the swapchain.
format: swapchain.format(),
format: swapchain.image_format(),
// TODO:
samples: 1,
}
@ -397,13 +418,16 @@ fn main() {
// In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
if recreate_swapchain {
// Get the new dimensions of the window.
let dimensions: [u32; 2] = surface.window().inner_size().into();
let (new_swapchain, new_images) =
match swapchain.recreate().dimensions(dimensions).build() {
match swapchain.recreate(SwapchainCreateInfo {
image_extent: surface.window().inner_size().into(),
..swapchain.create_info()
}) {
Ok(r) => r,
// This error tends to happen when the user is manually resizing the window.
// Simply restarting the loop is the easiest way to fix this issue.
Err(SwapchainCreationError::UnsupportedDimensions) => return,
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
};

View File

@ -6,7 +6,7 @@ use vulkano::swapchain::SurfaceCreationError;
/// Creates a vulkan surface from a generic window
/// which implements HasRawWindowHandle and thus can reveal the os-dependent handle
pub fn create_vk_surface_from_handle<W>(
pub fn create_surface_from_handle<W>(
window: W,
instance: Arc<Instance>,
) -> Result<Arc<Surface<W>>, SurfaceCreationError>
@ -15,17 +15,17 @@ where
{
unsafe {
match window.raw_window_handle() {
RawWindowHandle::UiKit(h) => Surface::from_ios_moltenvk(instance, h.ui_view, window),
RawWindowHandle::AppKit(h) => Surface::from_macos_moltenvk(instance, h.ns_view, window),
RawWindowHandle::Xlib(h) => Surface::from_xlib(instance, h.display, h.window, window),
RawWindowHandle::Xcb(h) => Surface::from_xcb(instance, h.connection, h.window, window),
RawWindowHandle::AndroidNdk(h) => {
Surface::from_android(instance, h.a_native_window, window)
}
RawWindowHandle::UiKit(h) => Surface::from_ios(instance, h.ui_view, window),
RawWindowHandle::AppKit(h) => Surface::from_mac_os(instance, h.ns_view, window),
RawWindowHandle::Wayland(h) => {
Surface::from_wayland(instance, h.display, h.surface, window)
}
RawWindowHandle::AndroidNdk(h) => {
Surface::from_anativewindow(instance, h.a_native_window, window)
}
RawWindowHandle::Win32(h) => Surface::from_hwnd(instance, h.hinstance, h.hwnd, window),
RawWindowHandle::Win32(h) => Surface::from_win32(instance, h.hinstance, h.hwnd, window),
RawWindowHandle::Xcb(h) => Surface::from_xcb(instance, h.connection, h.window, window),
RawWindowHandle::Xlib(h) => Surface::from_xlib(instance, h.display, h.window, window),
RawWindowHandle::Web(_) => unimplemented!(),
_ => unimplemented!(),
}

View File

@ -8,22 +8,11 @@ use vulkano::instance::Instance;
use vulkano::instance::InstanceExtensions;
use vulkano::swapchain::Surface;
use vulkano::swapchain::SurfaceCreationError;
use winit::error::OsError as WindowCreationError;
use winit::event_loop::EventLoopWindowTarget;
use winit::window::Window;
use winit::window::WindowBuilder;
#[cfg(target_os = "macos")]
use cocoa::appkit::{NSView, NSWindow};
#[cfg(target_os = "macos")]
use cocoa::base::id as cocoa_id;
#[cfg(target_os = "macos")]
use metal::CoreAnimationLayer;
#[cfg(target_os = "macos")]
use objc::runtime::YES;
#[cfg(target_os = "macos")]
use std::mem;
use winit::{
error::OsError as WindowCreationError,
event_loop::EventLoopWindowTarget,
window::{Window, WindowBuilder},
};
pub fn required_extensions() -> InstanceExtensions {
let ideal = InstanceExtensions {
@ -46,9 +35,10 @@ pub fn required_extensions() -> InstanceExtensions {
}
}
/// Create a surface from the window type `W`. The surface borrows the window
/// to prevent it from being dropped before the surface.
pub fn create_vk_surface<W>(
/// Create a surface from a Winit window or a reference to it. The surface takes `W` to prevent it
/// from being dropped before the surface.
#[inline]
pub fn create_surface_from_winit<W>(
window: W,
instance: Arc<Instance>,
) -> Result<Arc<Surface<W>>, SurfaceCreationError>
@ -67,13 +57,14 @@ pub trait VkSurfaceBuild<E> {
}
impl<E> VkSurfaceBuild<E> for WindowBuilder {
#[inline]
fn build_vk_surface(
self,
event_loop: &EventLoopWindowTarget<E>,
instance: Arc<Instance>,
) -> Result<Arc<Surface<Window>>, CreationError> {
let window = self.build(event_loop)?;
Ok(create_vk_surface(window, instance)?)
Ok(create_surface_from_winit(window, instance)?)
}
}
@ -125,13 +116,14 @@ impl From<WindowCreationError> for CreationError {
}
#[cfg(target_os = "android")]
#[inline]
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
instance: Arc<Instance>,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
use winit::platform::android::WindowExtAndroid;
Surface::from_anativewindow(instance, win.borrow().native_window(), win)
Surface::from_android(instance, win.borrow().native_window(), win)
}
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
@ -168,15 +160,17 @@ unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
}
}
#[cfg(target_os = "windows")]
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
instance: Arc<Instance>,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
use winit::platform::windows::WindowExtWindows;
Surface::from_hwnd(instance, win.borrow().hinstance(), win.borrow().hwnd(), win)
}
#[cfg(target_os = "macos")]
use cocoa::{
appkit::{NSView, NSWindow},
base::id as cocoa_id,
};
#[cfg(target_os = "macos")]
use metal::CoreAnimationLayer;
#[cfg(target_os = "macos")]
use objc::runtime::YES;
#[cfg(target_os = "macos")]
use std::mem;
#[cfg(target_os = "macos")]
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
@ -198,7 +192,30 @@ unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
view.setLayer(mem::transmute(layer.as_ref())); // Bombs here with out of memory
view.setWantsLayer(YES);
Surface::from_macos_moltenvk(instance, win.borrow().ns_view() as *const (), win)
Surface::from_mac_os(instance, win.borrow().ns_view() as *const (), win)
}
#[cfg(target_os = "windows")]
#[inline]
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
instance: Arc<Instance>,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
use winit::platform::windows::WindowExtWindows;
Surface::from_win32(instance, win.borrow().hinstance(), win.borrow().hwnd(), win)
}
#[cfg(target_os = "windows")]
use vulkano::swapchain::Win32Monitor;
#[cfg(target_os = "windows")]
use winit::{monitor::MonitorHandle, platform::windows::MonitorHandleExtWindows};
#[cfg(target_os = "windows")]
/// Creates a `Win32Monitor` from a Winit monitor handle.
#[inline]
pub fn create_win32_monitor_from_winit(monitor_handle: &MonitorHandle) -> Win32Monitor {
unsafe { Win32Monitor::new(monitor_handle.hmonitor()) }
}
/// An alternative to `Borrow<T>` with the requirement that all calls to

View File

@ -94,7 +94,7 @@ impl<'a> SubmitPresentBuilder<'a> {
image_num: u32,
present_region: Option<&'a PresentRegion>,
) {
debug_assert!(image_num < swapchain.num_images());
debug_assert!(image_num < swapchain.image_count());
if swapchain
.device()
@ -211,9 +211,9 @@ pub enum SubmitPresentError {
/// The surface is no longer accessible and must be recreated.
SurfaceLost,
/// The swapchain has lost or doesn't have fullscreen exclusivity possibly for
/// The swapchain has lost or doesn't have full-screen exclusivity possibly for
/// implementation-specific reasons outside of the applications control.
FullscreenExclusiveLost,
FullScreenExclusiveLost,
/// The surface has changed in a way that makes the swapchain unusable. You must query the
/// surface's new properties and recreate a new swapchain if you want to continue drawing.
@ -242,8 +242,8 @@ impl fmt::Display for SubmitPresentError {
SubmitPresentError::SurfaceLost =>
"the surface of this swapchain is no longer valid",
SubmitPresentError::OutOfDate => "the swapchain needs to be recreated",
SubmitPresentError::FullscreenExclusiveLost => {
"the swapchain no longer has fullscreen exclusivity"
SubmitPresentError::FullScreenExclusiveLost => {
"the swapchain no longer has full-screen exclusivity"
}
}
)
@ -259,7 +259,7 @@ impl From<Error> for SubmitPresentError {
Error::DeviceLost => SubmitPresentError::DeviceLost,
Error::SurfaceLost => SubmitPresentError::SurfaceLost,
Error::OutOfDate => SubmitPresentError::OutOfDate,
Error::FullscreenExclusiveLost => SubmitPresentError::FullscreenExclusiveLost,
Error::FullScreenExclusiveLost => SubmitPresentError::FullScreenExclusiveLost,
_ => panic!("unexpected error: {:?}", err),
}
}

View File

@ -13,11 +13,16 @@ use crate::image::view::ImageViewType;
use crate::image::{ImageCreateFlags, ImageTiling, ImageType, ImageUsage, SampleCounts};
use crate::instance::{Instance, InstanceCreationError};
use crate::memory::ExternalMemoryHandleType;
use crate::swapchain::{
ColorSpace, FullScreenExclusive, PresentMode, SupportedSurfaceTransforms, Surface, SurfaceApi,
SurfaceCapabilities, Win32Monitor,
};
use crate::sync::PipelineStage;
use crate::Version;
use crate::VulkanObject;
use crate::{check_errors, OomError};
use crate::{DeviceSize, Error};
use std::error;
use std::ffi::CStr;
use std::fmt;
use std::hash::Hash;
@ -706,6 +711,420 @@ impl<'a> PhysicalDevice<'a> {
None
}
}
/// Returns the capabilities that are supported by the physical device for the given surface.
///
/// # Panic
///
/// - Panics if the physical device and the surface don't belong to the same instance.
pub fn surface_capabilities<W>(
&self,
surface: &Surface<W>,
surface_info: SurfaceInfo,
) -> Result<SurfaceCapabilities, SurfacePropertiesError> {
assert_eq!(
self.instance.internal_object(),
surface.instance().internal_object(),
);
/* Input */
let SurfaceInfo {
full_screen_exclusive,
win32_monitor,
_ne: _,
} = surface_info;
let mut surface_full_screen_exclusive_info =
if self.supported_extensions().ext_full_screen_exclusive {
Some(ash::vk::SurfaceFullScreenExclusiveInfoEXT {
full_screen_exclusive: full_screen_exclusive.into(),
..Default::default()
})
} else {
if full_screen_exclusive != FullScreenExclusive::Default {
return Err(SurfacePropertiesError::NotSupported);
}
None
};
let mut surface_full_screen_exclusive_win32_info = if surface.api() == SurfaceApi::Win32
&& full_screen_exclusive == FullScreenExclusive::ApplicationControlled
{
if let Some(win32_monitor) = win32_monitor {
Some(ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT {
hmonitor: win32_monitor.0,
..Default::default()
})
} else {
return Err(SurfacePropertiesError::NotSupported);
}
} else {
if win32_monitor.is_some() {
return Err(SurfacePropertiesError::NotSupported);
} else {
None
}
};
let mut surface_info2 = ash::vk::PhysicalDeviceSurfaceInfo2KHR {
surface: surface.internal_object(),
..Default::default()
};
if let Some(surface_full_screen_exclusive_info) =
surface_full_screen_exclusive_info.as_mut()
{
surface_full_screen_exclusive_info.p_next = surface_info2.p_next as *mut _;
surface_info2.p_next = surface_full_screen_exclusive_info as *const _ as *const _;
}
if let Some(surface_full_screen_exclusive_win32_info) =
surface_full_screen_exclusive_win32_info.as_mut()
{
surface_full_screen_exclusive_win32_info.p_next = surface_info2.p_next as *mut _;
surface_info2.p_next = surface_full_screen_exclusive_win32_info as *const _ as *const _;
}
/* Output */
let mut surface_capabilities2 = ash::vk::SurfaceCapabilities2KHR::default();
let mut surface_capabilities_full_screen_exclusive =
if surface_full_screen_exclusive_info.is_some() {
Some(ash::vk::SurfaceCapabilitiesFullScreenExclusiveEXT::default())
} else {
None
};
if let Some(surface_capabilities_full_screen_exclusive) =
surface_capabilities_full_screen_exclusive.as_mut()
{
surface_capabilities_full_screen_exclusive.p_next =
surface_capabilities2.p_next as *mut _;
surface_capabilities2.p_next =
surface_capabilities_full_screen_exclusive as *mut _ as *mut _;
}
unsafe {
let fns = self.instance.fns();
if self
.instance
.enabled_extensions()
.khr_get_surface_capabilities2
{
check_errors(
fns.khr_get_surface_capabilities2
.get_physical_device_surface_capabilities2_khr(
self.internal_object(),
&surface_info2,
&mut surface_capabilities2,
),
)?;
} else {
check_errors(
fns.khr_surface
.get_physical_device_surface_capabilities_khr(
self.internal_object(),
surface_info2.surface,
&mut surface_capabilities2.surface_capabilities,
),
)?;
};
}
Ok(SurfaceCapabilities {
min_image_count: surface_capabilities2.surface_capabilities.min_image_count,
max_image_count: if surface_capabilities2.surface_capabilities.max_image_count == 0 {
None
} else {
Some(surface_capabilities2.surface_capabilities.max_image_count)
},
current_extent: if surface_capabilities2
.surface_capabilities
.current_extent
.width
== 0xffffffff
&& surface_capabilities2
.surface_capabilities
.current_extent
.height
== 0xffffffff
{
None
} else {
Some([
surface_capabilities2
.surface_capabilities
.current_extent
.width,
surface_capabilities2
.surface_capabilities
.current_extent
.height,
])
},
min_image_extent: [
surface_capabilities2
.surface_capabilities
.min_image_extent
.width,
surface_capabilities2
.surface_capabilities
.min_image_extent
.height,
],
max_image_extent: [
surface_capabilities2
.surface_capabilities
.max_image_extent
.width,
surface_capabilities2
.surface_capabilities
.max_image_extent
.height,
],
max_image_array_layers: surface_capabilities2
.surface_capabilities
.max_image_array_layers,
supported_transforms: surface_capabilities2
.surface_capabilities
.supported_transforms
.into(),
current_transform: SupportedSurfaceTransforms::from(
surface_capabilities2.surface_capabilities.current_transform,
)
.iter()
.next()
.unwrap(), // TODO:
supported_composite_alpha: surface_capabilities2
.surface_capabilities
.supported_composite_alpha
.into(),
supported_usage_flags: {
let usage = ImageUsage::from(
surface_capabilities2
.surface_capabilities
.supported_usage_flags,
);
debug_assert!(usage.color_attachment); // specs say that this must be true
usage
},
full_screen_exclusive_supported: surface_capabilities_full_screen_exclusive
.map_or(false, |c| c.full_screen_exclusive_supported != 0),
})
}
/// Returns the combinations of format and color space that are supported by the physical device
/// for the given surface.
///
/// # Panic
///
/// - Panics if the physical device and the surface don't belong to the same instance.
pub fn surface_formats<W>(
&self,
surface: &Surface<W>,
surface_info: SurfaceInfo,
) -> Result<Vec<(Format, ColorSpace)>, SurfacePropertiesError> {
assert_eq!(
self.instance.internal_object(),
surface.instance().internal_object(),
);
if self
.instance
.enabled_extensions()
.khr_get_surface_capabilities2
{
let SurfaceInfo {
full_screen_exclusive,
win32_monitor,
_ne: _,
} = surface_info;
let mut surface_full_screen_exclusive_info =
if full_screen_exclusive != FullScreenExclusive::Default {
if !self.supported_extensions().ext_full_screen_exclusive {
return Err(SurfacePropertiesError::NotSupported);
}
Some(ash::vk::SurfaceFullScreenExclusiveInfoEXT {
full_screen_exclusive: full_screen_exclusive.into(),
..Default::default()
})
} else {
None
};
let mut surface_full_screen_exclusive_win32_info = if surface.api() == SurfaceApi::Win32
&& full_screen_exclusive == FullScreenExclusive::ApplicationControlled
{
if let Some(win32_monitor) = win32_monitor {
Some(ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT {
hmonitor: win32_monitor.0,
..Default::default()
})
} else {
return Err(SurfacePropertiesError::NotSupported);
}
} else {
if win32_monitor.is_some() {
return Err(SurfacePropertiesError::NotSupported);
} else {
None
}
};
let mut surface_info2 = ash::vk::PhysicalDeviceSurfaceInfo2KHR {
surface: surface.internal_object(),
..Default::default()
};
if let Some(surface_full_screen_exclusive_info) =
surface_full_screen_exclusive_info.as_mut()
{
surface_full_screen_exclusive_info.p_next = surface_info2.p_next as *mut _;
surface_info2.p_next = surface_full_screen_exclusive_info as *const _ as *const _;
}
if let Some(surface_full_screen_exclusive_win32_info) =
surface_full_screen_exclusive_win32_info.as_mut()
{
surface_full_screen_exclusive_win32_info.p_next = surface_info2.p_next as *mut _;
surface_info2.p_next =
surface_full_screen_exclusive_win32_info as *const _ as *const _;
}
let mut surface_format2s;
unsafe {
let fns = self.instance.fns();
let mut num = 0;
check_errors(
fns.khr_get_surface_capabilities2
.get_physical_device_surface_formats2_khr(
self.internal_object(),
&surface_info2,
&mut num,
ptr::null_mut(),
),
)?;
surface_format2s = Vec::with_capacity(num as usize);
check_errors(
fns.khr_get_surface_capabilities2
.get_physical_device_surface_formats2_khr(
self.internal_object(),
&surface_info2,
&mut num,
surface_format2s.as_mut_ptr(),
),
)?;
surface_format2s.set_len(num as usize);
}
Ok(surface_format2s
.into_iter()
.filter_map(|surface_format2| {
(surface_format2.surface_format.format.try_into().ok())
.zip(surface_format2.surface_format.color_space.try_into().ok())
})
.collect())
} else {
if surface_info != SurfaceInfo::default() {
return Ok(Vec::new());
}
let mut surface_formats;
unsafe {
let fns = self.instance.fns();
let mut num = 0;
check_errors(fns.khr_surface.get_physical_device_surface_formats_khr(
self.internal_object(),
surface.internal_object(),
&mut num,
ptr::null_mut(),
))?;
surface_formats = Vec::with_capacity(num as usize);
check_errors(fns.khr_surface.get_physical_device_surface_formats_khr(
self.internal_object(),
surface.internal_object(),
&mut num,
surface_formats.as_mut_ptr(),
))?;
surface_formats.set_len(num as usize);
}
Ok(surface_formats
.into_iter()
.filter_map(|surface_format| {
(surface_format.format.try_into().ok())
.zip(surface_format.color_space.try_into().ok())
})
.collect())
}
}
/// Returns the present modes that are supported by the physical device for the given surface.
///
/// # Panic
///
/// - Panics if the physical device and the surface don't belong to the same instance.
pub fn surface_present_modes<W>(
&self,
surface: &Surface<W>,
) -> Result<impl Iterator<Item = PresentMode>, SurfacePropertiesError> {
assert_eq!(
self.instance.internal_object(),
surface.instance().internal_object(),
);
let modes = unsafe {
let fns = self.instance.fns();
let mut num = 0;
check_errors(
fns.khr_surface
.get_physical_device_surface_present_modes_khr(
self.internal_object(),
surface.internal_object(),
&mut num,
ptr::null_mut(),
),
)?;
let mut modes = Vec::with_capacity(num as usize);
check_errors(
fns.khr_surface
.get_physical_device_surface_present_modes_khr(
self.internal_object(),
surface.internal_object(),
&mut num,
modes.as_mut_ptr(),
),
)?;
modes.set_len(num as usize);
modes
};
debug_assert!(modes.len() > 0);
debug_assert!(modes
.iter()
.find(|&&m| m == ash::vk::PresentModeKHR::FIFO)
.is_some());
Ok(modes
.into_iter()
.filter_map(|mode_vk| mode_vk.try_into().ok()))
}
}
unsafe impl<'a> VulkanObject for PhysicalDevice<'a> {
@ -965,6 +1384,25 @@ impl<'a> QueueFamily<'a> {
.queue_flags
.contains(stage.required_queue_flags())
}
/// Returns whether queues of this family can draw on the given surface.
pub fn supports_surface<W>(
&self,
surface: &Surface<W>,
) -> Result<bool, SurfacePropertiesError> {
unsafe {
let fns = self.physical_device.instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.khr_surface.get_physical_device_surface_support_khr(
self.physical_device.internal_object(),
self.id,
surface.internal_object(),
output.as_mut_ptr(),
))?;
Ok(output.assume_init() != 0)
}
}
}
impl<'a> PartialEq for QueueFamily<'a> {
@ -1485,3 +1923,81 @@ impl From<ash::vk::ImageFormatProperties> for ImageFormatProperties {
}
}
}
/// Parameters for [`PhysicalDevice::surface_capabilities`] and
/// [`PhysicalDevice::surface_formats`].
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SurfaceInfo {
pub full_screen_exclusive: FullScreenExclusive,
pub win32_monitor: Option<Win32Monitor>,
pub _ne: crate::NonExhaustive,
}
impl Default for SurfaceInfo {
#[inline]
fn default() -> Self {
Self {
full_screen_exclusive: FullScreenExclusive::Default,
win32_monitor: None,
_ne: crate::NonExhaustive(()),
}
}
}
/// Error that can happen when retrieving properties of a surface.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum SurfacePropertiesError {
/// Not enough memory.
OomError(OomError),
/// The surface is no longer accessible and must be recreated.
SurfaceLost,
// The given `SurfaceInfo` values are not supported for the surface by the physical device.
NotSupported,
}
impl error::Error for SurfacePropertiesError {
#[inline]
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
Self::OomError(ref err) => Some(err),
_ => None,
}
}
}
impl fmt::Display for SurfacePropertiesError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
fmt,
"{}",
match *self {
Self::OomError(_) => "not enough memory",
Self::SurfaceLost => "the surface is no longer valid",
Self::NotSupported => "the given `SurfaceInfo` values are not supported for the surface by the physical device",
}
)
}
}
impl From<OomError> for SurfacePropertiesError {
#[inline]
fn from(err: OomError) -> SurfacePropertiesError {
Self::OomError(err)
}
}
impl From<Error> for SurfacePropertiesError {
#[inline]
fn from(err: Error) -> SurfacePropertiesError {
match err {
err @ Error::OutOfHostMemory => Self::OomError(OomError::from(err)),
err @ Error::OutOfDeviceMemory => Self::OomError(OomError::from(err)),
Error::SurfaceLost => Self::SurfaceLost,
_ => panic!("unexpected error: {:?}", err),
}
}
}

View File

@ -115,7 +115,7 @@ where
#[inline]
fn try_gpu_lock(&self, _: bool, _: bool, _: ImageLayout) -> Result<(), AccessError> {
if self.swapchain.is_fullscreen_exclusive() {
if self.swapchain.is_full_screen_exclusive() {
Ok(())
} else {
// Swapchain image are only accessible after being acquired.
@ -158,7 +158,7 @@ where
{
#[inline]
fn decode(&self, value: ClearValue) -> Option<ClearValue> {
Some(self.swapchain.format().decode_clear_value(value))
Some(self.swapchain.image_format().decode_clear_value(value))
}
}

View File

@ -198,7 +198,7 @@ pub(crate) enum Error {
IncompatibleDisplay = ash::vk::Result::ERROR_INCOMPATIBLE_DISPLAY_KHR.as_raw(),
ValidationFailed = ash::vk::Result::ERROR_VALIDATION_FAILED_EXT.as_raw(),
OutOfPoolMemory = ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR.as_raw(),
FullscreenExclusiveLost = ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT.as_raw(),
FullScreenExclusiveLost = ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT.as_raw(),
}
/// Checks whether the result returned correctly.
@ -229,7 +229,7 @@ fn check_errors(result: ash::vk::Result) -> Result<Success, Error> {
ash::vk::Result::ERROR_VALIDATION_FAILED_EXT => Err(Error::ValidationFailed),
ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR => Err(Error::OutOfPoolMemory),
ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT => {
Err(Error::FullscreenExclusiveLost)
Err(Error::FullScreenExclusiveLost)
}
ash::vk::Result::ERROR_INVALID_SHADER_NV => panic!(
"Vulkan function returned \

View File

@ -1,585 +0,0 @@
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use crate::format::Format;
use crate::image::ImageUsage;
/// The capabilities of a surface when used by a physical device.
///
/// You have to match these capabilities when you create a swapchain.
#[derive(Clone, Debug)]
pub struct Capabilities {
/// Minimum number of images that must be present in the swapchain.
pub min_image_count: u32,
/// Maximum number of images that must be present in the swapchain, or `None` if there is no
/// maximum value. Note that "no maximum" doesn't mean that you can set a very high value, as
/// you may still get out of memory errors.
pub max_image_count: Option<u32>,
/// The current dimensions of the surface. `None` means that the surface's dimensions will
/// depend on the dimensions of the swapchain that you are going to create.
pub current_extent: Option<[u32; 2]>,
/// Minimum width and height of a swapchain that uses this surface.
pub min_image_extent: [u32; 2],
/// Maximum width and height of a swapchain that uses this surface.
pub max_image_extent: [u32; 2],
/// Maximum number of image layers if you create an image array. The minimum is 1.
pub max_image_array_layers: u32,
/// List of transforms supported for the swapchain.
pub supported_transforms: SupportedSurfaceTransforms,
/// Current transform used by the surface.
pub current_transform: SurfaceTransform,
/// List of composite alpha modes supports for the swapchain.
pub supported_composite_alpha: SupportedCompositeAlpha,
/// List of image usages that are supported for images of the swapchain. Only
/// the `color_attachment` usage is guaranteed to be supported.
pub supported_usage_flags: ImageUsage,
/// List of formats supported for the swapchain.
pub supported_formats: Vec<(Format, ColorSpace)>, // TODO: https://github.com/KhronosGroup/Vulkan-Docs/issues/207
/// List of present modes that are supported. `Fifo` is always guaranteed to be supported.
pub present_modes: SupportedPresentModes,
}
/// The way presenting a swapchain is accomplished.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(i32)]
pub enum PresentMode {
/// Immediately shows the image to the user. May result in visible tearing.
Immediate = ash::vk::PresentModeKHR::IMMEDIATE.as_raw(),
/// The action of presenting an image puts it in wait. When the next vertical blanking period
/// happens, the waiting image is effectively shown to the user. If an image is presented while
/// another one is waiting, it is replaced.
Mailbox = ash::vk::PresentModeKHR::MAILBOX.as_raw(),
/// The action of presenting an image adds it to a queue of images. At each vertical blanking
/// period, the queue is popped and an image is presented.
///
/// Guaranteed to be always supported.
///
/// This is the equivalent of OpenGL's `SwapInterval` with a value of 1.
Fifo = ash::vk::PresentModeKHR::FIFO.as_raw(),
/// Same as `Fifo`, except that if the queue was empty during the previous vertical blanking
/// period then it is equivalent to `Immediate`.
///
/// This is the equivalent of OpenGL's `SwapInterval` with a value of -1.
Relaxed = ash::vk::PresentModeKHR::FIFO_RELAXED.as_raw(),
// TODO: These can't be enabled yet because they have to be used with shared present surfaces
// which vulkano doesnt support yet.
//SharedDemand = ash::vk::PresentModeKHR::SHARED_DEMAND_REFRESH,
//SharedContinuous = ash::vk::PresentModeKHR::SHARED_CONTINUOUS_REFRESH,
}
impl From<PresentMode> for ash::vk::PresentModeKHR {
#[inline]
fn from(val: PresentMode) -> Self {
Self::from_raw(val as i32)
}
}
/// List of `PresentMode`s that are supported.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SupportedPresentModes {
pub immediate: bool,
pub mailbox: bool,
pub fifo: bool,
pub relaxed: bool,
pub shared_demand: bool,
pub shared_continuous: bool,
}
impl FromIterator<ash::vk::PresentModeKHR> for SupportedPresentModes {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = ash::vk::PresentModeKHR>,
{
let mut result = SupportedPresentModes::none();
for e in iter {
match e {
ash::vk::PresentModeKHR::IMMEDIATE => result.immediate = true,
ash::vk::PresentModeKHR::MAILBOX => result.mailbox = true,
ash::vk::PresentModeKHR::FIFO => result.fifo = true,
ash::vk::PresentModeKHR::FIFO_RELAXED => result.relaxed = true,
ash::vk::PresentModeKHR::SHARED_DEMAND_REFRESH => result.shared_demand = true,
ash::vk::PresentModeKHR::SHARED_CONTINUOUS_REFRESH => {
result.shared_continuous = true
}
_ => {}
}
}
result
}
}
impl SupportedPresentModes {
/// Builds a `SupportedPresentModes` with all fields set to false.
#[inline]
pub fn none() -> SupportedPresentModes {
SupportedPresentModes {
immediate: false,
mailbox: false,
fifo: false,
relaxed: false,
shared_demand: false,
shared_continuous: false,
}
}
/// Returns true if the given present mode is in this list of supported modes.
#[inline]
pub fn supports(&self, mode: PresentMode) -> bool {
match mode {
PresentMode::Immediate => self.immediate,
PresentMode::Mailbox => self.mailbox,
PresentMode::Fifo => self.fifo,
PresentMode::Relaxed => self.relaxed,
}
}
/// Returns an iterator to the list of supported present modes.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = PresentMode> {
let moved = *self;
[
PresentMode::Immediate,
PresentMode::Mailbox,
PresentMode::Fifo,
PresentMode::Relaxed,
]
.into_iter()
.filter(move |&mode| moved.supports(mode))
}
}
/// A transformation to apply to the image before showing it on the screen.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum SurfaceTransform {
/// Don't transform the image.
Identity = ash::vk::SurfaceTransformFlagsKHR::IDENTITY.as_raw(),
/// Rotate 90 degrees.
Rotate90 = ash::vk::SurfaceTransformFlagsKHR::ROTATE_90.as_raw(),
/// Rotate 180 degrees.
Rotate180 = ash::vk::SurfaceTransformFlagsKHR::ROTATE_180.as_raw(),
/// Rotate 270 degrees.
Rotate270 = ash::vk::SurfaceTransformFlagsKHR::ROTATE_270.as_raw(),
/// Mirror the image horizontally.
HorizontalMirror = ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR.as_raw(),
/// Mirror the image horizontally and rotate 90 degrees.
HorizontalMirrorRotate90 =
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_90.as_raw(),
/// Mirror the image horizontally and rotate 180 degrees.
HorizontalMirrorRotate180 =
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_180.as_raw(),
/// Mirror the image horizontally and rotate 270 degrees.
HorizontalMirrorRotate270 =
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_270.as_raw(),
/// Let the operating system or driver implementation choose.
Inherit = ash::vk::SurfaceTransformFlagsKHR::INHERIT.as_raw(),
}
impl From<SurfaceTransform> for ash::vk::SurfaceTransformFlagsKHR {
#[inline]
fn from(val: SurfaceTransform) -> Self {
Self::from_raw(val as u32)
}
}
/// How the alpha values of the pixels of the window are treated.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum CompositeAlpha {
/// The alpha channel of the image is ignored. All the pixels are considered as if they have a
/// value of 1.0.
Opaque = ash::vk::CompositeAlphaFlagsKHR::OPAQUE.as_raw(),
/// The alpha channel of the image is respected. The color channels are expected to have
/// already been multiplied by the alpha value.
PreMultiplied = ash::vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED.as_raw(),
/// The alpha channel of the image is respected. The color channels will be multiplied by the
/// alpha value by the compositor before being added to what is behind.
PostMultiplied = ash::vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED.as_raw(),
/// Let the operating system or driver implementation choose.
Inherit = ash::vk::CompositeAlphaFlagsKHR::INHERIT.as_raw(),
}
impl From<CompositeAlpha> for ash::vk::CompositeAlphaFlagsKHR {
#[inline]
fn from(val: CompositeAlpha) -> Self {
Self::from_raw(val as u32)
}
}
/// List of supported composite alpha modes.
///
/// See the docs of `CompositeAlpha`.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct SupportedCompositeAlpha {
pub opaque: bool,
pub pre_multiplied: bool,
pub post_multiplied: bool,
pub inherit: bool,
}
impl From<ash::vk::CompositeAlphaFlagsKHR> for SupportedCompositeAlpha {
#[inline]
fn from(val: ash::vk::CompositeAlphaFlagsKHR) -> SupportedCompositeAlpha {
let mut result = SupportedCompositeAlpha::none();
if !(val & ash::vk::CompositeAlphaFlagsKHR::OPAQUE).is_empty() {
result.opaque = true;
}
if !(val & ash::vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED).is_empty() {
result.pre_multiplied = true;
}
if !(val & ash::vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED).is_empty() {
result.post_multiplied = true;
}
if !(val & ash::vk::CompositeAlphaFlagsKHR::INHERIT).is_empty() {
result.inherit = true;
}
result
}
}
impl SupportedCompositeAlpha {
/// Builds a `SupportedCompositeAlpha` with all fields set to false.
#[inline]
pub fn none() -> SupportedCompositeAlpha {
SupportedCompositeAlpha {
opaque: false,
pre_multiplied: false,
post_multiplied: false,
inherit: false,
}
}
/// Returns true if the given `CompositeAlpha` is in this list.
#[inline]
pub fn supports(&self, value: CompositeAlpha) -> bool {
match value {
CompositeAlpha::Opaque => self.opaque,
CompositeAlpha::PreMultiplied => self.pre_multiplied,
CompositeAlpha::PostMultiplied => self.post_multiplied,
CompositeAlpha::Inherit => self.inherit,
}
}
/// Returns an iterator to the list of supported composite alpha.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = CompositeAlpha> {
let moved = *self;
[
CompositeAlpha::Opaque,
CompositeAlpha::PreMultiplied,
CompositeAlpha::PostMultiplied,
CompositeAlpha::Inherit,
]
.into_iter()
.filter(move |&mode| moved.supports(mode))
}
}
/// List of supported composite alpha modes.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SupportedSurfaceTransforms {
pub identity: bool,
pub rotate90: bool,
pub rotate180: bool,
pub rotate270: bool,
pub horizontal_mirror: bool,
pub horizontal_mirror_rotate90: bool,
pub horizontal_mirror_rotate180: bool,
pub horizontal_mirror_rotate270: bool,
pub inherit: bool,
}
impl From<ash::vk::SurfaceTransformFlagsKHR> for SupportedSurfaceTransforms {
fn from(val: ash::vk::SurfaceTransformFlagsKHR) -> Self {
macro_rules! v {
($val:expr, $out:ident, $e:expr, $f:ident) => {
if !($val & $e).is_empty() {
$out.$f = true;
}
};
}
let mut result = SupportedSurfaceTransforms::none();
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::IDENTITY,
identity
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::ROTATE_90,
rotate90
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::ROTATE_180,
rotate180
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::ROTATE_270,
rotate270
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR,
horizontal_mirror
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_90,
horizontal_mirror_rotate90
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_180,
horizontal_mirror_rotate180
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_270,
horizontal_mirror_rotate270
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::INHERIT,
inherit
);
result
}
}
impl SupportedSurfaceTransforms {
/// Builds a `SupportedSurfaceTransforms` with all fields set to false.
#[inline]
pub fn none() -> SupportedSurfaceTransforms {
SupportedSurfaceTransforms {
identity: false,
rotate90: false,
rotate180: false,
rotate270: false,
horizontal_mirror: false,
horizontal_mirror_rotate90: false,
horizontal_mirror_rotate180: false,
horizontal_mirror_rotate270: false,
inherit: false,
}
}
/// Returns true if the given `SurfaceTransform` is in this list.
#[inline]
pub fn supports(&self, value: SurfaceTransform) -> bool {
match value {
SurfaceTransform::Identity => self.identity,
SurfaceTransform::Rotate90 => self.rotate90,
SurfaceTransform::Rotate180 => self.rotate180,
SurfaceTransform::Rotate270 => self.rotate270,
SurfaceTransform::HorizontalMirror => self.horizontal_mirror,
SurfaceTransform::HorizontalMirrorRotate90 => self.horizontal_mirror_rotate90,
SurfaceTransform::HorizontalMirrorRotate180 => self.horizontal_mirror_rotate180,
SurfaceTransform::HorizontalMirrorRotate270 => self.horizontal_mirror_rotate270,
SurfaceTransform::Inherit => self.inherit,
}
}
/// Returns an iterator to the list of supported composite alpha.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = SurfaceTransform> {
let moved = *self;
[
SurfaceTransform::Identity,
SurfaceTransform::Rotate90,
SurfaceTransform::Rotate180,
SurfaceTransform::Rotate270,
SurfaceTransform::HorizontalMirror,
SurfaceTransform::HorizontalMirrorRotate90,
SurfaceTransform::HorizontalMirrorRotate180,
SurfaceTransform::HorizontalMirrorRotate270,
SurfaceTransform::Inherit,
]
.into_iter()
.filter(move |&mode| moved.supports(mode))
}
}
impl Default for SurfaceTransform {
#[inline]
fn default() -> SurfaceTransform {
SurfaceTransform::Identity
}
}
/// How the presentation engine should interpret the data.
///
/// # A quick lesson about color spaces
///
/// ## What is a color space?
///
/// Each pixel of a monitor is made of three components: one red, one green, and one blue. In the
/// past, computers would simply send to the monitor the intensity of each of the three components.
///
/// This proved to be problematic, because depending on the brand of the monitor the colors would
/// not exactly be the same. For example on some monitors, a value of `[1.0, 0.0, 0.0]` would be a
/// bit more orange than on others.
///
/// In order to standardize this, there exist what are called *color spaces*: sRGB, AdobeRGB,
/// DCI-P3, scRGB, etc. When you manipulate RGB values in a specific color space, these values have
/// a precise absolute meaning in terms of color, that is the same across all systems and monitors.
///
/// > **Note**: Color spaces are orthogonal to concept of RGB. *RGB* only indicates what is the
/// > representation of the data, but not how it is interpreted. You can think of this a bit like
/// > text encoding. An *RGB* value is a like a byte, in other words it is the medium by which
/// > values are communicated, and a *color space* is like a text encoding (eg. UTF-8), in other
/// > words it is the way the value should be interpreted.
///
/// The most commonly used color space today is sRGB. Most monitors today use this color space,
/// and most images files are encoded in this color space.
///
/// ## Pixel formats and linear vs non-linear
///
/// In Vulkan all images have a specific format in which the data is stored. The data of an image
/// consists of pixels in RGB but contains no information about the color space (or lack thereof)
/// of these pixels. You are free to store them in whatever color space you want.
///
/// But one big practical problem with color spaces is that they are sometimes not linear, and in
/// particular the popular sRGB color space is not linear. In a non-linear color space, a value of
/// `[0.6, 0.6, 0.6]` for example is **not** twice as bright as a value of `[0.3, 0.3, 0.3]`. This
/// is problematic, because operations such as taking the average of two colors or calculating the
/// lighting of a texture with a dot product are mathematically incorrect and will produce
/// incorrect colors.
///
/// > **Note**: If the texture format has an alpha component, it is not affected by the color space
/// > and always behaves linearly.
///
/// In order to solve this Vulkan also provides image formats with the `Srgb` suffix, which are
/// expected to contain RGB data in the sRGB color space. When you sample an image with such a
/// format from a shader, the implementation will automatically turn the pixel values into a linear
/// color space that is suitable for linear operations (such as additions or multiplications).
/// When you write to a framebuffer attachment with such a format, the implementation will
/// automatically perform the opposite conversion. These conversions are most of the time performed
/// by the hardware and incur no additional cost.
///
/// ## Color space of the swapchain
///
/// The color space that you specify when you create a swapchain is how the implementation will
/// interpret the raw data inside of the image.
///
/// > **Note**: The implementation can choose to send the data in the swapchain image directly to
/// > the monitor, but it can also choose to write it in an intermediary buffer that is then read
/// > by the operating system or windowing system. Therefore the color space that the
/// > implementation supports is not necessarily the same as the one supported by the monitor.
///
/// It is *your* job to ensure that the data in the swapchain image is in the color space
/// that is specified here, otherwise colors will be incorrect.
/// The implementation will never perform any additional automatic conversion after the colors have
/// been written to the swapchain image.
///
/// # How do I handle this correctly?
///
/// The easiest way to handle color spaces in a cross-platform program is:
///
/// - Always request the `SrgbNonLinear` color space when creating the swapchain.
/// - Make sure that all your image files use the sRGB color space, and load them in images whose
/// format has the `Srgb` suffix. Only use non-sRGB image formats for intermediary computations
/// or to store non-color data.
/// - Swapchain images should have a format with the `Srgb` suffix.
///
/// > **Note**: It is unclear whether the `SrgbNonLinear` color space is always supported by the
/// > the implementation or not. See <https://github.com/KhronosGroup/Vulkan-Docs/issues/442>.
///
/// > **Note**: Lots of developers are confused by color spaces. You can sometimes find articles
/// > talking about gamma correction and suggestion to put your colors to the power 2.2 for
/// > example. These are all hacks and you should use the sRGB pixel formats instead.
///
/// If you follow these three rules, then everything should render the same way on all platforms.
///
/// Additionally you can try detect whether the implementation supports any additional color space
/// and perform a manual conversion to that color space from inside your shader.
///
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(i32)]
pub enum ColorSpace {
SrgbNonLinear = ash::vk::ColorSpaceKHR::SRGB_NONLINEAR.as_raw(),
DisplayP3NonLinear = ash::vk::ColorSpaceKHR::DISPLAY_P3_NONLINEAR_EXT.as_raw(),
ExtendedSrgbLinear = ash::vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT.as_raw(),
ExtendedSrgbNonLinear = ash::vk::ColorSpaceKHR::EXTENDED_SRGB_NONLINEAR_EXT.as_raw(),
DisplayP3Linear = ash::vk::ColorSpaceKHR::DISPLAY_P3_LINEAR_EXT.as_raw(),
DciP3NonLinear = ash::vk::ColorSpaceKHR::DCI_P3_NONLINEAR_EXT.as_raw(),
Bt709Linear = ash::vk::ColorSpaceKHR::BT709_LINEAR_EXT.as_raw(),
Bt709NonLinear = ash::vk::ColorSpaceKHR::BT709_NONLINEAR_EXT.as_raw(),
Bt2020Linear = ash::vk::ColorSpaceKHR::BT2020_LINEAR_EXT.as_raw(),
Hdr10St2084 = ash::vk::ColorSpaceKHR::HDR10_ST2084_EXT.as_raw(),
DolbyVision = ash::vk::ColorSpaceKHR::DOLBYVISION_EXT.as_raw(),
Hdr10Hlg = ash::vk::ColorSpaceKHR::HDR10_HLG_EXT.as_raw(),
AdobeRgbLinear = ash::vk::ColorSpaceKHR::ADOBERGB_LINEAR_EXT.as_raw(),
AdobeRgbNonLinear = ash::vk::ColorSpaceKHR::ADOBERGB_NONLINEAR_EXT.as_raw(),
PassThrough = ash::vk::ColorSpaceKHR::PASS_THROUGH_EXT.as_raw(),
DisplayNative = ash::vk::ColorSpaceKHR::DISPLAY_NATIVE_AMD.as_raw(),
}
impl From<ColorSpace> for ash::vk::ColorSpaceKHR {
#[inline]
fn from(val: ColorSpace) -> Self {
Self::from_raw(val as i32)
}
}
impl From<ash::vk::ColorSpaceKHR> for ColorSpace {
#[inline]
fn from(val: ash::vk::ColorSpaceKHR) -> Self {
match val {
ash::vk::ColorSpaceKHR::SRGB_NONLINEAR => ColorSpace::SrgbNonLinear,
ash::vk::ColorSpaceKHR::DISPLAY_P3_NONLINEAR_EXT => ColorSpace::DisplayP3NonLinear,
ash::vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT => ColorSpace::ExtendedSrgbLinear,
ash::vk::ColorSpaceKHR::EXTENDED_SRGB_NONLINEAR_EXT => {
ColorSpace::ExtendedSrgbNonLinear
}
ash::vk::ColorSpaceKHR::DISPLAY_P3_LINEAR_EXT => ColorSpace::DisplayP3Linear,
ash::vk::ColorSpaceKHR::DCI_P3_NONLINEAR_EXT => ColorSpace::DciP3NonLinear,
ash::vk::ColorSpaceKHR::BT709_LINEAR_EXT => ColorSpace::Bt709Linear,
ash::vk::ColorSpaceKHR::BT709_NONLINEAR_EXT => ColorSpace::Bt709NonLinear,
ash::vk::ColorSpaceKHR::BT2020_LINEAR_EXT => ColorSpace::Bt2020Linear,
ash::vk::ColorSpaceKHR::HDR10_ST2084_EXT => ColorSpace::Hdr10St2084,
ash::vk::ColorSpaceKHR::DOLBYVISION_EXT => ColorSpace::DolbyVision,
ash::vk::ColorSpaceKHR::HDR10_HLG_EXT => ColorSpace::Hdr10Hlg,
ash::vk::ColorSpaceKHR::ADOBERGB_LINEAR_EXT => ColorSpace::AdobeRgbLinear,
ash::vk::ColorSpaceKHR::ADOBERGB_NONLINEAR_EXT => ColorSpace::AdobeRgbNonLinear,
ash::vk::ColorSpaceKHR::PASS_THROUGH_EXT => ColorSpace::PassThrough,
ash::vk::ColorSpaceKHR::DISPLAY_NATIVE_AMD => ColorSpace::DisplayNative,
_ => panic!("Wrong value for color space enum {:?}", val),
}
}
}

View File

@ -22,7 +22,7 @@
//! rate. You can enumerate the modes available on a display with `Display::display_modes`, or
//! attempt to create your own mode with `TODO`.
//! - Choose a `DisplayPlane`. A display can show multiple planes in a stacking fashion.
//! - Create a `Surface` object with `Surface::from_display_mode` and pass the chosen `DisplayMode`
//! - Create a `Surface` object with `Surface::from_display_plane` and pass the chosen `DisplayMode`
//! and `DisplayPlane`.
#![allow(dead_code)] // TODO: this module isn't finished

View File

@ -40,7 +40,7 @@
//! - `VK_KHR_win32_surface`
//!
//! For example if you want to create a surface from an Android surface, you will have to enable
//! the `VK_KHR_android_surface` extension and use `Surface::from_anativewindow`.
//! the `VK_KHR_android_surface` extension and use `Surface::from_android`.
//! See the documentation of `Surface` for all the possible constructors.
//!
//! Trying to use one of these functions without enabling the proper extension will result in an
@ -85,7 +85,7 @@
//! 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.hwnd(), Arc::clone(&window)).unwrap()
//! Surface::from_win32(instance.clone(), hinstance, window.hwnd(), Arc::clone(&window)).unwrap()
//! };
//! ```
//!
@ -114,8 +114,7 @@
//! - How the alpha of the final output will be interpreted.
//! - How to perform the cycling between images in regard to vsync.
//!
//! You can query the supported values of all these properties with
//! [`Surface::capabilities`](crate::swapchain::Surface::capabilities).
//! You can query the supported values of all these properties from the physical device.
//!
//! ## Creating a swapchain
//!
@ -131,7 +130,9 @@
//! ```
//!
//! Then, query the capabilities of the surface with
//! [`Surface::capabilities`](crate::swapchain::Surface::capabilities)
//! [`PhysicalDevice::surface_capabilities`](crate::device::physical::PhysicalDevice::surface_capabilities)
//! and
//! [`PhysicalDevice::surface_formats`](crate::device::physical::PhysicalDevice::surface_formats)
//! and choose which values you are going to use.
//!
//! ```no_run
@ -140,27 +141,31 @@
//! # use vulkano::swapchain::Surface;
//! # use std::cmp::{max, min};
//! # fn choose_caps(device: Arc<Device>, surface: Arc<Surface<()>>) -> Result<(), Box<dyn std::error::Error>> {
//! let caps = surface.capabilities(device.physical_device())?;
//! let surface_capabilities = device
//! .physical_device()
//! .surface_capabilities(&surface, Default::default())?;
//!
//! // Use the current window size or some fixed resolution.
//! let dimensions = caps.current_extent.unwrap_or([640, 480]);
//! let image_extent = surface_capabilities.current_extent.unwrap_or([640, 480]);
//!
//! // Try to use double-buffering.
//! let buffers_count = match caps.max_image_count {
//! None => max(2, caps.min_image_count),
//! Some(limit) => min(max(2, caps.min_image_count), limit)
//! let min_image_count = match surface_capabilities.max_image_count {
//! None => max(2, surface_capabilities.min_image_count),
//! Some(limit) => min(max(2, surface_capabilities.min_image_count), limit)
//! };
//!
//! // Preserve the current surface transform.
//! let transform = caps.current_transform;
//! let pre_transform = surface_capabilities.current_transform;
//!
//! // Use the first available format.
//! let (format, color_space) = caps.supported_formats[0];
//! let (image_format, color_space) = device
//! .physical_device()
//! .surface_formats(&surface, Default::default())?[0];
//! # Ok(())
//! # }
//! ```
//!
//! Then, call [`Swapchain::start`](crate::swapchain::Swapchain::start).
//! Then, call [`Swapchain::new`](crate::swapchain::Swapchain::new).
//!
//! ```no_run
//! # use std::sync::Arc;
@ -168,43 +173,46 @@
//! # use vulkano::image::ImageUsage;
//! # use vulkano::sync::SharingMode;
//! # use vulkano::format::Format;
//! # use vulkano::swapchain::{Surface, Swapchain, SurfaceTransform, PresentMode, CompositeAlpha, ColorSpace, FullscreenExclusive};
//! # use vulkano::swapchain::{Surface, Swapchain, SurfaceTransform, PresentMode, CompositeAlpha, ColorSpace, FullScreenExclusive, SwapchainCreateInfo};
//! # fn create_swapchain(
//! # 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, fullscreen_exclusive: FullscreenExclusive
//! # device: Arc<Device>, surface: Arc<Surface<()>>,
//! # min_image_count: u32, image_format: Format, image_extent: [u32; 2],
//! # pre_transform: SurfaceTransform, composite_alpha: CompositeAlpha,
//! # present_mode: PresentMode, full_screen_exclusive: FullScreenExclusive
//! # ) -> Result<(), Box<dyn std::error::Error>> {
//! // The created swapchain will be used as a color attachment for rendering.
//! let usage = ImageUsage {
//! let image_usage = ImageUsage {
//! color_attachment: true,
//! .. ImageUsage::none()
//! };
//!
//! // Create the swapchain and its buffers.
//! let (swapchain, buffers) = Swapchain::start(
//! // Create the swapchain and its images.
//! let (swapchain, images) = Swapchain::new(
//! // Create the swapchain in this `device`'s memory.
//! device,
//! // The surface where the images will be presented.
//! surface,
//! )
//! // How many buffers to use in the swapchain.
//! .num_images(buffers_count)
//! // The format of the images.
//! .format(format)
//! // The size of each image.
//! .dimensions(dimensions)
//! // What the images are going to be used for.
//! .usage(usage)
//! // What transformation to use with the surface.
//! .transform(surface_transform)
//! // How to handle the alpha channel.
//! .composite_alpha(composite_alpha)
//! // How to present images.
//! .present_mode(present_mode)
//! // How to handle fullscreen exclusivity
//! .fullscreen_exclusive(fullscreen_exclusive)
//! .build()?;
//! // The creation parameters.
//! SwapchainCreateInfo {
//! // How many images to use in the swapchain.
//! min_image_count,
//! // The format of the images.
//! image_format: Some(image_format),
//! // The size of each image.
//! image_extent,
//! // What the images are going to be used for.
//! image_usage,
//! // What transformation to use with the surface.
//! pre_transform,
//! // How to handle the alpha channel.
//! composite_alpha,
//! // How to present images.
//! present_mode,
//! // How to handle full-screen exclusivity
//! full_screen_exclusive,
//! ..Default::default()
//! }
//! )?;
//!
//! # Ok(())
//! # }
@ -262,22 +270,27 @@
//!
//! ```
//! use vulkano::swapchain;
//! use vulkano::swapchain::AcquireError;
//! use vulkano::swapchain::{AcquireError, SwapchainCreateInfo};
//! use vulkano::sync::GpuFuture;
//!
//! // let mut swapchain = Swapchain::new(...);
//! # let mut swapchain: (::std::sync::Arc<::vulkano::swapchain::Swapchain<()>>, _) = return;
//! // let (swapchain, images) = Swapchain::new(...);
//! # let mut swapchain: ::std::sync::Arc<::vulkano::swapchain::Swapchain<()>> = return;
//! # let mut images: Vec<::std::sync::Arc<::vulkano::image::SwapchainImage<()>>> = return;
//! # let queue: ::std::sync::Arc<::vulkano::device::Queue> = return;
//! let mut recreate_swapchain = false;
//!
//! loop {
//! if recreate_swapchain {
//! swapchain = swapchain.0.recreate().dimensions([1024, 768]).build().unwrap();
//! let (new_swapchain, new_images) = swapchain.recreate(SwapchainCreateInfo {
//! image_extent: [1024, 768],
//! ..swapchain.create_info()
//! })
//! .unwrap();
//! swapchain = new_swapchain;
//! images = new_images;
//! recreate_swapchain = false;
//! }
//!
//! let (ref swapchain, ref _images) = swapchain;
//!
//! let (index, suboptimal, acq_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
//! Ok(r) => r,
//! Err(AcquireError::OutOfDate) => { recreate_swapchain = true; continue; },
@ -298,35 +311,34 @@
//! ```
//!
pub use self::capabilities::Capabilities;
pub use self::capabilities::ColorSpace;
pub use self::capabilities::CompositeAlpha;
pub use self::capabilities::PresentMode;
pub use self::capabilities::SupportedCompositeAlpha;
pub use self::capabilities::SupportedPresentModes;
pub use self::capabilities::SupportedSurfaceTransforms;
pub use self::capabilities::SurfaceTransform;
pub use self::present_region::PresentRegion;
pub use self::present_region::RectangleLayer;
pub use self::surface::CapabilitiesError;
pub use self::surface::ColorSpace;
pub use self::surface::CompositeAlpha;
pub use self::surface::PresentMode;
pub use self::surface::SupportedCompositeAlpha;
pub use self::surface::SupportedSurfaceTransforms;
pub use self::surface::Surface;
pub use self::surface::SurfaceApi;
pub use self::surface::SurfaceCapabilities;
pub use self::surface::SurfaceCreationError;
pub use self::surface::SurfaceTransform;
pub use self::swapchain::acquire_next_image;
pub use self::swapchain::acquire_next_image_raw;
pub use self::swapchain::present;
pub use self::swapchain::present_incremental;
pub use self::swapchain::AcquireError;
pub use self::swapchain::AcquiredImage;
pub use self::swapchain::FullscreenExclusive;
pub use self::swapchain::FullscreenExclusiveError;
pub use self::swapchain::FullScreenExclusive;
pub use self::swapchain::FullScreenExclusiveError;
pub use self::swapchain::PresentFuture;
pub use self::swapchain::Swapchain;
pub use self::swapchain::SwapchainAcquireFuture;
pub use self::swapchain::SwapchainBuilder;
pub use self::swapchain::SwapchainCreateInfo;
pub use self::swapchain::SwapchainCreationError;
pub use self::swapchain::Win32Monitor;
use std::sync::atomic::AtomicBool;
mod capabilities;
pub mod display;
mod present_region;
mod surface;

View File

@ -45,9 +45,9 @@ impl RectangleLayer {
// 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);
self.offset[0] as u32 + self.extent[0] <= swapchain.dimensions()[0]
&& self.offset[1] as u32 + self.extent[1] <= swapchain.dimensions()[1]
&& self.layer < swapchain.layers()
self.offset[0] as u32 + self.extent[0] <= swapchain.image_extent()[0]
&& self.offset[1] as u32 + self.extent[1] <= swapchain.image_extent()[1]
&& self.layer < swapchain.image_array_layers()
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -490,9 +490,9 @@ pub enum FlushError {
/// surface's new properties and recreate a new swapchain if you want to continue drawing.
OutOfDate,
/// The swapchain has lost or doesn't have fullscreen exclusivity possibly for
/// The swapchain has lost or doesn't have full screen exclusivity possibly for
/// implementation-specific reasons outside of the applications control.
FullscreenExclusiveLost,
FullScreenExclusiveLost,
/// The flush operation needed to block, but the timeout has elapsed.
Timeout,
@ -521,8 +521,8 @@ impl fmt::Display for FlushError {
FlushError::DeviceLost => "the connection to the device has been lost",
FlushError::SurfaceLost => "the surface of this swapchain is no longer valid",
FlushError::OutOfDate => "the swapchain needs to be recreated",
FlushError::FullscreenExclusiveLost => {
"the swapchain no longer has fullscreen exclusivity"
FlushError::FullScreenExclusiveLost => {
"the swapchain no longer has full screen exclusivity"
}
FlushError::Timeout => {
"the flush operation needed to block, but the timeout has \
@ -548,7 +548,7 @@ impl From<SubmitPresentError> for FlushError {
SubmitPresentError::DeviceLost => FlushError::DeviceLost,
SubmitPresentError::SurfaceLost => FlushError::SurfaceLost,
SubmitPresentError::OutOfDate => FlushError::OutOfDate,
SubmitPresentError::FullscreenExclusiveLost => FlushError::FullscreenExclusiveLost,
SubmitPresentError::FullScreenExclusiveLost => FlushError::FullScreenExclusiveLost,
}
}
}