diff options
Diffstat (limited to 'src/image/attachment.rs')
-rw-r--r-- | src/image/attachment.rs | 627 |
1 files changed, 328 insertions, 299 deletions
diff --git a/src/image/attachment.rs b/src/image/attachment.rs index 5892d3c..1a4faaf 100644 --- a/src/image/attachment.rs +++ b/src/image/attachment.rs @@ -7,39 +7,34 @@ // 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; +use super::{ + sys::{Image, ImageMemory, RawImage}, + traits::ImageContent, + ImageAccess, ImageAspects, ImageDescriptorLayouts, ImageError, ImageInner, ImageLayout, + ImageUsage, SampleCount, +}; +use crate::{ + device::{Device, DeviceOwned}, + format::Format, + image::{sys::ImageCreateInfo, ImageCreateFlags, ImageDimensions, ImageFormatInfo}, + memory::{ + allocator::{ + AllocationCreateInfo, AllocationType, MemoryAllocatePreference, MemoryAllocator, + MemoryUsage, + }, + is_aligned, DedicatedAllocation, DeviceMemoryError, ExternalMemoryHandleType, + ExternalMemoryHandleTypes, + }, + DeviceSize, +}; +use std::{ + fs::File, + hash::{Hash, Hasher}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, +}; /// ImageAccess whose purpose is to be used as a framebuffer attachment. /// @@ -71,15 +66,8 @@ use std::sync::Arc; /// // 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, +pub struct AttachmentImage { + inner: Arc<Image>, // Layout to use when the image is used as a framebuffer attachment. // Must be either "depth-stencil optimal" or "color optimal". @@ -87,10 +75,7 @@ pub struct AttachmentImage<A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>> // 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, + layout_initialized: AtomicBool, } impl AttachmentImage { @@ -100,16 +85,16 @@ impl AttachmentImage { /// format as a framebuffer attachment. #[inline] pub fn new( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { + ) -> Result<Arc<AttachmentImage>, ImageError> { AttachmentImage::new_impl( - device, + allocator, dimensions, 1, format, - ImageUsage::none(), + ImageUsage::empty(), SampleCount::Sample1, ) } @@ -119,17 +104,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `with_usage`. #[inline] pub fn input_attachment( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - input_attachment: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl( - device, + allocator, dimensions, 1, format, @@ -144,12 +126,19 @@ impl AttachmentImage { /// > want a regular image. #[inline] pub fn multisampled( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], samples: SampleCount, format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - AttachmentImage::new_impl(device, dimensions, 1, format, ImageUsage::none(), samples) + ) -> Result<Arc<AttachmentImage>, ImageError> { + AttachmentImage::new_impl( + allocator, + dimensions, + 1, + format, + ImageUsage::empty(), + samples, + ) } /// Same as `multisampled`, but creates an image that can be used as an input attachment. @@ -157,17 +146,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`. #[inline] pub fn multisampled_input_attachment( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], samples: SampleCount, format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - input_attachment: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::INPUT_ATTACHMENT; - AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples) + AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } /// Same as `new`, but lets you specify additional usages. @@ -177,12 +163,19 @@ impl AttachmentImage { /// addition to these two. #[inline] pub fn with_usage( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], format: Format, usage: ImageUsage, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - AttachmentImage::new_impl(device, dimensions, 1, format, usage, SampleCount::Sample1) + ) -> Result<Arc<AttachmentImage>, ImageError> { + AttachmentImage::new_impl( + allocator, + dimensions, + 1, + format, + usage, + SampleCount::Sample1, + ) } /// Same as `with_usage`, but creates a multisampled image. @@ -191,13 +184,13 @@ impl AttachmentImage { /// > want a regular image. #[inline] pub fn multisampled_with_usage( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], samples: SampleCount, format: Format, usage: ImageUsage, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - AttachmentImage::new_impl(device, dimensions, 1, format, usage, samples) + ) -> Result<Arc<AttachmentImage>, ImageError> { + AttachmentImage::new_impl(allocator, dimensions, 1, format, usage, samples) } /// Same as `multisampled_with_usage`, but creates an image with multiple layers. @@ -206,14 +199,14 @@ impl AttachmentImage { /// > want a regular image. #[inline] pub fn multisampled_with_usage_with_layers( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), 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) + ) -> Result<Arc<AttachmentImage>, ImageError> { + AttachmentImage::new_impl(allocator, dimensions, array_layers, format, usage, samples) } /// Same as `new`, except that the image can later be sampled. @@ -221,17 +214,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `with_usage`. #[inline] pub fn sampled( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - sampled: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::SAMPLED; AttachmentImage::new_impl( - device, + allocator, dimensions, 1, format, @@ -245,18 +235,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `with_usage`. #[inline] pub fn sampled_input_attachment( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - sampled: true, - input_attachment: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl( - device, + allocator, dimensions, 1, format, @@ -273,17 +259,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`. #[inline] pub fn sampled_multisampled( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], samples: SampleCount, format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - sampled: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::SAMPLED; - AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples) + AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } /// Same as `sampled_multisampled`, but creates an image that can be used as an input @@ -292,18 +275,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`. #[inline] pub fn sampled_multisampled_input_attachment( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], samples: SampleCount, format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - sampled: true, - input_attachment: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT; - AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples) + AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } /// Same as `new`, except that the image will be transient. @@ -314,17 +293,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `with_usage`. #[inline] pub fn transient( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - transient_attachment: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::TRANSIENT_ATTACHMENT; AttachmentImage::new_impl( - device, + allocator, dimensions, 1, format, @@ -338,18 +314,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `with_usage`. #[inline] pub fn transient_input_attachment( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT; AttachmentImage::new_impl( - device, + allocator, dimensions, 1, format, @@ -366,17 +338,14 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`. #[inline] pub fn transient_multisampled( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], samples: SampleCount, format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - transient_attachment: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::TRANSIENT_ATTACHMENT; - AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples) + AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } /// Same as `transient_multisampled`, but creates an image that can be used as an input @@ -385,116 +354,246 @@ impl AttachmentImage { /// > **Note**: This function is just a convenient shortcut for `multisampled_with_usage`. #[inline] pub fn transient_multisampled_input_attachment( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], samples: SampleCount, format: Format, - ) -> Result<Arc<AttachmentImage>, ImageCreationError> { - let base_usage = ImageUsage { - transient_attachment: true, - input_attachment: true, - ..ImageUsage::none() - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let base_usage = ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::INPUT_ATTACHMENT; - AttachmentImage::new_impl(device, dimensions, 1, format, base_usage, samples) + AttachmentImage::new_impl(allocator, dimensions, 1, format, base_usage, samples) } // All constructors dispatch to this one. fn new_impl( - device: Arc<Device>, + allocator: &(impl MemoryAllocator + ?Sized), dimensions: [u32; 2], array_layers: u32, format: Format, - base_usage: ImageUsage, + mut 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, - }; + ) -> Result<Arc<AttachmentImage>, ImageError> { + let physical_device = allocator.device().physical_device(); + let device_properties = physical_device.properties(); - let usage = ImageUsage { - color_attachment: !is_depth, - depth_stencil_attachment: is_depth, - ..base_usage - }; + if dimensions[0] > device_properties.max_framebuffer_height { + panic!("AttachmentImage height exceeds physical device's max_framebuffer_height"); + } + if dimensions[1] > device_properties.max_framebuffer_width { + panic!("AttachmentImage width exceeds physical device's max_framebuffer_width"); + } + if array_layers > device_properties.max_framebuffer_layers { + panic!("AttachmentImage layer count exceeds physical device's max_framebuffer_layers"); + } - let (image, mem_reqs) = unsafe { - let dims = ImageDimensions::Dim2d { - width: dimensions[0], - height: dimensions[1], - array_layers, - }; + let aspects = format.aspects(); + let is_depth_stencil = aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL); - UnsafeImage::new( - device.clone(), - usage, - format, - ImageCreateFlags::none(), - dims, + if is_depth_stencil { + usage -= ImageUsage::COLOR_ATTACHMENT; + usage |= ImageUsage::DEPTH_STENCIL_ATTACHMENT; + } else { + usage |= ImageUsage::COLOR_ATTACHMENT; + usage -= ImageUsage::DEPTH_STENCIL_ATTACHMENT; + } + + if format.compression().is_some() { + panic!() // TODO: message? + } + + let raw_image = RawImage::new( + allocator.device().clone(), + ImageCreateInfo { + dimensions: ImageDimensions::Dim2d { + width: dimensions[0], + height: dimensions[1], + array_layers, + }, + format: Some(format), samples, - 1, - Sharing::Exclusive::<Empty<u32>>, - false, - false, - )? + usage, + ..Default::default() + }, + )?; + let requirements = raw_image.memory_requirements()[0]; + let res = unsafe { + allocator.allocate_unchecked( + requirements, + AllocationType::NonLinear, + AllocationCreateInfo { + usage: MemoryUsage::DeviceOnly, + allocate_preference: MemoryAllocatePreference::Unknown, + _ne: crate::NonExhaustive(()), + }, + Some(DedicatedAllocation::Image(&raw_image)), + ) }; - 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 - } + match res { + Ok(alloc) => { + debug_assert!(is_aligned(alloc.offset(), requirements.layout.alignment())); + debug_assert!(alloc.size() == requirements.layout.size()); + + let inner = Arc::new( + unsafe { raw_image.bind_memory_unchecked([alloc]) } + .map_err(|(err, _, _)| err)?, + ); + + Ok(Arc::new(AttachmentImage { + inner, + attachment_layout: if is_depth_stencil { + ImageLayout::DepthStencilAttachmentOptimal + } else { + ImageLayout::ColorAttachmentOptimal + }, + layout_initialized: AtomicBool::new(false), + })) + } + Err(err) => Err(err.into()), + } + } + + pub fn new_with_exportable_fd( + allocator: &(impl MemoryAllocator + ?Sized), + dimensions: [u32; 2], + array_layers: u32, + format: Format, + mut usage: ImageUsage, + samples: SampleCount, + ) -> Result<Arc<AttachmentImage>, ImageError> { + let physical_device = allocator.device().physical_device(); + let device_properties = physical_device.properties(); + + if dimensions[0] > device_properties.max_framebuffer_height { + panic!("AttachmentImage height exceeds physical device's max_framebuffer_height"); + } + if dimensions[1] > device_properties.max_framebuffer_width { + panic!("AttachmentImage width exceeds physical device's max_framebuffer_width"); + } + if array_layers > device_properties.max_framebuffer_layers { + panic!("AttachmentImage layer count exceeds physical device's max_framebuffer_layers"); + } + + let aspects = format.aspects(); + let is_depth_stencil = aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL); + + if is_depth_stencil { + usage -= ImageUsage::COLOR_ATTACHMENT; + usage |= ImageUsage::DEPTH_STENCIL_ATTACHMENT; + } else { + usage |= ImageUsage::COLOR_ATTACHMENT; + usage -= ImageUsage::DEPTH_STENCIL_ATTACHMENT; + } + + let external_memory_properties = allocator + .device() + .physical_device() + .image_format_properties(ImageFormatInfo { + flags: ImageCreateFlags::MUTABLE_FORMAT, + format: Some(format), + usage, + external_memory_handle_type: Some(ExternalMemoryHandleType::OpaqueFd), + ..Default::default() + }) + .unwrap() + .unwrap() + .external_memory_properties; + // VUID-VkExportMemoryAllocateInfo-handleTypes-00656 + assert!(external_memory_properties.exportable); + + // VUID-VkMemoryAllocateInfo-pNext-00639 + // Guaranteed because we always create a dedicated allocation + + let external_memory_handle_types = ExternalMemoryHandleTypes::OPAQUE_FD; + let raw_image = RawImage::new( + allocator.device().clone(), + ImageCreateInfo { + flags: ImageCreateFlags::MUTABLE_FORMAT, + dimensions: ImageDimensions::Dim2d { + width: dimensions[0], + height: dimensions[1], + array_layers, + }, + format: Some(format), + samples, + usage, + external_memory_handle_types, + ..Default::default() }, )?; - debug_assert!((memory.offset() % mem_reqs.alignment) == 0); - unsafe { - image.bind_memory(memory.memory(), memory.offset())?; + let requirements = raw_image.memory_requirements()[0]; + let memory_type_index = allocator + .find_memory_type_index( + requirements.memory_type_bits, + MemoryUsage::DeviceOnly.into(), + ) + .expect("failed to find a suitable memory type"); + + match unsafe { + allocator.allocate_dedicated_unchecked( + memory_type_index, + requirements.layout.size(), + Some(DedicatedAllocation::Image(&raw_image)), + external_memory_handle_types, + ) + } { + Ok(alloc) => { + debug_assert!(is_aligned(alloc.offset(), requirements.layout.alignment())); + debug_assert!(alloc.size() == requirements.layout.size()); + + let inner = Arc::new(unsafe { + raw_image + .bind_memory_unchecked([alloc]) + .map_err(|(err, _, _)| err)? + }); + + Ok(Arc::new(AttachmentImage { + inner, + attachment_layout: if is_depth_stencil { + ImageLayout::DepthStencilAttachmentOptimal + } else { + ImageLayout::ColorAttachmentOptimal + }, + layout_initialized: AtomicBool::new(false), + })) + } + Err(err) => Err(err.into()), } + } - 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), - })) + /// Exports posix file descriptor for the allocated memory. + /// Requires `khr_external_memory_fd` and `khr_external_memory` extensions to be loaded. + #[inline] + pub fn export_posix_fd(&self) -> Result<File, DeviceMemoryError> { + let allocation = match self.inner.memory() { + ImageMemory::Normal(a) => &a[0], + _ => unreachable!(), + }; + + allocation + .device_memory() + .export_fd(ExternalMemoryHandleType::OpaqueFd) } -} -impl<A> AttachmentImage<A> { - /// Returns the dimensions of the image. + /// Return the size of the allocated memory (used e.g. with cuda). #[inline] - pub fn dimensions(&self) -> [u32; 2] { - let dims = self.image.dimensions(); - [dims.width(), dims.height()] + pub fn mem_size(&self) -> DeviceSize { + let allocation = match self.inner.memory() { + ImageMemory::Normal(a) => &a[0], + _ => unreachable!(), + }; + + allocation.device_memory().allocation_size() } } -unsafe impl<A> ImageAccess for AttachmentImage<A> { +unsafe impl ImageAccess for AttachmentImage { #[inline] - fn inner(&self) -> ImageInner { + fn inner(&self) -> ImageInner<'_> { ImageInner { - image: &self.image, + image: &self.inner, first_layer: 0, - num_layers: self.image.dimensions().array_layers() as usize, + num_layers: self.inner.dimensions().array_layers(), first_mipmap_level: 0, num_mipmap_levels: 1, } @@ -513,7 +612,7 @@ unsafe impl<A> ImageAccess for AttachmentImage<A> { #[inline] fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> { Some(ImageDescriptorLayouts { - storage_image: ImageLayout::ShaderReadOnlyOptimal, + storage_image: ImageLayout::General, combined_image_sampler: ImageLayout::ShaderReadOnlyOptimal, sampled_image: ImageLayout::ShaderReadOnlyOptimal, input_attachment: ImageLayout::ShaderReadOnlyOptimal, @@ -521,139 +620,69 @@ unsafe impl<A> ImageAccess for AttachmentImage<A> { } #[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); + self.layout_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 + self.layout_initialized.load(Ordering::SeqCst) } } -unsafe impl<A> ImageClearValue<ClearValue> for Arc<AttachmentImage<A>> { +unsafe impl DeviceOwned for AttachmentImage { #[inline] - fn decode(&self, value: ClearValue) -> Option<ClearValue> { - Some(self.format.decode_clear_value(value)) + fn device(&self) -> &Arc<Device> { + self.inner.device() } } -unsafe impl<P, A> ImageContent<P> for Arc<AttachmentImage<A>> { - #[inline] +unsafe impl<P> ImageContent<P> for AttachmentImage { fn matches_format(&self) -> bool { true // FIXME: } } -impl<A> PartialEq for AttachmentImage<A> { +impl PartialEq for AttachmentImage { #[inline] fn eq(&self, other: &Self) -> bool { - ImageAccess::inner(self) == ImageAccess::inner(other) + self.inner() == other.inner() } } -impl<A> Eq for AttachmentImage<A> {} +impl Eq for AttachmentImage {} -impl<A> Hash for AttachmentImage<A> { - #[inline] +impl Hash for AttachmentImage { fn hash<H: Hasher>(&self, state: &mut H) { - ImageAccess::inner(self).hash(state); + self.inner().hash(state); } } #[cfg(test)] mod tests { - use super::AttachmentImage; - use crate::format::Format; + use super::*; + use crate::memory::allocator::StandardMemoryAllocator; #[test] fn create_regular() { let (device, _) = gfx_dev_and_queue!(); - let _img = AttachmentImage::new(device, [32, 32], Format::R8G8B8A8Unorm).unwrap(); + let memory_allocator = StandardMemoryAllocator::new_default(device); + let _img = + AttachmentImage::new(&memory_allocator, [32, 32], Format::R8G8B8A8_UNORM).unwrap(); } #[test] fn create_transient() { let (device, _) = gfx_dev_and_queue!(); - let _img = AttachmentImage::transient(device, [32, 32], Format::R8G8B8A8Unorm).unwrap(); + let memory_allocator = StandardMemoryAllocator::new_default(device); + let _img = AttachmentImage::transient(&memory_allocator, [32, 32], Format::R8G8B8A8_UNORM) + .unwrap(); } #[test] fn d16_unorm_always_supported() { let (device, _) = gfx_dev_and_queue!(); - let _img = AttachmentImage::new(device, [32, 32], Format::D16Unorm).unwrap(); + let memory_allocator = StandardMemoryAllocator::new_default(device); + let _img = AttachmentImage::new(&memory_allocator, [32, 32], Format::D16_UNORM).unwrap(); } } |