blob: 6fa6853075ff405a56f226629096d7b867a4fcd1 [file] [log] [blame]
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use super::{
sys::{Image, ImageMemory},
traits::ImageContent,
ImageAccess, ImageDescriptorLayouts, ImageInner, ImageLayout,
};
use crate::{
device::{Device, DeviceOwned},
swapchain::Swapchain,
OomError,
};
use std::{
hash::{Hash, Hasher},
sync::Arc,
};
/// An image that is part of a swapchain.
///
/// Creating a `SwapchainImage` is automatically done when creating a swapchain.
///
/// A swapchain image is special in the sense that it can only be used after being acquired by
/// calling the `acquire` method on the swapchain. You have no way to know in advance which
/// swapchain image is going to be acquired, so you should keep all of them alive.
///
/// After a swapchain image has been acquired, you are free to perform all the usual operations
/// on it. When you are done you can then *present* the image (by calling the corresponding
/// method on the swapchain), which will have the effect of showing the content of the image to
/// the screen. Once an image has been presented, it can no longer be used unless it is acquired
/// again.
#[derive(Debug)]
pub struct SwapchainImage {
inner: Arc<Image>,
}
impl SwapchainImage {
pub(crate) unsafe fn from_handle(
handle: ash::vk::Image,
swapchain: Arc<Swapchain>,
image_index: u32,
) -> Result<Arc<SwapchainImage>, OomError> {
Ok(Arc::new(SwapchainImage {
inner: Arc::new(Image::from_swapchain(handle, swapchain, image_index)),
}))
}
/// Returns the swapchain this image belongs to.
pub fn swapchain(&self) -> &Arc<Swapchain> {
match self.inner.memory() {
ImageMemory::Swapchain {
swapchain,
image_index: _,
} => swapchain,
_ => unreachable!(),
}
}
}
unsafe impl DeviceOwned for SwapchainImage {
fn device(&self) -> &Arc<Device> {
self.inner.device()
}
}
unsafe impl ImageAccess for SwapchainImage {
fn inner(&self) -> ImageInner<'_> {
ImageInner {
image: &self.inner,
first_layer: 0,
num_layers: self.inner.dimensions().array_layers(),
first_mipmap_level: 0,
num_mipmap_levels: 1,
}
}
fn initial_layout_requirement(&self) -> ImageLayout {
ImageLayout::PresentSrc
}
fn final_layout_requirement(&self) -> ImageLayout {
ImageLayout::PresentSrc
}
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
Some(ImageDescriptorLayouts {
storage_image: ImageLayout::General,
combined_image_sampler: ImageLayout::ShaderReadOnlyOptimal,
sampled_image: ImageLayout::ShaderReadOnlyOptimal,
input_attachment: ImageLayout::ShaderReadOnlyOptimal,
})
}
unsafe fn layout_initialized(&self) {
match self.inner.memory() {
&ImageMemory::Swapchain {
ref swapchain,
image_index,
} => swapchain.image_layout_initialized(image_index),
_ => unreachable!(),
}
}
fn is_layout_initialized(&self) -> bool {
match self.inner.memory() {
&ImageMemory::Swapchain {
ref swapchain,
image_index,
} => swapchain.is_image_layout_initialized(image_index),
_ => unreachable!(),
}
}
}
unsafe impl<P> ImageContent<P> for SwapchainImage {
fn matches_format(&self) -> bool {
true // FIXME:
}
}
impl PartialEq for SwapchainImage {
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner()
}
}
impl Eq for SwapchainImage {}
impl Hash for SwapchainImage {
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
}
}