• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 use crate::buffer::BufferAccess;
11 use crate::buffer::BufferUsage;
12 use crate::buffer::CpuAccessibleBuffer;
13 use crate::buffer::TypedBufferAccess;
14 use crate::command_buffer::AutoCommandBufferBuilder;
15 use crate::command_buffer::CommandBufferExecFuture;
16 use crate::command_buffer::CommandBufferUsage;
17 use crate::command_buffer::PrimaryAutoCommandBuffer;
18 use crate::command_buffer::PrimaryCommandBuffer;
19 use crate::device::physical::QueueFamily;
20 use crate::device::Device;
21 use crate::device::Queue;
22 use crate::format::Format;
23 use crate::format::Pixel;
24 use crate::image::sys::ImageCreationError;
25 use crate::image::sys::UnsafeImage;
26 use crate::image::traits::ImageAccess;
27 use crate::image::traits::ImageContent;
28 use crate::image::ImageCreateFlags;
29 use crate::image::ImageDescriptorLayouts;
30 use crate::image::ImageDimensions;
31 use crate::image::ImageInner;
32 use crate::image::ImageLayout;
33 use crate::image::ImageUsage;
34 use crate::image::MipmapsCount;
35 use crate::image::SampleCount;
36 use crate::memory::pool::AllocFromRequirementsFilter;
37 use crate::memory::pool::AllocLayout;
38 use crate::memory::pool::MappingRequirement;
39 use crate::memory::pool::MemoryPool;
40 use crate::memory::pool::MemoryPoolAlloc;
41 use crate::memory::pool::PotentialDedicatedAllocation;
42 use crate::memory::pool::StdMemoryPoolAlloc;
43 use crate::memory::DedicatedAlloc;
44 use crate::sampler::Filter;
45 use crate::sync::AccessError;
46 use crate::sync::NowFuture;
47 use crate::sync::Sharing;
48 use smallvec::SmallVec;
49 use std::hash::Hash;
50 use std::hash::Hasher;
51 use std::sync::atomic::AtomicBool;
52 use std::sync::atomic::Ordering;
53 use std::sync::Arc;
54 
55 /// Image whose purpose is to be used for read-only purposes. You can write to the image once,
56 /// but then you must only ever read from it.
57 // TODO: type (2D, 3D, array, etc.) as template parameter
58 #[derive(Debug)]
59 pub struct ImmutableImage<A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>> {
60     image: UnsafeImage,
61     dimensions: ImageDimensions,
62     memory: A,
63     format: Format,
64     initialized: AtomicBool,
65     layout: ImageLayout,
66 }
67 
68 /// Image whose purpose is to access only a part of one image, for any kind of access
69 /// We define a part of one image here by a level of mipmap, or a layer of an array
70 /// The image attribute must be an implementation of ImageAccess
71 /// The mip_levels_access must be a range showing which mipmaps will be accessed
72 /// The layer_levels_access must be a range showing which layers will be accessed
73 /// The layout must be the layout of the image at the beginning and at the end of the command buffer
74 pub struct SubImage {
75     image: Arc<dyn ImageAccess + Sync + Send>,
76     mip_levels_access: std::ops::Range<u32>,
77     layer_levels_access: std::ops::Range<u32>,
78     layout: ImageLayout,
79 }
80 
81 impl SubImage {
new( image: Arc<dyn ImageAccess + Sync + Send>, mip_level: u32, mip_level_count: u32, layer_level: u32, layer_level_count: u32, layout: ImageLayout, ) -> Arc<SubImage>82     pub fn new(
83         image: Arc<dyn ImageAccess + Sync + Send>,
84         mip_level: u32,
85         mip_level_count: u32,
86         layer_level: u32,
87         layer_level_count: u32,
88         layout: ImageLayout,
89     ) -> Arc<SubImage> {
90         debug_assert!(mip_level + mip_level_count <= image.mipmap_levels());
91         debug_assert!(layer_level + layer_level_count <= image.dimensions().array_layers());
92 
93         let last_level = mip_level + mip_level_count;
94         let mip_levels_access = mip_level..last_level;
95 
96         let last_level = layer_level + layer_level_count;
97         let layer_levels_access = layer_level..last_level;
98 
99         Arc::new(SubImage {
100             image,
101             mip_levels_access,
102             layer_levels_access,
103             layout: ImageLayout::ShaderReadOnlyOptimal,
104         })
105     }
106 }
107 
108 // Must not implement Clone, as that would lead to multiple `used` values.
109 pub struct ImmutableImageInitialization<A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>> {
110     image: Arc<ImmutableImage<A>>,
111     used: AtomicBool,
112     mip_levels_access: std::ops::Range<u32>,
113     layer_levels_access: std::ops::Range<u32>,
114 }
115 
has_mipmaps(mipmaps: MipmapsCount) -> bool116 fn has_mipmaps(mipmaps: MipmapsCount) -> bool {
117     match mipmaps {
118         MipmapsCount::One => false,
119         MipmapsCount::Log2 => true,
120         MipmapsCount::Specific(x) => x > 1,
121     }
122 }
123 
generate_mipmaps<L, Img>( cbb: &mut AutoCommandBufferBuilder<L>, image: Arc<Img>, dimensions: ImageDimensions, layout: ImageLayout, ) where Img: ImageAccess + Send + Sync + 'static,124 fn generate_mipmaps<L, Img>(
125     cbb: &mut AutoCommandBufferBuilder<L>,
126     image: Arc<Img>,
127     dimensions: ImageDimensions,
128     layout: ImageLayout,
129 ) where
130     Img: ImageAccess + Send + Sync + 'static,
131 {
132     for level in 1..image.mipmap_levels() {
133         let [xs, ys, ds] = dimensions
134             .mipmap_dimensions(level - 1)
135             .unwrap()
136             .width_height_depth();
137         let [xd, yd, dd] = dimensions
138             .mipmap_dimensions(level)
139             .unwrap()
140             .width_height_depth();
141 
142         let src = SubImage::new(
143             image.clone(),
144             level - 1,
145             1,
146             0,
147             dimensions.array_layers(),
148             layout,
149         );
150 
151         let dst = SubImage::new(
152             image.clone(),
153             level,
154             1,
155             0,
156             dimensions.array_layers(),
157             layout,
158         );
159 
160         cbb.blit_image(
161             src,                               //source
162             [0, 0, 0],                         //source_top_left
163             [xs as i32, ys as i32, ds as i32], //source_bottom_right
164             0,                                 //source_base_array_layer
165             level - 1,                         //source_mip_level
166             dst,                               //destination
167             [0, 0, 0],                         //destination_top_left
168             [xd as i32, yd as i32, dd as i32], //destination_bottom_right
169             0,                                 //destination_base_array_layer
170             level,                             //destination_mip_level
171             1,                                 //layer_count
172             Filter::Linear,                    //filter
173         )
174         .expect("failed to blit a mip map to image!");
175     }
176 }
177 
178 impl ImmutableImage {
179     #[deprecated(note = "use ImmutableImage::uninitialized instead")]
180     #[inline]
new<'a, I>( device: Arc<Device>, dimensions: ImageDimensions, format: Format, queue_families: I, ) -> Result<Arc<ImmutableImage>, ImageCreationError> where I: IntoIterator<Item = QueueFamily<'a>>,181     pub fn new<'a, I>(
182         device: Arc<Device>,
183         dimensions: ImageDimensions,
184         format: Format,
185         queue_families: I,
186     ) -> Result<Arc<ImmutableImage>, ImageCreationError>
187     where
188         I: IntoIterator<Item = QueueFamily<'a>>,
189     {
190         #[allow(deprecated)]
191         ImmutableImage::with_mipmaps(
192             device,
193             dimensions,
194             format,
195             MipmapsCount::One,
196             queue_families,
197         )
198     }
199 
200     #[deprecated(note = "use ImmutableImage::uninitialized instead")]
201     #[inline]
with_mipmaps<'a, I, M>( device: Arc<Device>, dimensions: ImageDimensions, format: Format, mipmaps: M, queue_families: I, ) -> Result<Arc<ImmutableImage>, ImageCreationError> where I: IntoIterator<Item = QueueFamily<'a>>, M: Into<MipmapsCount>,202     pub fn with_mipmaps<'a, I, M>(
203         device: Arc<Device>,
204         dimensions: ImageDimensions,
205         format: Format,
206         mipmaps: M,
207         queue_families: I,
208     ) -> Result<Arc<ImmutableImage>, ImageCreationError>
209     where
210         I: IntoIterator<Item = QueueFamily<'a>>,
211         M: Into<MipmapsCount>,
212     {
213         let usage = ImageUsage {
214             transfer_source: true, // for blits
215             transfer_destination: true,
216             sampled: true,
217             ..ImageUsage::none()
218         };
219 
220         let flags = ImageCreateFlags::none();
221 
222         let (image, _) = ImmutableImage::uninitialized(
223             device,
224             dimensions,
225             format,
226             mipmaps,
227             usage,
228             flags,
229             ImageLayout::ShaderReadOnlyOptimal,
230             queue_families,
231         )?;
232         image.initialized.store(true, Ordering::Relaxed); // Allow uninitialized access for backwards compatibility
233         Ok(image)
234     }
235 
236     /// Builds an uninitialized immutable image.
237     ///
238     /// Returns two things: the image, and a special access that should be used for the initial upload to the image.
uninitialized<'a, I, M>( device: Arc<Device>, dimensions: ImageDimensions, format: Format, mipmaps: M, usage: ImageUsage, flags: ImageCreateFlags, layout: ImageLayout, queue_families: I, ) -> Result<(Arc<ImmutableImage>, ImmutableImageInitialization), ImageCreationError> where I: IntoIterator<Item = QueueFamily<'a>>, M: Into<MipmapsCount>,239     pub fn uninitialized<'a, I, M>(
240         device: Arc<Device>,
241         dimensions: ImageDimensions,
242         format: Format,
243         mipmaps: M,
244         usage: ImageUsage,
245         flags: ImageCreateFlags,
246         layout: ImageLayout,
247         queue_families: I,
248     ) -> Result<(Arc<ImmutableImage>, ImmutableImageInitialization), ImageCreationError>
249     where
250         I: IntoIterator<Item = QueueFamily<'a>>,
251         M: Into<MipmapsCount>,
252     {
253         let queue_families = queue_families
254             .into_iter()
255             .map(|f| f.id())
256             .collect::<SmallVec<[u32; 4]>>();
257 
258         let (image, mem_reqs) = unsafe {
259             let sharing = if queue_families.len() >= 2 {
260                 Sharing::Concurrent(queue_families.iter().cloned())
261             } else {
262                 Sharing::Exclusive
263             };
264 
265             UnsafeImage::new(
266                 device.clone(),
267                 usage,
268                 format,
269                 flags,
270                 dimensions,
271                 SampleCount::Sample1,
272                 mipmaps,
273                 sharing,
274                 false,
275                 false,
276             )?
277         };
278 
279         let memory = MemoryPool::alloc_from_requirements(
280             &Device::standard_pool(&device),
281             &mem_reqs,
282             AllocLayout::Optimal,
283             MappingRequirement::DoNotMap,
284             DedicatedAlloc::Image(&image),
285             |t| {
286                 if t.is_device_local() {
287                     AllocFromRequirementsFilter::Preferred
288                 } else {
289                     AllocFromRequirementsFilter::Allowed
290                 }
291             },
292         )?;
293         debug_assert!((memory.offset() % mem_reqs.alignment) == 0);
294         unsafe {
295             image.bind_memory(memory.memory(), memory.offset())?;
296         }
297 
298         let image = Arc::new(ImmutableImage {
299             image,
300             memory,
301             dimensions,
302             format,
303             initialized: AtomicBool::new(false),
304             layout,
305         });
306 
307         let init = ImmutableImageInitialization {
308             image: image.clone(),
309             used: AtomicBool::new(false),
310             mip_levels_access: 0..image.mipmap_levels(),
311             layer_levels_access: 0..image.dimensions().array_layers(),
312         };
313 
314         Ok((image, init))
315     }
316 
317     /// Construct an ImmutableImage from the contents of `iter`.
318     #[inline]
from_iter<Px, I>( iter: I, dimensions: ImageDimensions, mipmaps: MipmapsCount, format: Format, queue: Arc<Queue>, ) -> Result< ( Arc<Self>, CommandBufferExecFuture<NowFuture, PrimaryAutoCommandBuffer>, ), ImageCreationError, > where Px: Pixel + Send + Sync + Clone + 'static, I: ExactSizeIterator<Item = Px>,319     pub fn from_iter<Px, I>(
320         iter: I,
321         dimensions: ImageDimensions,
322         mipmaps: MipmapsCount,
323         format: Format,
324         queue: Arc<Queue>,
325     ) -> Result<
326         (
327             Arc<Self>,
328             CommandBufferExecFuture<NowFuture, PrimaryAutoCommandBuffer>,
329         ),
330         ImageCreationError,
331     >
332     where
333         Px: Pixel + Send + Sync + Clone + 'static,
334         I: ExactSizeIterator<Item = Px>,
335     {
336         let source = CpuAccessibleBuffer::from_iter(
337             queue.device().clone(),
338             BufferUsage::transfer_source(),
339             false,
340             iter,
341         )?;
342         ImmutableImage::from_buffer(source, dimensions, mipmaps, format, queue)
343     }
344 
345     /// Construct an ImmutableImage containing a copy of the data in `source`.
from_buffer<B, Px>( source: B, dimensions: ImageDimensions, mipmaps: MipmapsCount, format: Format, queue: Arc<Queue>, ) -> Result< ( Arc<Self>, CommandBufferExecFuture<NowFuture, PrimaryAutoCommandBuffer>, ), ImageCreationError, > where B: BufferAccess + TypedBufferAccess<Content = [Px]> + 'static + Clone + Send + Sync, Px: Pixel + Send + Sync + Clone + 'static,346     pub fn from_buffer<B, Px>(
347         source: B,
348         dimensions: ImageDimensions,
349         mipmaps: MipmapsCount,
350         format: Format,
351         queue: Arc<Queue>,
352     ) -> Result<
353         (
354             Arc<Self>,
355             CommandBufferExecFuture<NowFuture, PrimaryAutoCommandBuffer>,
356         ),
357         ImageCreationError,
358     >
359     where
360         B: BufferAccess + TypedBufferAccess<Content = [Px]> + 'static + Clone + Send + Sync,
361         Px: Pixel + Send + Sync + Clone + 'static,
362     {
363         let need_to_generate_mipmaps = has_mipmaps(mipmaps);
364         let usage = ImageUsage {
365             transfer_destination: true,
366             transfer_source: need_to_generate_mipmaps,
367             sampled: true,
368             ..ImageUsage::none()
369         };
370         let flags = ImageCreateFlags::none();
371         let layout = ImageLayout::ShaderReadOnlyOptimal;
372 
373         let (image, initializer) = ImmutableImage::uninitialized(
374             source.device().clone(),
375             dimensions,
376             format,
377             mipmaps,
378             usage,
379             flags,
380             layout,
381             source.device().active_queue_families(),
382         )?;
383 
384         let init = SubImage::new(
385             Arc::new(initializer),
386             0,
387             1,
388             0,
389             1,
390             ImageLayout::ShaderReadOnlyOptimal,
391         );
392 
393         let mut cbb = AutoCommandBufferBuilder::primary(
394             source.device().clone(),
395             queue.family(),
396             CommandBufferUsage::MultipleSubmit,
397         )?;
398         cbb.copy_buffer_to_image_dimensions(
399             source,
400             init,
401             [0, 0, 0],
402             dimensions.width_height_depth(),
403             0,
404             dimensions.array_layers(),
405             0,
406         )
407         .unwrap();
408 
409         if need_to_generate_mipmaps {
410             generate_mipmaps(
411                 &mut cbb,
412                 image.clone(),
413                 image.dimensions,
414                 ImageLayout::ShaderReadOnlyOptimal,
415             );
416         }
417 
418         let cb = cbb.build().unwrap();
419 
420         let future = match cb.execute(queue) {
421             Ok(f) => f,
422             Err(e) => unreachable!("{:?}", e),
423         };
424 
425         image.initialized.store(true, Ordering::Relaxed);
426 
427         Ok((image, future))
428     }
429 }
430 
431 impl<A> ImmutableImage<A> {
432     /// Returns the dimensions of the image.
433     #[inline]
dimensions(&self) -> ImageDimensions434     pub fn dimensions(&self) -> ImageDimensions {
435         self.dimensions
436     }
437 
438     /// Returns the number of mipmap levels of the image.
439     #[inline]
mipmap_levels(&self) -> u32440     pub fn mipmap_levels(&self) -> u32 {
441         self.image.mipmap_levels()
442     }
443 }
444 
445 unsafe impl<A> ImageAccess for ImmutableImage<A> {
446     #[inline]
inner(&self) -> ImageInner447     fn inner(&self) -> ImageInner {
448         ImageInner {
449             image: &self.image,
450             first_layer: 0,
451             num_layers: self.image.dimensions().array_layers() as usize,
452             first_mipmap_level: 0,
453             num_mipmap_levels: self.image.mipmap_levels() as usize,
454         }
455     }
456 
457     #[inline]
initial_layout_requirement(&self) -> ImageLayout458     fn initial_layout_requirement(&self) -> ImageLayout {
459         self.layout
460     }
461 
462     #[inline]
final_layout_requirement(&self) -> ImageLayout463     fn final_layout_requirement(&self) -> ImageLayout {
464         self.layout
465     }
466 
467     #[inline]
descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>468     fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
469         Some(ImageDescriptorLayouts {
470             storage_image: self.layout,
471             combined_image_sampler: self.layout,
472             sampled_image: self.layout,
473             input_attachment: self.layout,
474         })
475     }
476 
477     #[inline]
conflict_key(&self) -> u64478     fn conflict_key(&self) -> u64 {
479         self.image.key()
480     }
481 
482     #[inline]
try_gpu_lock( &self, exclusive_access: bool, uninitialized_safe: bool, expected_layout: ImageLayout, ) -> Result<(), AccessError>483     fn try_gpu_lock(
484         &self,
485         exclusive_access: bool,
486         uninitialized_safe: bool,
487         expected_layout: ImageLayout,
488     ) -> Result<(), AccessError> {
489         if expected_layout != self.layout && expected_layout != ImageLayout::Undefined {
490             return Err(AccessError::UnexpectedImageLayout {
491                 requested: expected_layout,
492                 allowed: self.layout,
493             });
494         }
495 
496         if exclusive_access {
497             return Err(AccessError::ExclusiveDenied);
498         }
499 
500         if !self.initialized.load(Ordering::Relaxed) {
501             return Err(AccessError::BufferNotInitialized);
502         }
503 
504         Ok(())
505     }
506 
507     #[inline]
increase_gpu_lock(&self)508     unsafe fn increase_gpu_lock(&self) {}
509 
510     #[inline]
unlock(&self, new_layout: Option<ImageLayout>)511     unsafe fn unlock(&self, new_layout: Option<ImageLayout>) {
512         debug_assert!(new_layout.is_none());
513     }
514 
515     #[inline]
current_miplevels_access(&self) -> std::ops::Range<u32>516     fn current_miplevels_access(&self) -> std::ops::Range<u32> {
517         0..self.mipmap_levels()
518     }
519 
520     #[inline]
current_layer_levels_access(&self) -> std::ops::Range<u32>521     fn current_layer_levels_access(&self) -> std::ops::Range<u32> {
522         0..self.dimensions().array_layers()
523     }
524 }
525 
526 unsafe impl<P, A> ImageContent<P> for ImmutableImage<A> {
527     #[inline]
matches_format(&self) -> bool528     fn matches_format(&self) -> bool {
529         true // FIXME:
530     }
531 }
532 
533 unsafe impl ImageAccess for SubImage {
534     #[inline]
inner(&self) -> ImageInner535     fn inner(&self) -> ImageInner {
536         self.image.inner()
537     }
538 
539     #[inline]
initial_layout_requirement(&self) -> ImageLayout540     fn initial_layout_requirement(&self) -> ImageLayout {
541         self.image.initial_layout_requirement()
542     }
543 
544     #[inline]
final_layout_requirement(&self) -> ImageLayout545     fn final_layout_requirement(&self) -> ImageLayout {
546         self.image.final_layout_requirement()
547     }
548 
549     #[inline]
descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>550     fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
551         None
552     }
553 
current_miplevels_access(&self) -> std::ops::Range<u32>554     fn current_miplevels_access(&self) -> std::ops::Range<u32> {
555         self.mip_levels_access.clone()
556     }
557 
current_layer_levels_access(&self) -> std::ops::Range<u32>558     fn current_layer_levels_access(&self) -> std::ops::Range<u32> {
559         self.layer_levels_access.clone()
560     }
561 
562     #[inline]
conflict_key(&self) -> u64563     fn conflict_key(&self) -> u64 {
564         self.image.conflict_key()
565     }
566 
567     #[inline]
try_gpu_lock( &self, exclusive_access: bool, uninitialized_safe: bool, expected_layout: ImageLayout, ) -> Result<(), AccessError>568     fn try_gpu_lock(
569         &self,
570         exclusive_access: bool,
571         uninitialized_safe: bool,
572         expected_layout: ImageLayout,
573     ) -> Result<(), AccessError> {
574         if expected_layout != self.layout && expected_layout != ImageLayout::Undefined {
575             return Err(AccessError::UnexpectedImageLayout {
576                 requested: expected_layout,
577                 allowed: self.layout,
578             });
579         }
580 
581         Ok(())
582     }
583 
584     #[inline]
increase_gpu_lock(&self)585     unsafe fn increase_gpu_lock(&self) {
586         self.image.increase_gpu_lock()
587     }
588 
589     #[inline]
unlock(&self, new_layout: Option<ImageLayout>)590     unsafe fn unlock(&self, new_layout: Option<ImageLayout>) {
591         self.image.unlock(new_layout)
592     }
593 }
594 
595 impl<A> PartialEq for ImmutableImage<A> {
596     #[inline]
eq(&self, other: &Self) -> bool597     fn eq(&self, other: &Self) -> bool {
598         ImageAccess::inner(self) == ImageAccess::inner(other)
599     }
600 }
601 
602 impl<A> Eq for ImmutableImage<A> {}
603 
604 impl<A> Hash for ImmutableImage<A> {
605     #[inline]
hash<H: Hasher>(&self, state: &mut H)606     fn hash<H: Hasher>(&self, state: &mut H) {
607         ImageAccess::inner(self).hash(state);
608     }
609 }
610 
611 unsafe impl<A> ImageAccess for ImmutableImageInitialization<A> {
612     #[inline]
inner(&self) -> ImageInner613     fn inner(&self) -> ImageInner {
614         ImageAccess::inner(&self.image)
615     }
616 
617     #[inline]
initial_layout_requirement(&self) -> ImageLayout618     fn initial_layout_requirement(&self) -> ImageLayout {
619         ImageLayout::Undefined
620     }
621 
622     #[inline]
final_layout_requirement(&self) -> ImageLayout623     fn final_layout_requirement(&self) -> ImageLayout {
624         self.image.layout
625     }
626 
627     #[inline]
descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>628     fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
629         None
630     }
631 
632     #[inline]
conflict_key(&self) -> u64633     fn conflict_key(&self) -> u64 {
634         self.image.image.key()
635     }
636 
637     #[inline]
try_gpu_lock( &self, _: bool, uninitialized_safe: bool, expected_layout: ImageLayout, ) -> Result<(), AccessError>638     fn try_gpu_lock(
639         &self,
640         _: bool,
641         uninitialized_safe: bool,
642         expected_layout: ImageLayout,
643     ) -> Result<(), AccessError> {
644         if expected_layout != ImageLayout::Undefined {
645             return Err(AccessError::UnexpectedImageLayout {
646                 requested: expected_layout,
647                 allowed: ImageLayout::Undefined,
648             });
649         }
650 
651         if self.image.initialized.load(Ordering::Relaxed) {
652             return Err(AccessError::AlreadyInUse);
653         }
654 
655         // FIXME: Mipmapped textures require multiple writes to initialize
656         if !self
657             .used
658             .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
659             .unwrap_or_else(|e| e)
660         {
661             Ok(())
662         } else {
663             Err(AccessError::AlreadyInUse)
664         }
665     }
666 
667     #[inline]
increase_gpu_lock(&self)668     unsafe fn increase_gpu_lock(&self) {
669         debug_assert!(self.used.load(Ordering::Relaxed));
670     }
671 
672     #[inline]
unlock(&self, new_layout: Option<ImageLayout>)673     unsafe fn unlock(&self, new_layout: Option<ImageLayout>) {
674         assert_eq!(new_layout, Some(self.image.layout));
675         self.image.initialized.store(true, Ordering::Relaxed);
676     }
677 
678     #[inline]
current_miplevels_access(&self) -> std::ops::Range<u32>679     fn current_miplevels_access(&self) -> std::ops::Range<u32> {
680         self.mip_levels_access.clone()
681     }
682 
683     #[inline]
current_layer_levels_access(&self) -> std::ops::Range<u32>684     fn current_layer_levels_access(&self) -> std::ops::Range<u32> {
685         self.layer_levels_access.clone()
686     }
687 }
688 
689 impl<A> PartialEq for ImmutableImageInitialization<A> {
690     #[inline]
eq(&self, other: &Self) -> bool691     fn eq(&self, other: &Self) -> bool {
692         ImageAccess::inner(self) == ImageAccess::inner(other)
693     }
694 }
695 
696 impl<A> Eq for ImmutableImageInitialization<A> {}
697 
698 impl<A> Hash for ImmutableImageInitialization<A> {
699     #[inline]
hash<H: Hasher>(&self, state: &mut H)700     fn hash<H: Hasher>(&self, state: &mut H) {
701         ImageAccess::inner(self).hash(state);
702     }
703 }
704