1 //! Image related structures.
2 //!
3 //! An image is a block of GPU memory representing a grid of texels.
4
5 use crate::{
6 buffer::Offset as RawOffset,
7 device, format,
8 pso::{Comparison, Rect},
9 };
10 use std::{f32, hash, ops::Range};
11
12 /// Dimension size.
13 pub type Size = u32;
14 /// Number of MSAA samples.
15 pub type NumSamples = u8;
16 /// Image layer.
17 pub type Layer = u16;
18 /// Image mipmap level.
19 pub type Level = u8;
20 /// Maximum accessible mipmap level of an image.
21 pub const MAX_LEVEL: Level = 15;
22 /// A texel coordinate in an image.
23 pub type TexelCoordinate = i32;
24
25 /// Describes the size of an image, which may be up to three dimensional.
26 #[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)]
27 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
28 pub struct Extent {
29 /// Image width
30 pub width: Size,
31 /// Image height
32 pub height: Size,
33 /// Image depth.
34 pub depth: Size,
35 }
36
37 impl Extent {
38 /// Return true if one of the dimensions is zero.
is_empty(&self) -> bool39 pub fn is_empty(&self) -> bool {
40 self.width == 0 || self.height == 0 || self.depth == 0
41 }
42 /// Get the extent at a particular mipmap level.
at_level(&self, level: Level) -> Self43 pub fn at_level(&self, level: Level) -> Self {
44 Extent {
45 width: 1.max(self.width >> level),
46 height: 1.max(self.height >> level),
47 depth: 1.max(self.depth >> level),
48 }
49 }
50 /// Get a rectangle for the full area of extent.
rect(&self) -> Rect51 pub fn rect(&self) -> Rect {
52 Rect {
53 x: 0,
54 y: 0,
55 w: self.width as i16,
56 h: self.height as i16,
57 }
58 }
59 }
60
61 /// An offset into an `Image` used for image-to-image
62 /// copy operations. All offsets are in texels, and
63 /// specifying offsets other than 0 for dimensions
64 /// that do not exist is undefined behavior -- for
65 /// example, specifying a `z` offset of `1` in a
66 /// two-dimensional image.
67 #[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)]
68 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69 pub struct Offset {
70 /// X offset.
71 pub x: TexelCoordinate,
72 /// Y offset.
73 pub y: TexelCoordinate,
74 /// Z offset.
75 pub z: TexelCoordinate,
76 }
77
78 impl Offset {
79 /// Zero offset shortcut.
80 pub const ZERO: Self = Offset { x: 0, y: 0, z: 0 };
81
82 /// Convert the offset into 2-sided bounds given the extent.
into_bounds(self, extent: &Extent) -> Range<Offset>83 pub fn into_bounds(self, extent: &Extent) -> Range<Offset> {
84 let end = Offset {
85 x: self.x + extent.width as i32,
86 y: self.y + extent.height as i32,
87 z: self.z + extent.depth as i32,
88 };
89 self..end
90 }
91 }
92
93 /// Image tiling modes.
94 #[repr(u32)]
95 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
96 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
97 pub enum Tiling {
98 /// Optimal tiling for GPU memory access. Implementation-dependent.
99 Optimal = 0,
100 /// Optimal for CPU read/write. Texels are laid out in row-major order,
101 /// possibly with some padding on each row.
102 Linear = 1,
103 }
104
105 /// Pure image object creation error.
106 #[derive(Clone, Debug, PartialEq, thiserror::Error)]
107 pub enum CreationError {
108 /// Out of either host or device memory.
109 #[error(transparent)]
110 OutOfMemory(#[from] device::OutOfMemory),
111 /// The format is not supported by the device.
112 #[error("Unsupported format: {0:?}")]
113 Format(format::Format),
114 /// The kind doesn't support a particular operation.
115 #[error("Specified kind doesn't support particular operation")]
116 Kind,
117 /// Failed to map a given multisampled kind to the device.
118 #[error("Specified format doesn't support specified sampling {0:}")]
119 Samples(NumSamples),
120 /// Unsupported size in one of the dimensions.
121 #[error("Unsupported size in one of the dimensions {0:}")]
122 Size(Size),
123 /// The given data has a different size than the target image slice.
124 #[error("The given data has a different size ({0:}) than the target image slice")]
125 Data(usize),
126 /// The mentioned usage mode is not supported
127 #[error("Unsupported usage: {0:?}")]
128 Usage(Usage),
129 }
130
131 /// Error creating an `ImageView`.
132 #[derive(Clone, Debug, PartialEq, thiserror::Error)]
133 pub enum ViewCreationError {
134 /// Out of either Host or Device memory
135 #[error(transparent)]
136 OutOfMemory(#[from] device::OutOfMemory),
137 /// The required usage flag is not present in the image.
138 #[error("Specified usage flags are not present in the image {0:?}")]
139 Usage(Usage),
140 /// Selected mip level doesn't exist.
141 #[error("Selected level doesn't exist in the image {0:}")]
142 Level(Level),
143 /// Selected array layer doesn't exist.
144 #[error(transparent)]
145 Layer(#[from] LayerError),
146 /// An incompatible format was requested for the view.
147 #[error("Incompatible format: {0:?}")]
148 BadFormat(format::Format),
149 /// An incompatible view kind was requested for the view.
150 #[error("Incompatible kind: {0:?}")]
151 BadKind(ViewKind),
152 /// The backend refused for some reason.
153 #[error("Implementation specific error occurred")]
154 Unsupported,
155 }
156
157 /// An error associated with selected image layer.
158 #[derive(Clone, Debug, PartialEq, thiserror::Error)]
159 pub enum LayerError {
160 /// The source image kind doesn't support array slices.
161 #[error("Source image doesn't support view kind {0:?}")]
162 NotExpected(Kind),
163 /// Selected layers are outside of the provided range.
164 #[error("Selected layers are out of bounds")]
165 OutOfBounds,
166 }
167
168 /// How to [filter](https://en.wikipedia.org/wiki/Texture_filtering) the
169 /// image when sampling. They correspond to increasing levels of quality,
170 /// but also cost.
171 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
172 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
173 pub enum Filter {
174 /// Selects a single texel from the current mip level and uses its value.
175 ///
176 /// Mip filtering selects the filtered value from one level.
177 Nearest,
178 /// Selects multiple texels and calculates the value via multivariate interpolation.
179 /// * 1D: Linear interpolation
180 /// * 2D/Cube: Bilinear interpolation
181 /// * 3D: Trilinear interpolation
182 Linear,
183 }
184
185 /// The face of a cube image to do an operation on.
186 #[allow(missing_docs)]
187 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
188 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
189 #[repr(u8)]
190 pub enum CubeFace {
191 PosX,
192 NegX,
193 PosY,
194 NegY,
195 PosZ,
196 NegZ,
197 }
198
199 /// A constant array of cube faces in the order they map to the hardware.
200 pub const CUBE_FACES: [CubeFace; 6] = [
201 CubeFace::PosX,
202 CubeFace::NegX,
203 CubeFace::PosY,
204 CubeFace::NegY,
205 CubeFace::PosZ,
206 CubeFace::NegZ,
207 ];
208
209 /// Specifies the dimensionality of an image to be allocated,
210 /// along with the number of mipmap layers and MSAA samples
211 /// if applicable.
212 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
213 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
214 pub enum Kind {
215 /// A single one-dimensional row of texels.
216 D1(Size, Layer),
217 /// Two-dimensional image.
218 D2(Size, Size, Layer, NumSamples),
219 /// Volumetric image.
220 D3(Size, Size, Size),
221 }
222
223 impl Kind {
224 /// Get the image extent.
extent(&self) -> Extent225 pub fn extent(&self) -> Extent {
226 match *self {
227 Kind::D1(width, _) => Extent {
228 width,
229 height: 1,
230 depth: 1,
231 },
232 Kind::D2(width, height, _, _) => Extent {
233 width,
234 height,
235 depth: 1,
236 },
237 Kind::D3(width, height, depth) => Extent {
238 width,
239 height,
240 depth,
241 },
242 }
243 }
244
245 /// Get the extent of a particular mipmap level.
level_extent(&self, level: Level) -> Extent246 pub fn level_extent(&self, level: Level) -> Extent {
247 use std::cmp::{max, min};
248 // must be at least 1
249 let map = |val| max(min(val, 1), val >> min(level, MAX_LEVEL));
250 match *self {
251 Kind::D1(w, _) => Extent {
252 width: map(w),
253 height: 1,
254 depth: 1,
255 },
256 Kind::D2(w, h, _, _) => Extent {
257 width: map(w),
258 height: map(h),
259 depth: 1,
260 },
261 Kind::D3(w, h, d) => Extent {
262 width: map(w),
263 height: map(h),
264 depth: map(d),
265 },
266 }
267 }
268
269 /// Count the number of mipmap levels.
compute_num_levels(&self) -> Level270 pub fn compute_num_levels(&self) -> Level {
271 use std::cmp::max;
272 match *self {
273 Kind::D2(_, _, _, s) if s > 1 => {
274 // anti-aliased images can't have mipmaps
275 1
276 }
277 _ => {
278 let extent = self.extent();
279 let dominant = max(max(extent.width, extent.height), extent.depth);
280 (1..).find(|level| dominant >> level == 0).unwrap()
281 }
282 }
283 }
284
285 /// Return the number of layers in an array type.
286 ///
287 /// Each cube face counts as separate layer.
num_layers(&self) -> Layer288 pub fn num_layers(&self) -> Layer {
289 match *self {
290 Kind::D1(_, a) | Kind::D2(_, _, a, _) => a,
291 Kind::D3(..) => 1,
292 }
293 }
294
295 /// Return the number of MSAA samples for the kind.
num_samples(&self) -> NumSamples296 pub fn num_samples(&self) -> NumSamples {
297 match *self {
298 Kind::D1(..) => 1,
299 Kind::D2(_, _, _, s) => s,
300 Kind::D3(..) => 1,
301 }
302 }
303 }
304
305 /// Specifies the kind/dimensionality of an image view.
306 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
307 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
308 pub enum ViewKind {
309 /// A single one-dimensional row of texels.
310 D1,
311 /// An array of rows of texels. Equivalent to `D2` except that texels
312 /// in different rows are not sampled, so filtering will be constrained
313 /// to a single row of texels at a time.
314 D1Array,
315 /// A traditional 2D image, with rows arranged contiguously.
316 D2,
317 /// An array of 2D images. Equivalent to `D3` except that texels in
318 /// a different depth level are not sampled.
319 D2Array,
320 /// A volume image, with each 2D layer arranged contiguously.
321 D3,
322 /// A set of 6 2D images, one for each face of a cube.
323 Cube,
324 /// An array of Cube images.
325 CubeArray,
326 }
327
328 bitflags!(
329 /// Capabilities to create views into an image.
330 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
331 #[derive(Default)]
332 pub struct ViewCapabilities: u32 {
333 /// Support creation of views with different formats.
334 const MUTABLE_FORMAT = 0x0000_0008;
335 /// Support creation of `Cube` and `CubeArray` kinds of views.
336 const KIND_CUBE = 0x0000_0010;
337 /// Support creation of `D2Array` kind of view.
338 const KIND_2D_ARRAY = 0x0000_0020;
339 }
340 );
341
342 bitflags!(
343 /// TODO: Find out if TRANSIENT_ATTACHMENT + INPUT_ATTACHMENT
344 /// are applicable on backends other than Vulkan. --AP
345 /// Image usage flags
346 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
347 pub struct Usage: u32 {
348 /// The image is used as a transfer source.
349 const TRANSFER_SRC = 0x1;
350 /// The image is used as a transfer destination.
351 const TRANSFER_DST = 0x2;
352 /// The image is a [sampled image](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#descriptorsets-sampledimage)
353 const SAMPLED = 0x4;
354 /// The image is a [storage image](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#descriptorsets-storageimage)
355 const STORAGE = 0x8;
356 /// The image is used as a color attachment -- that is, color input to a rendering pass.
357 const COLOR_ATTACHMENT = 0x10;
358 /// The image is used as a depth attachment.
359 const DEPTH_STENCIL_ATTACHMENT = 0x20;
360 ///
361 const TRANSIENT_ATTACHMENT = 0x40;
362 ///
363 const INPUT_ATTACHMENT = 0x80;
364
365 }
366 );
367
368 impl Usage {
369 /// Returns true if this image can be used in transfer operations.
can_transfer(&self) -> bool370 pub fn can_transfer(&self) -> bool {
371 self.intersects(Usage::TRANSFER_SRC | Usage::TRANSFER_DST)
372 }
373
374 /// Returns true if this image can be used as a target.
can_target(&self) -> bool375 pub fn can_target(&self) -> bool {
376 self.intersects(Usage::COLOR_ATTACHMENT | Usage::DEPTH_STENCIL_ATTACHMENT)
377 }
378 }
379
380 /// Specifies how image coordinates outside the range `[0, 1]` are handled.
381 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
382 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
383 pub enum WrapMode {
384 /// Tile the image, that is, sample the coordinate modulo `1.0`, so
385 /// addressing the image beyond an edge will "wrap" back from the
386 /// other edge.
387 Tile,
388 /// Mirror the image. Like tile, but uses abs(coord) before the modulo.
389 Mirror,
390 /// Clamp the image to the value at `0.0` or `1.0` respectively.
391 Clamp,
392 /// Use border color.
393 Border,
394 /// Mirror once and clamp to edge otherwise.
395 ///
396 /// Only valid if `Features::SAMPLER_MIRROR_CLAMP_EDGE` is enabled.
397 MirrorClamp,
398 }
399
400 /// Specifies how the image texels in the filter kernel are reduced to a single value.
401 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
402 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
403 pub enum ReductionMode {
404 ///
405 WeightedAverage,
406 ///
407 /// Only valid if `Features::SAMPLER_FILTER_MINMAX` is enabled.
408 Minimum,
409 ///
410 /// Only valid if `Features::SAMPLER_FILTER_MINMAX` is enabled.
411 Maximum,
412 }
413
414 /// A wrapper for the LOD level of an image. Needed so that we can
415 /// implement Eq and Hash for it.
416 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
417 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
418 pub struct Lod(pub f32);
419
420 impl Lod {
421 /// Possible LOD range.
422 pub const RANGE: Range<Self> = Lod(f32::MIN)..Lod(f32::MAX);
423 }
424
425 impl Eq for Lod {}
426 impl hash::Hash for Lod {
hash<H: hash::Hasher>(&self, state: &mut H)427 fn hash<H: hash::Hasher>(&self, state: &mut H) {
428 self.0.to_bits().hash(state)
429 }
430 }
431
432 /// A wrapper for an RGBA color with 8 bits per texel, encoded as a u32.
433 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
434 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
435 pub struct PackedColor(pub u32);
436
437 impl From<[f32; 4]> for PackedColor {
from(c: [f32; 4]) -> PackedColor438 fn from(c: [f32; 4]) -> PackedColor {
439 PackedColor(
440 c.iter()
441 .rev()
442 .fold(0, |u, &c| (u << 8) + (c * 255.0) as u32),
443 )
444 }
445 }
446
447 impl Into<[f32; 4]> for PackedColor {
into(self) -> [f32; 4]448 fn into(self) -> [f32; 4] {
449 let mut out = [0.0; 4];
450 for (i, channel) in out.iter_mut().enumerate() {
451 let byte = (self.0 >> (i << 3)) & 0xFF;
452 *channel = byte as f32 / 255.0;
453 }
454 out
455 }
456 }
457
458 /// The border color for `WrapMode::Border` wrap mode.
459 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
460 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
461 pub enum BorderColor {
462 ///
463 TransparentBlack,
464 ///
465 OpaqueBlack,
466 ///
467 OpaqueWhite,
468 }
469
470 impl Into<[f32; 4]> for BorderColor {
into(self) -> [f32; 4]471 fn into(self) -> [f32; 4] {
472 match self {
473 BorderColor::TransparentBlack => [0.0, 0.0, 0.0, 0.0],
474 BorderColor::OpaqueBlack => [0.0, 0.0, 0.0, 1.0],
475 BorderColor::OpaqueWhite => [1.0, 1.0, 1.0, 1.0],
476 }
477 }
478 }
479
480 /// Specifies how to sample from an image. These are all the parameters
481 /// available that alter how the GPU goes from a coordinate in an image
482 /// to producing an actual value from the texture, including filtering/
483 /// scaling, wrap mode, etc.
484 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
485 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
486 pub struct SamplerDesc {
487 /// Minification filter method to use.
488 pub min_filter: Filter,
489 /// Magnification filter method to use.
490 pub mag_filter: Filter,
491 /// Mip filter method to use.
492 pub mip_filter: Filter,
493 /// Reduction mode over the filter.
494 pub reduction_mode: ReductionMode,
495 /// Wrapping mode for each of the U, V, and W axis (S, T, and R in OpenGL
496 /// speak).
497 pub wrap_mode: (WrapMode, WrapMode, WrapMode),
498 /// This bias is added to every computed mipmap level (N + lod_bias). For
499 /// example, if it would select mipmap level 2 and lod_bias is 1, it will
500 /// use mipmap level 3.
501 pub lod_bias: Lod,
502 /// This range is used to clamp LOD level used for sampling.
503 pub lod_range: Range<Lod>,
504 /// Comparison mode, used primary for a shadow map.
505 pub comparison: Option<Comparison>,
506 /// Border color is used when one of the wrap modes is set to border.
507 pub border: BorderColor,
508 /// Specifies whether the texture coordinates are normalized.
509 pub normalized: bool,
510 /// Anisotropic filtering.
511 ///
512 /// Can be `Some(_)` only if `Features::SAMPLER_ANISOTROPY` is enabled.
513 pub anisotropy_clamp: Option<u8>,
514 }
515
516 impl SamplerDesc {
517 /// Create a new sampler description with a given filter method for all filtering operations
518 /// and a wrapping mode, using no LOD modifications.
new(filter: Filter, wrap: WrapMode) -> Self519 pub fn new(filter: Filter, wrap: WrapMode) -> Self {
520 SamplerDesc {
521 min_filter: filter,
522 mag_filter: filter,
523 mip_filter: filter,
524 reduction_mode: ReductionMode::WeightedAverage,
525 wrap_mode: (wrap, wrap, wrap),
526 lod_bias: Lod(0.0),
527 lod_range: Lod::RANGE.clone(),
528 comparison: None,
529 border: BorderColor::TransparentBlack,
530 normalized: true,
531 anisotropy_clamp: None,
532 }
533 }
534 }
535
536 /// Specifies options for how memory for an image is arranged.
537 /// These are hints to the GPU driver and may or may not have actual
538 /// performance effects, but describe constraints on how the data
539 /// may be used that a program *must* obey. They do not specify
540 /// how channel values or such are laid out in memory; the actual
541 /// image data is considered opaque.
542 ///
543 /// Details may be found in [the Vulkan spec](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#resources-image-layouts)
544 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
545 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
546 pub enum Layout {
547 /// General purpose, no restrictions on usage.
548 General,
549 /// Must only be used as a color attachment in a framebuffer.
550 ColorAttachmentOptimal,
551 /// Must only be used as a depth attachment in a framebuffer.
552 DepthStencilAttachmentOptimal,
553 /// Must only be used as a depth attachment in a framebuffer,
554 /// or as a read-only depth or stencil buffer in a shader.
555 DepthStencilReadOnlyOptimal,
556 /// Must only be used as a read-only image in a shader.
557 ShaderReadOnlyOptimal,
558 /// Must only be used as the source for a transfer command.
559 TransferSrcOptimal,
560 /// Must only be used as the destination for a transfer command.
561 TransferDstOptimal,
562 /// No layout, does not support device access. Only valid as a
563 /// source layout when transforming data to a specific destination
564 /// layout or initializing data. Does NOT guarentee that the contents
565 /// of the source buffer are preserved.
566 Undefined,
567 /// Like `Undefined`, but does guarentee that the contents of the source
568 /// buffer are preserved.
569 Preinitialized,
570 /// The layout that an image must be in to be presented to the display.
571 Present,
572 }
573
574 impl Default for Layout {
default() -> Self575 fn default() -> Self {
576 Self::General
577 }
578 }
579
580 bitflags!(
581 /// Bitflags to describe how memory in an image or buffer can be accessed.
582 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
583 pub struct Access: u32 {
584 /// Read access to an input attachment from within a fragment shader.
585 const INPUT_ATTACHMENT_READ = 0x10;
586 /// Read-only state for SRV access, or combine with `SHADER_WRITE` to have r/w access to UAV.
587 const SHADER_READ = 0x20;
588 /// Writeable state for UAV access.
589 /// Combine with `SHADER_READ` to have r/w access to UAV.
590 const SHADER_WRITE = 0x40;
591 /// Read state but can only be combined with `COLOR_ATTACHMENT_WRITE`.
592 const COLOR_ATTACHMENT_READ = 0x80;
593 /// Write-only state but can be combined with `COLOR_ATTACHMENT_READ`.
594 const COLOR_ATTACHMENT_WRITE = 0x100;
595 /// Read access to a depth/stencil attachment in a depth or stencil operation.
596 const DEPTH_STENCIL_ATTACHMENT_READ = 0x200;
597 /// Write access to a depth/stencil attachment in a depth or stencil operation.
598 const DEPTH_STENCIL_ATTACHMENT_WRITE = 0x400;
599 /// Read access to the buffer in a copy operation.
600 const TRANSFER_READ = 0x800;
601 /// Write access to the buffer in a copy operation.
602 const TRANSFER_WRITE = 0x1000;
603 /// Read access for raw memory to be accessed by the host system (ie, CPU).
604 const HOST_READ = 0x2000;
605 /// Write access for raw memory to be accessed by the host system.
606 const HOST_WRITE = 0x4000;
607 /// Read access for memory to be accessed by a non-specific entity. This may
608 /// be the host system, or it may be something undefined or specified by an
609 /// extension.
610 const MEMORY_READ = 0x8000;
611 /// Write access for memory to be accessed by a non-specific entity.
612 const MEMORY_WRITE = 0x10000;
613 }
614 );
615
616 /// Image state, combining access methods and the image's layout.
617 pub type State = (Access, Layout);
618
619 /// Selector of a concrete subresource in an image.
620 #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
621 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
622 pub struct Subresource {
623 /// Included aspects: color/depth/stencil
624 pub aspects: format::Aspects,
625 /// Selected mipmap level
626 pub level: Level,
627 /// Selected array level
628 pub layer: Layer,
629 }
630
631 /// A subset of resource layers contained within an image's level.
632 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
633 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
634 pub struct SubresourceLayers {
635 /// Included aspects: color/depth/stencil
636 pub aspects: format::Aspects,
637 /// Selected mipmap level
638 pub level: Level,
639 /// Included array levels
640 pub layers: Range<Layer>,
641 }
642
643 /// A subset of resources contained within an image.
644 #[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
645 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
646 pub struct SubresourceRange {
647 /// Included aspects: color/depth/stencil
648 pub aspects: format::Aspects,
649 /// First mipmap level in this subresource
650 pub level_start: Level,
651 /// Number of sequential levels in this subresource.
652 ///
653 /// A value of `None` indicates the subresource contains
654 /// all of the remaining levels.
655 pub level_count: Option<Level>,
656 /// First layer in this subresource
657 pub layer_start: Layer,
658 /// Number of sequential layers in this subresource.
659 ///
660 /// A value of `None` indicates the subresource contains
661 /// all of the remaining layers.
662 pub layer_count: Option<Layer>,
663 }
664
665 impl From<SubresourceLayers> for SubresourceRange {
from(sub: SubresourceLayers) -> Self666 fn from(sub: SubresourceLayers) -> Self {
667 SubresourceRange {
668 aspects: sub.aspects,
669 level_start: sub.level,
670 level_count: Some(1),
671 layer_start: sub.layers.start,
672 layer_count: Some(sub.layers.end - sub.layers.start),
673 }
674 }
675 }
676
677 impl SubresourceRange {
678 /// Resolve the concrete level count based on the total number of layers in an image.
resolve_level_count(&self, total: Level) -> Level679 pub fn resolve_level_count(&self, total: Level) -> Level {
680 self.level_count.unwrap_or(total - self.level_start)
681 }
682
683 /// Resolve the concrete layer count based on the total number of layer in an image.
resolve_layer_count(&self, total: Layer) -> Layer684 pub fn resolve_layer_count(&self, total: Layer) -> Layer {
685 self.layer_count.unwrap_or(total - self.layer_start)
686 }
687 }
688
689 /// Image format properties.
690 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
691 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
692 pub struct FormatProperties {
693 /// Maximum extent.
694 pub max_extent: Extent,
695 /// Max number of mipmap levels.
696 pub max_levels: Level,
697 /// Max number of array layers.
698 pub max_layers: Layer,
699 /// Bit mask of supported sample counts.
700 pub sample_count_mask: NumSamples,
701 /// Maximum size of the resource in bytes.
702 pub max_resource_size: usize,
703 }
704
705 /// Footprint of a subresource in memory.
706 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
707 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
708 pub struct SubresourceFootprint {
709 /// Byte slice occupied by the subresource.
710 pub slice: Range<RawOffset>,
711 /// Byte distance between rows.
712 pub row_pitch: RawOffset,
713 /// Byte distance between array layers.
714 pub array_pitch: RawOffset,
715 /// Byte distance between depth slices.
716 pub depth_pitch: RawOffset,
717 }
718
719 /// The type of tile to check for with `get_tile_size`.
720 #[derive(Debug)]
721 pub enum TileKind {
722 /// A volume or 3D image tile kind.
723 Volume,
724 /// A flat or 2D image tile kind, with the number of samples for MSAA.
725 Flat(NumSamples),
726 }
727
728 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#sparsememory-standard-shapes
729 // https://docs.microsoft.com/en-us/windows/win32/direct3d11/texture2d-and-texture2darray-subresource-tiling
730 /// Tile or block size for sparse binding
get_tile_size(tile_kind: TileKind, texel_bits: u16) -> (u16, u16, u16)731 pub fn get_tile_size(tile_kind: TileKind, texel_bits: u16) -> (u16, u16, u16) {
732 match tile_kind {
733 TileKind::Flat(samples) => {
734 let sizes = match texel_bits {
735 8 => (256, 256, 1),
736 16 => (256, 128, 1),
737 32 => (128, 128, 1),
738 64 => (128, 64, 1),
739 128 => (64, 64, 1),
740 _ => unimplemented!(),
741 };
742 match samples {
743 1 => sizes,
744 2 => (sizes.0 / 2, sizes.1, 1),
745 4 => (sizes.0 / 2, sizes.1 / 2, 1),
746 8 => (sizes.0 / 4, sizes.1 / 2, 1),
747 16 => (sizes.0 / 4, sizes.1 / 4, 1),
748 _ => unimplemented!(),
749 }
750 }
751 TileKind::Volume => match texel_bits {
752 8 => (64, 32, 32),
753 16 => (32, 32, 32),
754 32 => (32, 32, 16),
755 64 => (32, 16, 16),
756 128 => (16, 16, 16),
757 _ => unimplemented!(),
758 },
759 }
760 }
761
762 /// Description of a framebuffer attachment.
763 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
764 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
765 pub struct FramebufferAttachment {
766 /// Usage that an image is created with.
767 pub usage: Usage,
768 /// View capabilities that an image is created with.
769 pub view_caps: ViewCapabilities,
770 //TODO: make this a list
771 /// The image view format.
772 pub format: format::Format,
773 }
774