ValidationError-ify Surface and Swapchain (#2236)

* Add `RequiresAllOf`, automatically enable required extensions and features

* Add more missing backticks and backslashes to error messages

* Use updated VUIDs that require `acceleration_structure`

* ValidationError-ify `Surface` and `Swapchain`

* Update vulkano/src/lib.rs

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>

* Update vulkano/src/lib.rs

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>

* Don't draw if the window has zero size

---------

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>
This commit is contained in:
Rua 2023-06-26 11:17:53 +02:00 committed by GitHub
parent 2d6ff1061c
commit da09477d01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 3599 additions and 2919 deletions

View File

@ -85,7 +85,7 @@ use vulkano::{
sampler::{Sampler, SamplerCreateInfo}, sampler::{Sampler, SamplerCreateInfo},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -545,21 +545,19 @@ fn main() {
channel.send(()).unwrap(); channel.send(()).unwrap();
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = let (new_swapchain, new_images) = swapchain
match swapchain.recreate(SwapchainCreateInfo { .recreate(SwapchainCreateInfo {
image_extent: dimensions.into(), image_extent,
..swapchain.create_info() ..swapchain.create_info()
}) { })
Ok(r) => r, .expect("failed to recreate swapchain");
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = window_size_dependent_setup( framebuffers = window_size_dependent_setup(

View File

@ -45,7 +45,7 @@ use vulkano::{
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -292,23 +292,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = let (new_swapchain, new_images) = swapchain
match swapchain.recreate(SwapchainCreateInfo { .recreate(SwapchainCreateInfo {
image_extent: dimensions.into(), image_extent,
..swapchain.create_info() ..swapchain.create_info()
}) { })
Ok(r) => r, .expect("failed to recreate swapchain");
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = window_size_dependent_setup( framebuffers = window_size_dependent_setup(

View File

@ -22,7 +22,7 @@ use vulkano::{
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -175,22 +175,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
width = swapchain.image_extent()[0]; width = swapchain.image_extent()[0];

View File

@ -42,7 +42,7 @@ use vulkano::{
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -199,22 +199,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
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_default(image).unwrap()) .map(|image| ImageView::new_default(image).unwrap())

View File

@ -50,10 +50,7 @@ mod linux {
}, },
render_pass::{Framebuffer, RenderPass, Subpass}, render_pass::{Framebuffer, RenderPass, Subpass},
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo}, sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
swapchain::{ swapchain::{AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo},
AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
SwapchainPresentInfo,
},
sync::{ sync::{
now, now,
semaphore::{ semaphore::{
@ -287,20 +284,21 @@ mod linux {
}) })
.unwrap(); .unwrap();
let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) {
return;
}
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = let (new_swapchain, new_images) = swapchain
match swapchain.recreate(SwapchainCreateInfo { .recreate(SwapchainCreateInfo {
image_extent: window.inner_size().into(), image_extent,
..swapchain.create_info() ..swapchain.create_info()
}) { })
Ok(r) => r, .expect("failed to recreate swapchain");
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => {
return
}
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = window_size_dependent_setup( framebuffers = window_size_dependent_setup(

View File

@ -48,7 +48,7 @@ use vulkano::{
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo}, sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -421,22 +421,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = framebuffers =

View File

@ -46,7 +46,7 @@ use vulkano::{
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo}, sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -347,22 +347,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = framebuffers =

View File

@ -55,7 +55,7 @@ use vulkano::{
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo}, sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -368,22 +368,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = framebuffers =

View File

@ -62,7 +62,7 @@ use vulkano::{
single_pass_renderpass, single_pass_renderpass,
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -384,23 +384,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = let (new_swapchain, new_images) = swapchain
match swapchain.recreate(SwapchainCreateInfo { .recreate(SwapchainCreateInfo {
image_extent: dimensions.into(), image_extent,
..swapchain.create_info() ..swapchain.create_info()
}) { })
Ok(r) => r, .expect("failed to recreate swapchain");
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = window_size_dependent_setup( framebuffers = window_size_dependent_setup(

View File

@ -43,7 +43,7 @@ use vulkano::{
single_pass_renderpass, single_pass_renderpass,
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -364,23 +364,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = let (new_swapchain, new_images) = swapchain
match swapchain.recreate(SwapchainCreateInfo { .recreate(SwapchainCreateInfo {
image_extent: dimensions.into(), image_extent,
..swapchain.create_info() ..swapchain.create_info()
}) { })
Ok(r) => r, .expect("failed to recreate swapchain");
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = window_size_dependent_setup( framebuffers = window_size_dependent_setup(

View File

@ -46,7 +46,7 @@ use vulkano::{
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -415,22 +415,21 @@ fn main() {
previous_frame_end, previous_frame_end,
} = window_surfaces.get_mut(&window_id).unwrap(); } = window_surfaces.get_mut(&window_id).unwrap();
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if *recreate_swapchain { if *recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
*swapchain = new_swapchain; *swapchain = new_swapchain;
*framebuffers = *framebuffers =

View File

@ -44,7 +44,7 @@ use vulkano::{
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -382,22 +382,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = window_size_dependent_setup( framebuffers = window_size_dependent_setup(

View File

@ -44,7 +44,7 @@ use vulkano::{
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo}, sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -341,22 +341,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = framebuffers =

View File

@ -52,7 +52,7 @@ use vulkano::{
shader::ShaderModule, shader::ShaderModule,
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -312,22 +312,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = framebuffers =

View File

@ -47,7 +47,7 @@ use vulkano::{
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo}, sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -455,22 +455,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = framebuffers =

View File

@ -524,8 +524,9 @@ fn main() {
*control_flow = ControlFlow::Exit; *control_flow = ControlFlow::Exit;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }

View File

@ -49,7 +49,7 @@ use vulkano::{
shader::EntryPoint, shader::EntryPoint,
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -276,23 +276,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = let (new_swapchain, new_images) = swapchain
match swapchain.recreate(SwapchainCreateInfo { .recreate(SwapchainCreateInfo {
image_extent: dimensions.into(), image_extent,
..swapchain.create_info() ..swapchain.create_info()
}) { })
Ok(r) => r, .expect("failed to recreate swapchain");
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
let (new_pipeline, new_framebuffers) = window_size_dependent_setup( let (new_pipeline, new_framebuffers) = window_size_dependent_setup(

View File

@ -52,7 +52,7 @@ use vulkano::{
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -424,22 +424,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = framebuffers =

View File

@ -46,7 +46,7 @@ use vulkano::{
sampler::{Sampler, SamplerCreateInfo}, sampler::{Sampler, SamplerCreateInfo},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -352,22 +352,21 @@ fn main() {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
previous_frame_end.as_mut().unwrap().cleanup_finished(); previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo { let (new_swapchain, new_images) = swapchain
image_extent: dimensions.into(), .recreate(SwapchainCreateInfo {
..swapchain.create_info() image_extent,
}) { ..swapchain.create_info()
Ok(r) => r, })
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .expect("failed to recreate swapchain");
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;
framebuffers = framebuffers =

View File

@ -52,7 +52,7 @@ use vulkano::{
render_pass::{AttachmentLoadOp, AttachmentStoreOp}, render_pass::{AttachmentLoadOp, AttachmentStoreOp},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
Version, VulkanLibrary, Version, VulkanLibrary,
@ -527,8 +527,9 @@ fn main() {
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
// Do not draw the frame when the screen dimensions are zero. On Windows, this can // Do not draw the frame when the screen dimensions are zero. On Windows, this can
// occur when minimizing the application. // occur when minimizing the application.
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
@ -542,18 +543,12 @@ fn main() {
// window size. In this example that includes the swapchain, the framebuffers and // window size. In this example that includes the swapchain, the framebuffers and
// the dynamic state viewport. // the dynamic state viewport.
if recreate_swapchain { if recreate_swapchain {
let (new_swapchain, new_images) = let (new_swapchain, new_images) = swapchain
match swapchain.recreate(SwapchainCreateInfo { .recreate(SwapchainCreateInfo {
image_extent: dimensions.into(), image_extent,
..swapchain.create_info() ..swapchain.create_info()
}) { })
Ok(r) => r, .expect("failed to recreate swapchain");
// This error tends to happen when the user is manually resizing the
// window. Simply restarting the loop is the easiest way to fix this
// issue.
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;

View File

@ -46,7 +46,7 @@ use vulkano::{
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
swapchain::{ swapchain::{
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo, acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
SwapchainCreationError, SwapchainPresentInfo, SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
VulkanLibrary, VulkanLibrary,
@ -522,8 +522,9 @@ fn main() {
Event::RedrawEventsCleared => { Event::RedrawEventsCleared => {
// Do not draw the frame when the screen dimensions are zero. On Windows, this can // Do not draw the frame when the screen dimensions are zero. On Windows, this can
// occur when minimizing the application. // occur when minimizing the application.
let dimensions = window.inner_size(); let image_extent: [u32; 2] = window.inner_size().into();
if dimensions.width == 0 || dimensions.height == 0 {
if image_extent.contains(&0) {
return; return;
} }
@ -539,18 +540,12 @@ fn main() {
if recreate_swapchain { if recreate_swapchain {
// Use the new dimensions of the window. // Use the new dimensions of the window.
let (new_swapchain, new_images) = let (new_swapchain, new_images) = swapchain
match swapchain.recreate(SwapchainCreateInfo { .recreate(SwapchainCreateInfo {
image_extent: dimensions.into(), image_extent,
..swapchain.create_info() ..swapchain.create_info()
}) { })
Ok(r) => r, .expect("failed to recreate swapchain");
// This error tends to happen when the user is manually resizing the
// window. Simply restarting the loop is the easiest way to fix this
// issue.
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
Err(e) => panic!("failed to recreate swapchain: {e}"),
};
swapchain = new_swapchain; swapchain = new_swapchain;

View File

@ -18,8 +18,7 @@ use vulkano::{
}, },
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
swapchain::{ swapchain::{
self, AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError, self, AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo,
SwapchainPresentInfo,
}, },
sync::{self, FlushError, GpuFuture}, sync::{self, FlushError, GpuFuture},
}; };
@ -337,17 +336,21 @@ impl VulkanoWindowRenderer {
/// Recreates swapchain images and image views which follow the window size. /// Recreates swapchain images and image views which follow the window 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 image_extent: [u32; 2] = self.window().inner_size().into();
let (new_swapchain, new_images) = match self.swapchain.recreate(SwapchainCreateInfo {
image_extent: dimensions, if image_extent.contains(&0) {
// Use present mode from current state return;
present_mode: self.present_mode, }
..self.swapchain.create_info()
}) { let (new_swapchain, new_images) = self
Ok(r) => r, .swapchain
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return, .recreate(SwapchainCreateInfo {
Err(e) => panic!("failed to recreate swapchain: {e}"), image_extent,
}; // Use present mode from current state
present_mode: self.present_mode,
..self.swapchain.create_info()
})
.expect("failed to recreate swapchain");
self.swapchain = new_swapchain; self.swapchain = new_swapchain;
let new_images = new_images let new_images = new_images

View File

@ -14,7 +14,7 @@
`Surface::from_window` instead" `Surface::from_window` instead"
)] )]
#![doc(html_logo_url = "https://raw.githubusercontent.com/vulkano-rs/vulkano/master/logo.png")] #![doc(html_logo_url = "https://raw.githubusercontent.com/vulkano-rs/vulkano/master/logo.png")]
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc, clippy::result_large_err)]
#![warn(rust_2018_idioms, rust_2021_compatibility)] #![warn(rust_2018_idioms, rust_2021_compatibility)]
#[cfg(feature = "raw-window-handle")] #[cfg(feature = "raw-window-handle")]

View File

@ -6,17 +6,14 @@ use raw_window_handle::{
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
}; };
use std::{any::Any, sync::Arc}; use std::{any::Any, sync::Arc};
use vulkano::{ use vulkano::{instance::Instance, swapchain::Surface, VulkanError};
instance::Instance,
swapchain::{Surface, SurfaceCreationError},
};
/// Creates a Vulkan surface from a generic window which implements `HasRawWindowHandle` and thus /// Creates a Vulkan surface from a generic window which implements `HasRawWindowHandle` and thus
/// can reveal the OS-dependent handle. /// can reveal the OS-dependent handle.
pub fn create_surface_from_handle( pub fn create_surface_from_handle(
window: Arc<impl Any + Send + Sync + HasRawWindowHandle + HasRawDisplayHandle>, window: Arc<impl Any + Send + Sync + HasRawWindowHandle + HasRawDisplayHandle>,
instance: Arc<Instance>, instance: Arc<Instance>,
) -> Result<Arc<Surface>, SurfaceCreationError> { ) -> Result<Arc<Surface>, VulkanError> {
unsafe { unsafe {
match window.raw_window_handle() { match window.raw_window_handle() {
RawWindowHandle::AndroidNdk(h) => { RawWindowHandle::AndroidNdk(h) => {
@ -85,7 +82,7 @@ pub fn create_surface_from_handle(
pub unsafe fn create_surface_from_handle_ref( pub unsafe fn create_surface_from_handle_ref(
window: &(impl HasRawWindowHandle + HasRawDisplayHandle), window: &(impl HasRawWindowHandle + HasRawDisplayHandle),
instance: Arc<Instance>, instance: Arc<Instance>,
) -> Result<Arc<Surface>, SurfaceCreationError> { ) -> Result<Arc<Surface>, VulkanError> {
unsafe { unsafe {
match window.raw_window_handle() { match window.raw_window_handle() {
RawWindowHandle::AndroidNdk(h) => { RawWindowHandle::AndroidNdk(h) => {

View File

@ -5,8 +5,8 @@ use std::{
}; };
use vulkano::{ use vulkano::{
instance::{Instance, InstanceExtensions}, instance::{Instance, InstanceExtensions},
swapchain::{Surface, SurfaceCreationError}, swapchain::Surface,
VulkanLibrary, VulkanError, VulkanLibrary,
}; };
use winit::{ use winit::{
error::OsError as WindowCreationError, error::OsError as WindowCreationError,
@ -37,7 +37,7 @@ pub fn required_extensions(library: &VulkanLibrary) -> InstanceExtensions {
pub fn create_surface_from_winit( pub fn create_surface_from_winit(
window: Arc<Window>, window: Arc<Window>,
instance: Arc<Instance>, instance: Arc<Instance>,
) -> Result<Arc<Surface>, SurfaceCreationError> { ) -> Result<Arc<Surface>, VulkanError> {
unsafe { winit_to_surface(instance, window) } unsafe { winit_to_surface(instance, window) }
} }
@ -65,7 +65,8 @@ impl<E> VkSurfaceBuild<E> for WindowBuilder {
#[derive(Debug)] #[derive(Debug)]
pub enum CreationError { pub enum CreationError {
/// Error when creating the surface. /// Error when creating the surface.
SurfaceCreationError(SurfaceCreationError), VulkanError(VulkanError),
/// Error when creating the window. /// Error when creating the window.
WindowCreationError(WindowCreationError), WindowCreationError(WindowCreationError),
} }
@ -73,7 +74,7 @@ pub enum CreationError {
impl Error for CreationError { impl Error for CreationError {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match self { match self {
CreationError::SurfaceCreationError(err) => Some(err), CreationError::VulkanError(err) => Some(err),
CreationError::WindowCreationError(err) => Some(err), CreationError::WindowCreationError(err) => Some(err),
} }
} }
@ -85,16 +86,16 @@ impl Display for CreationError {
f, f,
"{}", "{}",
match self { match self {
CreationError::SurfaceCreationError(_) => "error while creating the surface", CreationError::VulkanError(_) => "error while creating the surface",
CreationError::WindowCreationError(_) => "error while creating the window", CreationError::WindowCreationError(_) => "error while creating the window",
} }
) )
} }
} }
impl From<SurfaceCreationError> for CreationError { impl From<VulkanError> for CreationError {
fn from(err: SurfaceCreationError) -> CreationError { fn from(err: VulkanError) -> CreationError {
CreationError::SurfaceCreationError(err) CreationError::VulkanError(err)
} }
} }
@ -108,7 +109,7 @@ impl From<WindowCreationError> for CreationError {
unsafe fn winit_to_surface( unsafe fn winit_to_surface(
instance: Arc<Instance>, instance: Arc<Instance>,
window: Arc<Window>, window: Arc<Window>,
) -> Result<Arc<Surface>, SurfaceCreationError> { ) -> Result<Arc<Surface>, VulkanError> {
use raw_window_handle::HasRawWindowHandle; use raw_window_handle::HasRawWindowHandle;
use raw_window_handle::RawWindowHandle::AndroidNdk; use raw_window_handle::RawWindowHandle::AndroidNdk;
if let AndroidNdk(handle) = window.raw_window_handle() { if let AndroidNdk(handle) = window.raw_window_handle() {
@ -127,7 +128,7 @@ unsafe fn winit_to_surface(
unsafe fn winit_to_surface( unsafe fn winit_to_surface(
instance: Arc<Instance>, instance: Arc<Instance>,
window: Arc<Window>, window: Arc<Window>,
) -> Result<Arc<Surface>, SurfaceCreationError> { ) -> Result<Arc<Surface>, VulkanError> {
use winit::platform::{wayland::WindowExtWayland, x11::WindowExtX11}; use winit::platform::{wayland::WindowExtWayland, x11::WindowExtX11};
match (window.wayland_display(), window.wayland_surface()) { match (window.wayland_display(), window.wayland_surface()) {
@ -193,7 +194,7 @@ pub(crate) unsafe fn get_metal_layer_macos(view: *mut std::ffi::c_void) -> *mut
unsafe fn winit_to_surface( unsafe fn winit_to_surface(
instance: Arc<Instance>, instance: Arc<Instance>,
window: Arc<Window>, window: Arc<Window>,
) -> Result<Arc<Surface>, SurfaceCreationError> { ) -> Result<Arc<Surface>, VulkanError> {
use winit::platform::macos::WindowExtMacOS; use winit::platform::macos::WindowExtMacOS;
let layer = get_metal_layer_macos(window.ns_view()); let layer = get_metal_layer_macos(window.ns_view());
Surface::from_mac_os(instance, layer as *const (), Some(window)) Surface::from_mac_os(instance, layer as *const (), Some(window))
@ -224,7 +225,7 @@ pub(crate) unsafe fn get_metal_layer_ios(view: *mut std::ffi::c_void) -> IOSMeta
unsafe fn winit_to_surface( unsafe fn winit_to_surface(
instance: Arc<Instance>, instance: Arc<Instance>,
window: Arc<Window>, window: Arc<Window>,
) -> Result<Arc<Surface>, SurfaceCreationError> { ) -> Result<Arc<Surface>, VulkanError> {
use winit::platform::ios::WindowExtIOS; use winit::platform::ios::WindowExtIOS;
let layer = get_metal_layer_ios(window.ui_view()); let layer = get_metal_layer_ios(window.ui_view());
Surface::from_ios(instance, layer, Some(window)) Surface::from_ios(instance, layer, Some(window))
@ -234,7 +235,7 @@ unsafe fn winit_to_surface(
unsafe fn winit_to_surface( unsafe fn winit_to_surface(
instance: Arc<Instance>, instance: Arc<Instance>,
window: Arc<Window>, window: Arc<Window>,
) -> Result<Arc<Surface>, SurfaceCreationError> { ) -> Result<Arc<Surface>, VulkanError> {
use winit::platform::windows::WindowExtWindows; use winit::platform::windows::WindowExtWindows;
Surface::from_win32( Surface::from_win32(

View File

@ -1387,11 +1387,31 @@ impl PhysicalDevice {
.map_err(|err| err.add_context("surface_info"))?; .map_err(|err| err.add_context("surface_info"))?;
let &SurfaceInfo { let &SurfaceInfo {
present_mode,
full_screen_exclusive, full_screen_exclusive,
win32_monitor, win32_monitor,
_ne: _, _ne: _,
} = surface_info; } = surface_info;
if let Some(present_mode) = present_mode {
let mut present_modes = unsafe {
self.surface_present_modes_unchecked(surface)
.map_err(|_err| ValidationError {
context: "PhysicalDevice::surface_present_modes".into(),
problem: "returned an error".into(),
..Default::default()
})?
};
if !present_modes.any(|mode| mode == present_mode) {
return Err(ValidationError {
problem: "`surface_info.present_mode` is not supported for `surface`".into(),
vuids: &["VUID-VkSurfacePresentModeEXT-presentMode-07780"],
..Default::default()
});
}
}
match ( match (
surface.api() == SurfaceApi::Win32 surface.api() == SurfaceApi::Win32
&& full_screen_exclusive == FullScreenExclusive::ApplicationControlled, && full_screen_exclusive == FullScreenExclusive::ApplicationControlled,
@ -1433,6 +1453,7 @@ impl PhysicalDevice {
/* Input */ /* Input */
let SurfaceInfo { let SurfaceInfo {
present_mode,
full_screen_exclusive, full_screen_exclusive,
win32_monitor, win32_monitor,
_ne: _, _ne: _,
@ -1442,10 +1463,21 @@ impl PhysicalDevice {
surface: surface.handle(), surface: surface.handle(),
..Default::default() ..Default::default()
}; };
let mut present_mode_vk = None;
let mut full_screen_exclusive_info_vk = None; let mut full_screen_exclusive_info_vk = None;
let mut full_screen_exclusive_win32_info_vk = None; let mut full_screen_exclusive_win32_info_vk = None;
if self.supported_extensions().ext_full_screen_exclusive && win32_monitor.is_some() { if let Some(present_mode) = present_mode {
let next = present_mode_vk.insert(ash::vk::SurfacePresentModeEXT {
present_mode: present_mode.into(),
..Default::default()
});
next.p_next = info_vk.p_next as *mut _;
info_vk.p_next = next as *const _ as *const _;
}
if full_screen_exclusive != FullScreenExclusive::Default {
let next = let next =
full_screen_exclusive_info_vk.insert(ash::vk::SurfaceFullScreenExclusiveInfoEXT { full_screen_exclusive_info_vk.insert(ash::vk::SurfaceFullScreenExclusiveInfoEXT {
full_screen_exclusive: full_screen_exclusive.into(), full_screen_exclusive: full_screen_exclusive.into(),
@ -1472,7 +1504,11 @@ impl PhysicalDevice {
let mut capabilities_vk = ash::vk::SurfaceCapabilities2KHR::default(); let mut capabilities_vk = ash::vk::SurfaceCapabilities2KHR::default();
let mut capabilities_full_screen_exclusive_vk = None; let mut capabilities_full_screen_exclusive_vk = None;
let mut protected_capabilities_vk = None; let mut capabilities_present_modes_vk =
[ash::vk::PresentModeKHR::default(); PresentMode::COUNT];
let mut capabilities_present_mode_compatibility_vk = None;
let mut capabilities_present_scaling_vk = None;
let mut capabilities_protected_vk = None;
if full_screen_exclusive_info_vk.is_some() { if full_screen_exclusive_info_vk.is_some() {
let next = capabilities_full_screen_exclusive_vk let next = capabilities_full_screen_exclusive_vk
@ -1482,12 +1518,35 @@ impl PhysicalDevice {
capabilities_vk.p_next = next as *mut _ as *mut _; capabilities_vk.p_next = next as *mut _ as *mut _;
} }
if present_mode.is_some() {
{
let next = capabilities_present_mode_compatibility_vk.insert(
ash::vk::SurfacePresentModeCompatibilityEXT {
present_mode_count: capabilities_present_modes_vk.len() as u32,
p_present_modes: capabilities_present_modes_vk.as_mut_ptr(),
..Default::default()
},
);
next.p_next = capabilities_vk.p_next as *mut _;
capabilities_vk.p_next = next as *mut _ as *mut _;
}
{
let next = capabilities_present_scaling_vk
.insert(ash::vk::SurfacePresentScalingCapabilitiesEXT::default());
next.p_next = capabilities_vk.p_next as *mut _;
capabilities_vk.p_next = next as *mut _ as *mut _;
}
}
if self if self
.instance .instance
.enabled_extensions() .enabled_extensions()
.khr_surface_protected_capabilities .khr_surface_protected_capabilities
{ {
let next = protected_capabilities_vk let next = capabilities_protected_vk
.insert(ash::vk::SurfaceProtectedCapabilitiesKHR::default()); .insert(ash::vk::SurfaceProtectedCapabilitiesKHR::default());
next.p_next = capabilities_vk.p_next as *mut _; next.p_next = capabilities_vk.p_next as *mut _;
@ -1521,22 +1580,19 @@ impl PhysicalDevice {
Ok(SurfaceCapabilities { Ok(SurfaceCapabilities {
min_image_count: capabilities_vk.surface_capabilities.min_image_count, min_image_count: capabilities_vk.surface_capabilities.min_image_count,
max_image_count: if capabilities_vk.surface_capabilities.max_image_count == 0 { max_image_count: (capabilities_vk.surface_capabilities.max_image_count != 0)
None .then_some(capabilities_vk.surface_capabilities.max_image_count),
} else { current_extent: (!matches!(
Some(capabilities_vk.surface_capabilities.max_image_count) capabilities_vk.surface_capabilities.current_extent,
}, ash::vk::Extent2D {
current_extent: if capabilities_vk.surface_capabilities.current_extent.width width: u32::MAX,
== 0xffffffff height: u32::MAX
&& capabilities_vk.surface_capabilities.current_extent.height == 0xffffffff }
{ ))
None .then_some([
} else { capabilities_vk.surface_capabilities.current_extent.width,
Some([ capabilities_vk.surface_capabilities.current_extent.height,
capabilities_vk.surface_capabilities.current_extent.width, ]),
capabilities_vk.surface_capabilities.current_extent.height,
])
},
min_image_extent: [ min_image_extent: [
capabilities_vk.surface_capabilities.min_image_extent.width, capabilities_vk.surface_capabilities.min_image_extent.width,
capabilities_vk.surface_capabilities.min_image_extent.height, capabilities_vk.surface_capabilities.min_image_extent.height,
@ -1561,14 +1617,75 @@ impl PhysicalDevice {
.surface_capabilities .surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.into(), .into(),
supported_usage_flags: { supported_usage_flags: ImageUsage::from(
let usage = capabilities_vk.surface_capabilities.supported_usage_flags,
ImageUsage::from(capabilities_vk.surface_capabilities.supported_usage_flags); ),
debug_assert!(usage.intersects(ImageUsage::COLOR_ATTACHMENT)); // specs say that this must be true
usage
},
supports_protected: protected_capabilities_vk compatible_present_modes: capabilities_present_mode_compatibility_vk.map_or_else(
Default::default,
|capabilities_present_mode_compatibility_vk| {
capabilities_present_modes_vk
[..capabilities_present_mode_compatibility_vk.present_mode_count as usize]
.iter()
.copied()
.map(PresentMode::try_from)
.filter_map(Result::ok)
.collect()
},
),
supported_present_scaling: capabilities_present_scaling_vk
.as_ref()
.map_or_else(Default::default, |c| c.supported_present_scaling.into()),
supported_present_gravity: capabilities_present_scaling_vk.as_ref().map_or_else(
Default::default,
|c| {
[
c.supported_present_gravity_x.into(),
c.supported_present_gravity_y.into(),
]
},
),
min_scaled_image_extent: capabilities_present_scaling_vk.as_ref().map_or(
Some([
capabilities_vk.surface_capabilities.min_image_extent.width,
capabilities_vk.surface_capabilities.min_image_extent.height,
]),
|c| {
(!matches!(
c.min_scaled_image_extent,
ash::vk::Extent2D {
width: u32::MAX,
height: u32::MAX,
}
))
.then_some([
c.min_scaled_image_extent.width,
c.min_scaled_image_extent.height,
])
},
),
max_scaled_image_extent: capabilities_present_scaling_vk.as_ref().map_or(
Some([
capabilities_vk.surface_capabilities.max_image_extent.width,
capabilities_vk.surface_capabilities.max_image_extent.height,
]),
|c| {
(!matches!(
c.max_scaled_image_extent,
ash::vk::Extent2D {
width: u32::MAX,
height: u32::MAX,
}
))
.then_some([
c.max_scaled_image_extent.width,
c.max_scaled_image_extent.height,
])
},
),
supports_protected: capabilities_protected_vk
.map_or(false, |c| c.supports_protected != 0), .map_or(false, |c| c.supports_protected != 0),
full_screen_exclusive_supported: capabilities_full_screen_exclusive_vk full_screen_exclusive_supported: capabilities_full_screen_exclusive_vk
@ -1630,12 +1747,36 @@ impl PhysicalDevice {
}); });
} }
surface_info
.validate(self)
.map_err(|err| err.add_context("surface_info"))?;
let &SurfaceInfo { let &SurfaceInfo {
present_mode,
full_screen_exclusive, full_screen_exclusive,
win32_monitor, win32_monitor,
_ne: _, _ne: _,
} = surface_info; } = surface_info;
if let Some(present_mode) = present_mode {
let mut present_modes = unsafe {
self.surface_present_modes_unchecked(surface)
.map_err(|_err| ValidationError {
context: "PhysicalDevice::surface_present_modes".into(),
problem: "returned an error".into(),
..Default::default()
})?
};
if !present_modes.any(|mode| mode == present_mode) {
return Err(ValidationError {
problem: "`surface_info.present_mode` is not supported for `surface`".into(),
vuids: &["VUID-VkSurfacePresentModeEXT-presentMode-07780"],
..Default::default()
});
}
}
if !self if !self
.instance .instance
.enabled_extensions() .enabled_extensions()
@ -1706,46 +1847,52 @@ impl PhysicalDevice {
(self.handle, surface_info), (self.handle, surface_info),
|(_, surface_info)| { |(_, surface_info)| {
let &SurfaceInfo { let &SurfaceInfo {
present_mode,
full_screen_exclusive, full_screen_exclusive,
win32_monitor, win32_monitor,
_ne: _, _ne: _,
} = surface_info; } = surface_info;
let mut surface_full_screen_exclusive_info = (full_screen_exclusive let mut info_vk = ash::vk::PhysicalDeviceSurfaceInfo2KHR {
!= FullScreenExclusive::Default)
.then(|| ash::vk::SurfaceFullScreenExclusiveInfoEXT {
full_screen_exclusive: full_screen_exclusive.into(),
..Default::default()
});
let mut surface_full_screen_exclusive_win32_info =
win32_monitor.map(|win32_monitor| {
ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT {
hmonitor: win32_monitor.0,
..Default::default()
}
});
let mut surface_info2 = ash::vk::PhysicalDeviceSurfaceInfo2KHR {
surface: surface.handle(), surface: surface.handle(),
..Default::default() ..Default::default()
}; };
let mut present_mode_vk = None;
let mut full_screen_exclusive_info_vk = None;
let mut full_screen_exclusive_win32_info_vk = None;
if let Some(surface_full_screen_exclusive_info) = if let Some(present_mode) = present_mode {
surface_full_screen_exclusive_info.as_mut() let next = present_mode_vk.insert(ash::vk::SurfacePresentModeEXT {
{ present_mode: present_mode.into(),
surface_full_screen_exclusive_info.p_next = surface_info2.p_next as *mut _; ..Default::default()
surface_info2.p_next = });
surface_full_screen_exclusive_info as *const _ as *const _;
next.p_next = info_vk.p_next as *mut _;
info_vk.p_next = next as *const _ as *const _;
} }
if let Some(surface_full_screen_exclusive_win32_info) = if full_screen_exclusive != FullScreenExclusive::Default {
surface_full_screen_exclusive_win32_info.as_mut() let next = full_screen_exclusive_info_vk.insert(
{ ash::vk::SurfaceFullScreenExclusiveInfoEXT {
surface_full_screen_exclusive_win32_info.p_next = full_screen_exclusive: full_screen_exclusive.into(),
surface_info2.p_next as *mut _; ..Default::default()
surface_info2.p_next = },
surface_full_screen_exclusive_win32_info as *const _ as *const _; );
next.p_next = info_vk.p_next as *mut _;
info_vk.p_next = next as *const _ as *const _;
}
if let Some(win32_monitor) = win32_monitor {
let next = full_screen_exclusive_win32_info_vk.insert(
ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT {
hmonitor: win32_monitor.0,
..Default::default()
},
);
next.p_next = info_vk.p_next as *mut _;
info_vk.p_next = next as *const _ as *const _;
} }
let fns = self.instance.fns(); let fns = self.instance.fns();
@ -1755,40 +1902,40 @@ impl PhysicalDevice {
.enabled_extensions() .enabled_extensions()
.khr_get_surface_capabilities2 .khr_get_surface_capabilities2
{ {
let surface_format2s = loop { let surface_format2s_vk = loop {
let mut count = 0; let mut count = 0;
(fns.khr_get_surface_capabilities2 (fns.khr_get_surface_capabilities2
.get_physical_device_surface_formats2_khr)( .get_physical_device_surface_formats2_khr)(
self.handle(), self.handle(),
&surface_info2, &info_vk,
&mut count, &mut count,
ptr::null_mut(), ptr::null_mut(),
) )
.result() .result()
.map_err(RuntimeError::from)?; .map_err(RuntimeError::from)?;
let mut surface_format2s = let mut surface_format2s_vk =
vec![ash::vk::SurfaceFormat2KHR::default(); count as usize]; vec![ash::vk::SurfaceFormat2KHR::default(); count as usize];
let result = (fns let result = (fns
.khr_get_surface_capabilities2 .khr_get_surface_capabilities2
.get_physical_device_surface_formats2_khr)( .get_physical_device_surface_formats2_khr)(
self.handle(), self.handle(),
&surface_info2, &info_vk,
&mut count, &mut count,
surface_format2s.as_mut_ptr(), surface_format2s_vk.as_mut_ptr(),
); );
match result { match result {
ash::vk::Result::SUCCESS => { ash::vk::Result::SUCCESS => {
surface_format2s.set_len(count as usize); surface_format2s_vk.set_len(count as usize);
break surface_format2s; break surface_format2s_vk;
} }
ash::vk::Result::INCOMPLETE => (), ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)), err => return Err(RuntimeError::from(err)),
} }
}; };
Ok(surface_format2s Ok(surface_format2s_vk
.into_iter() .into_iter()
.filter_map(|surface_format2| { .filter_map(|surface_format2| {
(surface_format2.surface_format.format.try_into().ok()) (surface_format2.surface_format.format.try_into().ok())

View File

@ -529,8 +529,8 @@ impl<'a> QueueGuard<'a> {
states: &mut States<'_>, states: &mut States<'_>,
) -> Result<impl ExactSizeIterator<Item = Result<bool, RuntimeError>>, RuntimeError> { ) -> Result<impl ExactSizeIterator<Item = Result<bool, RuntimeError>>, RuntimeError> {
let PresentInfo { let PresentInfo {
ref wait_semaphores, wait_semaphores,
ref swapchain_infos, swapchain_infos,
_ne: _, _ne: _,
} = present_info; } = present_info;
@ -542,11 +542,13 @@ impl<'a> QueueGuard<'a> {
let mut swapchains_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len()); let mut swapchains_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len());
let mut image_indices_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len()); let mut image_indices_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len());
let mut present_ids_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len()); let mut present_ids_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len());
let mut present_modes_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len());
let mut present_regions_vk: SmallVec<[_; 4]> = let mut present_regions_vk: SmallVec<[_; 4]> =
SmallVec::with_capacity(swapchain_infos.len()); SmallVec::with_capacity(swapchain_infos.len());
let mut rectangles_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len()); let mut rectangles_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchain_infos.len());
let mut has_present_ids = false; let mut has_present_ids = false;
let mut has_present_modes = false;
let mut has_present_regions = false; let mut has_present_regions = false;
for swapchain_info in swapchain_infos { for swapchain_info in swapchain_infos {
@ -554,6 +556,7 @@ impl<'a> QueueGuard<'a> {
ref swapchain, ref swapchain,
image_index, image_index,
present_id, present_id,
present_mode,
ref present_regions, ref present_regions,
_ne: _, _ne: _,
} = swapchain_info; } = swapchain_info;
@ -561,6 +564,7 @@ impl<'a> QueueGuard<'a> {
swapchains_vk.push(swapchain.handle()); swapchains_vk.push(swapchain.handle());
image_indices_vk.push(image_index); image_indices_vk.push(image_index);
present_ids_vk.push(present_id.map_or(0, u64::from)); present_ids_vk.push(present_id.map_or(0, u64::from));
present_modes_vk.push(present_mode.map_or_else(Default::default, Into::into));
present_regions_vk.push(ash::vk::PresentRegionKHR::default()); present_regions_vk.push(ash::vk::PresentRegionKHR::default());
rectangles_vk.push( rectangles_vk.push(
present_regions present_regions
@ -573,6 +577,10 @@ impl<'a> QueueGuard<'a> {
has_present_ids = true; has_present_ids = true;
} }
if present_mode.is_some() {
has_present_modes = true;
}
if !present_regions.is_empty() { if !present_regions.is_empty() {
has_present_regions = true; has_present_regions = true;
} }
@ -589,6 +597,7 @@ impl<'a> QueueGuard<'a> {
..Default::default() ..Default::default()
}; };
let mut present_id_info_vk = None; let mut present_id_info_vk = None;
let mut present_mode_info_vk = None;
let mut present_region_info_vk = None; let mut present_region_info_vk = None;
if has_present_ids { if has_present_ids {
@ -602,6 +611,17 @@ impl<'a> QueueGuard<'a> {
info_vk.p_next = next as *const _ as *const _; info_vk.p_next = next as *const _ as *const _;
} }
if has_present_modes {
let next = present_mode_info_vk.insert(ash::vk::SwapchainPresentModeInfoEXT {
swapchain_count: present_modes_vk.len() as u32,
p_present_modes: present_modes_vk.as_ptr(),
..Default::default()
});
next.p_next = info_vk.p_next as _;
info_vk.p_next = next as *const _ as *const _;
}
if has_present_regions { if has_present_regions {
for (present_regions_vk, rectangles_vk) in for (present_regions_vk, rectangles_vk) in
(present_regions_vk.iter_mut()).zip(rectangles_vk.iter()) (present_regions_vk.iter_mut()).zip(rectangles_vk.iter())

View File

@ -15,7 +15,6 @@ use super::{
use crate::{ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
swapchain::Swapchain, swapchain::Swapchain,
OomError,
}; };
use std::{ use std::{
hash::{Hash, Hasher}, hash::{Hash, Hasher},
@ -45,10 +44,10 @@ impl SwapchainImage {
handle: ash::vk::Image, handle: ash::vk::Image,
swapchain: Arc<Swapchain>, swapchain: Arc<Swapchain>,
image_index: u32, image_index: u32,
) -> Result<Arc<SwapchainImage>, OomError> { ) -> Arc<SwapchainImage> {
Ok(Arc::new(SwapchainImage { Arc::new(SwapchainImage {
inner: Arc::new(Image::from_swapchain(handle, swapchain, image_index)), inner: Arc::new(Image::from_swapchain(handle, swapchain, image_index)),
})) })
} }
/// Returns the swapchain this image belongs to. /// Returns the swapchain this image belongs to.

View File

@ -591,11 +591,16 @@ macro_rules! vulkan_enum {
)+ )+
} }
$( impl $ty {
impl $ty { #[allow(dead_code)]
pub(crate) const COUNT: usize = [
$(ash::vk::$ty_ffi::$flag_name_ffi.as_raw()),+
].len();
$(
$($impls)* $($impls)*
} )?
)? }
impl From<$ty> for ash::vk::$ty_ffi { impl From<$ty> for ash::vk::$ty_ffi {
#[inline] #[inline]
@ -653,6 +658,11 @@ macro_rules! vulkan_enum {
} }
impl $ty { impl $ty {
#[allow(dead_code)]
pub(crate) const COUNT: usize = [
$(ash::vk::$ty_ffi::$flag_name_ffi.as_raw()),+
].len();
#[allow(dead_code)] #[allow(dead_code)]
#[inline] #[inline]
pub(crate) fn validate_device( pub(crate) fn validate_device(

View File

@ -521,13 +521,13 @@ impl From<&Viewport> for ash::vk::Viewport {
} }
} }
/// State of a single scissor box. /// A two-dimensional subregion.
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Scissor { pub struct Scissor {
/// Coordinates in pixels of the top-left hand corner of the box. /// Coordinates of the top-left hand corner of the box.
pub offset: [u32; 2], pub offset: [u32; 2],
/// Dimensions in pixels of the box. /// Dimensions of the box.
pub extent: [u32; 2], pub extent: [u32; 2],
} }
@ -565,3 +565,13 @@ impl From<&Scissor> for ash::vk::Rect2D {
} }
} }
} }
impl From<ash::vk::Rect2D> for Scissor {
#[inline]
fn from(val: ash::vk::Rect2D) -> Self {
Scissor {
offset: [val.offset.x as u32, val.offset.y as u32],
extent: [val.extent.width, val.extent.height],
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use super::{FullScreenExclusive, Win32Monitor}; use super::{FullScreenExclusive, PresentGravityFlags, PresentScalingFlags, Win32Monitor};
use crate::{ use crate::{
cache::OnceCache, cache::OnceCache,
device::physical::PhysicalDevice, device::physical::PhysicalDevice,
@ -15,25 +15,23 @@ use crate::{
image::ImageUsage, image::ImageUsage,
instance::{Instance, InstanceExtensions}, instance::{Instance, InstanceExtensions},
macros::{impl_id_counter, vulkan_bitflags_enum, vulkan_enum}, macros::{impl_id_counter, vulkan_bitflags_enum, vulkan_enum},
swapchain::{ swapchain::display::{DisplayMode, DisplayPlane},
display::{DisplayMode, DisplayPlane}, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, VulkanError,
SurfaceSwapchainLock, VulkanObject,
},
OomError, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, VulkanObject,
}; };
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
use objc::{class, msg_send, runtime::Object, sel, sel_impl}; use objc::{class, msg_send, runtime::Object, sel, sel_impl};
use raw_window_handle::{ use raw_window_handle::{
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
}; };
use smallvec::SmallVec;
use std::{ use std::{
any::Any, any::Any,
error::Error, fmt::{Debug, Error as FmtError, Formatter},
fmt::{Debug, Display, Error as FmtError, Formatter},
mem::MaybeUninit, mem::MaybeUninit,
num::NonZeroU64, num::NonZeroU64,
ptr, ptr,
sync::{atomic::AtomicBool, Arc}, sync::Arc,
}; };
/// Represents a surface on the screen. /// Represents a surface on the screen.
@ -45,9 +43,6 @@ pub struct Surface {
id: NonZeroU64, id: NonZeroU64,
api: SurfaceApi, api: SurfaceApi,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
// If true, a swapchain has been associated to this surface, and that any new swapchain
// creation should be forbidden.
has_swapchain: AtomicBool,
// FIXME: This field is never set. // FIXME: This field is never set.
#[cfg(target_os = "ios")] #[cfg(target_os = "ios")]
metal_layer: IOSMetalLayer, metal_layer: IOSMetalLayer,
@ -88,7 +83,7 @@ impl Surface {
pub fn from_window( pub fn from_window(
instance: Arc<Instance>, instance: Arc<Instance>,
window: Arc<impl HasRawWindowHandle + HasRawDisplayHandle + Any + Send + Sync>, window: Arc<impl HasRawWindowHandle + HasRawDisplayHandle + Any + Send + Sync>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
let mut surface = unsafe { Self::from_window_ref(instance, &*window) }?; let mut surface = unsafe { Self::from_window_ref(instance, &*window) }?;
Arc::get_mut(&mut surface).unwrap().object = Some(window); Arc::get_mut(&mut surface).unwrap().object = Some(window);
@ -104,7 +99,7 @@ impl Surface {
pub unsafe fn from_window_ref( pub unsafe fn from_window_ref(
instance: Arc<Instance>, instance: Arc<Instance>,
window: &(impl HasRawWindowHandle + HasRawDisplayHandle), window: &(impl HasRawWindowHandle + HasRawDisplayHandle),
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
match (window.raw_window_handle(), window.raw_display_handle()) { match (window.raw_window_handle(), window.raw_display_handle()) {
(RawWindowHandle::AndroidNdk(window), RawDisplayHandle::Android(_display)) => { (RawWindowHandle::AndroidNdk(window), RawDisplayHandle::Android(_display)) => {
Self::from_android(instance, window.a_native_window, None) Self::from_android(instance, window.a_native_window, None)
@ -159,7 +154,6 @@ impl Surface {
id: Self::next_id(), id: Self::next_id(),
api, api,
object, object,
has_swapchain: AtomicBool::new(false),
#[cfg(target_os = "ios")] #[cfg(target_os = "ios")]
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
surface_formats: OnceCache::new(), surface_formats: OnceCache::new(),
@ -175,19 +169,19 @@ impl Surface {
pub fn headless( pub fn headless(
instance: Arc<Instance>, instance: Arc<Instance>,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_headless(&instance)?; Self::validate_headless(&instance)?;
unsafe { Ok(Self::headless_unchecked(instance, object)?) } unsafe { Ok(Self::headless_unchecked(instance, object)?) }
} }
fn validate_headless(instance: &Instance) -> Result<(), SurfaceCreationError> { fn validate_headless(instance: &Instance) -> Result<(), ValidationError> {
if !instance.enabled_extensions().ext_headless_surface { if !instance.enabled_extensions().ext_headless_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::headless`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_headless_surface", "ext_headless_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -235,7 +229,7 @@ impl Surface {
pub fn from_display_plane( pub fn from_display_plane(
display_mode: &DisplayMode, display_mode: &DisplayMode,
plane: &DisplayPlane, plane: &DisplayPlane,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_display_plane(display_mode, plane)?; Self::validate_from_display_plane(display_mode, plane)?;
unsafe { Ok(Self::from_display_plane_unchecked(display_mode, plane)?) } unsafe { Ok(Self::from_display_plane_unchecked(display_mode, plane)?) }
@ -244,7 +238,7 @@ impl Surface {
fn validate_from_display_plane( fn validate_from_display_plane(
display_mode: &DisplayMode, display_mode: &DisplayMode,
plane: &DisplayPlane, plane: &DisplayPlane,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !display_mode if !display_mode
.display() .display()
.physical_device() .physical_device()
@ -252,11 +246,11 @@ impl Surface {
.enabled_extensions() .enabled_extensions()
.khr_display .khr_display
{ {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_display_plane`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_display", "khr_display",
)])]), )])]),
..Default::default()
}); });
} }
@ -325,7 +319,7 @@ impl Surface {
instance: Arc<Instance>, instance: Arc<Instance>,
window: *const W, window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_android(&instance, window)?; Self::validate_from_android(&instance, window)?;
Ok(Self::from_android_unchecked(instance, window, object)?) Ok(Self::from_android_unchecked(instance, window, object)?)
@ -334,13 +328,13 @@ impl Surface {
fn validate_from_android<W>( fn validate_from_android<W>(
instance: &Instance, instance: &Instance,
_window: *const W, _window: *const W,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().khr_android_surface { if !instance.enabled_extensions().khr_android_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_android`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_android_surface", "khr_android_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -397,7 +391,7 @@ impl Surface {
dfb: *const D, dfb: *const D,
surface: *const S, surface: *const S,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_directfb(&instance, dfb, surface)?; Self::validate_from_directfb(&instance, dfb, surface)?;
Ok(Self::from_directfb_unchecked( Ok(Self::from_directfb_unchecked(
@ -409,13 +403,13 @@ impl Surface {
instance: &Instance, instance: &Instance,
_dfb: *const D, _dfb: *const D,
_surface: *const S, _surface: *const S,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().ext_directfb_surface { if !instance.enabled_extensions().ext_directfb_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_directfb`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_directfb_surface", "ext_directfb_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -475,7 +469,7 @@ impl Surface {
instance: Arc<Instance>, instance: Arc<Instance>,
image_pipe_handle: ash::vk::zx_handle_t, image_pipe_handle: ash::vk::zx_handle_t,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_fuchsia_image_pipe(&instance, image_pipe_handle)?; Self::validate_from_fuchsia_image_pipe(&instance, image_pipe_handle)?;
Ok(Self::from_fuchsia_image_pipe_unchecked( Ok(Self::from_fuchsia_image_pipe_unchecked(
@ -488,13 +482,13 @@ impl Surface {
fn validate_from_fuchsia_image_pipe( fn validate_from_fuchsia_image_pipe(
instance: &Instance, instance: &Instance,
_image_pipe_handle: ash::vk::zx_handle_t, _image_pipe_handle: ash::vk::zx_handle_t,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().fuchsia_imagepipe_surface { if !instance.enabled_extensions().fuchsia_imagepipe_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_fuchsia_image_pipe`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"fuchsia_imagepipe_surface", "fuchsia_imagepipe_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -550,7 +544,7 @@ impl Surface {
instance: Arc<Instance>, instance: Arc<Instance>,
stream_descriptor: ash::vk::GgpStreamDescriptor, stream_descriptor: ash::vk::GgpStreamDescriptor,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_ggp_stream_descriptor(&instance, stream_descriptor)?; Self::validate_from_ggp_stream_descriptor(&instance, stream_descriptor)?;
Ok(Self::from_ggp_stream_descriptor_unchecked( Ok(Self::from_ggp_stream_descriptor_unchecked(
@ -563,13 +557,13 @@ impl Surface {
fn validate_from_ggp_stream_descriptor( fn validate_from_ggp_stream_descriptor(
instance: &Instance, instance: &Instance,
_stream_descriptor: ash::vk::GgpStreamDescriptor, _stream_descriptor: ash::vk::GgpStreamDescriptor,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().ggp_stream_descriptor_surface { if !instance.enabled_extensions().ggp_stream_descriptor_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_ggp_stream_descriptor`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ggp_stream_descriptor_surface", "ggp_stream_descriptor_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -627,7 +621,7 @@ impl Surface {
instance: Arc<Instance>, instance: Arc<Instance>,
metal_layer: IOSMetalLayer, metal_layer: IOSMetalLayer,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_ios(&instance, &metal_layer)?; Self::validate_from_ios(&instance, &metal_layer)?;
Ok(Self::from_ios_unchecked(instance, metal_layer, object)?) Ok(Self::from_ios_unchecked(instance, metal_layer, object)?)
@ -637,13 +631,13 @@ impl Surface {
fn validate_from_ios( fn validate_from_ios(
instance: &Instance, instance: &Instance,
_metal_layer: &IOSMetalLayer, _metal_layer: &IOSMetalLayer,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().mvk_ios_surface { if !instance.enabled_extensions().mvk_ios_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_ios`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"mvk_ios_surface", "mvk_ios_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -704,7 +698,7 @@ impl Surface {
instance: Arc<Instance>, instance: Arc<Instance>,
view: *const V, view: *const V,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_mac_os(&instance, view)?; Self::validate_from_mac_os(&instance, view)?;
Ok(Self::from_mac_os_unchecked(instance, view, object)?) Ok(Self::from_mac_os_unchecked(instance, view, object)?)
@ -714,13 +708,13 @@ impl Surface {
fn validate_from_mac_os<V>( fn validate_from_mac_os<V>(
instance: &Instance, instance: &Instance,
_view: *const V, _view: *const V,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().mvk_macos_surface { if !instance.enabled_extensions().mvk_macos_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_mac_os`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"mvk_macos_surface", "mvk_macos_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -779,7 +773,7 @@ impl Surface {
instance: Arc<Instance>, instance: Arc<Instance>,
layer: *const L, layer: *const L,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_metal(&instance, layer)?; Self::validate_from_metal(&instance, layer)?;
Ok(Self::from_metal_unchecked(instance, layer, object)?) Ok(Self::from_metal_unchecked(instance, layer, object)?)
@ -788,13 +782,13 @@ impl Surface {
fn validate_from_metal<L>( fn validate_from_metal<L>(
instance: &Instance, instance: &Instance,
_layer: *const L, _layer: *const L,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().ext_metal_surface { if !instance.enabled_extensions().ext_metal_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_metal`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_metal_surface", "ext_metal_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -848,7 +842,7 @@ impl Surface {
context: *const C, context: *const C,
window: *const W, window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_qnx_screen(&instance, context, window)?; Self::validate_from_qnx_screen(&instance, context, window)?;
Ok(Self::from_qnx_screen_unchecked( Ok(Self::from_qnx_screen_unchecked(
@ -860,13 +854,13 @@ impl Surface {
instance: &Instance, instance: &Instance,
_context: *const C, _context: *const C,
_window: *const W, _window: *const W,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().qnx_screen_surface { if !instance.enabled_extensions().qnx_screen_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_qnx_screen`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"qnx_screen_surface", "qnx_screen_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -926,22 +920,19 @@ impl Surface {
instance: Arc<Instance>, instance: Arc<Instance>,
window: *const W, window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_vi(&instance, window)?; Self::validate_from_vi(&instance, window)?;
Ok(Self::from_vi_unchecked(instance, window, object)?) Ok(Self::from_vi_unchecked(instance, window, object)?)
} }
fn validate_from_vi<W>( fn validate_from_vi<W>(instance: &Instance, _window: *const W) -> Result<(), ValidationError> {
instance: &Instance,
_window: *const W,
) -> Result<(), SurfaceCreationError> {
if !instance.enabled_extensions().nn_vi_surface { if !instance.enabled_extensions().nn_vi_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_vi`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"nn_vi_surface", "nn_vi_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -1000,7 +991,7 @@ impl Surface {
display: *const D, display: *const D,
surface: *const S, surface: *const S,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_wayland(&instance, display, surface)?; Self::validate_from_wayland(&instance, display, surface)?;
Ok(Self::from_wayland_unchecked( Ok(Self::from_wayland_unchecked(
@ -1012,13 +1003,13 @@ impl Surface {
instance: &Instance, instance: &Instance,
_display: *const D, _display: *const D,
_surface: *const S, _surface: *const S,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().khr_wayland_surface { if !instance.enabled_extensions().khr_wayland_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_wayland`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_wayland_surface", "khr_wayland_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -1082,7 +1073,7 @@ impl Surface {
hinstance: *const I, hinstance: *const I,
hwnd: *const W, hwnd: *const W,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_win32(&instance, hinstance, hwnd)?; Self::validate_from_win32(&instance, hinstance, hwnd)?;
Ok(Self::from_win32_unchecked( Ok(Self::from_win32_unchecked(
@ -1094,13 +1085,13 @@ impl Surface {
instance: &Instance, instance: &Instance,
_hinstance: *const I, _hinstance: *const I,
_hwnd: *const W, _hwnd: *const W,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().khr_win32_surface { if !instance.enabled_extensions().khr_win32_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_win32`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_win32_surface", "khr_win32_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -1164,7 +1155,7 @@ impl Surface {
connection: *const C, connection: *const C,
window: ash::vk::xcb_window_t, window: ash::vk::xcb_window_t,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_xcb(&instance, connection, window)?; Self::validate_from_xcb(&instance, connection, window)?;
Ok(Self::from_xcb_unchecked( Ok(Self::from_xcb_unchecked(
@ -1176,13 +1167,13 @@ impl Surface {
instance: &Instance, instance: &Instance,
_connection: *const C, _connection: *const C,
_window: ash::vk::xcb_window_t, _window: ash::vk::xcb_window_t,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().khr_xcb_surface { if !instance.enabled_extensions().khr_xcb_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_xcb`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_xcb_surface", "khr_xcb_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -1246,7 +1237,7 @@ impl Surface {
display: *const D, display: *const D,
window: ash::vk::Window, window: ash::vk::Window,
object: Option<Arc<dyn Any + Send + Sync>>, object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, SurfaceCreationError> { ) -> Result<Arc<Self>, VulkanError> {
Self::validate_from_xlib(&instance, display, window)?; Self::validate_from_xlib(&instance, display, window)?;
Ok(Self::from_xlib_unchecked( Ok(Self::from_xlib_unchecked(
@ -1258,13 +1249,13 @@ impl Surface {
instance: &Instance, instance: &Instance,
_display: *const D, _display: *const D,
_window: ash::vk::Window, _window: ash::vk::Window,
) -> Result<(), SurfaceCreationError> { ) -> Result<(), ValidationError> {
if !instance.enabled_extensions().khr_xlib_surface { if !instance.enabled_extensions().khr_xlib_surface {
return Err(SurfaceCreationError::RequirementNotMet { return Err(ValidationError {
required_for: "`Surface::from_xlib`",
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension( requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_xlib_surface", "khr_xlib_surface",
)])]), )])]),
..Default::default()
}); });
} }
@ -1379,7 +1370,6 @@ impl Debug for Surface {
instance, instance,
api, api,
object: _, object: _,
has_swapchain,
.. ..
} = self; } = self;
@ -1388,18 +1378,10 @@ impl Debug for Surface {
.field("instance", instance) .field("instance", instance)
.field("api", api) .field("api", api)
.field("window", &()) .field("window", &())
.field("has_swapchain", &has_swapchain)
.finish() .finish()
} }
} }
unsafe impl SurfaceSwapchainLock for Surface {
#[inline]
fn flag(&self) -> &AtomicBool {
&self.has_swapchain
}
}
/// Get sublayer from iOS main view (ui_view). The sublayer is created as `CAMetalLayer`. /// Get sublayer from iOS main view (ui_view). The sublayer is created as `CAMetalLayer`.
#[cfg(target_os = "ios")] #[cfg(target_os = "ios")]
unsafe fn get_metal_layer_ios(ui_view: *mut std::ffi::c_void) -> IOSMetalLayer { unsafe fn get_metal_layer_ios(ui_view: *mut std::ffi::c_void) -> IOSMetalLayer {
@ -1447,63 +1429,6 @@ unsafe fn get_metal_layer_macos(ns_view: *mut std::ffi::c_void) -> *mut Object {
} }
} }
/// Error that can happen when creating a surface.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SurfaceCreationError {
/// Not enough memory.
OomError(OomError),
RequirementNotMet {
required_for: &'static str,
requires_one_of: RequiresOneOf,
},
}
impl Error for SurfaceCreationError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
SurfaceCreationError::OomError(err) => Some(err),
_ => None,
}
}
}
impl Display for SurfaceCreationError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match self {
Self::OomError(_) => write!(f, "not enough memory available"),
Self::RequirementNotMet {
required_for,
requires_one_of,
} => write!(
f,
"a requirement was not met for: {}; requires one of: {}",
required_for, requires_one_of,
),
}
}
}
impl From<OomError> for SurfaceCreationError {
fn from(err: OomError) -> SurfaceCreationError {
SurfaceCreationError::OomError(err)
}
}
impl From<RuntimeError> for SurfaceCreationError {
fn from(err: RuntimeError) -> SurfaceCreationError {
match err {
err @ RuntimeError::OutOfHostMemory => {
SurfaceCreationError::OomError(OomError::from(err))
}
err @ RuntimeError::OutOfDeviceMemory => {
SurfaceCreationError::OomError(OomError::from(err))
}
_ => panic!("unexpected error: {:?}", err),
}
}
}
/// The windowing API that was used to construct a surface. /// The windowing API that was used to construct a surface.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive] #[non_exhaustive]
@ -1882,8 +1807,21 @@ vulkan_enum! {
/// [`PhysicalDevice::surface_formats`]: crate::device::physical::PhysicalDevice::surface_formats /// [`PhysicalDevice::surface_formats`]: crate::device::physical::PhysicalDevice::surface_formats
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SurfaceInfo { pub struct SurfaceInfo {
/// If this is `Some`, the
/// [`ext_surface_maintenance1`](crate::instance::InstanceExtensions::ext_surface_maintenance1)
/// extension must be enabled on the instance.
pub present_mode: Option<PresentMode>,
/// If this is not [`FullScreenExclusive::Default`], the
/// [`ext_full_screen_exclusive`](crate::device::DeviceExtensions::ext_full_screen_exclusive)
/// extension must be supported by the physical device.
pub full_screen_exclusive: FullScreenExclusive, pub full_screen_exclusive: FullScreenExclusive,
/// If `full_screen_exclusive` is [`FullScreenExclusive::ApplicationControlled`], and the
/// surface being queried is a Win32 surface, then this must be `Some`. Otherwise, it must be
/// `None`.
pub win32_monitor: Option<Win32Monitor>, pub win32_monitor: Option<Win32Monitor>,
pub _ne: crate::NonExhaustive, pub _ne: crate::NonExhaustive,
} }
@ -1891,6 +1829,7 @@ impl Default for SurfaceInfo {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
Self { Self {
present_mode: None,
full_screen_exclusive: FullScreenExclusive::Default, full_screen_exclusive: FullScreenExclusive::Default,
win32_monitor: None, win32_monitor: None,
_ne: crate::NonExhaustive(()), _ne: crate::NonExhaustive(()),
@ -1901,15 +1840,41 @@ impl Default for SurfaceInfo {
impl SurfaceInfo { impl SurfaceInfo {
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> { pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
let &Self { let &Self {
present_mode,
full_screen_exclusive, full_screen_exclusive,
win32_monitor: _, win32_monitor: _,
_ne: _, _ne: _,
} = self; } = self;
if !physical_device if let Some(present_mode) = present_mode {
.supported_extensions() if !physical_device
.ext_full_screen_exclusive .instance()
&& full_screen_exclusive != FullScreenExclusive::Default .enabled_extensions()
.ext_surface_maintenance1
{
return Err(ValidationError {
context: "present_mode".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::InstanceExtension("ext_surface_maintenance1"),
])]),
..Default::default()
});
}
present_mode
.validate_physical_device(physical_device)
.map_err(|err| ValidationError {
context: "present_mode".into(),
vuids: &["VUID-VkSurfacePresentModeEXT-presentMode-parameter"],
..ValidationError::from_requirement(err)
})?;
}
if full_screen_exclusive != FullScreenExclusive::Default
&& !physical_device
.supported_extensions()
.ext_full_screen_exclusive
{ {
return Err(ValidationError { return Err(ValidationError {
context: "full_screen_exclusive".into(), context: "full_screen_exclusive".into(),
@ -1972,8 +1937,9 @@ pub struct SurfaceCapabilities {
/// you may still get out of memory errors. /// you may still get out of memory errors.
pub max_image_count: Option<u32>, pub max_image_count: Option<u32>,
/// The current dimensions of the surface. `None` means that the surface's dimensions will /// The current dimensions of the surface.
/// depend on the dimensions of the swapchain that you are going to create. ///
/// `None` means that the surface's dimensions will depend on the dimensions of the swapchain.
pub current_extent: Option<[u32; 2]>, pub current_extent: Option<[u32; 2]>,
/// Minimum width and height of a swapchain that uses this surface. /// Minimum width and height of a swapchain that uses this surface.
@ -1998,6 +1964,49 @@ pub struct SurfaceCapabilities {
/// the `color_attachment` usage is guaranteed to be supported. /// the `color_attachment` usage is guaranteed to be supported.
pub supported_usage_flags: ImageUsage, pub supported_usage_flags: ImageUsage,
/// When [`SurfaceInfo::present_mode`] is provided,
/// lists that present mode and any modes that are compatible with that present mode.
///
/// If [`SurfaceInfo::present_mode`] was not provided, the value will be empty.
pub compatible_present_modes: SmallVec<[PresentMode; PresentMode::COUNT]>,
/// When [`SurfaceInfo::present_mode`] is provided,
/// the supported present scaling modes for the queried present mode.
///
/// If [`SurfaceInfo::present_mode`] was not provided, the value will be empty.
pub supported_present_scaling: PresentScalingFlags,
/// When [`SurfaceInfo::present_mode`] is provided,
/// the supported present gravity modes, horizontally and vertically,
/// for the queried present mode.
///
/// If [`SurfaceInfo::present_mode`] was not provided, both values will be empty.
pub supported_present_gravity: [PresentGravityFlags; 2],
/// When [`SurfaceInfo::present_mode`] is provided,
/// the smallest allowed extent for a swapchain, if it uses the queried present mode, and
/// one of the scaling modes in `supported_present_scaling`.
///
/// This is never greater than [`SurfaceCapabilities::min_image_extent`].
///
/// `None` means that the surface's dimensions will depend on the dimensions of the swapchain.
///
/// If [`SurfaceInfo::present_mode`] was not provided, this is will be equal to
/// `min_image_extent`.
pub min_scaled_image_extent: Option<[u32; 2]>,
/// When [`SurfaceInfo::present_mode`] is provided,
/// the largest allowed extent for a swapchain, if it uses the queried present mode, and
/// one of the scaling modes in `supported_present_scaling`.
///
/// This is never less than [`SurfaceCapabilities::max_image_extent`].
///
/// `None` means that the surface's dimensions will depend on the dimensions of the swapchain.
///
/// If [`SurfaceInfo::present_mode`] was not provided, this is will be equal to
/// `max_image_extent`.
pub max_scaled_image_extent: Option<[u32; 2]>,
/// Whether creating a protected swapchain is supported. /// Whether creating a protected swapchain is supported.
pub supports_protected: bool, pub supports_protected: bool,
@ -2008,8 +2017,7 @@ pub struct SurfaceCapabilities {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
swapchain::{Surface, SurfaceCreationError}, swapchain::Surface, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanError,
Requires, RequiresAllOf, RequiresOneOf,
}; };
use std::ptr; use std::ptr;
@ -2017,11 +2025,11 @@ mod tests {
fn khr_win32_surface_ext_missing() { fn khr_win32_surface_ext_missing() {
let instance = instance!(); let instance = instance!();
match unsafe { Surface::from_win32(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) } { match unsafe { Surface::from_win32(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) } {
Err(SurfaceCreationError::RequirementNotMet { Err(VulkanError::ValidationError(ValidationError {
requires_one_of: requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_win32_surface")])]), RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_win32_surface")])]),
.. ..
}) => (), })) => (),
_ => panic!(), _ => panic!(),
} }
} }
@ -2030,11 +2038,11 @@ mod tests {
fn khr_xcb_surface_ext_missing() { fn khr_xcb_surface_ext_missing() {
let instance = instance!(); let instance = instance!();
match unsafe { Surface::from_xcb(instance, ptr::null::<u8>(), 0, None) } { match unsafe { Surface::from_xcb(instance, ptr::null::<u8>(), 0, None) } {
Err(SurfaceCreationError::RequirementNotMet { Err(VulkanError::ValidationError(ValidationError {
requires_one_of: requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_xcb_surface")])]), RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_xcb_surface")])]),
.. ..
}) => (), })) => (),
_ => panic!(), _ => panic!(),
} }
} }
@ -2043,11 +2051,11 @@ mod tests {
fn khr_xlib_surface_ext_missing() { fn khr_xlib_surface_ext_missing() {
let instance = instance!(); let instance = instance!();
match unsafe { Surface::from_xlib(instance, ptr::null::<u8>(), 0, None) } { match unsafe { Surface::from_xlib(instance, ptr::null::<u8>(), 0, None) } {
Err(SurfaceCreationError::RequirementNotMet { Err(VulkanError::ValidationError(ValidationError {
requires_one_of: requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_xlib_surface")])]), RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_xlib_surface")])]),
.. ..
}) => (), })) => (),
_ => panic!(), _ => panic!(),
} }
} }
@ -2057,11 +2065,11 @@ mod tests {
let instance = instance!(); let instance = instance!();
match unsafe { Surface::from_wayland(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) } match unsafe { Surface::from_wayland(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) }
{ {
Err(SurfaceCreationError::RequirementNotMet { Err(VulkanError::ValidationError(ValidationError {
requires_one_of: requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_wayland_surface")])]), RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_wayland_surface")])]),
.. ..
}) => (), })) => (),
_ => panic!(), _ => panic!(),
} }
} }
@ -2070,11 +2078,11 @@ mod tests {
fn khr_android_surface_ext_missing() { fn khr_android_surface_ext_missing() {
let instance = instance!(); let instance = instance!();
match unsafe { Surface::from_android(instance, ptr::null::<u8>(), None) } { match unsafe { Surface::from_android(instance, ptr::null::<u8>(), None) } {
Err(SurfaceCreationError::RequirementNotMet { Err(VulkanError::ValidationError(ValidationError {
requires_one_of: requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_android_surface")])]), RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_android_surface")])]),
.. ..
}) => (), })) => (),
_ => panic!(), _ => panic!(),
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -310,8 +310,12 @@ where
.map_err(|err| OutcomeErr::Full(err.into())) .map_err(|err| OutcomeErr::Full(err.into()))
} }
SubmitAnyBuilder::QueuePresent(present_info) => { SubmitAnyBuilder::QueuePresent(present_info) => {
let intermediary_result = if partially_flushed { if partially_flushed {
Ok(()) queue
.with(|mut q| {
q.submit_unchecked([Default::default()], Some(new_fence.clone()))
})
.map_err(|err| OutcomeErr::Partial(err.into()))
} else { } else {
// VUID-VkPresentIdKHR-presentIds-04999 // VUID-VkPresentIdKHR-presentIds-04999
for swapchain_info in &present_info.swapchain_infos { for swapchain_info in &present_info.swapchain_infos {
@ -334,19 +338,22 @@ where
} }
} }
queue let intermediary_result = queue
.with(|mut q| q.present_unchecked(present_info))? .with(|mut q| q.present_unchecked(present_info))?
.map(|r| r.map(|_| ())) .map(|r| r.map(|_| ()))
.fold(Ok(()), Result::and) .fold(Ok(()), Result::and);
};
match intermediary_result { match intermediary_result {
Ok(()) => queue Ok(()) => queue
.with(|mut q| { .with(|mut q| {
q.submit_unchecked([Default::default()], Some(new_fence.clone())) q.submit_unchecked(
}) [Default::default()],
.map_err(|err| OutcomeErr::Partial(err.into())), Some(new_fence.clone()),
Err(err) => Err(OutcomeErr::Full(err.into())), )
})
.map_err(|err| OutcomeErr::Partial(err.into())),
Err(err) => Err(OutcomeErr::Full(err.into())),
}
} }
} }
}; };

View File

@ -597,6 +597,10 @@ pub enum FlushError {
/// for the same swapchain. /// for the same swapchain.
PresentIdLessThanOrEqual, PresentIdLessThanOrEqual,
/// A new present mode was provided, but this mode was not one of the valid present modes
/// that the swapchain was created with.
PresentModeNotValid,
/// Access to a resource has been denied. /// Access to a resource has been denied.
ResourceAccessError { ResourceAccessError {
error: AccessError, error: AccessError,
@ -615,9 +619,9 @@ pub enum FlushError {
impl Error for FlushError { impl Error for FlushError {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match self { match self {
FlushError::AccessError(err) => Some(err), Self::AccessError(err) => Some(err),
FlushError::OomError(err) => Some(err), Self::OomError(err) => Some(err),
FlushError::ResourceAccessError { error, .. } => Some(error), Self::ResourceAccessError { error, .. } => Some(error),
_ => None, _ => None,
} }
} }
@ -629,27 +633,31 @@ impl Display for FlushError {
f, f,
"{}", "{}",
match self { match self {
FlushError::AccessError(_) => "access to a resource has been denied", Self::AccessError(_) => "access to a resource has been denied",
FlushError::OomError(_) => "not enough memory", Self::OomError(_) => "not enough memory",
FlushError::DeviceLost => "the connection to the device has been lost", Self::DeviceLost => "the connection to the device has been lost",
FlushError::SurfaceLost => "the surface of this swapchain is no longer valid", Self::SurfaceLost => "the surface of this swapchain is no longer valid",
FlushError::OutOfDate => "the swapchain needs to be recreated", Self::OutOfDate => "the swapchain needs to be recreated",
FlushError::FullScreenExclusiveModeLost => { Self::FullScreenExclusiveModeLost => {
"the swapchain no longer has full screen exclusivity" "the swapchain no longer has full screen exclusivity"
} }
FlushError::Timeout => { Self::Timeout => {
"the flush operation needed to block, but the timeout has elapsed" "the flush operation needed to block, but the timeout has elapsed"
} }
FlushError::PresentIdLessThanOrEqual => { Self::PresentIdLessThanOrEqual => {
"present id is less than or equal to previous" "present id is less than or equal to previous"
} }
FlushError::ResourceAccessError { .. } => "access to a resource has been denied", Self::PresentModeNotValid => {
FlushError::OneTimeSubmitAlreadySubmitted => { "a new present mode was provided, but this mode was not one of the valid \
present modes that the swapchain was created with"
}
Self::ResourceAccessError { .. } => "access to a resource has been denied",
Self::OneTimeSubmitAlreadySubmitted => {
"the command buffer or one of the secondary command buffers it executes was \ "the command buffer or one of the secondary command buffers it executes was \
created with the \"one time submit\" flag, but has already been submitted in \ created with the \"one time submit\" flag, but has already been submitted in \
the past" the past"
} }
FlushError::ExclusiveAlreadyInUse => { Self::ExclusiveAlreadyInUse => {
"the command buffer or one of the secondary command buffers it executes is \ "the command buffer or one of the secondary command buffers it executes is \
already in use was not created with the \"concurrent\" flag" already in use was not created with the \"concurrent\" flag"
} }
@ -660,7 +668,7 @@ impl Display for FlushError {
impl From<AccessError> for FlushError { impl From<AccessError> for FlushError {
fn from(err: AccessError) -> FlushError { fn from(err: AccessError) -> FlushError {
FlushError::AccessError(err) Self::AccessError(err)
} }
} }
@ -682,9 +690,9 @@ impl From<RuntimeError> for FlushError {
impl From<FenceError> for FlushError { impl From<FenceError> for FlushError {
fn from(err: FenceError) -> FlushError { fn from(err: FenceError) -> FlushError {
match err { match err {
FenceError::OomError(err) => FlushError::OomError(err), FenceError::OomError(err) => Self::OomError(err),
FenceError::Timeout => FlushError::Timeout, FenceError::Timeout => Self::Timeout,
FenceError::DeviceLost => FlushError::DeviceLost, FenceError::DeviceLost => Self::DeviceLost,
_ => unreachable!(), _ => unreachable!(),
} }
} }