Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_image/src/serialized_image.rs
6595 views
1
use crate::{Image, ImageSampler};
2
use bevy_asset::RenderAssetUsages;
3
use core::fmt::Debug;
4
use serde::{Deserialize, Serialize};
5
use wgpu_types::{
6
TextureAspect, TextureDataOrder, TextureDescriptor, TextureFormat, TextureUsages,
7
TextureViewDescriptor, TextureViewDimension,
8
};
9
10
/// A version of [`Image`] suitable for serializing for short-term transfer.
11
///
12
/// [`Image`] does not implement [`Serialize`] / [`Deserialize`] because it is made with the renderer in mind.
13
/// It is not a general-purpose image implementation, and its internals are subject to frequent change.
14
/// As such, storing an [`Image`] on disk is highly discouraged.
15
/// Use an existing image asset format such as `.png` instead!
16
///
17
/// But there are still some valid use cases for serializing an [`Image`], namely transferring images between processes.
18
/// To support this, you can create a [`SerializedImage`] from an [`Image`] with [`SerializedImage::from_image`],
19
/// and then deserialize it with [`SerializedImage::into_image`].
20
///
21
/// The caveats are:
22
/// - The image representation is not valid across different versions of Bevy.
23
/// - This conversion is lossy. The following information is not preserved:
24
/// - texture descriptor and texture view descriptor labels
25
/// - texture descriptor view formats
26
#[derive(Debug, Clone, Serialize, Deserialize)]
27
pub struct SerializedImage {
28
data: Option<Vec<u8>>,
29
data_order: SerializedTextureDataOrder,
30
texture_descriptor: TextureDescriptor<(), ()>,
31
sampler: ImageSampler,
32
texture_view_descriptor: Option<SerializedTextureViewDescriptor>,
33
}
34
35
#[derive(Debug, Clone, Serialize, Deserialize)]
36
struct SerializedTextureViewDescriptor {
37
format: Option<TextureFormat>,
38
dimension: Option<TextureViewDimension>,
39
usage: Option<TextureUsages>,
40
aspect: TextureAspect,
41
base_mip_level: u32,
42
mip_level_count: Option<u32>,
43
base_array_layer: u32,
44
array_layer_count: Option<u32>,
45
}
46
47
impl SerializedTextureViewDescriptor {
48
fn from_texture_view_descriptor(
49
descriptor: TextureViewDescriptor<Option<&'static str>>,
50
) -> Self {
51
Self {
52
format: descriptor.format,
53
dimension: descriptor.dimension,
54
usage: descriptor.usage,
55
aspect: descriptor.aspect,
56
base_mip_level: descriptor.base_mip_level,
57
mip_level_count: descriptor.mip_level_count,
58
base_array_layer: descriptor.base_array_layer,
59
array_layer_count: descriptor.array_layer_count,
60
}
61
}
62
63
fn into_texture_view_descriptor(self) -> TextureViewDescriptor<Option<&'static str>> {
64
TextureViewDescriptor {
65
// Not used for asset-based images other than debugging
66
label: None,
67
format: self.format,
68
dimension: self.dimension,
69
usage: self.usage,
70
aspect: self.aspect,
71
base_mip_level: self.base_mip_level,
72
mip_level_count: self.mip_level_count,
73
base_array_layer: self.base_array_layer,
74
array_layer_count: self.array_layer_count,
75
}
76
}
77
}
78
79
#[derive(Debug, Clone, Serialize, Deserialize)]
80
enum SerializedTextureDataOrder {
81
LayerMajor,
82
MipMajor,
83
}
84
85
impl SerializedTextureDataOrder {
86
fn from_texture_data_order(order: TextureDataOrder) -> Self {
87
match order {
88
TextureDataOrder::LayerMajor => SerializedTextureDataOrder::LayerMajor,
89
TextureDataOrder::MipMajor => SerializedTextureDataOrder::MipMajor,
90
}
91
}
92
93
fn into_texture_data_order(self) -> TextureDataOrder {
94
match self {
95
SerializedTextureDataOrder::LayerMajor => TextureDataOrder::LayerMajor,
96
SerializedTextureDataOrder::MipMajor => TextureDataOrder::MipMajor,
97
}
98
}
99
}
100
101
impl SerializedImage {
102
/// Creates a new [`SerializedImage`] from an [`Image`].
103
pub fn from_image(image: Image) -> Self {
104
Self {
105
data: image.data,
106
data_order: SerializedTextureDataOrder::from_texture_data_order(image.data_order),
107
texture_descriptor: TextureDescriptor {
108
label: (),
109
size: image.texture_descriptor.size,
110
mip_level_count: image.texture_descriptor.mip_level_count,
111
sample_count: image.texture_descriptor.sample_count,
112
dimension: image.texture_descriptor.dimension,
113
format: image.texture_descriptor.format,
114
usage: image.texture_descriptor.usage,
115
view_formats: (),
116
},
117
sampler: image.sampler,
118
texture_view_descriptor: image.texture_view_descriptor.map(|descriptor| {
119
SerializedTextureViewDescriptor::from_texture_view_descriptor(descriptor)
120
}),
121
}
122
}
123
124
/// Create an [`Image`] from a [`SerializedImage`].
125
pub fn into_image(self) -> Image {
126
Image {
127
data: self.data,
128
data_order: self.data_order.into_texture_data_order(),
129
texture_descriptor: TextureDescriptor {
130
// Not used for asset-based images other than debugging
131
label: None,
132
size: self.texture_descriptor.size,
133
mip_level_count: self.texture_descriptor.mip_level_count,
134
sample_count: self.texture_descriptor.sample_count,
135
dimension: self.texture_descriptor.dimension,
136
format: self.texture_descriptor.format,
137
usage: self.texture_descriptor.usage,
138
// Not used for asset-based images
139
view_formats: &[],
140
},
141
sampler: self.sampler,
142
texture_view_descriptor: self
143
.texture_view_descriptor
144
.map(SerializedTextureViewDescriptor::into_texture_view_descriptor),
145
asset_usage: RenderAssetUsages::RENDER_WORLD,
146
copy_on_resize: false,
147
}
148
}
149
}
150
151
#[cfg(test)]
152
mod tests {
153
use wgpu_types::{Extent3d, TextureDimension};
154
155
use super::*;
156
157
#[test]
158
fn serialize_deserialize_image() {
159
let image = Image::new(
160
Extent3d {
161
width: 3,
162
height: 1,
163
depth_or_array_layers: 1,
164
},
165
TextureDimension::D2,
166
vec![255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255],
167
TextureFormat::Rgba8UnormSrgb,
168
RenderAssetUsages::RENDER_WORLD,
169
);
170
171
let serialized_image = SerializedImage::from_image(image.clone());
172
let serialized_string = serde_json::to_string(&serialized_image).unwrap();
173
let serialized_image_from_string: SerializedImage =
174
serde_json::from_str(&serialized_string).unwrap();
175
let deserialized_image = serialized_image_from_string.into_image();
176
assert_eq!(image, deserialized_image);
177
}
178
}
179
180