mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 22:34:43 +00:00
Add SwapchainCreateInfo
, various related changes (#1832)
This commit is contained in:
parent
7f14f6ff7a
commit
645faa4530
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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,
|
||||
}
|
||||
},
|
||||
|
@ -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 =
|
||||
|
@ -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 =
|
||||
|
@ -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 =
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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())
|
||||
|
@ -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 =
|
||||
|
@ -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 {
|
||||
|
@ -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())
|
||||
|
@ -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 =
|
||||
|
@ -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 =
|
||||
|
@ -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 =
|
||||
|
@ -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 =
|
||||
|
@ -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,
|
||||
|
@ -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 =
|
||||
|
@ -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 =
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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!(),
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 application’s 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),
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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 application’s 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user