mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 16:25:31 +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::graphics::viewport::{Viewport, ViewportState};
|
||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -68,7 +70,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -101,20 +103,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Vertex Buffer Pool
|
// Vertex Buffer Pool
|
||||||
@ -159,7 +174,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -207,11 +222,13 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
|
||||||
let (new_swapchain, new_images) =
|
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,
|
Ok(r) => r,
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
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::graphics::viewport::ViewportState;
|
||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -49,7 +51,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -81,20 +83,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
mod vs {
|
mod vs {
|
||||||
@ -133,7 +148,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -153,8 +168,8 @@ fn main() {
|
|||||||
.build(device.clone())
|
.build(device.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut width = swapchain.dimensions()[0];
|
let mut width = swapchain.image_extent()[0];
|
||||||
let mut height = swapchain.dimensions()[1];
|
let mut height = swapchain.image_extent()[1];
|
||||||
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone());
|
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone());
|
||||||
|
|
||||||
let mut recreate_swapchain = false;
|
let mut recreate_swapchain = false;
|
||||||
@ -177,17 +192,18 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
width = dimensions[0];
|
image_extent: surface.window().inner_size().into(),
|
||||||
height = dimensions[1];
|
..swapchain.create_info()
|
||||||
let (new_swapchain, new_images) =
|
}) {
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
Ok(r) => r,
|
||||||
Ok(r) => r,
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
};
|
||||||
};
|
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
|
width = swapchain.image_extent()[0];
|
||||||
|
height = swapchain.image_extent()[1];
|
||||||
framebuffers = window_size_dependent_setup(&new_images, render_pass.clone());
|
framebuffers = window_size_dependent_setup(&new_images, render_pass.clone());
|
||||||
recreate_swapchain = false;
|
recreate_swapchain = false;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ use vulkano::image::view::ImageView;
|
|||||||
use vulkano::image::ImageUsage;
|
use vulkano::image::ImageUsage;
|
||||||
use vulkano::instance::{Instance, InstanceCreateInfo};
|
use vulkano::instance::{Instance, InstanceCreateInfo};
|
||||||
use vulkano::swapchain;
|
use vulkano::swapchain;
|
||||||
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreationError};
|
use vulkano::swapchain::{AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError};
|
||||||
use vulkano::sync;
|
use vulkano::sync;
|
||||||
use vulkano::sync::{FlushError, GpuFuture};
|
use vulkano::sync::{FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
@ -72,7 +72,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -104,20 +104,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, mut images) = {
|
let (mut swapchain, mut images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
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()
|
|
||||||
.unwrap();
|
.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
|
let images = images
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|image| ImageView::new(image.clone()).unwrap())
|
.map(|image| ImageView::new(image.clone()).unwrap())
|
||||||
@ -126,7 +139,7 @@ fn main() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Here is the basic initialization for the deferred system.
|
// 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 =
|
let triangle_draw_system =
|
||||||
TriangleDrawSystem::new(queue.clone(), frame_system.deferred_subpass());
|
TriangleDrawSystem::new(queue.clone(), frame_system.deferred_subpass());
|
||||||
|
|
||||||
@ -150,13 +163,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
let new_images = new_images
|
let new_images = new_images
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|image| ImageView::new(image.clone()).unwrap())
|
.map(|image| ImageView::new(image.clone()).unwrap())
|
||||||
|
@ -35,7 +35,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
render_pass::{Framebuffer, RenderPass, Subpass},
|
render_pass::{Framebuffer, RenderPass, Subpass},
|
||||||
sampler::{Filter, Sampler, SamplerAddressMode},
|
sampler::{Filter, Sampler, SamplerAddressMode},
|
||||||
swapchain::{AcquireError, Swapchain, SwapchainCreationError},
|
swapchain::{AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError},
|
||||||
sync::{now, FlushError, GpuFuture, PipelineStages, Semaphore},
|
sync::{now, FlushError, GpuFuture, PipelineStages, Semaphore},
|
||||||
};
|
};
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
@ -233,11 +233,13 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
|
||||||
let (new_swapchain, new_images) =
|
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,
|
Ok(r) => r,
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
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(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.filter(|(p, _)| p.properties().driver_uuid.unwrap() == display.driver_uuid().unwrap())
|
.filter(|(p, _)| p.properties().driver_uuid.unwrap() == display.driver_uuid().unwrap())
|
||||||
@ -433,20 +435,33 @@ fn vk_setup(
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (swapchain, images) = {
|
let (swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
let vertex_buffer = CpuAccessibleBuffer::<[Vertex]>::from_iter(
|
||||||
@ -480,7 +495,7 @@ fn vk_setup(
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -27,7 +27,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
|||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -58,7 +60,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -90,20 +92,31 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device.surface_capabilities(&surface, Default::default()).unwrap();
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
let image_format = Some(
|
||||||
let format = caps.supported_formats[0].0;
|
physical_device
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -144,7 +157,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -304,13 +317,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -28,7 +28,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
|||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -59,7 +61,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -91,20 +93,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -145,7 +160,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -238,13 +253,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -37,7 +37,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
|||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -65,7 +67,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -97,20 +99,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -151,7 +166,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -246,13 +261,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -47,7 +47,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
|
|||||||
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
||||||
use vulkano::pipeline::{ComputePipeline, GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{ComputePipeline, GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -85,7 +87,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -118,20 +120,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
mod vs {
|
mod vs {
|
||||||
@ -231,7 +246,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -279,11 +294,13 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
|
||||||
let (new_swapchain, new_images) =
|
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,
|
Ok(r) => r,
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
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::graphics::viewport::{Viewport, ViewportState};
|
||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -81,7 +83,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -114,20 +116,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
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.
|
// We now create a buffer that will store the shape of our triangle.
|
||||||
@ -229,7 +244,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -283,11 +298,13 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
|
||||||
let (new_swapchain, new_images) =
|
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,
|
Ok(r) => r,
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ Usage:
|
|||||||
Space: Toggle between Mandelbrot and Julia
|
Space: Toggle between Mandelbrot and Julia
|
||||||
Enter: Randomize color palette
|
Enter: Randomize color palette
|
||||||
Equals/Minus: Increase/Decrease max iterations
|
Equals/Minus: Increase/Decrease max iterations
|
||||||
F: Toggle fullscreen
|
F: Toggle full-screen
|
||||||
Right mouse: Stop movement in Julia (mouse position determines c)
|
Right mouse: Stop movement in Julia (mouse position determines c)
|
||||||
Esc: Quit\
|
Esc: Quit\
|
||||||
"
|
"
|
||||||
@ -175,9 +175,9 @@ Usage:
|
|||||||
if self.input_state.randomize_palette {
|
if self.input_state.randomize_palette {
|
||||||
self.fractal_pipeline.randomize_palette();
|
self.fractal_pipeline.randomize_palette();
|
||||||
}
|
}
|
||||||
// Toggle fullscreen
|
// Toggle full-screen
|
||||||
if self.input_state.toggle_fullscreen {
|
if self.input_state.toggle_full_screen {
|
||||||
renderer.toggle_fullscreen()
|
renderer.toggle_full_screen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ struct InputState {
|
|||||||
pub increase_iterations: bool,
|
pub increase_iterations: bool,
|
||||||
pub decrease_iterations: bool,
|
pub decrease_iterations: bool,
|
||||||
pub randomize_palette: bool,
|
pub randomize_palette: bool,
|
||||||
pub toggle_fullscreen: bool,
|
pub toggle_full_screen: bool,
|
||||||
pub toggle_julia: bool,
|
pub toggle_julia: bool,
|
||||||
pub toggle_c: bool,
|
pub toggle_c: bool,
|
||||||
pub should_quit: bool,
|
pub should_quit: bool,
|
||||||
@ -230,7 +230,7 @@ impl InputState {
|
|||||||
increase_iterations: false,
|
increase_iterations: false,
|
||||||
decrease_iterations: false,
|
decrease_iterations: false,
|
||||||
randomize_palette: false,
|
randomize_palette: false,
|
||||||
toggle_fullscreen: false,
|
toggle_full_screen: false,
|
||||||
toggle_julia: false,
|
toggle_julia: false,
|
||||||
toggle_c: false,
|
toggle_c: false,
|
||||||
should_quit: false,
|
should_quit: false,
|
||||||
@ -250,7 +250,7 @@ impl InputState {
|
|||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
*self = InputState {
|
*self = InputState {
|
||||||
scroll_delta: 0.0,
|
scroll_delta: 0.0,
|
||||||
toggle_fullscreen: false,
|
toggle_full_screen: false,
|
||||||
toggle_julia: false,
|
toggle_julia: false,
|
||||||
toggle_c: false,
|
toggle_c: false,
|
||||||
randomize_palette: false,
|
randomize_palette: false,
|
||||||
@ -284,7 +284,7 @@ impl InputState {
|
|||||||
VirtualKeyCode::A => self.pan_left = state_is_pressed(input.state),
|
VirtualKeyCode::A => self.pan_left = state_is_pressed(input.state),
|
||||||
VirtualKeyCode::S => self.pan_down = 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::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::Return => self.randomize_palette = state_is_pressed(input.state),
|
||||||
VirtualKeyCode::Equals => self.increase_iterations = 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),
|
VirtualKeyCode::Minus => self.decrease_iterations = state_is_pressed(input.state),
|
||||||
|
@ -25,8 +25,7 @@ use vulkano::image::{
|
|||||||
use vulkano::instance::InstanceExtensions;
|
use vulkano::instance::InstanceExtensions;
|
||||||
use vulkano::instance::{Instance, InstanceCreateInfo};
|
use vulkano::instance::{Instance, InstanceCreateInfo};
|
||||||
use vulkano::swapchain::{
|
use vulkano::swapchain::{
|
||||||
AcquireError, ColorSpace, FullscreenExclusive, PresentMode, Surface, SurfaceTransform,
|
AcquireError, PresentMode, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
|
||||||
Swapchain, SwapchainCreationError,
|
|
||||||
};
|
};
|
||||||
use vulkano::sync::{FlushError, GpuFuture};
|
use vulkano::sync::{FlushError, GpuFuture};
|
||||||
use vulkano::{swapchain, sync};
|
use vulkano::{swapchain, sync};
|
||||||
@ -67,7 +66,7 @@ pub struct Renderer {
|
|||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
surface: Arc<Surface<Window>>,
|
surface: Arc<Surface<Window>>,
|
||||||
queue: Arc<Queue>,
|
queue: Arc<Queue>,
|
||||||
swap_chain: Arc<Swapchain<Window>>,
|
swapchain: Arc<Swapchain<Window>>,
|
||||||
image_index: usize,
|
image_index: usize,
|
||||||
final_views: Vec<FinalImageView>,
|
final_views: Vec<FinalImageView>,
|
||||||
/// Image view that is to be rendered with our pipeline.
|
/// Image view that is to be rendered with our pipeline.
|
||||||
@ -76,7 +75,7 @@ pub struct Renderer {
|
|||||||
recreate_swapchain: bool,
|
recreate_swapchain: bool,
|
||||||
previous_frame_end: Option<Box<dyn GpuFuture>>,
|
previous_frame_end: Option<Box<dyn GpuFuture>>,
|
||||||
render_passes: RenderPasses,
|
render_passes: RenderPasses,
|
||||||
is_fullscreen: bool,
|
is_full_screen: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
@ -120,11 +119,10 @@ impl Renderer {
|
|||||||
// Create device
|
// Create device
|
||||||
let (device, queue) = Self::create_device(physical_device, surface.clone());
|
let (device, queue) = Self::create_device(physical_device, surface.clone());
|
||||||
// Create swap chain & frame(s) to which we'll render
|
// 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(),
|
surface.clone(),
|
||||||
physical_device,
|
physical_device,
|
||||||
device.clone(),
|
device.clone(),
|
||||||
queue.clone(),
|
|
||||||
if opts.v_sync {
|
if opts.v_sync {
|
||||||
PresentMode::Fifo
|
PresentMode::Fifo
|
||||||
} else {
|
} else {
|
||||||
@ -132,7 +130,7 @@ impl Renderer {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
let previous_frame_end = Some(sync::now(device.clone()).boxed());
|
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 image_format = final_images.first().unwrap().format();
|
||||||
let render_passes = RenderPasses {
|
let render_passes = RenderPasses {
|
||||||
place_over_frame: RenderPassPlaceOverFrame::new(queue.clone(), image_format),
|
place_over_frame: RenderPassPlaceOverFrame::new(queue.clone(), image_format),
|
||||||
@ -143,14 +141,14 @@ impl Renderer {
|
|||||||
device,
|
device,
|
||||||
surface,
|
surface,
|
||||||
queue,
|
queue,
|
||||||
swap_chain,
|
swapchain,
|
||||||
image_index: 0,
|
image_index: 0,
|
||||||
final_views: final_images,
|
final_views: final_images,
|
||||||
interim_image_views: HashMap::new(),
|
interim_image_views: HashMap::new(),
|
||||||
previous_frame_end,
|
previous_frame_end,
|
||||||
recreate_swapchain: false,
|
recreate_swapchain: false,
|
||||||
render_passes,
|
render_passes,
|
||||||
is_fullscreen,
|
is_full_screen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +159,7 @@ impl Renderer {
|
|||||||
) -> (Arc<Device>, Arc<Queue>) {
|
) -> (Arc<Device>, Arc<Queue>) {
|
||||||
let queue_family = physical_device
|
let queue_family = physical_device
|
||||||
.queue_families()
|
.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();
|
.unwrap();
|
||||||
|
|
||||||
// Add device extensions based on needs,
|
// Add device extensions based on needs,
|
||||||
@ -191,37 +189,46 @@ impl Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates swapchain and swapchain images
|
/// Creates swapchain and swapchain images
|
||||||
fn create_swap_chain(
|
fn create_swapchain(
|
||||||
surface: Arc<Surface<Window>>,
|
surface: Arc<Surface<Window>>,
|
||||||
physical: PhysicalDevice,
|
physical: PhysicalDevice,
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
queue: Arc<Queue>,
|
|
||||||
present_mode: PresentMode,
|
present_mode: PresentMode,
|
||||||
) -> (Arc<Swapchain<Window>>, Vec<FinalImageView>) {
|
) -> (Arc<Swapchain<Window>>, Vec<FinalImageView>) {
|
||||||
let caps = surface.capabilities(physical).unwrap();
|
let surface_capabilities = physical
|
||||||
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
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()
|
|
||||||
.unwrap();
|
.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
|
let images = images
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|image| ImageView::new(image).unwrap())
|
.map(|image| ImageView::new(image).unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
(swap_chain, images)
|
(swapchain, images)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return default image format for images (swapchain format may differ)
|
/// Return default image format for images (swapchain format may differ)
|
||||||
@ -334,10 +341,10 @@ impl Renderer {
|
|||||||
self.interim_image_views.remove(&key);
|
self.interim_image_views.remove(&key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toggles fullscreen view
|
/// Toggles full-screen view
|
||||||
pub fn toggle_fullscreen(&mut self) {
|
pub fn toggle_full_screen(&mut self) {
|
||||||
self.is_fullscreen = !self.is_fullscreen;
|
self.is_full_screen = !self.is_full_screen;
|
||||||
self.window().set_fullscreen(if self.is_fullscreen {
|
self.window().set_fullscreen(if self.is_full_screen {
|
||||||
Some(Fullscreen::Borderless(self.window().current_monitor()))
|
Some(Fullscreen::Borderless(self.window().current_monitor()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -367,7 +374,7 @@ impl Renderer {
|
|||||||
|
|
||||||
// Acquire next image in the swapchain
|
// Acquire next image in the swapchain
|
||||||
let (image_num, suboptimal, acquire_future) =
|
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,
|
Ok(r) => r,
|
||||||
Err(AcquireError::OutOfDate) => {
|
Err(AcquireError::OutOfDate) => {
|
||||||
self.recreate_swapchain = true;
|
self.recreate_swapchain = true;
|
||||||
@ -388,11 +395,7 @@ impl Renderer {
|
|||||||
/// Finishes render by presenting the swapchain
|
/// Finishes render by presenting the swapchain
|
||||||
pub(crate) fn finish_frame(&mut self, after_future: Box<dyn GpuFuture>) {
|
pub(crate) fn finish_frame(&mut self, after_future: Box<dyn GpuFuture>) {
|
||||||
let future = after_future
|
let future = after_future
|
||||||
.then_swapchain_present(
|
.then_swapchain_present(self.queue.clone(), self.swapchain.clone(), self.image_index)
|
||||||
self.queue.clone(),
|
|
||||||
self.swap_chain.clone(),
|
|
||||||
self.image_index,
|
|
||||||
)
|
|
||||||
.then_signal_fence_and_flush();
|
.then_signal_fence_and_flush();
|
||||||
match future {
|
match future {
|
||||||
Ok(future) => {
|
Ok(future) => {
|
||||||
@ -418,21 +421,19 @@ impl Renderer {
|
|||||||
/// Swapchain is recreated when resized. Interim image views that should follow swapchain
|
/// Swapchain is recreated when resized. Interim image views that should follow swapchain
|
||||||
/// are also recreated
|
/// are also recreated
|
||||||
fn recreate_swapchain_and_views(&mut self) {
|
fn recreate_swapchain_and_views(&mut self) {
|
||||||
let dimensions: [u32; 2] = self.window().inner_size().into();
|
let (new_swapchain, new_images) = match self.swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: self.window().inner_size().into(),
|
||||||
match self.swap_chain.recreate().dimensions(dimensions).build() {
|
..self.swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => {
|
Ok(r) => r,
|
||||||
println!(
|
Err(e @ SwapchainCreationError::ImageExtentNotSupported { .. }) => {
|
||||||
"{}",
|
println!("{}", e);
|
||||||
SwapchainCreationError::UnsupportedDimensions.to_string()
|
return;
|
||||||
);
|
}
|
||||||
return;
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
}
|
};
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.swap_chain = new_swapchain;
|
self.swapchain = new_swapchain;
|
||||||
let new_images = new_images
|
let new_images = new_images
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|image| ImageView::new(image).unwrap())
|
.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::graphics::viewport::{Viewport, ViewportState};
|
||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::ElementState;
|
use winit::event::ElementState;
|
||||||
@ -67,7 +69,7 @@ fn main() {
|
|||||||
let window_id = surface.window().id();
|
let window_id = surface.window().id();
|
||||||
|
|
||||||
// Find the device and a queue.
|
// 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, queue, surface_caps) = {
|
||||||
let device_extensions = DeviceExtensions {
|
let device_extensions = DeviceExtensions {
|
||||||
@ -78,7 +80,9 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -111,30 +115,40 @@ fn main() {
|
|||||||
(
|
(
|
||||||
device,
|
device,
|
||||||
queues.next().unwrap(),
|
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
|
// The swapchain and framebuffer images for this perticular window
|
||||||
|
|
||||||
let (swapchain, images) = {
|
let (swapchain, images) = {
|
||||||
let composite_alpha = surface_caps
|
let image_format = Some(
|
||||||
.supported_composite_alpha
|
device
|
||||||
.iter()
|
.physical_device()
|
||||||
.next()
|
.surface_formats(&surface, Default::default())
|
||||||
.unwrap();
|
.unwrap()[0]
|
||||||
let format = surface_caps.supported_formats[0].0;
|
.0,
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(surface_caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_caps.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_caps
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -203,7 +217,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -280,18 +294,27 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let format = surface_caps.supported_formats[0].0;
|
let image_format = Some(
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
device
|
||||||
|
.physical_device()
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(surface_caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_caps.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
window_surfaces.insert(
|
window_surfaces.insert(
|
||||||
@ -326,13 +349,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if *recreate_swapchain {
|
if *recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
*swapchain = new_swapchain;
|
*swapchain = new_swapchain;
|
||||||
*framebuffers =
|
*framebuffers =
|
||||||
|
@ -24,7 +24,8 @@ use vulkano::{
|
|||||||
Instance, InstanceCreateInfo, InstanceExtensions,
|
Instance, InstanceCreateInfo, InstanceExtensions,
|
||||||
},
|
},
|
||||||
swapchain::{
|
swapchain::{
|
||||||
ColorSpace, FullscreenExclusive, PresentMode, Surface, SurfaceTransform, Swapchain,
|
ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceTransform, Swapchain,
|
||||||
|
SwapchainCreateInfo,
|
||||||
},
|
},
|
||||||
Version,
|
Version,
|
||||||
};
|
};
|
||||||
@ -165,36 +166,48 @@ impl VulkanoContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates swapchain and swapchain images
|
/// Creates swapchain and swapchain images
|
||||||
pub(crate) fn create_swap_chain(
|
pub(crate) fn create_swapchain(
|
||||||
&self,
|
&self,
|
||||||
surface: Arc<Surface<Window>>,
|
surface: Arc<Surface<Window>>,
|
||||||
queue: Arc<Queue>,
|
|
||||||
present_mode: PresentMode,
|
present_mode: PresentMode,
|
||||||
) -> (Arc<Swapchain<Window>>, Vec<FinalImageView>) {
|
) -> (Arc<Swapchain<Window>>, Vec<FinalImageView>) {
|
||||||
let caps = surface.capabilities(self.device.physical_device()).unwrap();
|
let surface_capabilities = self
|
||||||
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.device
|
||||||
let format = caps.supported_formats[0].0;
|
.physical_device()
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
.surface_capabilities(&surface, Default::default())
|
||||||
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()
|
|
||||||
.unwrap();
|
.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
|
let images = images
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|image| ImageView::new(image).unwrap())
|
.map(|image| ImageView::new(image).unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
(swap_chain, images)
|
(swapchain, images)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_name(&self) -> &str {
|
pub fn device_name(&self) -> &str {
|
||||||
|
@ -9,15 +9,17 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
device::Queue,
|
device::{DeviceOwned, Queue},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, ImageAccess, ImageViewAbstract},
|
image::{view::ImageView, ImageAccess, ImageViewAbstract},
|
||||||
swapchain,
|
swapchain,
|
||||||
swapchain::{AcquireError, PresentMode, Surface, Swapchain, SwapchainCreationError},
|
swapchain::{
|
||||||
|
AcquireError, PresentMode, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
|
||||||
|
},
|
||||||
sync,
|
sync,
|
||||||
sync::{FlushError, GpuFuture},
|
sync::{FlushError, GpuFuture},
|
||||||
};
|
};
|
||||||
use vulkano_win::create_vk_surface_from_handle;
|
use vulkano_win::create_surface_from_handle;
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
|
|
||||||
use crate::vulkano_context::{DeviceImageView, FinalImageView, VulkanoContext};
|
use crate::vulkano_context::{DeviceImageView, FinalImageView, VulkanoContext};
|
||||||
@ -28,7 +30,7 @@ use vulkano::image::{ImageCreateFlags, ImageDimensions, ImageUsage, StorageImage
|
|||||||
pub struct VulkanoWindow {
|
pub struct VulkanoWindow {
|
||||||
surface: Arc<Surface<Window>>,
|
surface: Arc<Surface<Window>>,
|
||||||
graphics_queue: Arc<Queue>,
|
graphics_queue: Arc<Queue>,
|
||||||
swap_chain: Arc<Swapchain<Window>>,
|
swapchain: Arc<Swapchain<Window>>,
|
||||||
final_views: Vec<FinalImageView>,
|
final_views: Vec<FinalImageView>,
|
||||||
/// Image view that is to be rendered with our pipeline.
|
/// Image view that is to be rendered with our pipeline.
|
||||||
/// (bool refers to whether it should get resized with swapchain resize)
|
/// (bool refers to whether it should get resized with swapchain resize)
|
||||||
@ -51,11 +53,10 @@ impl VulkanoWindow {
|
|||||||
vsync: bool,
|
vsync: bool,
|
||||||
) -> VulkanoWindow {
|
) -> VulkanoWindow {
|
||||||
// Create rendering surface from window
|
// 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
|
// 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(),
|
surface.clone(),
|
||||||
vulkano_context.graphics_queue(),
|
|
||||||
if vsync {
|
if vsync {
|
||||||
PresentMode::Fifo
|
PresentMode::Fifo
|
||||||
} else {
|
} else {
|
||||||
@ -68,7 +69,7 @@ impl VulkanoWindow {
|
|||||||
VulkanoWindow {
|
VulkanoWindow {
|
||||||
surface,
|
surface,
|
||||||
graphics_queue: vulkano_context.graphics_queue(),
|
graphics_queue: vulkano_context.graphics_queue(),
|
||||||
swap_chain,
|
swapchain,
|
||||||
final_views,
|
final_views,
|
||||||
image_views: HashMap::default(),
|
image_views: HashMap::default(),
|
||||||
recreate_swapchain: false,
|
recreate_swapchain: false,
|
||||||
@ -186,7 +187,7 @@ impl VulkanoWindow {
|
|||||||
|
|
||||||
// Acquire next image in the swapchain
|
// Acquire next image in the swapchain
|
||||||
let (image_num, suboptimal, acquire_future) =
|
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,
|
Ok(r) => r,
|
||||||
Err(AcquireError::OutOfDate) => {
|
Err(AcquireError::OutOfDate) => {
|
||||||
self.recreate_swapchain = true;
|
self.recreate_swapchain = true;
|
||||||
@ -210,7 +211,7 @@ impl VulkanoWindow {
|
|||||||
let future = after_future
|
let future = after_future
|
||||||
.then_swapchain_present(
|
.then_swapchain_present(
|
||||||
self.graphics_queue.clone(),
|
self.graphics_queue.clone(),
|
||||||
self.swap_chain.clone(),
|
self.swapchain.clone(),
|
||||||
self.image_index,
|
self.image_index,
|
||||||
)
|
)
|
||||||
.then_signal_fence_and_flush();
|
.then_signal_fence_and_flush();
|
||||||
@ -239,21 +240,19 @@ impl VulkanoWindow {
|
|||||||
|
|
||||||
/// Recreates swapchain images and image views that should follow swap chain image size
|
/// Recreates swapchain images and image views that should follow swap chain image size
|
||||||
fn recreate_swapchain_and_views(&mut self) {
|
fn recreate_swapchain_and_views(&mut self) {
|
||||||
let dimensions: [u32; 2] = self.window().inner_size().into();
|
let (new_swapchain, new_images) = match self.swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: self.window().inner_size().into(),
|
||||||
match self.swap_chain.recreate().dimensions(dimensions).build() {
|
..self.swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => {
|
Ok(r) => r,
|
||||||
println!(
|
Err(e @ SwapchainCreationError::ImageExtentNotSupported { .. }) => {
|
||||||
"{}",
|
println!("{}", e);
|
||||||
SwapchainCreationError::UnsupportedDimensions.to_string()
|
return;
|
||||||
);
|
}
|
||||||
return;
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
}
|
};
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.swap_chain = new_swapchain;
|
self.swapchain = new_swapchain;
|
||||||
let new_images = new_images
|
let new_images = new_images
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|image| ImageView::new(image).unwrap())
|
.map(|image| ImageView::new(image).unwrap())
|
||||||
|
@ -27,7 +27,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
|||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::query::{QueryControlFlags, QueryPool, QueryResultFlags, QueryType};
|
use vulkano::query::{QueryControlFlags, QueryPool, QueryResultFlags, QueryType};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -55,7 +57,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -87,19 +89,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
physical_device
|
||||||
.num_images(caps.min_image_count)
|
.surface_formats(&surface, Default::default())
|
||||||
.format(format)
|
.unwrap()[0]
|
||||||
.dimensions(dimensions)
|
.0,
|
||||||
.usage(ImageUsage::color_attachment())
|
);
|
||||||
.sharing_mode(&queue)
|
|
||||||
.composite_alpha(composite_alpha)
|
Swapchain::new(
|
||||||
.build()
|
device.clone(),
|
||||||
.unwrap()
|
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)]
|
#[repr(C)]
|
||||||
@ -225,7 +241,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
},
|
},
|
||||||
depth: {
|
depth: {
|
||||||
@ -284,13 +300,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -28,7 +28,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
|||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -57,7 +59,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -89,20 +91,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -143,7 +158,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -228,13 +243,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -37,7 +37,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
|||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::shader::ShaderModule;
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -74,7 +76,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -106,20 +108,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let render_pass = vulkano::single_pass_renderpass!(
|
let render_pass = vulkano::single_pass_renderpass!(
|
||||||
@ -128,7 +143,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -226,13 +241,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -31,7 +31,9 @@ use vulkano::pipeline::layout::PipelineLayout;
|
|||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -62,7 +64,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -101,20 +103,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -205,7 +220,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -357,13 +372,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -29,7 +29,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
|||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::shader::ShaderModule;
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -60,7 +62,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -91,23 +93,35 @@ fn main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let format = caps.supported_formats[0].0;
|
.surface_capabilities(&surface, Default::default())
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let vertices = VERTICES.iter().cloned();
|
let vertices = VERTICES.iter().cloned();
|
||||||
@ -133,7 +147,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
},
|
},
|
||||||
depth: {
|
depth: {
|
||||||
@ -175,11 +189,13 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
|
||||||
let (new_swapchain, new_images) =
|
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,
|
Ok(r) => r,
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
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
|
// 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
|
// 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(
|
let proj = cgmath::perspective(
|
||||||
Rad(std::f32::consts::FRAC_PI_2),
|
Rad(std::f32::consts::FRAC_PI_2),
|
||||||
aspect_ratio,
|
aspect_ratio,
|
||||||
|
@ -33,7 +33,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
|
|||||||
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -162,7 +164,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_features().is_superset_of(&features))
|
.filter(|&p| p.supported_features().is_superset_of(&features))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -195,20 +197,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
@ -267,7 +282,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -329,13 +344,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -33,7 +33,9 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
|||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::sampler::Sampler;
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ fn main() {
|
|||||||
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
.filter(|&p| p.supported_extensions().is_superset_of(&device_extensions))
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
p.queue_families()
|
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))
|
.map(|q| (p, q))
|
||||||
})
|
})
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
@ -95,20 +97,33 @@ fn main() {
|
|||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
|
||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
.surface_capabilities(&surface, Default::default())
|
||||||
let format = caps.supported_formats[0].0;
|
.unwrap();
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap()[0]
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
image_format,
|
||||||
.composite_alpha(composite_alpha)
|
image_extent: surface.window().inner_size().into(),
|
||||||
.build()
|
image_usage: ImageUsage::color_attachment(),
|
||||||
.unwrap()
|
composite_alpha: surface_capabilities
|
||||||
|
.supported_composite_alpha
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -149,7 +164,7 @@ fn main() {
|
|||||||
color: {
|
color: {
|
||||||
load: Clear,
|
load: Clear,
|
||||||
store: Store,
|
store: Store,
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -246,13 +261,14 @@ fn main() {
|
|||||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||||
let (new_swapchain, new_images) =
|
image_extent: surface.window().inner_size().into(),
|
||||||
match swapchain.recreate().dimensions(dimensions).build() {
|
..swapchain.create_info()
|
||||||
Ok(r) => r,
|
}) {
|
||||||
Err(SwapchainCreationError::UnsupportedDimensions) => return,
|
Ok(r) => r,
|
||||||
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||||
};
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
|
};
|
||||||
|
|
||||||
swapchain = new_swapchain;
|
swapchain = new_swapchain;
|
||||||
framebuffers =
|
framebuffers =
|
||||||
|
@ -29,7 +29,9 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
|
|||||||
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
||||||
use vulkano::pipeline::GraphicsPipeline;
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
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::sync::{self, FlushError, GpuFuture};
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
@ -103,7 +105,7 @@ fn main() {
|
|||||||
// We select a queue family that supports graphics operations. When drawing to
|
// 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
|
// 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.
|
// 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
|
// 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
|
// found, `None` is returned to `filter_map`, which disqualifies this physical
|
||||||
@ -175,37 +177,56 @@ fn main() {
|
|||||||
let (mut swapchain, images) = {
|
let (mut swapchain, images) = {
|
||||||
// Querying the capabilities of the surface. When we create the swapchain we can only
|
// Querying the capabilities of the surface. When we create the swapchain we can only
|
||||||
// pass values that are allowed by the capabilities.
|
// pass values that are allowed by the capabilities.
|
||||||
let caps = surface.capabilities(physical_device).unwrap();
|
let surface_capabilities = physical_device
|
||||||
|
.surface_capabilities(&surface, Default::default())
|
||||||
// The alpha mode indicates how the alpha value of the final image will behave. For example,
|
.unwrap();
|
||||||
// you can choose whether the window will be opaque or transparent.
|
|
||||||
let composite_alpha = caps.supported_composite_alpha.iter().next().unwrap();
|
|
||||||
|
|
||||||
// Choosing the internal format that the images will have.
|
// Choosing the internal format that the images will have.
|
||||||
let format = caps.supported_formats[0].0;
|
let image_format = Some(
|
||||||
|
physical_device
|
||||||
// The dimensions of the window, only used to initially setup the swapchain.
|
.surface_formats(&surface, Default::default())
|
||||||
// NOTE:
|
.unwrap()[0]
|
||||||
// On some drivers the swapchain dimensions are specified by `caps.current_extent` and the
|
.0,
|
||||||
// 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();
|
|
||||||
|
|
||||||
// Please take a look at the docs for the meaning of the parameters we didn't mention.
|
// Please take a look at the docs for the meaning of the parameters we didn't mention.
|
||||||
Swapchain::start(device.clone(), surface.clone())
|
Swapchain::new(
|
||||||
.num_images(caps.min_image_count)
|
device.clone(),
|
||||||
.format(format)
|
surface.clone(),
|
||||||
.dimensions(dimensions)
|
SwapchainCreateInfo {
|
||||||
.usage(ImageUsage::color_attachment())
|
min_image_count: surface_capabilities.min_image_count,
|
||||||
.sharing_mode(&queue)
|
|
||||||
.composite_alpha(composite_alpha)
|
image_format,
|
||||||
.build()
|
// The dimensions of the window, only used to initially setup the swapchain.
|
||||||
.unwrap()
|
// 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.
|
// 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
|
// 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
|
// of your structs that implements the `FormatDesc` trait). Here we use the
|
||||||
// same format as the swapchain.
|
// same format as the swapchain.
|
||||||
format: swapchain.format(),
|
format: swapchain.image_format(),
|
||||||
// TODO:
|
// TODO:
|
||||||
samples: 1,
|
samples: 1,
|
||||||
}
|
}
|
||||||
@ -397,13 +418,16 @@ fn main() {
|
|||||||
// In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
|
// In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
// Get the new dimensions of the window.
|
// Get the new dimensions of the window.
|
||||||
let dimensions: [u32; 2] = surface.window().inner_size().into();
|
|
||||||
let (new_swapchain, new_images) =
|
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,
|
Ok(r) => r,
|
||||||
// This error tends to happen when the user is manually resizing the window.
|
// 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.
|
// 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),
|
Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use vulkano::swapchain::SurfaceCreationError;
|
|||||||
|
|
||||||
/// Creates a vulkan surface from a generic window
|
/// Creates a vulkan surface from a generic window
|
||||||
/// which implements HasRawWindowHandle and thus can reveal the os-dependent handle
|
/// 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,
|
window: W,
|
||||||
instance: Arc<Instance>,
|
instance: Arc<Instance>,
|
||||||
) -> Result<Arc<Surface<W>>, SurfaceCreationError>
|
) -> Result<Arc<Surface<W>>, SurfaceCreationError>
|
||||||
@ -15,17 +15,17 @@ where
|
|||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
match window.raw_window_handle() {
|
match window.raw_window_handle() {
|
||||||
RawWindowHandle::UiKit(h) => Surface::from_ios_moltenvk(instance, h.ui_view, window),
|
RawWindowHandle::AndroidNdk(h) => {
|
||||||
RawWindowHandle::AppKit(h) => Surface::from_macos_moltenvk(instance, h.ns_view, window),
|
Surface::from_android(instance, h.a_native_window, 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::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) => {
|
RawWindowHandle::Wayland(h) => {
|
||||||
Surface::from_wayland(instance, h.display, h.surface, window)
|
Surface::from_wayland(instance, h.display, h.surface, window)
|
||||||
}
|
}
|
||||||
RawWindowHandle::AndroidNdk(h) => {
|
RawWindowHandle::Win32(h) => Surface::from_win32(instance, h.hinstance, h.hwnd, window),
|
||||||
Surface::from_anativewindow(instance, h.a_native_window, 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::Win32(h) => Surface::from_hwnd(instance, h.hinstance, h.hwnd, window),
|
|
||||||
RawWindowHandle::Web(_) => unimplemented!(),
|
RawWindowHandle::Web(_) => unimplemented!(),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
@ -8,22 +8,11 @@ use vulkano::instance::Instance;
|
|||||||
use vulkano::instance::InstanceExtensions;
|
use vulkano::instance::InstanceExtensions;
|
||||||
use vulkano::swapchain::Surface;
|
use vulkano::swapchain::Surface;
|
||||||
use vulkano::swapchain::SurfaceCreationError;
|
use vulkano::swapchain::SurfaceCreationError;
|
||||||
use winit::error::OsError as WindowCreationError;
|
use winit::{
|
||||||
use winit::event_loop::EventLoopWindowTarget;
|
error::OsError as WindowCreationError,
|
||||||
use winit::window::Window;
|
event_loop::EventLoopWindowTarget,
|
||||||
use winit::window::WindowBuilder;
|
window::{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;
|
|
||||||
|
|
||||||
pub fn required_extensions() -> InstanceExtensions {
|
pub fn required_extensions() -> InstanceExtensions {
|
||||||
let ideal = 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
|
/// Create a surface from a Winit window or a reference to it. The surface takes `W` to prevent it
|
||||||
/// to prevent it from being dropped before the surface.
|
/// from being dropped before the surface.
|
||||||
pub fn create_vk_surface<W>(
|
#[inline]
|
||||||
|
pub fn create_surface_from_winit<W>(
|
||||||
window: W,
|
window: W,
|
||||||
instance: Arc<Instance>,
|
instance: Arc<Instance>,
|
||||||
) -> Result<Arc<Surface<W>>, SurfaceCreationError>
|
) -> Result<Arc<Surface<W>>, SurfaceCreationError>
|
||||||
@ -67,13 +57,14 @@ pub trait VkSurfaceBuild<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<E> VkSurfaceBuild<E> for WindowBuilder {
|
impl<E> VkSurfaceBuild<E> for WindowBuilder {
|
||||||
|
#[inline]
|
||||||
fn build_vk_surface(
|
fn build_vk_surface(
|
||||||
self,
|
self,
|
||||||
event_loop: &EventLoopWindowTarget<E>,
|
event_loop: &EventLoopWindowTarget<E>,
|
||||||
instance: Arc<Instance>,
|
instance: Arc<Instance>,
|
||||||
) -> Result<Arc<Surface<Window>>, CreationError> {
|
) -> Result<Arc<Surface<Window>>, CreationError> {
|
||||||
let window = self.build(event_loop)?;
|
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")]
|
#[cfg(target_os = "android")]
|
||||||
|
#[inline]
|
||||||
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
|
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
|
||||||
instance: Arc<Instance>,
|
instance: Arc<Instance>,
|
||||||
win: W,
|
win: W,
|
||||||
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
|
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
|
||||||
use winit::platform::android::WindowExtAndroid;
|
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")))]
|
#[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")]
|
#[cfg(target_os = "macos")]
|
||||||
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
|
use cocoa::{
|
||||||
instance: Arc<Instance>,
|
appkit::{NSView, NSWindow},
|
||||||
win: W,
|
base::id as cocoa_id,
|
||||||
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
|
};
|
||||||
use winit::platform::windows::WindowExtWindows;
|
#[cfg(target_os = "macos")]
|
||||||
|
use metal::CoreAnimationLayer;
|
||||||
Surface::from_hwnd(instance, win.borrow().hinstance(), win.borrow().hwnd(), win)
|
#[cfg(target_os = "macos")]
|
||||||
}
|
use objc::runtime::YES;
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
|
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.setLayer(mem::transmute(layer.as_ref())); // Bombs here with out of memory
|
||||||
view.setWantsLayer(YES);
|
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
|
/// An alternative to `Borrow<T>` with the requirement that all calls to
|
||||||
|
@ -94,7 +94,7 @@ impl<'a> SubmitPresentBuilder<'a> {
|
|||||||
image_num: u32,
|
image_num: u32,
|
||||||
present_region: Option<&'a PresentRegion>,
|
present_region: Option<&'a PresentRegion>,
|
||||||
) {
|
) {
|
||||||
debug_assert!(image_num < swapchain.num_images());
|
debug_assert!(image_num < swapchain.image_count());
|
||||||
|
|
||||||
if swapchain
|
if swapchain
|
||||||
.device()
|
.device()
|
||||||
@ -211,9 +211,9 @@ pub enum SubmitPresentError {
|
|||||||
/// The surface is no longer accessible and must be recreated.
|
/// The surface is no longer accessible and must be recreated.
|
||||||
SurfaceLost,
|
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.
|
/// 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
|
/// 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.
|
/// 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 =>
|
SubmitPresentError::SurfaceLost =>
|
||||||
"the surface of this swapchain is no longer valid",
|
"the surface of this swapchain is no longer valid",
|
||||||
SubmitPresentError::OutOfDate => "the swapchain needs to be recreated",
|
SubmitPresentError::OutOfDate => "the swapchain needs to be recreated",
|
||||||
SubmitPresentError::FullscreenExclusiveLost => {
|
SubmitPresentError::FullScreenExclusiveLost => {
|
||||||
"the swapchain no longer has fullscreen exclusivity"
|
"the swapchain no longer has full-screen exclusivity"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -259,7 +259,7 @@ impl From<Error> for SubmitPresentError {
|
|||||||
Error::DeviceLost => SubmitPresentError::DeviceLost,
|
Error::DeviceLost => SubmitPresentError::DeviceLost,
|
||||||
Error::SurfaceLost => SubmitPresentError::SurfaceLost,
|
Error::SurfaceLost => SubmitPresentError::SurfaceLost,
|
||||||
Error::OutOfDate => SubmitPresentError::OutOfDate,
|
Error::OutOfDate => SubmitPresentError::OutOfDate,
|
||||||
Error::FullscreenExclusiveLost => SubmitPresentError::FullscreenExclusiveLost,
|
Error::FullScreenExclusiveLost => SubmitPresentError::FullScreenExclusiveLost,
|
||||||
_ => panic!("unexpected error: {:?}", err),
|
_ => panic!("unexpected error: {:?}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,16 @@ use crate::image::view::ImageViewType;
|
|||||||
use crate::image::{ImageCreateFlags, ImageTiling, ImageType, ImageUsage, SampleCounts};
|
use crate::image::{ImageCreateFlags, ImageTiling, ImageType, ImageUsage, SampleCounts};
|
||||||
use crate::instance::{Instance, InstanceCreationError};
|
use crate::instance::{Instance, InstanceCreationError};
|
||||||
use crate::memory::ExternalMemoryHandleType;
|
use crate::memory::ExternalMemoryHandleType;
|
||||||
|
use crate::swapchain::{
|
||||||
|
ColorSpace, FullScreenExclusive, PresentMode, SupportedSurfaceTransforms, Surface, SurfaceApi,
|
||||||
|
SurfaceCapabilities, Win32Monitor,
|
||||||
|
};
|
||||||
use crate::sync::PipelineStage;
|
use crate::sync::PipelineStage;
|
||||||
use crate::Version;
|
use crate::Version;
|
||||||
use crate::VulkanObject;
|
use crate::VulkanObject;
|
||||||
use crate::{check_errors, OomError};
|
use crate::{check_errors, OomError};
|
||||||
use crate::{DeviceSize, Error};
|
use crate::{DeviceSize, Error};
|
||||||
|
use std::error;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
@ -706,6 +711,420 @@ impl<'a> PhysicalDevice<'a> {
|
|||||||
None
|
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> {
|
unsafe impl<'a> VulkanObject for PhysicalDevice<'a> {
|
||||||
@ -965,6 +1384,25 @@ impl<'a> QueueFamily<'a> {
|
|||||||
.queue_flags
|
.queue_flags
|
||||||
.contains(stage.required_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> {
|
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]
|
#[inline]
|
||||||
fn try_gpu_lock(&self, _: bool, _: bool, _: ImageLayout) -> Result<(), AccessError> {
|
fn try_gpu_lock(&self, _: bool, _: bool, _: ImageLayout) -> Result<(), AccessError> {
|
||||||
if self.swapchain.is_fullscreen_exclusive() {
|
if self.swapchain.is_full_screen_exclusive() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
// Swapchain image are only accessible after being acquired.
|
// Swapchain image are only accessible after being acquired.
|
||||||
@ -158,7 +158,7 @@ where
|
|||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(&self, value: ClearValue) -> Option<ClearValue> {
|
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(),
|
IncompatibleDisplay = ash::vk::Result::ERROR_INCOMPATIBLE_DISPLAY_KHR.as_raw(),
|
||||||
ValidationFailed = ash::vk::Result::ERROR_VALIDATION_FAILED_EXT.as_raw(),
|
ValidationFailed = ash::vk::Result::ERROR_VALIDATION_FAILED_EXT.as_raw(),
|
||||||
OutOfPoolMemory = ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR.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.
|
/// 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_VALIDATION_FAILED_EXT => Err(Error::ValidationFailed),
|
||||||
ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR => Err(Error::OutOfPoolMemory),
|
ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR => Err(Error::OutOfPoolMemory),
|
||||||
ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT => {
|
ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT => {
|
||||||
Err(Error::FullscreenExclusiveLost)
|
Err(Error::FullScreenExclusiveLost)
|
||||||
}
|
}
|
||||||
ash::vk::Result::ERROR_INVALID_SHADER_NV => panic!(
|
ash::vk::Result::ERROR_INVALID_SHADER_NV => panic!(
|
||||||
"Vulkan function returned \
|
"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
|
//! rate. You can enumerate the modes available on a display with `Display::display_modes`, or
|
||||||
//! attempt to create your own mode with `TODO`.
|
//! attempt to create your own mode with `TODO`.
|
||||||
//! - Choose a `DisplayPlane`. A display can show multiple planes in a stacking fashion.
|
//! - 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`.
|
//! and `DisplayPlane`.
|
||||||
|
|
||||||
#![allow(dead_code)] // TODO: this module isn't finished
|
#![allow(dead_code)] // TODO: this module isn't finished
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
//! - `VK_KHR_win32_surface`
|
//! - `VK_KHR_win32_surface`
|
||||||
//!
|
//!
|
||||||
//! For example if you want to create a surface from an Android surface, you will have to enable
|
//! 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.
|
//! 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
|
//! 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 window = build_window(); // Third-party function, not provided by vulkano
|
||||||
//! let _surface = unsafe {
|
//! let _surface = unsafe {
|
||||||
//! let hinstance: *const () = ptr::null(); // Windows-specific object
|
//! 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 the alpha of the final output will be interpreted.
|
||||||
//! - How to perform the cycling between images in regard to vsync.
|
//! - How to perform the cycling between images in regard to vsync.
|
||||||
//!
|
//!
|
||||||
//! You can query the supported values of all these properties with
|
//! You can query the supported values of all these properties from the physical device.
|
||||||
//! [`Surface::capabilities`](crate::swapchain::Surface::capabilities).
|
|
||||||
//!
|
//!
|
||||||
//! ## Creating a swapchain
|
//! ## Creating a swapchain
|
||||||
//!
|
//!
|
||||||
@ -131,7 +130,9 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Then, query the capabilities of the surface with
|
//! 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.
|
//! and choose which values you are going to use.
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
@ -140,27 +141,31 @@
|
|||||||
//! # use vulkano::swapchain::Surface;
|
//! # use vulkano::swapchain::Surface;
|
||||||
//! # use std::cmp::{max, min};
|
//! # use std::cmp::{max, min};
|
||||||
//! # fn choose_caps(device: Arc<Device>, surface: Arc<Surface<()>>) -> Result<(), Box<dyn std::error::Error>> {
|
//! # 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.
|
//! // 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.
|
//! // Try to use double-buffering.
|
||||||
//! let buffers_count = match caps.max_image_count {
|
//! let min_image_count = match surface_capabilities.max_image_count {
|
||||||
//! None => max(2, caps.min_image_count),
|
//! None => max(2, surface_capabilities.min_image_count),
|
||||||
//! Some(limit) => min(max(2, caps.min_image_count), limit)
|
//! Some(limit) => min(max(2, surface_capabilities.min_image_count), limit)
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
//! // Preserve the current surface transform.
|
//! // Preserve the current surface transform.
|
||||||
//! let transform = caps.current_transform;
|
//! let pre_transform = surface_capabilities.current_transform;
|
||||||
//!
|
//!
|
||||||
//! // Use the first available format.
|
//! // 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(())
|
//! # Ok(())
|
||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Then, call [`Swapchain::start`](crate::swapchain::Swapchain::start).
|
//! Then, call [`Swapchain::new`](crate::swapchain::Swapchain::new).
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! # use std::sync::Arc;
|
//! # use std::sync::Arc;
|
||||||
@ -168,43 +173,46 @@
|
|||||||
//! # use vulkano::image::ImageUsage;
|
//! # use vulkano::image::ImageUsage;
|
||||||
//! # use vulkano::sync::SharingMode;
|
//! # use vulkano::sync::SharingMode;
|
||||||
//! # use vulkano::format::Format;
|
//! # 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(
|
//! # fn create_swapchain(
|
||||||
//! # device: Arc<Device>, surface: Arc<Surface<()>>, present_queue: Arc<Queue>,
|
//! # device: Arc<Device>, surface: Arc<Surface<()>>,
|
||||||
//! # buffers_count: u32, format: Format, dimensions: [u32; 2],
|
//! # min_image_count: u32, image_format: Format, image_extent: [u32; 2],
|
||||||
//! # surface_transform: SurfaceTransform, composite_alpha: CompositeAlpha,
|
//! # pre_transform: SurfaceTransform, composite_alpha: CompositeAlpha,
|
||||||
//! # present_mode: PresentMode, fullscreen_exclusive: FullscreenExclusive
|
//! # present_mode: PresentMode, full_screen_exclusive: FullScreenExclusive
|
||||||
//! # ) -> Result<(), Box<dyn std::error::Error>> {
|
//! # ) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
//! // The created swapchain will be used as a color attachment for rendering.
|
//! // The created swapchain will be used as a color attachment for rendering.
|
||||||
//! let usage = ImageUsage {
|
//! let image_usage = ImageUsage {
|
||||||
//! color_attachment: true,
|
//! color_attachment: true,
|
||||||
//! .. ImageUsage::none()
|
//! .. ImageUsage::none()
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
//! // Create the swapchain and its buffers.
|
//! // Create the swapchain and its images.
|
||||||
//! let (swapchain, buffers) = Swapchain::start(
|
//! let (swapchain, images) = Swapchain::new(
|
||||||
//! // Create the swapchain in this `device`'s memory.
|
//! // Create the swapchain in this `device`'s memory.
|
||||||
//! device,
|
//! device,
|
||||||
//! // The surface where the images will be presented.
|
//! // The surface where the images will be presented.
|
||||||
//! surface,
|
//! surface,
|
||||||
//! )
|
//! // The creation parameters.
|
||||||
//! // How many buffers to use in the swapchain.
|
//! SwapchainCreateInfo {
|
||||||
//! .num_images(buffers_count)
|
//! // How many images to use in the swapchain.
|
||||||
//! // The format of the images.
|
//! min_image_count,
|
||||||
//! .format(format)
|
//! // The format of the images.
|
||||||
//! // The size of each image.
|
//! image_format: Some(image_format),
|
||||||
//! .dimensions(dimensions)
|
//! // The size of each image.
|
||||||
//! // What the images are going to be used for.
|
//! image_extent,
|
||||||
//! .usage(usage)
|
//! // What the images are going to be used for.
|
||||||
//! // What transformation to use with the surface.
|
//! image_usage,
|
||||||
//! .transform(surface_transform)
|
//! // What transformation to use with the surface.
|
||||||
//! // How to handle the alpha channel.
|
//! pre_transform,
|
||||||
//! .composite_alpha(composite_alpha)
|
//! // How to handle the alpha channel.
|
||||||
//! // How to present images.
|
//! composite_alpha,
|
||||||
//! .present_mode(present_mode)
|
//! // How to present images.
|
||||||
//! // How to handle fullscreen exclusivity
|
//! present_mode,
|
||||||
//! .fullscreen_exclusive(fullscreen_exclusive)
|
//! // How to handle full-screen exclusivity
|
||||||
//! .build()?;
|
//! full_screen_exclusive,
|
||||||
|
//! ..Default::default()
|
||||||
|
//! }
|
||||||
|
//! )?;
|
||||||
//!
|
//!
|
||||||
//! # Ok(())
|
//! # Ok(())
|
||||||
//! # }
|
//! # }
|
||||||
@ -262,22 +270,27 @@
|
|||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use vulkano::swapchain;
|
//! use vulkano::swapchain;
|
||||||
//! use vulkano::swapchain::AcquireError;
|
//! use vulkano::swapchain::{AcquireError, SwapchainCreateInfo};
|
||||||
//! use vulkano::sync::GpuFuture;
|
//! use vulkano::sync::GpuFuture;
|
||||||
//!
|
//!
|
||||||
//! // let mut swapchain = Swapchain::new(...);
|
//! // let (swapchain, images) = Swapchain::new(...);
|
||||||
//! # let mut swapchain: (::std::sync::Arc<::vulkano::swapchain::Swapchain<()>>, _) = return;
|
//! # 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 queue: ::std::sync::Arc<::vulkano::device::Queue> = return;
|
||||||
//! let mut recreate_swapchain = false;
|
//! let mut recreate_swapchain = false;
|
||||||
//!
|
//!
|
||||||
//! loop {
|
//! loop {
|
||||||
//! if recreate_swapchain {
|
//! 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;
|
//! recreate_swapchain = false;
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! let (ref swapchain, ref _images) = swapchain;
|
|
||||||
//!
|
|
||||||
//! let (index, suboptimal, acq_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
|
//! let (index, suboptimal, acq_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
|
||||||
//! Ok(r) => r,
|
//! Ok(r) => r,
|
||||||
//! Err(AcquireError::OutOfDate) => { recreate_swapchain = true; continue; },
|
//! 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::PresentRegion;
|
||||||
pub use self::present_region::RectangleLayer;
|
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::Surface;
|
||||||
|
pub use self::surface::SurfaceApi;
|
||||||
|
pub use self::surface::SurfaceCapabilities;
|
||||||
pub use self::surface::SurfaceCreationError;
|
pub use self::surface::SurfaceCreationError;
|
||||||
|
pub use self::surface::SurfaceTransform;
|
||||||
pub use self::swapchain::acquire_next_image;
|
pub use self::swapchain::acquire_next_image;
|
||||||
pub use self::swapchain::acquire_next_image_raw;
|
pub use self::swapchain::acquire_next_image_raw;
|
||||||
pub use self::swapchain::present;
|
pub use self::swapchain::present;
|
||||||
pub use self::swapchain::present_incremental;
|
pub use self::swapchain::present_incremental;
|
||||||
pub use self::swapchain::AcquireError;
|
pub use self::swapchain::AcquireError;
|
||||||
pub use self::swapchain::AcquiredImage;
|
pub use self::swapchain::AcquiredImage;
|
||||||
pub use self::swapchain::FullscreenExclusive;
|
pub use self::swapchain::FullScreenExclusive;
|
||||||
pub use self::swapchain::FullscreenExclusiveError;
|
pub use self::swapchain::FullScreenExclusiveError;
|
||||||
pub use self::swapchain::PresentFuture;
|
pub use self::swapchain::PresentFuture;
|
||||||
pub use self::swapchain::Swapchain;
|
pub use self::swapchain::Swapchain;
|
||||||
pub use self::swapchain::SwapchainAcquireFuture;
|
pub use self::swapchain::SwapchainAcquireFuture;
|
||||||
pub use self::swapchain::SwapchainBuilder;
|
pub use self::swapchain::SwapchainCreateInfo;
|
||||||
pub use self::swapchain::SwapchainCreationError;
|
pub use self::swapchain::SwapchainCreationError;
|
||||||
|
pub use self::swapchain::Win32Monitor;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
mod capabilities;
|
|
||||||
pub mod display;
|
pub mod display;
|
||||||
mod present_region;
|
mod present_region;
|
||||||
mod surface;
|
mod surface;
|
||||||
|
@ -45,9 +45,9 @@ impl RectangleLayer {
|
|||||||
// FIXME negative offset is not disallowed by spec, but semantically should not be possible
|
// FIXME negative offset is not disallowed by spec, but semantically should not be possible
|
||||||
debug_assert!(self.offset[0] >= 0);
|
debug_assert!(self.offset[0] >= 0);
|
||||||
debug_assert!(self.offset[1] >= 0);
|
debug_assert!(self.offset[1] >= 0);
|
||||||
self.offset[0] as u32 + self.extent[0] <= swapchain.dimensions()[0]
|
self.offset[0] as u32 + self.extent[0] <= swapchain.image_extent()[0]
|
||||||
&& self.offset[1] as u32 + self.extent[1] <= swapchain.dimensions()[1]
|
&& self.offset[1] as u32 + self.extent[1] <= swapchain.image_extent()[1]
|
||||||
&& self.layer < swapchain.layers()
|
&& 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.
|
/// surface's new properties and recreate a new swapchain if you want to continue drawing.
|
||||||
OutOfDate,
|
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.
|
/// implementation-specific reasons outside of the application’s control.
|
||||||
FullscreenExclusiveLost,
|
FullScreenExclusiveLost,
|
||||||
|
|
||||||
/// The flush operation needed to block, but the timeout has elapsed.
|
/// The flush operation needed to block, but the timeout has elapsed.
|
||||||
Timeout,
|
Timeout,
|
||||||
@ -521,8 +521,8 @@ impl fmt::Display for FlushError {
|
|||||||
FlushError::DeviceLost => "the connection to the device has been lost",
|
FlushError::DeviceLost => "the connection to the device has been lost",
|
||||||
FlushError::SurfaceLost => "the surface of this swapchain is no longer valid",
|
FlushError::SurfaceLost => "the surface of this swapchain is no longer valid",
|
||||||
FlushError::OutOfDate => "the swapchain needs to be recreated",
|
FlushError::OutOfDate => "the swapchain needs to be recreated",
|
||||||
FlushError::FullscreenExclusiveLost => {
|
FlushError::FullScreenExclusiveLost => {
|
||||||
"the swapchain no longer has fullscreen exclusivity"
|
"the swapchain no longer has full screen exclusivity"
|
||||||
}
|
}
|
||||||
FlushError::Timeout => {
|
FlushError::Timeout => {
|
||||||
"the flush operation needed to block, but the timeout has \
|
"the flush operation needed to block, but the timeout has \
|
||||||
@ -548,7 +548,7 @@ impl From<SubmitPresentError> for FlushError {
|
|||||||
SubmitPresentError::DeviceLost => FlushError::DeviceLost,
|
SubmitPresentError::DeviceLost => FlushError::DeviceLost,
|
||||||
SubmitPresentError::SurfaceLost => FlushError::SurfaceLost,
|
SubmitPresentError::SurfaceLost => FlushError::SurfaceLost,
|
||||||
SubmitPresentError::OutOfDate => FlushError::OutOfDate,
|
SubmitPresentError::OutOfDate => FlushError::OutOfDate,
|
||||||
SubmitPresentError::FullscreenExclusiveLost => FlushError::FullscreenExclusiveLost,
|
SubmitPresentError::FullScreenExclusiveLost => FlushError::FullScreenExclusiveLost,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user