mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 16:25:31 +00:00
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:
parent
2d6ff1061c
commit
da09477d01
@ -85,7 +85,7 @@ use vulkano::{
|
||||
sampler::{Sampler, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -545,21 +545,19 @@ fn main() {
|
||||
channel.send(()).unwrap();
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) =
|
||||
match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers = window_size_dependent_setup(
|
||||
|
@ -45,7 +45,7 @@ use vulkano::{
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -292,23 +292,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) =
|
||||
match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers = window_size_dependent_setup(
|
||||
|
@ -22,7 +22,7 @@ use vulkano::{
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -175,22 +175,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
width = swapchain.image_extent()[0];
|
||||
|
@ -42,7 +42,7 @@ use vulkano::{
|
||||
memory::allocator::StandardMemoryAllocator,
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -199,22 +199,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
let new_images = new_images
|
||||
.into_iter()
|
||||
.map(|image| ImageView::new_default(image).unwrap())
|
||||
|
@ -50,10 +50,7 @@ mod linux {
|
||||
},
|
||||
render_pass::{Framebuffer, RenderPass, Subpass},
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
swapchain::{AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo},
|
||||
sync::{
|
||||
now,
|
||||
semaphore::{
|
||||
@ -287,20 +284,21 @@ mod linux {
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) =
|
||||
match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: window.inner_size().into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => {
|
||||
return
|
||||
}
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers = window_size_dependent_setup(
|
||||
|
@ -48,7 +48,7 @@ use vulkano::{
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -421,22 +421,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers =
|
||||
|
@ -46,7 +46,7 @@ use vulkano::{
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -347,22 +347,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers =
|
||||
|
@ -55,7 +55,7 @@ use vulkano::{
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -368,22 +368,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers =
|
||||
|
@ -62,7 +62,7 @@ use vulkano::{
|
||||
single_pass_renderpass,
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -384,23 +384,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) =
|
||||
match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers = window_size_dependent_setup(
|
||||
|
@ -43,7 +43,7 @@ use vulkano::{
|
||||
single_pass_renderpass,
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -364,23 +364,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) =
|
||||
match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers = window_size_dependent_setup(
|
||||
|
@ -46,7 +46,7 @@ use vulkano::{
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -415,22 +415,21 @@ fn main() {
|
||||
previous_frame_end,
|
||||
} = window_surfaces.get_mut(&window_id).unwrap();
|
||||
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if *recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
*swapchain = new_swapchain;
|
||||
*framebuffers =
|
||||
|
@ -44,7 +44,7 @@ use vulkano::{
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -382,22 +382,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers = window_size_dependent_setup(
|
||||
|
@ -44,7 +44,7 @@ use vulkano::{
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -341,22 +341,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers =
|
||||
|
@ -52,7 +52,7 @@ use vulkano::{
|
||||
shader::ShaderModule,
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -312,22 +312,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers =
|
||||
|
@ -47,7 +47,7 @@ use vulkano::{
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -455,22 +455,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers =
|
||||
|
@ -524,8 +524,9 @@ fn main() {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ use vulkano::{
|
||||
shader::EntryPoint,
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -276,23 +276,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) =
|
||||
match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
let (new_pipeline, new_framebuffers) = window_size_dependent_setup(
|
||||
|
@ -52,7 +52,7 @@ use vulkano::{
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -424,22 +424,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers =
|
||||
|
@ -46,7 +46,7 @@ use vulkano::{
|
||||
sampler::{Sampler, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -352,22 +352,21 @@ fn main() {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) = match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
framebuffers =
|
||||
|
@ -52,7 +52,7 @@ use vulkano::{
|
||||
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
Version, VulkanLibrary,
|
||||
@ -527,8 +527,9 @@ fn main() {
|
||||
Event::RedrawEventsCleared => {
|
||||
// Do not draw the frame when the screen dimensions are zero. On Windows, this can
|
||||
// occur when minimizing the application.
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -542,18 +543,12 @@ fn main() {
|
||||
// window size. In this example that includes the swapchain, the framebuffers and
|
||||
// the dynamic state viewport.
|
||||
if recreate_swapchain {
|
||||
let (new_swapchain, new_images) =
|
||||
match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
// This error tends to happen when the user is manually resizing the
|
||||
// window. Simply restarting the loop is the easiest way to fix this
|
||||
// issue.
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
|
||||
|
@ -46,7 +46,7 @@ use vulkano::{
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainCreationError, SwapchainPresentInfo,
|
||||
SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
VulkanLibrary,
|
||||
@ -522,8 +522,9 @@ fn main() {
|
||||
Event::RedrawEventsCleared => {
|
||||
// Do not draw the frame when the screen dimensions are zero. On Windows, this can
|
||||
// occur when minimizing the application.
|
||||
let dimensions = window.inner_size();
|
||||
if dimensions.width == 0 || dimensions.height == 0 {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -539,18 +540,12 @@ fn main() {
|
||||
if recreate_swapchain {
|
||||
// Use the new dimensions of the window.
|
||||
|
||||
let (new_swapchain, new_images) =
|
||||
match swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions.into(),
|
||||
let (new_swapchain, new_images) = swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
..swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
// This error tends to happen when the user is manually resizing the
|
||||
// window. Simply restarting the loop is the easiest way to fix this
|
||||
// issue.
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
swapchain = new_swapchain;
|
||||
|
||||
|
@ -18,8 +18,7 @@ use vulkano::{
|
||||
},
|
||||
memory::allocator::StandardMemoryAllocator,
|
||||
swapchain::{
|
||||
self, AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
|
||||
SwapchainPresentInfo,
|
||||
self, AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo,
|
||||
},
|
||||
sync::{self, FlushError, GpuFuture},
|
||||
};
|
||||
@ -337,17 +336,21 @@ impl VulkanoWindowRenderer {
|
||||
|
||||
/// Recreates swapchain images and image views which follow the window size.
|
||||
fn recreate_swapchain_and_views(&mut self) {
|
||||
let dimensions: [u32; 2] = self.window().inner_size().into();
|
||||
let (new_swapchain, new_images) = match self.swapchain.recreate(SwapchainCreateInfo {
|
||||
image_extent: dimensions,
|
||||
let image_extent: [u32; 2] = self.window().inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let (new_swapchain, new_images) = self
|
||||
.swapchain
|
||||
.recreate(SwapchainCreateInfo {
|
||||
image_extent,
|
||||
// Use present mode from current state
|
||||
present_mode: self.present_mode,
|
||||
..self.swapchain.create_info()
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(SwapchainCreationError::ImageExtentNotSupported { .. }) => return,
|
||||
Err(e) => panic!("failed to recreate swapchain: {e}"),
|
||||
};
|
||||
})
|
||||
.expect("failed to recreate swapchain");
|
||||
|
||||
self.swapchain = new_swapchain;
|
||||
let new_images = new_images
|
||||
|
@ -14,7 +14,7 @@
|
||||
`Surface::from_window` instead"
|
||||
)]
|
||||
#![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)]
|
||||
|
||||
#[cfg(feature = "raw-window-handle")]
|
||||
|
@ -6,17 +6,14 @@ use raw_window_handle::{
|
||||
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
|
||||
};
|
||||
use std::{any::Any, sync::Arc};
|
||||
use vulkano::{
|
||||
instance::Instance,
|
||||
swapchain::{Surface, SurfaceCreationError},
|
||||
};
|
||||
use vulkano::{instance::Instance, swapchain::Surface, VulkanError};
|
||||
|
||||
/// Creates a Vulkan surface from a generic window which implements `HasRawWindowHandle` and thus
|
||||
/// can reveal the OS-dependent handle.
|
||||
pub fn create_surface_from_handle(
|
||||
window: Arc<impl Any + Send + Sync + HasRawWindowHandle + HasRawDisplayHandle>,
|
||||
instance: Arc<Instance>,
|
||||
) -> Result<Arc<Surface>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Surface>, VulkanError> {
|
||||
unsafe {
|
||||
match window.raw_window_handle() {
|
||||
RawWindowHandle::AndroidNdk(h) => {
|
||||
@ -85,7 +82,7 @@ pub fn create_surface_from_handle(
|
||||
pub unsafe fn create_surface_from_handle_ref(
|
||||
window: &(impl HasRawWindowHandle + HasRawDisplayHandle),
|
||||
instance: Arc<Instance>,
|
||||
) -> Result<Arc<Surface>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Surface>, VulkanError> {
|
||||
unsafe {
|
||||
match window.raw_window_handle() {
|
||||
RawWindowHandle::AndroidNdk(h) => {
|
||||
|
@ -5,8 +5,8 @@ use std::{
|
||||
};
|
||||
use vulkano::{
|
||||
instance::{Instance, InstanceExtensions},
|
||||
swapchain::{Surface, SurfaceCreationError},
|
||||
VulkanLibrary,
|
||||
swapchain::Surface,
|
||||
VulkanError, VulkanLibrary,
|
||||
};
|
||||
use winit::{
|
||||
error::OsError as WindowCreationError,
|
||||
@ -37,7 +37,7 @@ pub fn required_extensions(library: &VulkanLibrary) -> InstanceExtensions {
|
||||
pub fn create_surface_from_winit(
|
||||
window: Arc<Window>,
|
||||
instance: Arc<Instance>,
|
||||
) -> Result<Arc<Surface>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Surface>, VulkanError> {
|
||||
unsafe { winit_to_surface(instance, window) }
|
||||
}
|
||||
|
||||
@ -65,7 +65,8 @@ impl<E> VkSurfaceBuild<E> for WindowBuilder {
|
||||
#[derive(Debug)]
|
||||
pub enum CreationError {
|
||||
/// Error when creating the surface.
|
||||
SurfaceCreationError(SurfaceCreationError),
|
||||
VulkanError(VulkanError),
|
||||
|
||||
/// Error when creating the window.
|
||||
WindowCreationError(WindowCreationError),
|
||||
}
|
||||
@ -73,7 +74,7 @@ pub enum CreationError {
|
||||
impl Error for CreationError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
CreationError::SurfaceCreationError(err) => Some(err),
|
||||
CreationError::VulkanError(err) => Some(err),
|
||||
CreationError::WindowCreationError(err) => Some(err),
|
||||
}
|
||||
}
|
||||
@ -85,16 +86,16 @@ impl Display for CreationError {
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
CreationError::SurfaceCreationError(_) => "error while creating the surface",
|
||||
CreationError::VulkanError(_) => "error while creating the surface",
|
||||
CreationError::WindowCreationError(_) => "error while creating the window",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SurfaceCreationError> for CreationError {
|
||||
fn from(err: SurfaceCreationError) -> CreationError {
|
||||
CreationError::SurfaceCreationError(err)
|
||||
impl From<VulkanError> for CreationError {
|
||||
fn from(err: VulkanError) -> CreationError {
|
||||
CreationError::VulkanError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +109,7 @@ impl From<WindowCreationError> for CreationError {
|
||||
unsafe fn winit_to_surface(
|
||||
instance: Arc<Instance>,
|
||||
window: Arc<Window>,
|
||||
) -> Result<Arc<Surface>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Surface>, VulkanError> {
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
use raw_window_handle::RawWindowHandle::AndroidNdk;
|
||||
if let AndroidNdk(handle) = window.raw_window_handle() {
|
||||
@ -127,7 +128,7 @@ unsafe fn winit_to_surface(
|
||||
unsafe fn winit_to_surface(
|
||||
instance: Arc<Instance>,
|
||||
window: Arc<Window>,
|
||||
) -> Result<Arc<Surface>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Surface>, VulkanError> {
|
||||
use winit::platform::{wayland::WindowExtWayland, x11::WindowExtX11};
|
||||
|
||||
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(
|
||||
instance: Arc<Instance>,
|
||||
window: Arc<Window>,
|
||||
) -> Result<Arc<Surface>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Surface>, VulkanError> {
|
||||
use winit::platform::macos::WindowExtMacOS;
|
||||
let layer = get_metal_layer_macos(window.ns_view());
|
||||
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(
|
||||
instance: Arc<Instance>,
|
||||
window: Arc<Window>,
|
||||
) -> Result<Arc<Surface>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Surface>, VulkanError> {
|
||||
use winit::platform::ios::WindowExtIOS;
|
||||
let layer = get_metal_layer_ios(window.ui_view());
|
||||
Surface::from_ios(instance, layer, Some(window))
|
||||
@ -234,7 +235,7 @@ unsafe fn winit_to_surface(
|
||||
unsafe fn winit_to_surface(
|
||||
instance: Arc<Instance>,
|
||||
window: Arc<Window>,
|
||||
) -> Result<Arc<Surface>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Surface>, VulkanError> {
|
||||
use winit::platform::windows::WindowExtWindows;
|
||||
|
||||
Surface::from_win32(
|
||||
|
@ -1387,11 +1387,31 @@ impl PhysicalDevice {
|
||||
.map_err(|err| err.add_context("surface_info"))?;
|
||||
|
||||
let &SurfaceInfo {
|
||||
present_mode,
|
||||
full_screen_exclusive,
|
||||
win32_monitor,
|
||||
_ne: _,
|
||||
} = 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 (
|
||||
surface.api() == SurfaceApi::Win32
|
||||
&& full_screen_exclusive == FullScreenExclusive::ApplicationControlled,
|
||||
@ -1433,6 +1453,7 @@ impl PhysicalDevice {
|
||||
/* Input */
|
||||
|
||||
let SurfaceInfo {
|
||||
present_mode,
|
||||
full_screen_exclusive,
|
||||
win32_monitor,
|
||||
_ne: _,
|
||||
@ -1442,10 +1463,21 @@ impl PhysicalDevice {
|
||||
surface: surface.handle(),
|
||||
..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 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 =
|
||||
full_screen_exclusive_info_vk.insert(ash::vk::SurfaceFullScreenExclusiveInfoEXT {
|
||||
full_screen_exclusive: full_screen_exclusive.into(),
|
||||
@ -1472,7 +1504,11 @@ impl PhysicalDevice {
|
||||
|
||||
let mut capabilities_vk = ash::vk::SurfaceCapabilities2KHR::default();
|
||||
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() {
|
||||
let next = capabilities_full_screen_exclusive_vk
|
||||
@ -1482,12 +1518,35 @@ impl PhysicalDevice {
|
||||
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
|
||||
.instance
|
||||
.enabled_extensions()
|
||||
.khr_surface_protected_capabilities
|
||||
{
|
||||
let next = protected_capabilities_vk
|
||||
let next = capabilities_protected_vk
|
||||
.insert(ash::vk::SurfaceProtectedCapabilitiesKHR::default());
|
||||
|
||||
next.p_next = capabilities_vk.p_next as *mut _;
|
||||
@ -1521,22 +1580,19 @@ impl PhysicalDevice {
|
||||
|
||||
Ok(SurfaceCapabilities {
|
||||
min_image_count: capabilities_vk.surface_capabilities.min_image_count,
|
||||
max_image_count: if capabilities_vk.surface_capabilities.max_image_count == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(capabilities_vk.surface_capabilities.max_image_count)
|
||||
},
|
||||
current_extent: if capabilities_vk.surface_capabilities.current_extent.width
|
||||
== 0xffffffff
|
||||
&& capabilities_vk.surface_capabilities.current_extent.height == 0xffffffff
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some([
|
||||
max_image_count: (capabilities_vk.surface_capabilities.max_image_count != 0)
|
||||
.then_some(capabilities_vk.surface_capabilities.max_image_count),
|
||||
current_extent: (!matches!(
|
||||
capabilities_vk.surface_capabilities.current_extent,
|
||||
ash::vk::Extent2D {
|
||||
width: u32::MAX,
|
||||
height: u32::MAX
|
||||
}
|
||||
))
|
||||
.then_some([
|
||||
capabilities_vk.surface_capabilities.current_extent.width,
|
||||
capabilities_vk.surface_capabilities.current_extent.height,
|
||||
])
|
||||
},
|
||||
]),
|
||||
min_image_extent: [
|
||||
capabilities_vk.surface_capabilities.min_image_extent.width,
|
||||
capabilities_vk.surface_capabilities.min_image_extent.height,
|
||||
@ -1561,14 +1617,75 @@ impl PhysicalDevice {
|
||||
.surface_capabilities
|
||||
.supported_composite_alpha
|
||||
.into(),
|
||||
supported_usage_flags: {
|
||||
let usage =
|
||||
ImageUsage::from(capabilities_vk.surface_capabilities.supported_usage_flags);
|
||||
debug_assert!(usage.intersects(ImageUsage::COLOR_ATTACHMENT)); // specs say that this must be true
|
||||
usage
|
||||
},
|
||||
supported_usage_flags: ImageUsage::from(
|
||||
capabilities_vk.surface_capabilities.supported_usage_flags,
|
||||
),
|
||||
|
||||
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),
|
||||
|
||||
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 {
|
||||
present_mode,
|
||||
full_screen_exclusive,
|
||||
win32_monitor,
|
||||
_ne: _,
|
||||
} = 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
|
||||
.instance
|
||||
.enabled_extensions()
|
||||
@ -1706,46 +1847,52 @@ impl PhysicalDevice {
|
||||
(self.handle, surface_info),
|
||||
|(_, surface_info)| {
|
||||
let &SurfaceInfo {
|
||||
present_mode,
|
||||
full_screen_exclusive,
|
||||
win32_monitor,
|
||||
_ne: _,
|
||||
} = surface_info;
|
||||
|
||||
let mut surface_full_screen_exclusive_info = (full_screen_exclusive
|
||||
!= 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 {
|
||||
let mut info_vk = ash::vk::PhysicalDeviceSurfaceInfo2KHR {
|
||||
surface: surface.handle(),
|
||||
..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) =
|
||||
surface_full_screen_exclusive_info.as_mut()
|
||||
{
|
||||
surface_full_screen_exclusive_info.p_next = surface_info2.p_next as *mut _;
|
||||
surface_info2.p_next =
|
||||
surface_full_screen_exclusive_info as *const _ as *const _;
|
||||
if let Some(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 let Some(surface_full_screen_exclusive_win32_info) =
|
||||
surface_full_screen_exclusive_win32_info.as_mut()
|
||||
{
|
||||
surface_full_screen_exclusive_win32_info.p_next =
|
||||
surface_info2.p_next as *mut _;
|
||||
surface_info2.p_next =
|
||||
surface_full_screen_exclusive_win32_info as *const _ as *const _;
|
||||
if full_screen_exclusive != FullScreenExclusive::Default {
|
||||
let next = full_screen_exclusive_info_vk.insert(
|
||||
ash::vk::SurfaceFullScreenExclusiveInfoEXT {
|
||||
full_screen_exclusive: full_screen_exclusive.into(),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
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();
|
||||
@ -1755,40 +1902,40 @@ impl PhysicalDevice {
|
||||
.enabled_extensions()
|
||||
.khr_get_surface_capabilities2
|
||||
{
|
||||
let surface_format2s = loop {
|
||||
let surface_format2s_vk = loop {
|
||||
let mut count = 0;
|
||||
(fns.khr_get_surface_capabilities2
|
||||
.get_physical_device_surface_formats2_khr)(
|
||||
self.handle(),
|
||||
&surface_info2,
|
||||
&info_vk,
|
||||
&mut count,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
.result()
|
||||
.map_err(RuntimeError::from)?;
|
||||
|
||||
let mut surface_format2s =
|
||||
let mut surface_format2s_vk =
|
||||
vec![ash::vk::SurfaceFormat2KHR::default(); count as usize];
|
||||
let result = (fns
|
||||
.khr_get_surface_capabilities2
|
||||
.get_physical_device_surface_formats2_khr)(
|
||||
self.handle(),
|
||||
&surface_info2,
|
||||
&info_vk,
|
||||
&mut count,
|
||||
surface_format2s.as_mut_ptr(),
|
||||
surface_format2s_vk.as_mut_ptr(),
|
||||
);
|
||||
|
||||
match result {
|
||||
ash::vk::Result::SUCCESS => {
|
||||
surface_format2s.set_len(count as usize);
|
||||
break surface_format2s;
|
||||
surface_format2s_vk.set_len(count as usize);
|
||||
break surface_format2s_vk;
|
||||
}
|
||||
ash::vk::Result::INCOMPLETE => (),
|
||||
err => return Err(RuntimeError::from(err)),
|
||||
}
|
||||
};
|
||||
|
||||
Ok(surface_format2s
|
||||
Ok(surface_format2s_vk
|
||||
.into_iter()
|
||||
.filter_map(|surface_format2| {
|
||||
(surface_format2.surface_format.format.try_into().ok())
|
||||
|
@ -529,8 +529,8 @@ impl<'a> QueueGuard<'a> {
|
||||
states: &mut States<'_>,
|
||||
) -> Result<impl ExactSizeIterator<Item = Result<bool, RuntimeError>>, RuntimeError> {
|
||||
let PresentInfo {
|
||||
ref wait_semaphores,
|
||||
ref swapchain_infos,
|
||||
wait_semaphores,
|
||||
swapchain_infos,
|
||||
_ne: _,
|
||||
} = present_info;
|
||||
|
||||
@ -542,11 +542,13 @@ impl<'a> QueueGuard<'a> {
|
||||
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 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]> =
|
||||
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_modes = false;
|
||||
let mut has_present_regions = false;
|
||||
|
||||
for swapchain_info in swapchain_infos {
|
||||
@ -554,6 +556,7 @@ impl<'a> QueueGuard<'a> {
|
||||
ref swapchain,
|
||||
image_index,
|
||||
present_id,
|
||||
present_mode,
|
||||
ref present_regions,
|
||||
_ne: _,
|
||||
} = swapchain_info;
|
||||
@ -561,6 +564,7 @@ impl<'a> QueueGuard<'a> {
|
||||
swapchains_vk.push(swapchain.handle());
|
||||
image_indices_vk.push(image_index);
|
||||
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());
|
||||
rectangles_vk.push(
|
||||
present_regions
|
||||
@ -573,6 +577,10 @@ impl<'a> QueueGuard<'a> {
|
||||
has_present_ids = true;
|
||||
}
|
||||
|
||||
if present_mode.is_some() {
|
||||
has_present_modes = true;
|
||||
}
|
||||
|
||||
if !present_regions.is_empty() {
|
||||
has_present_regions = true;
|
||||
}
|
||||
@ -589,6 +597,7 @@ impl<'a> QueueGuard<'a> {
|
||||
..Default::default()
|
||||
};
|
||||
let mut present_id_info_vk = None;
|
||||
let mut present_mode_info_vk = None;
|
||||
let mut present_region_info_vk = None;
|
||||
|
||||
if has_present_ids {
|
||||
@ -602,6 +611,17 @@ impl<'a> QueueGuard<'a> {
|
||||
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 {
|
||||
for (present_regions_vk, rectangles_vk) in
|
||||
(present_regions_vk.iter_mut()).zip(rectangles_vk.iter())
|
||||
|
@ -15,7 +15,6 @@ use super::{
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
swapchain::Swapchain,
|
||||
OomError,
|
||||
};
|
||||
use std::{
|
||||
hash::{Hash, Hasher},
|
||||
@ -45,10 +44,10 @@ impl SwapchainImage {
|
||||
handle: ash::vk::Image,
|
||||
swapchain: Arc<Swapchain>,
|
||||
image_index: u32,
|
||||
) -> Result<Arc<SwapchainImage>, OomError> {
|
||||
Ok(Arc::new(SwapchainImage {
|
||||
) -> Arc<SwapchainImage> {
|
||||
Arc::new(SwapchainImage {
|
||||
inner: Arc::new(Image::from_swapchain(handle, swapchain, image_index)),
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the swapchain this image belongs to.
|
||||
|
@ -591,11 +591,16 @@ macro_rules! vulkan_enum {
|
||||
)+
|
||||
}
|
||||
|
||||
$(
|
||||
impl $ty {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) const COUNT: usize = [
|
||||
$(ash::vk::$ty_ffi::$flag_name_ffi.as_raw()),+
|
||||
].len();
|
||||
|
||||
$(
|
||||
$($impls)*
|
||||
}
|
||||
)?
|
||||
}
|
||||
|
||||
impl From<$ty> for ash::vk::$ty_ffi {
|
||||
#[inline]
|
||||
@ -653,6 +658,11 @@ macro_rules! vulkan_enum {
|
||||
}
|
||||
|
||||
impl $ty {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) const COUNT: usize = [
|
||||
$(ash::vk::$ty_ffi::$flag_name_ffi.as_raw()),+
|
||||
].len();
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub(crate) fn validate_device(
|
||||
|
@ -521,13 +521,13 @@ impl From<&Viewport> for ash::vk::Viewport {
|
||||
}
|
||||
}
|
||||
|
||||
/// State of a single scissor box.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
/// A two-dimensional subregion.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
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],
|
||||
|
||||
/// Dimensions in pixels of the box.
|
||||
/// Dimensions of the box.
|
||||
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],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1025
vulkano/src/swapchain/acquire_present.rs
Normal file
1025
vulkano/src/swapchain/acquire_present.rs
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use super::{FullScreenExclusive, Win32Monitor};
|
||||
use super::{FullScreenExclusive, PresentGravityFlags, PresentScalingFlags, Win32Monitor};
|
||||
use crate::{
|
||||
cache::OnceCache,
|
||||
device::physical::PhysicalDevice,
|
||||
@ -15,25 +15,23 @@ use crate::{
|
||||
image::ImageUsage,
|
||||
instance::{Instance, InstanceExtensions},
|
||||
macros::{impl_id_counter, vulkan_bitflags_enum, vulkan_enum},
|
||||
swapchain::{
|
||||
display::{DisplayMode, DisplayPlane},
|
||||
SurfaceSwapchainLock,
|
||||
},
|
||||
OomError, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, VulkanObject,
|
||||
swapchain::display::{DisplayMode, DisplayPlane},
|
||||
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, VulkanError,
|
||||
VulkanObject,
|
||||
};
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
use objc::{class, msg_send, runtime::Object, sel, sel_impl};
|
||||
use raw_window_handle::{
|
||||
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
any::Any,
|
||||
error::Error,
|
||||
fmt::{Debug, Display, Error as FmtError, Formatter},
|
||||
fmt::{Debug, Error as FmtError, Formatter},
|
||||
mem::MaybeUninit,
|
||||
num::NonZeroU64,
|
||||
ptr,
|
||||
sync::{atomic::AtomicBool, Arc},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
/// Represents a surface on the screen.
|
||||
@ -45,9 +43,6 @@ pub struct Surface {
|
||||
id: NonZeroU64,
|
||||
api: SurfaceApi,
|
||||
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.
|
||||
#[cfg(target_os = "ios")]
|
||||
metal_layer: IOSMetalLayer,
|
||||
@ -88,7 +83,7 @@ impl Surface {
|
||||
pub fn from_window(
|
||||
instance: Arc<Instance>,
|
||||
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) }?;
|
||||
Arc::get_mut(&mut surface).unwrap().object = Some(window);
|
||||
|
||||
@ -104,7 +99,7 @@ impl Surface {
|
||||
pub unsafe fn from_window_ref(
|
||||
instance: Arc<Instance>,
|
||||
window: &(impl HasRawWindowHandle + HasRawDisplayHandle),
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
match (window.raw_window_handle(), window.raw_display_handle()) {
|
||||
(RawWindowHandle::AndroidNdk(window), RawDisplayHandle::Android(_display)) => {
|
||||
Self::from_android(instance, window.a_native_window, None)
|
||||
@ -159,7 +154,6 @@ impl Surface {
|
||||
id: Self::next_id(),
|
||||
api,
|
||||
object,
|
||||
has_swapchain: AtomicBool::new(false),
|
||||
#[cfg(target_os = "ios")]
|
||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||
surface_formats: OnceCache::new(),
|
||||
@ -175,19 +169,19 @@ impl Surface {
|
||||
pub fn headless(
|
||||
instance: Arc<Instance>,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_headless(&instance)?;
|
||||
|
||||
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 {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::headless`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"ext_headless_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -235,7 +229,7 @@ impl Surface {
|
||||
pub fn from_display_plane(
|
||||
display_mode: &DisplayMode,
|
||||
plane: &DisplayPlane,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_display_plane(display_mode, plane)?;
|
||||
|
||||
unsafe { Ok(Self::from_display_plane_unchecked(display_mode, plane)?) }
|
||||
@ -244,7 +238,7 @@ impl Surface {
|
||||
fn validate_from_display_plane(
|
||||
display_mode: &DisplayMode,
|
||||
plane: &DisplayPlane,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !display_mode
|
||||
.display()
|
||||
.physical_device()
|
||||
@ -252,11 +246,11 @@ impl Surface {
|
||||
.enabled_extensions()
|
||||
.khr_display
|
||||
{
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_display_plane`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"khr_display",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -325,7 +319,7 @@ impl Surface {
|
||||
instance: Arc<Instance>,
|
||||
window: *const W,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_android(&instance, window)?;
|
||||
|
||||
Ok(Self::from_android_unchecked(instance, window, object)?)
|
||||
@ -334,13 +328,13 @@ impl Surface {
|
||||
fn validate_from_android<W>(
|
||||
instance: &Instance,
|
||||
_window: *const W,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().khr_android_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_android`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"khr_android_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -397,7 +391,7 @@ impl Surface {
|
||||
dfb: *const D,
|
||||
surface: *const S,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_directfb(&instance, dfb, surface)?;
|
||||
|
||||
Ok(Self::from_directfb_unchecked(
|
||||
@ -409,13 +403,13 @@ impl Surface {
|
||||
instance: &Instance,
|
||||
_dfb: *const D,
|
||||
_surface: *const S,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().ext_directfb_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_directfb`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"ext_directfb_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -475,7 +469,7 @@ impl Surface {
|
||||
instance: Arc<Instance>,
|
||||
image_pipe_handle: ash::vk::zx_handle_t,
|
||||
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)?;
|
||||
|
||||
Ok(Self::from_fuchsia_image_pipe_unchecked(
|
||||
@ -488,13 +482,13 @@ impl Surface {
|
||||
fn validate_from_fuchsia_image_pipe(
|
||||
instance: &Instance,
|
||||
_image_pipe_handle: ash::vk::zx_handle_t,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().fuchsia_imagepipe_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_fuchsia_image_pipe`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"fuchsia_imagepipe_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -550,7 +544,7 @@ impl Surface {
|
||||
instance: Arc<Instance>,
|
||||
stream_descriptor: ash::vk::GgpStreamDescriptor,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_ggp_stream_descriptor(&instance, stream_descriptor)?;
|
||||
|
||||
Ok(Self::from_ggp_stream_descriptor_unchecked(
|
||||
@ -563,13 +557,13 @@ impl Surface {
|
||||
fn validate_from_ggp_stream_descriptor(
|
||||
instance: &Instance,
|
||||
_stream_descriptor: ash::vk::GgpStreamDescriptor,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().ggp_stream_descriptor_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_ggp_stream_descriptor`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"ggp_stream_descriptor_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -627,7 +621,7 @@ impl Surface {
|
||||
instance: Arc<Instance>,
|
||||
metal_layer: IOSMetalLayer,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_ios(&instance, &metal_layer)?;
|
||||
|
||||
Ok(Self::from_ios_unchecked(instance, metal_layer, object)?)
|
||||
@ -637,13 +631,13 @@ impl Surface {
|
||||
fn validate_from_ios(
|
||||
instance: &Instance,
|
||||
_metal_layer: &IOSMetalLayer,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().mvk_ios_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_ios`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"mvk_ios_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -704,7 +698,7 @@ impl Surface {
|
||||
instance: Arc<Instance>,
|
||||
view: *const V,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_mac_os(&instance, view)?;
|
||||
|
||||
Ok(Self::from_mac_os_unchecked(instance, view, object)?)
|
||||
@ -714,13 +708,13 @@ impl Surface {
|
||||
fn validate_from_mac_os<V>(
|
||||
instance: &Instance,
|
||||
_view: *const V,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().mvk_macos_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_mac_os`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"mvk_macos_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -779,7 +773,7 @@ impl Surface {
|
||||
instance: Arc<Instance>,
|
||||
layer: *const L,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_metal(&instance, layer)?;
|
||||
|
||||
Ok(Self::from_metal_unchecked(instance, layer, object)?)
|
||||
@ -788,13 +782,13 @@ impl Surface {
|
||||
fn validate_from_metal<L>(
|
||||
instance: &Instance,
|
||||
_layer: *const L,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().ext_metal_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_metal`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"ext_metal_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -848,7 +842,7 @@ impl Surface {
|
||||
context: *const C,
|
||||
window: *const W,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_qnx_screen(&instance, context, window)?;
|
||||
|
||||
Ok(Self::from_qnx_screen_unchecked(
|
||||
@ -860,13 +854,13 @@ impl Surface {
|
||||
instance: &Instance,
|
||||
_context: *const C,
|
||||
_window: *const W,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().qnx_screen_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_qnx_screen`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"qnx_screen_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -926,22 +920,19 @@ impl Surface {
|
||||
instance: Arc<Instance>,
|
||||
window: *const W,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_vi(&instance, window)?;
|
||||
|
||||
Ok(Self::from_vi_unchecked(instance, window, object)?)
|
||||
}
|
||||
|
||||
fn validate_from_vi<W>(
|
||||
instance: &Instance,
|
||||
_window: *const W,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
fn validate_from_vi<W>(instance: &Instance, _window: *const W) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().nn_vi_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_vi`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"nn_vi_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -1000,7 +991,7 @@ impl Surface {
|
||||
display: *const D,
|
||||
surface: *const S,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_wayland(&instance, display, surface)?;
|
||||
|
||||
Ok(Self::from_wayland_unchecked(
|
||||
@ -1012,13 +1003,13 @@ impl Surface {
|
||||
instance: &Instance,
|
||||
_display: *const D,
|
||||
_surface: *const S,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().khr_wayland_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_wayland`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"khr_wayland_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -1082,7 +1073,7 @@ impl Surface {
|
||||
hinstance: *const I,
|
||||
hwnd: *const W,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_win32(&instance, hinstance, hwnd)?;
|
||||
|
||||
Ok(Self::from_win32_unchecked(
|
||||
@ -1094,13 +1085,13 @@ impl Surface {
|
||||
instance: &Instance,
|
||||
_hinstance: *const I,
|
||||
_hwnd: *const W,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().khr_win32_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_win32`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"khr_win32_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -1164,7 +1155,7 @@ impl Surface {
|
||||
connection: *const C,
|
||||
window: ash::vk::xcb_window_t,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_xcb(&instance, connection, window)?;
|
||||
|
||||
Ok(Self::from_xcb_unchecked(
|
||||
@ -1176,13 +1167,13 @@ impl Surface {
|
||||
instance: &Instance,
|
||||
_connection: *const C,
|
||||
_window: ash::vk::xcb_window_t,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().khr_xcb_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_xcb`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"khr_xcb_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -1246,7 +1237,7 @@ impl Surface {
|
||||
display: *const D,
|
||||
window: ash::vk::Window,
|
||||
object: Option<Arc<dyn Any + Send + Sync>>,
|
||||
) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
) -> Result<Arc<Self>, VulkanError> {
|
||||
Self::validate_from_xlib(&instance, display, window)?;
|
||||
|
||||
Ok(Self::from_xlib_unchecked(
|
||||
@ -1258,13 +1249,13 @@ impl Surface {
|
||||
instance: &Instance,
|
||||
_display: *const D,
|
||||
_window: ash::vk::Window,
|
||||
) -> Result<(), SurfaceCreationError> {
|
||||
) -> Result<(), ValidationError> {
|
||||
if !instance.enabled_extensions().khr_xlib_surface {
|
||||
return Err(SurfaceCreationError::RequirementNotMet {
|
||||
required_for: "`Surface::from_xlib`",
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
|
||||
"khr_xlib_surface",
|
||||
)])]),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@ -1379,7 +1370,6 @@ impl Debug for Surface {
|
||||
instance,
|
||||
api,
|
||||
object: _,
|
||||
has_swapchain,
|
||||
..
|
||||
} = self;
|
||||
|
||||
@ -1388,18 +1378,10 @@ impl Debug for Surface {
|
||||
.field("instance", instance)
|
||||
.field("api", api)
|
||||
.field("window", &())
|
||||
.field("has_swapchain", &has_swapchain)
|
||||
.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`.
|
||||
#[cfg(target_os = "ios")]
|
||||
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.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
@ -1882,8 +1807,21 @@ vulkan_enum! {
|
||||
/// [`PhysicalDevice::surface_formats`]: crate::device::physical::PhysicalDevice::surface_formats
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
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,
|
||||
|
||||
/// 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 _ne: crate::NonExhaustive,
|
||||
}
|
||||
|
||||
@ -1891,6 +1829,7 @@ impl Default for SurfaceInfo {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
present_mode: None,
|
||||
full_screen_exclusive: FullScreenExclusive::Default,
|
||||
win32_monitor: None,
|
||||
_ne: crate::NonExhaustive(()),
|
||||
@ -1901,15 +1840,41 @@ impl Default for SurfaceInfo {
|
||||
impl SurfaceInfo {
|
||||
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
|
||||
let &Self {
|
||||
present_mode,
|
||||
full_screen_exclusive,
|
||||
win32_monitor: _,
|
||||
_ne: _,
|
||||
} = self;
|
||||
|
||||
if let Some(present_mode) = present_mode {
|
||||
if !physical_device
|
||||
.instance()
|
||||
.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
|
||||
&& full_screen_exclusive != FullScreenExclusive::Default
|
||||
{
|
||||
return Err(ValidationError {
|
||||
context: "full_screen_exclusive".into(),
|
||||
@ -1972,8 +1937,9 @@ pub struct SurfaceCapabilities {
|
||||
/// you may still get out of memory errors.
|
||||
pub max_image_count: Option<u32>,
|
||||
|
||||
/// The current dimensions of the surface. `None` means that the surface's dimensions will
|
||||
/// depend on the dimensions of the swapchain that you are going to create.
|
||||
/// The current dimensions of the surface.
|
||||
///
|
||||
/// `None` means that the surface's dimensions will depend on the dimensions of the swapchain.
|
||||
pub current_extent: Option<[u32; 2]>,
|
||||
|
||||
/// 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.
|
||||
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.
|
||||
pub supports_protected: bool,
|
||||
|
||||
@ -2008,8 +2017,7 @@ pub struct SurfaceCapabilities {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
swapchain::{Surface, SurfaceCreationError},
|
||||
Requires, RequiresAllOf, RequiresOneOf,
|
||||
swapchain::Surface, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanError,
|
||||
};
|
||||
use std::ptr;
|
||||
|
||||
@ -2017,11 +2025,11 @@ mod tests {
|
||||
fn khr_win32_surface_ext_missing() {
|
||||
let instance = instance!();
|
||||
match unsafe { Surface::from_win32(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) } {
|
||||
Err(SurfaceCreationError::RequirementNotMet {
|
||||
Err(VulkanError::ValidationError(ValidationError {
|
||||
requires_one_of:
|
||||
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_win32_surface")])]),
|
||||
..
|
||||
}) => (),
|
||||
})) => (),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
@ -2030,11 +2038,11 @@ mod tests {
|
||||
fn khr_xcb_surface_ext_missing() {
|
||||
let instance = instance!();
|
||||
match unsafe { Surface::from_xcb(instance, ptr::null::<u8>(), 0, None) } {
|
||||
Err(SurfaceCreationError::RequirementNotMet {
|
||||
Err(VulkanError::ValidationError(ValidationError {
|
||||
requires_one_of:
|
||||
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_xcb_surface")])]),
|
||||
..
|
||||
}) => (),
|
||||
})) => (),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
@ -2043,11 +2051,11 @@ mod tests {
|
||||
fn khr_xlib_surface_ext_missing() {
|
||||
let instance = instance!();
|
||||
match unsafe { Surface::from_xlib(instance, ptr::null::<u8>(), 0, None) } {
|
||||
Err(SurfaceCreationError::RequirementNotMet {
|
||||
Err(VulkanError::ValidationError(ValidationError {
|
||||
requires_one_of:
|
||||
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_xlib_surface")])]),
|
||||
..
|
||||
}) => (),
|
||||
})) => (),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
@ -2057,11 +2065,11 @@ mod tests {
|
||||
let instance = instance!();
|
||||
match unsafe { Surface::from_wayland(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) }
|
||||
{
|
||||
Err(SurfaceCreationError::RequirementNotMet {
|
||||
Err(VulkanError::ValidationError(ValidationError {
|
||||
requires_one_of:
|
||||
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_wayland_surface")])]),
|
||||
..
|
||||
}) => (),
|
||||
})) => (),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
@ -2070,11 +2078,11 @@ mod tests {
|
||||
fn khr_android_surface_ext_missing() {
|
||||
let instance = instance!();
|
||||
match unsafe { Surface::from_android(instance, ptr::null::<u8>(), None) } {
|
||||
Err(SurfaceCreationError::RequirementNotMet {
|
||||
Err(VulkanError::ValidationError(ValidationError {
|
||||
requires_one_of:
|
||||
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_android_surface")])]),
|
||||
..
|
||||
}) => (),
|
||||
})) => (),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -310,8 +310,12 @@ where
|
||||
.map_err(|err| OutcomeErr::Full(err.into()))
|
||||
}
|
||||
SubmitAnyBuilder::QueuePresent(present_info) => {
|
||||
let intermediary_result = if partially_flushed {
|
||||
Ok(())
|
||||
if partially_flushed {
|
||||
queue
|
||||
.with(|mut q| {
|
||||
q.submit_unchecked([Default::default()], Some(new_fence.clone()))
|
||||
})
|
||||
.map_err(|err| OutcomeErr::Partial(err.into()))
|
||||
} else {
|
||||
// VUID-VkPresentIdKHR-presentIds-04999
|
||||
for swapchain_info in &present_info.swapchain_infos {
|
||||
@ -334,21 +338,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
queue
|
||||
let intermediary_result = queue
|
||||
.with(|mut q| q.present_unchecked(present_info))?
|
||||
.map(|r| r.map(|_| ()))
|
||||
.fold(Ok(()), Result::and)
|
||||
};
|
||||
.fold(Ok(()), Result::and);
|
||||
|
||||
match intermediary_result {
|
||||
Ok(()) => queue
|
||||
.with(|mut q| {
|
||||
q.submit_unchecked([Default::default()], Some(new_fence.clone()))
|
||||
q.submit_unchecked(
|
||||
[Default::default()],
|
||||
Some(new_fence.clone()),
|
||||
)
|
||||
})
|
||||
.map_err(|err| OutcomeErr::Partial(err.into())),
|
||||
Err(err) => Err(OutcomeErr::Full(err.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Restore the state before returning.
|
||||
|
@ -597,6 +597,10 @@ pub enum FlushError {
|
||||
/// for the same swapchain.
|
||||
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.
|
||||
ResourceAccessError {
|
||||
error: AccessError,
|
||||
@ -615,9 +619,9 @@ pub enum FlushError {
|
||||
impl Error for FlushError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
FlushError::AccessError(err) => Some(err),
|
||||
FlushError::OomError(err) => Some(err),
|
||||
FlushError::ResourceAccessError { error, .. } => Some(error),
|
||||
Self::AccessError(err) => Some(err),
|
||||
Self::OomError(err) => Some(err),
|
||||
Self::ResourceAccessError { error, .. } => Some(error),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -629,27 +633,31 @@ impl Display for FlushError {
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
FlushError::AccessError(_) => "access to a resource has been denied",
|
||||
FlushError::OomError(_) => "not enough memory",
|
||||
FlushError::DeviceLost => "the connection to the device has been lost",
|
||||
FlushError::SurfaceLost => "the surface of this swapchain is no longer valid",
|
||||
FlushError::OutOfDate => "the swapchain needs to be recreated",
|
||||
FlushError::FullScreenExclusiveModeLost => {
|
||||
Self::AccessError(_) => "access to a resource has been denied",
|
||||
Self::OomError(_) => "not enough memory",
|
||||
Self::DeviceLost => "the connection to the device has been lost",
|
||||
Self::SurfaceLost => "the surface of this swapchain is no longer valid",
|
||||
Self::OutOfDate => "the swapchain needs to be recreated",
|
||||
Self::FullScreenExclusiveModeLost => {
|
||||
"the swapchain no longer has full screen exclusivity"
|
||||
}
|
||||
FlushError::Timeout => {
|
||||
Self::Timeout => {
|
||||
"the flush operation needed to block, but the timeout has elapsed"
|
||||
}
|
||||
FlushError::PresentIdLessThanOrEqual => {
|
||||
Self::PresentIdLessThanOrEqual => {
|
||||
"present id is less than or equal to previous"
|
||||
}
|
||||
FlushError::ResourceAccessError { .. } => "access to a resource has been denied",
|
||||
FlushError::OneTimeSubmitAlreadySubmitted => {
|
||||
Self::PresentModeNotValid => {
|
||||
"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 \
|
||||
created with the \"one time submit\" flag, but has already been submitted in \
|
||||
the past"
|
||||
}
|
||||
FlushError::ExclusiveAlreadyInUse => {
|
||||
Self::ExclusiveAlreadyInUse => {
|
||||
"the command buffer or one of the secondary command buffers it executes is \
|
||||
already in use was not created with the \"concurrent\" flag"
|
||||
}
|
||||
@ -660,7 +668,7 @@ impl Display for FlushError {
|
||||
|
||||
impl From<AccessError> for 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 {
|
||||
fn from(err: FenceError) -> FlushError {
|
||||
match err {
|
||||
FenceError::OomError(err) => FlushError::OomError(err),
|
||||
FenceError::Timeout => FlushError::Timeout,
|
||||
FenceError::DeviceLost => FlushError::DeviceLost,
|
||||
FenceError::OomError(err) => Self::OomError(err),
|
||||
FenceError::Timeout => Self::Timeout,
|
||||
FenceError::DeviceLost => Self::DeviceLost,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user