rafx_framework/upload/
gpu_image_data.rs

1use rafx_api::RafxFormat;
2
3#[derive(Copy, Clone, Debug, PartialEq)]
4pub enum GpuImageDataColorSpace {
5    Srgb,
6    Linear,
7}
8
9impl GpuImageDataColorSpace {
10    pub fn rgba8(self) -> RafxFormat {
11        match self {
12            GpuImageDataColorSpace::Srgb => RafxFormat::R8G8B8A8_SRGB,
13            GpuImageDataColorSpace::Linear => RafxFormat::R8G8B8A8_UNORM,
14        }
15    }
16
17    pub fn astc4x4(self) -> RafxFormat {
18        match self {
19            GpuImageDataColorSpace::Srgb => RafxFormat::ASTC_4X4_SRGB_BLOCK,
20            GpuImageDataColorSpace::Linear => RafxFormat::ASTC_4X4_UNORM_BLOCK,
21        }
22    }
23
24    pub fn bc7(self) -> RafxFormat {
25        match self {
26            GpuImageDataColorSpace::Srgb => RafxFormat::BC7_SRGB_BLOCK,
27            GpuImageDataColorSpace::Linear => RafxFormat::BC7_UNORM_BLOCK,
28        }
29    }
30}
31
32#[derive(Debug)]
33pub struct GpuImageData {
34    pub width: u32,
35    pub height: u32,
36    pub format: RafxFormat,
37    pub layers: Vec<GpuImageDataLayer>,
38}
39
40impl GpuImageData {
41    pub fn new(
42        layers: Vec<GpuImageDataLayer>,
43        format: RafxFormat,
44    ) -> Self {
45        #[cfg(debug_assertions)]
46        {
47            for i in 1..layers.len() {
48                debug_assert_eq!(layers[0].mip_levels.len(), layers[i].mip_levels.len());
49                for j in 1..layers[0].mip_levels.len() {
50                    debug_assert_eq!(layers[0].mip_levels[j].width, layers[i].mip_levels[j].width);
51                    debug_assert_eq!(
52                        layers[0].mip_levels[j].height,
53                        layers[i].mip_levels[j].height
54                    );
55                    debug_assert_eq!(layers[0].mip_levels[j].width, layers[i].mip_levels[j].width);
56                }
57            }
58        }
59
60        GpuImageData {
61            width: layers[0].mip_levels[0].width,
62            height: layers[0].mip_levels[0].height,
63            format,
64            layers,
65        }
66    }
67
68    pub fn new_simple_image_from_bytes(
69        width: u32,
70        height: u32,
71        format: RafxFormat,
72        data: Vec<u8>,
73    ) -> Self {
74        GpuImageData {
75            width,
76            height,
77            format,
78            layers: vec![GpuImageDataLayer::new_single_level(width, height, data)],
79        }
80    }
81
82    pub fn total_size(
83        &self,
84        required_image_alignment: u32,
85        required_row_alignment: u32,
86    ) -> u64 {
87        let mut bytes_required = 0;
88        for layer in &self.layers {
89            for level in &layer.mip_levels {
90                // We may need to align to place the first row
91                bytes_required += required_image_alignment as u64;
92
93                // Determine size required for rows, factoring in required pitch per row. Don't
94                // count the first image
95                let row_size = level.data.len() as u64 / level.height as u64;
96                bytes_required += rafx_base::memory::round_size_up_to_alignment_u64(
97                    row_size,
98                    required_row_alignment as u64,
99                ) * (level.height as u64 - 1);
100            }
101        }
102
103        bytes_required
104    }
105
106    #[cfg(debug_assertions)]
107    pub fn verify_state(&self) {
108        let first_layer = &self.layers[0];
109        let first_level = &first_layer.mip_levels[0];
110        assert_eq!(first_level.width, self.width);
111        assert_eq!(first_level.height, self.height);
112
113        for layer in &self.layers {
114            assert_eq!(first_layer.mip_levels.len(), layer.mip_levels.len());
115            for (i, level) in layer.mip_levels.iter().enumerate() {
116                assert_eq!(first_layer.mip_levels[i].width, level.width);
117                assert_eq!(first_layer.mip_levels[i].height, level.height);
118            }
119        }
120    }
121}
122
123#[derive(Debug)]
124pub struct GpuImageDataLayer {
125    pub mip_levels: Vec<GpuImageDataMipLevel>,
126}
127
128impl GpuImageDataLayer {
129    pub fn new(mip_levels: Vec<GpuImageDataMipLevel>) -> Self {
130        GpuImageDataLayer { mip_levels }
131    }
132
133    pub fn new_single_level(
134        width: u32,
135        height: u32,
136        data: Vec<u8>,
137    ) -> Self {
138        GpuImageDataLayer {
139            mip_levels: vec![GpuImageDataMipLevel {
140                width,
141                height,
142                data,
143            }],
144        }
145    }
146}
147
148pub struct GpuImageDataMipLevel {
149    pub width: u32,
150    pub height: u32,
151    pub data: Vec<u8>,
152}
153
154impl std::fmt::Debug for GpuImageDataMipLevel {
155    fn fmt(
156        &self,
157        f: &mut std::fmt::Formatter,
158    ) -> std::fmt::Result {
159        f.debug_struct("GpuImageDataMipLevel")
160            .field("width", &self.width)
161            .field("height", &self.height)
162            .field("data_length", &self.data.len())
163            .finish()
164    }
165}
166
167impl GpuImageData {
168    pub fn new_1x1_rgba8(
169        r: u8,
170        g: u8,
171        b: u8,
172        a: u8,
173        color_space: GpuImageDataColorSpace,
174    ) -> Self {
175        GpuImageData::new_simple_image_from_bytes(1, 1, color_space.rgba8(), vec![r, g, b, a])
176    }
177
178    pub fn new_1x1_d32(d: f32) -> Self {
179        let bytes = d.to_bits().to_ne_bytes().to_vec();
180        GpuImageData::new_simple_image_from_bytes(1, 1, RafxFormat::D32_SFLOAT, bytes)
181    }
182}