rendy_resource/
image.rs

1//! Image usage, format, kind, extent, creation-info and wrappers.
2
3pub use rendy_core::hal::image::*;
4
5use {
6    crate::{
7        core::{device_owned, Device, DeviceId},
8        escape::Handle,
9        memory::{Block, Heaps, MemoryBlock, MemoryUsage},
10        CreationError,
11    },
12    relevant::Relevant,
13    rendy_core::hal::{device::Device as _, format, Backend},
14};
15
16/// Image info.
17#[derive(Clone, Copy, Debug)]
18pub struct ImageInfo {
19    /// Kind of the image.
20    pub kind: Kind,
21
22    /// Image mip-level count.
23    pub levels: Level,
24
25    /// Image format.
26    pub format: format::Format,
27
28    /// Image tiling mode.
29    pub tiling: Tiling,
30
31    /// Image view capabilities.
32    pub view_caps: ViewCapabilities,
33
34    /// Image usage flags.
35    pub usage: Usage,
36}
37
38/// Generic image resource wrapper.
39///
40/// # Parameters
41///
42/// `B` - raw image type.
43#[derive(Debug)]
44pub struct Image<B: Backend> {
45    device: DeviceId,
46    raw: B::Image,
47    block: Option<MemoryBlock<B>>,
48    info: ImageInfo,
49    relevant: Relevant,
50}
51
52device_owned!(Image<B>);
53/// Alias for the error to create an image.
54pub type ImageCreationError = CreationError<rendy_core::hal::image::CreationError>;
55
56impl<B> Image<B>
57where
58    B: Backend,
59{
60    /// Create image.
61    ///
62    /// # Safety
63    ///
64    /// In order to guarantee that `Heap::allocate` will return
65    /// memory range owned by this `Device`,
66    /// this `Heaps` instance must always be used with this `Device` instance.
67    ///
68    /// Otherwise usage of hal methods must be always valid.
69    pub unsafe fn create(
70        device: &Device<B>,
71        heaps: &mut Heaps<B>,
72        info: ImageInfo,
73        memory_usage: impl MemoryUsage,
74    ) -> Result<Self, ImageCreationError> {
75        assert!(
76            info.levels <= info.kind.num_levels(),
77            "Number of mip leves ({}) cannot be greater than {} for given kind {:?}",
78            info.levels,
79            info.kind.num_levels(),
80            info.kind,
81        );
82
83        log::trace!("{:#?}@{:#?}", info, memory_usage);
84
85        let mut img = device
86            .create_image(
87                info.kind,
88                info.levels,
89                info.format,
90                info.tiling,
91                info.usage,
92                info.view_caps,
93            )
94            .map_err(CreationError::Create)?;
95        let reqs = device.get_image_requirements(&img);
96        let block = heaps
97            .allocate(
98                device,
99                reqs.type_mask as u32,
100                memory_usage,
101                reqs.size,
102                reqs.alignment,
103            )
104            .map_err(CreationError::Allocate)?;
105
106        device
107            .bind_image_memory(block.memory(), block.range().start, &mut img)
108            .map_err(CreationError::Bind)?;
109
110        Ok(Image {
111            device: device.id(),
112            raw: img,
113            block: Some(block),
114            info,
115            relevant: Relevant,
116        })
117    }
118
119    /// Create image handler for swapchain image.
120    pub unsafe fn create_from_swapchain(device: DeviceId, info: ImageInfo, raw: B::Image) -> Self {
121        Image {
122            device,
123            raw,
124            block: None,
125            info,
126            relevant: Relevant,
127        }
128    }
129
130    /// Destroy image resource.
131    pub unsafe fn dispose(self, device: &Device<B>, heaps: &mut Heaps<B>) {
132        self.assert_device_owner(device);
133        device.destroy_image(self.raw);
134        self.block.map(|block| heaps.free(device, block));
135        self.relevant.dispose();
136    }
137
138    /// Drop image wrapper for swapchain image.
139    pub unsafe fn dispose_swapchain_image(self, device: DeviceId) {
140        assert_eq!(self.device_id(), device);
141        assert!(self.block.is_none());
142        self.relevant.dispose();
143    }
144
145    /// Get reference for raw image resource.
146    pub fn raw(&self) -> &B::Image {
147        &self.raw
148    }
149
150    /// Get mutable reference for raw image resource.
151    pub unsafe fn raw_mut(&mut self) -> &mut B::Image {
152        &mut self.raw
153    }
154
155    /// Get reference to memory block occupied by image.
156    pub fn block(&self) -> Option<&MemoryBlock<B>> {
157        self.block.as_ref()
158    }
159
160    /// Get mutable reference to memory block occupied by image.
161    pub unsafe fn block_mut(&mut self) -> Option<&mut MemoryBlock<B>> {
162        self.block.as_mut()
163    }
164
165    /// Get image info.
166    pub fn info(&self) -> &ImageInfo {
167        &self.info
168    }
169
170    /// Get [`Kind`] of the image.
171    ///
172    /// [`Kind`]: ../gfx-hal/image/struct.Kind.html
173    pub fn kind(&self) -> Kind {
174        self.info.kind
175    }
176
177    /// Get [`Format`] of the image.
178    ///
179    /// [`Format`]: ../gfx-hal/format/struct.Format.html
180    pub fn format(&self) -> format::Format {
181        self.info.format
182    }
183
184    /// Get levels count of the image.
185    pub fn levels(&self) -> u8 {
186        self.info.levels
187    }
188
189    /// Get layers count of the image.
190    pub fn layers(&self) -> u16 {
191        self.info.kind.num_layers()
192    }
193}
194
195/// Image view info
196#[derive(Clone, Debug)]
197pub struct ImageViewInfo {
198    /// View kind
199    pub view_kind: ViewKind,
200    /// Format for this view
201    pub format: format::Format,
202    /// Swizzle operator for this view
203    pub swizzle: format::Swizzle,
204    /// Range of full image to view
205    pub range: SubresourceRange,
206}
207
208/// Generic image view resource wrapper.
209#[derive(Debug)]
210pub struct ImageView<B: Backend> {
211    raw: B::ImageView,
212    image: Handle<Image<B>>,
213    info: ImageViewInfo,
214    relevant: Relevant,
215}
216
217device_owned!(ImageView<B> @ |view: &Self| view.image.device_id());
218/// Alias for the error to create an image view.
219pub type ImageViewCreationError = CreationError<ViewError>;
220
221impl<B> ImageView<B>
222where
223    B: Backend,
224{
225    /// Create an image view.
226    pub fn create(
227        device: &Device<B>,
228        info: ImageViewInfo,
229        image: Handle<Image<B>>,
230    ) -> Result<Self, ImageViewCreationError> {
231        log::trace!("{:#?}@{:#?}", info, image);
232
233        image.assert_device_owner(device);
234
235        assert!(match_kind(
236            image.kind(),
237            info.view_kind,
238            image.info().view_caps
239        ));
240
241        let view = unsafe {
242            device
243                .create_image_view(
244                    image.raw(),
245                    info.view_kind,
246                    info.format,
247                    info.swizzle,
248                    SubresourceRange {
249                        aspects: info.range.aspects.clone(),
250                        layers: info.range.layers.clone(),
251                        levels: info.range.levels.clone(),
252                    },
253                )
254                .map_err(CreationError::Create)?
255        };
256
257        Ok(ImageView {
258            raw: view,
259            image,
260            info,
261            relevant: Relevant,
262        })
263    }
264
265    /// Destroy image view resource.
266    pub unsafe fn dispose(self, device: &Device<B>) {
267        device.destroy_image_view(self.raw);
268        drop(self.image);
269        self.relevant.dispose();
270    }
271
272    /// Get reference to raw image view resoruce.
273    pub fn raw(&self) -> &B::ImageView {
274        &self.raw
275    }
276
277    /// Get mutable reference to raw image view resoruce.
278    pub unsafe fn raw_mut(&mut self) -> &mut B::ImageView {
279        &mut self.raw
280    }
281
282    /// Get image view info.
283    pub fn info(&self) -> &ImageViewInfo {
284        &self.info
285    }
286
287    /// Get image of this view.
288    pub fn image(&self) -> &Handle<Image<B>> {
289        &self.image
290    }
291}
292
293fn match_kind(kind: Kind, view_kind: ViewKind, view_caps: ViewCapabilities) -> bool {
294    match kind {
295        Kind::D1(..) => match view_kind {
296            ViewKind::D1 | ViewKind::D1Array => true,
297            _ => false,
298        },
299        Kind::D2(..) => match view_kind {
300            ViewKind::D2 | ViewKind::D2Array => true,
301            ViewKind::Cube => {
302                if view_caps.contains(ViewCapabilities::KIND_CUBE) {
303                    true
304                } else {
305                    false
306                }
307            }
308            _ => false,
309        },
310        Kind::D3(..) => {
311            if view_caps == ViewCapabilities::KIND_2D_ARRAY {
312                if view_kind == ViewKind::D2 {
313                    true
314                } else if view_kind == ViewKind::D2Array {
315                    true
316                } else {
317                    false
318                }
319            } else if view_kind == ViewKind::D3 {
320                true
321            } else {
322                false
323            }
324        }
325    }
326}