1pub 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#[derive(Clone, Copy, Debug)]
18pub struct ImageInfo {
19 pub kind: Kind,
21
22 pub levels: Level,
24
25 pub format: format::Format,
27
28 pub tiling: Tiling,
30
31 pub view_caps: ViewCapabilities,
33
34 pub usage: Usage,
36}
37
38#[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>);
53pub type ImageCreationError = CreationError<rendy_core::hal::image::CreationError>;
55
56impl<B> Image<B>
57where
58 B: Backend,
59{
60 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 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 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 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 pub fn raw(&self) -> &B::Image {
147 &self.raw
148 }
149
150 pub unsafe fn raw_mut(&mut self) -> &mut B::Image {
152 &mut self.raw
153 }
154
155 pub fn block(&self) -> Option<&MemoryBlock<B>> {
157 self.block.as_ref()
158 }
159
160 pub unsafe fn block_mut(&mut self) -> Option<&mut MemoryBlock<B>> {
162 self.block.as_mut()
163 }
164
165 pub fn info(&self) -> &ImageInfo {
167 &self.info
168 }
169
170 pub fn kind(&self) -> Kind {
174 self.info.kind
175 }
176
177 pub fn format(&self) -> format::Format {
181 self.info.format
182 }
183
184 pub fn levels(&self) -> u8 {
186 self.info.levels
187 }
188
189 pub fn layers(&self) -> u16 {
191 self.info.kind.num_layers()
192 }
193}
194
195#[derive(Clone, Debug)]
197pub struct ImageViewInfo {
198 pub view_kind: ViewKind,
200 pub format: format::Format,
202 pub swizzle: format::Swizzle,
204 pub range: SubresourceRange,
206}
207
208#[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());
218pub type ImageViewCreationError = CreationError<ViewError>;
220
221impl<B> ImageView<B>
222where
223 B: Backend,
224{
225 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 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 pub fn raw(&self) -> &B::ImageView {
274 &self.raw
275 }
276
277 pub unsafe fn raw_mut(&mut self) -> &mut B::ImageView {
279 &mut self.raw
280 }
281
282 pub fn info(&self) -> &ImageViewInfo {
284 &self.info
285 }
286
287 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}