aboutsummaryrefslogtreecommitdiff
path: root/src/image/attachment.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/image/attachment.rs')
-rw-r--r--src/image/attachment.rs659
1 files changed, 0 insertions, 659 deletions
diff --git a/src/image/attachment.rs b/src/image/attachment.rs
deleted file mode 100644
index 5892d3c..0000000
--- a/src/image/attachment.rs
+++ /dev/null
@@ -1,659 +0,0 @@
-// Copyright (c) 2016 The vulkano developers
-// Licensed under the Apache License, Version 2.0
-// <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
-// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
-// at your option. All files in the project carrying such
-// notice may not be copied, modified, or distributed except
-// according to those terms.
-
-use crate::device::Device;
-use crate::format::ClearValue;
-use crate::format::Format;
-use crate::format::FormatTy;
-use crate::image::sys::ImageCreationError;
-use crate::image::sys::UnsafeImage;
-use crate::image::traits::ImageAccess;
-use crate::image::traits::ImageClearValue;
-use crate::image::traits::ImageContent;
-use crate::image::ImageCreateFlags;
-use crate::image::ImageDescriptorLayouts;
-use crate::image::ImageDimensions;
-use crate::image::ImageInner;
-use crate::image::ImageLayout;
-use crate::image::ImageUsage;
-use crate::image::SampleCount;
-use crate::memory::pool::AllocFromRequirementsFilter;
-use crate::memory::pool::AllocLayout;
-use crate::memory::pool::MappingRequirement;
-use crate::memory::pool::MemoryPool;
-use crate::memory::pool::MemoryPoolAlloc;
-use crate::memory::pool::PotentialDedicatedAllocation;
-use crate::memory::pool::StdMemoryPoolAlloc;
-use crate::memory::DedicatedAlloc;
-use crate::sync::AccessError;
-use crate::sync::Sharing;
-use std::hash::Hash;
-use std::hash::Hasher;
-use std::iter::Empty;
-use std::sync::atomic::AtomicBool;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering;
-use std::sync::Arc;
-
-/// ImageAccess whose purpose is to be used as a framebuffer attachment.
-///
-/// The image is always two-dimensional and has only one mipmap, but it can have any kind of
-/// format. Trying to use a format that the backend doesn't support for rendering will result in
-/// an error being returned when creating the image. Once you have an `AttachmentImage`, you are
-/// guaranteed that you will be able to draw on it.
-///
-/// The template parameter of `AttachmentImage` is a type that describes the format of the image.
-///
-/// # Regular vs transient
-///
-/// Calling `AttachmentImage::new` will create a regular image, while calling
-/// `AttachmentImage::transient` will create a *transient* image. Transient image are only
-/// relevant for images that serve as attachments, so `AttachmentImage` is the only type of
-/// image in vulkano that provides a shortcut for this.
-///
-/// A transient image is a special kind of image whose content is undefined outside of render
-/// passes. Once you finish drawing, reading from it will returned undefined data (which can be
-/// either valid or garbage, depending on the implementation).
-///
-/// This gives a hint to the Vulkan implementation that it is possible for the image's content to
-/// live exclusively in some cache memory, and that no real memory has to be allocated for it.
-///
-/// In other words, if you are going to read from the image after drawing to it, use a regular
-/// image. If you don't need to read from it (for example if it's some kind of intermediary color,
-/// or a depth buffer that is only used once) then use a transient image as it may improve
-/// performance.
-///
-// TODO: forbid reading transient images outside render passes?
-#[derive(Debug)]
-pub struct AttachmentImage<A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>> {
- // Inner implementation.
- image: UnsafeImage,
-
- // Memory used to back the image.
- memory: A,
-
- // Format.
- format: Format,
-
- // Layout to use when the image is used as a framebuffer attachment.
- // Must be either "depth-stencil optimal" or "color optimal".
- attachment_layout: ImageLayout,
-
- // If true, then the image is in the layout of `attachment_layout` (above). If false, then it
- // is still `Undefined`.
- initialized: AtomicBool,
-
- // Number of times this image is locked on the GPU side.
- gpu_lock: AtomicUsize,
-}
-
-impl AttachmentImage {
- /// Creates a new image with the given dimensions and format.
- ///
- /// Returns an error if the dimensions are too large or if the backend doesn't support this
- /// format as a framebuffer attachment.
- #[inline]
- pub fn new(
- device: Arc<Device>,
- dimensions: [u32; 2],
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- AttachmentImage::new_impl(
- device,
- dimensions,
- 1,
- format,
- ImageUsage::none(),
- SampleCount::Sample1,
- )
- }
-
- /// Same as `new`, but creates an image that can be used as an input attachment.
- ///
- /// > **Note**: This function is just a convenient shortcut for `with_usage`.
- #[inline]
- pub fn input_attachment(
- device: Arc<Device>,
- dimensions: [u32; 2],
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- input_attachment: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(
- device,
- dimensions,
- 1,
- format,
- base_usage,
- SampleCount::Sample1,
- )
- }
-
- /// Same as `new`, but creates a multisampled image.
- ///
- /// > **Note**: You can also use this function and pass `1` for the number of samples if you
- /// > want a regular image.
- #[inline]
- pub fn multisampled(
- device: Arc<Device>,
- dimensions: [u32; 2],
- samples: SampleCount,
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- AttachmentImage::new_impl(device, dimensions, 1, format, ImageUsage::none(), samples)
- }
-
- /// Same as `multisampled`, but creates an image that can be used as an input attachment.
- ///
- /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`.
- #[inline]
- pub fn multisampled_input_attachment(
- device: Arc<Device>,
- dimensions: [u32; 2],
- samples: SampleCount,
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- input_attachment: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples)
- }
-
- /// Same as `new`, but lets you specify additional usages.
- ///
- /// The `color_attachment` or `depth_stencil_attachment` usages are automatically added based
- /// on the format of the usage. Therefore the `usage` parameter allows you specify usages in
- /// addition to these two.
- #[inline]
- pub fn with_usage(
- device: Arc<Device>,
- dimensions: [u32; 2],
- format: Format,
- usage: ImageUsage,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- AttachmentImage::new_impl(device, dimensions, 1, format, usage, SampleCount::Sample1)
- }
-
- /// Same as `with_usage`, but creates a multisampled image.
- ///
- /// > **Note**: You can also use this function and pass `1` for the number of samples if you
- /// > want a regular image.
- #[inline]
- pub fn multisampled_with_usage(
- device: Arc<Device>,
- dimensions: [u32; 2],
- samples: SampleCount,
- format: Format,
- usage: ImageUsage,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- AttachmentImage::new_impl(device, dimensions, 1, format, usage, samples)
- }
-
- /// Same as `multisampled_with_usage`, but creates an image with multiple layers.
- ///
- /// > **Note**: You can also use this function and pass `1` for the number of layers if you
- /// > want a regular image.
- #[inline]
- pub fn multisampled_with_usage_with_layers(
- device: Arc<Device>,
- dimensions: [u32; 2],
- array_layers: u32,
- samples: SampleCount,
- format: Format,
- usage: ImageUsage,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- AttachmentImage::new_impl(device, dimensions, array_layers, format, usage, samples)
- }
-
- /// Same as `new`, except that the image can later be sampled.
- ///
- /// > **Note**: This function is just a convenient shortcut for `with_usage`.
- #[inline]
- pub fn sampled(
- device: Arc<Device>,
- dimensions: [u32; 2],
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- sampled: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(
- device,
- dimensions,
- 1,
- format,
- base_usage,
- SampleCount::Sample1,
- )
- }
-
- /// Same as `sampled`, except that the image can be used as an input attachment.
- ///
- /// > **Note**: This function is just a convenient shortcut for `with_usage`.
- #[inline]
- pub fn sampled_input_attachment(
- device: Arc<Device>,
- dimensions: [u32; 2],
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- sampled: true,
- input_attachment: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(
- device,
- dimensions,
- 1,
- format,
- base_usage,
- SampleCount::Sample1,
- )
- }
-
- /// Same as `sampled`, but creates a multisampled image.
- ///
- /// > **Note**: You can also use this function and pass `1` for the number of samples if you
- /// > want a regular image.
- ///
- /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`.
- #[inline]
- pub fn sampled_multisampled(
- device: Arc<Device>,
- dimensions: [u32; 2],
- samples: SampleCount,
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- sampled: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples)
- }
-
- /// Same as `sampled_multisampled`, but creates an image that can be used as an input
- /// attachment.
- ///
- /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`.
- #[inline]
- pub fn sampled_multisampled_input_attachment(
- device: Arc<Device>,
- dimensions: [u32; 2],
- samples: SampleCount,
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- sampled: true,
- input_attachment: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples)
- }
-
- /// Same as `new`, except that the image will be transient.
- ///
- /// A transient image is special because its content is undefined outside of a render pass.
- /// This means that the implementation has the possibility to not allocate any memory for it.
- ///
- /// > **Note**: This function is just a convenient shortcut for `with_usage`.
- #[inline]
- pub fn transient(
- device: Arc<Device>,
- dimensions: [u32; 2],
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- transient_attachment: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(
- device,
- dimensions,
- 1,
- format,
- base_usage,
- SampleCount::Sample1,
- )
- }
-
- /// Same as `transient`, except that the image can be used as an input attachment.
- ///
- /// > **Note**: This function is just a convenient shortcut for `with_usage`.
- #[inline]
- pub fn transient_input_attachment(
- device: Arc<Device>,
- dimensions: [u32; 2],
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- transient_attachment: true,
- input_attachment: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(
- device,
- dimensions,
- 1,
- format,
- base_usage,
- SampleCount::Sample1,
- )
- }
-
- /// Same as `transient`, but creates a multisampled image.
- ///
- /// > **Note**: You can also use this function and pass `1` for the number of samples if you
- /// > want a regular image.
- ///
- /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`.
- #[inline]
- pub fn transient_multisampled(
- device: Arc<Device>,
- dimensions: [u32; 2],
- samples: SampleCount,
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- transient_attachment: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples)
- }
-
- /// Same as `transient_multisampled`, but creates an image that can be used as an input
- /// attachment.
- ///
- /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`.
- #[inline]
- pub fn transient_multisampled_input_attachment(
- device: Arc<Device>,
- dimensions: [u32; 2],
- samples: SampleCount,
- format: Format,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- let base_usage = ImageUsage {
- transient_attachment: true,
- input_attachment: true,
- ..ImageUsage::none()
- };
-
- AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples)
- }
-
- // All constructors dispatch to this one.
- fn new_impl(
- device: Arc<Device>,
- dimensions: [u32; 2],
- array_layers: u32,
- format: Format,
- base_usage: ImageUsage,
- samples: SampleCount,
- ) -> Result<Arc<AttachmentImage>, ImageCreationError> {
- // TODO: check dimensions against the max_framebuffer_width/height/layers limits
-
- let is_depth = match format.ty() {
- FormatTy::Depth => true,
- FormatTy::DepthStencil => true,
- FormatTy::Stencil => true,
- FormatTy::Compressed => panic!(),
- _ => false,
- };
-
- let usage = ImageUsage {
- color_attachment: !is_depth,
- depth_stencil_attachment: is_depth,
- ..base_usage
- };
-
- let (image, mem_reqs) = unsafe {
- let dims = ImageDimensions::Dim2d {
- width: dimensions[0],
- height: dimensions[1],
- array_layers,
- };
-
- UnsafeImage::new(
- device.clone(),
- usage,
- format,
- ImageCreateFlags::none(),
- dims,
- samples,
- 1,
- Sharing::Exclusive::<Empty<u32>>,
- false,
- false,
- )?
- };
-
- let memory = MemoryPool::alloc_from_requirements(
- &Device::standard_pool(&device),
- &mem_reqs,
- AllocLayout::Optimal,
- MappingRequirement::DoNotMap,
- DedicatedAlloc::Image(&image),
- |t| {
- if t.is_device_local() {
- AllocFromRequirementsFilter::Preferred
- } else {
- AllocFromRequirementsFilter::Allowed
- }
- },
- )?;
- debug_assert!((memory.offset() % mem_reqs.alignment) == 0);
- unsafe {
- image.bind_memory(memory.memory(), memory.offset())?;
- }
-
- Ok(Arc::new(AttachmentImage {
- image,
- memory,
- format,
- attachment_layout: if is_depth {
- ImageLayout::DepthStencilAttachmentOptimal
- } else {
- ImageLayout::ColorAttachmentOptimal
- },
- initialized: AtomicBool::new(false),
- gpu_lock: AtomicUsize::new(0),
- }))
- }
-}
-
-impl<A> AttachmentImage<A> {
- /// Returns the dimensions of the image.
- #[inline]
- pub fn dimensions(&self) -> [u32; 2] {
- let dims = self.image.dimensions();
- [dims.width(), dims.height()]
- }
-}
-
-unsafe impl<A> ImageAccess for AttachmentImage<A> {
- #[inline]
- fn inner(&self) -> ImageInner {
- ImageInner {
- image: &self.image,
- first_layer: 0,
- num_layers: self.image.dimensions().array_layers() as usize,
- first_mipmap_level: 0,
- num_mipmap_levels: 1,
- }
- }
-
- #[inline]
- fn initial_layout_requirement(&self) -> ImageLayout {
- self.attachment_layout
- }
-
- #[inline]
- fn final_layout_requirement(&self) -> ImageLayout {
- self.attachment_layout
- }
-
- #[inline]
- fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
- Some(ImageDescriptorLayouts {
- storage_image: ImageLayout::ShaderReadOnlyOptimal,
- combined_image_sampler: ImageLayout::ShaderReadOnlyOptimal,
- sampled_image: ImageLayout::ShaderReadOnlyOptimal,
- input_attachment: ImageLayout::ShaderReadOnlyOptimal,
- })
- }
-
- #[inline]
- fn conflict_key(&self) -> u64 {
- self.image.key()
- }
-
- #[inline]
- fn try_gpu_lock(
- &self,
- _: bool,
- uninitialized_safe: bool,
- expected_layout: ImageLayout,
- ) -> Result<(), AccessError> {
- if expected_layout != self.attachment_layout && expected_layout != ImageLayout::Undefined {
- if self.initialized.load(Ordering::SeqCst) {
- return Err(AccessError::UnexpectedImageLayout {
- requested: expected_layout,
- allowed: self.attachment_layout,
- });
- } else {
- return Err(AccessError::UnexpectedImageLayout {
- requested: expected_layout,
- allowed: ImageLayout::Undefined,
- });
- }
- }
-
- if !uninitialized_safe && expected_layout != ImageLayout::Undefined {
- if !self.initialized.load(Ordering::SeqCst) {
- return Err(AccessError::ImageNotInitialized {
- requested: expected_layout,
- });
- }
- }
-
- if self
- .gpu_lock
- .compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst)
- .unwrap_or_else(|e| e)
- == 0
- {
- Ok(())
- } else {
- Err(AccessError::AlreadyInUse)
- }
- }
-
- #[inline]
- unsafe fn increase_gpu_lock(&self) {
- let val = self.gpu_lock.fetch_add(1, Ordering::SeqCst);
- debug_assert!(val >= 1);
- }
-
- #[inline]
- unsafe fn unlock(&self, new_layout: Option<ImageLayout>) {
- if let Some(new_layout) = new_layout {
- debug_assert_eq!(new_layout, self.attachment_layout);
- self.initialized.store(true, Ordering::SeqCst);
- }
-
- let prev_val = self.gpu_lock.fetch_sub(1, Ordering::SeqCst);
- debug_assert!(prev_val >= 1);
- }
-
- #[inline]
- unsafe fn layout_initialized(&self) {
- self.initialized.store(true, Ordering::SeqCst);
- }
-
- #[inline]
- fn is_layout_initialized(&self) -> bool {
- self.initialized.load(Ordering::SeqCst)
- }
-
- #[inline]
- fn current_miplevels_access(&self) -> std::ops::Range<u32> {
- 0..self.mipmap_levels()
- }
-
- #[inline]
- fn current_layer_levels_access(&self) -> std::ops::Range<u32> {
- 0..1
- }
-}
-
-unsafe impl<A> ImageClearValue<ClearValue> for Arc<AttachmentImage<A>> {
- #[inline]
- fn decode(&self, value: ClearValue) -> Option<ClearValue> {
- Some(self.format.decode_clear_value(value))
- }
-}
-
-unsafe impl<P, A> ImageContent<P> for Arc<AttachmentImage<A>> {
- #[inline]
- fn matches_format(&self) -> bool {
- true // FIXME:
- }
-}
-
-impl<A> PartialEq for AttachmentImage<A> {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- ImageAccess::inner(self) == ImageAccess::inner(other)
- }
-}
-
-impl<A> Eq for AttachmentImage<A> {}
-
-impl<A> Hash for AttachmentImage<A> {
- #[inline]
- fn hash<H: Hasher>(&self, state: &mut H) {
- ImageAccess::inner(self).hash(state);
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::AttachmentImage;
- use crate::format::Format;
-
- #[test]
- fn create_regular() {
- let (device, _) = gfx_dev_and_queue!();
- let _img = AttachmentImage::new(device, [32, 32], Format::R8G8B8A8Unorm).unwrap();
- }
-
- #[test]
- fn create_transient() {
- let (device, _) = gfx_dev_and_queue!();
- let _img = AttachmentImage::transient(device, [32, 32], Format::R8G8B8A8Unorm).unwrap();
- }
-
- #[test]
- fn d16_unorm_always_supported() {
- let (device, _) = gfx_dev_and_queue!();
- let _img = AttachmentImage::new(device, [32, 32], Format::D16Unorm).unwrap();
- }
-}