1use crate::{Image, ImageSampler};
2use bevy_asset::RenderAssetUsages;
3use core::fmt::Debug;
4use serde::{Deserialize, Serialize};
5use wgpu_types::{
6 TextureAspect, TextureDataOrder, TextureDescriptor, TextureFormat, TextureUsages,
7 TextureViewDescriptor, TextureViewDimension,
8};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
27pub 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)]
36struct 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
47impl 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 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)]
80enum SerializedTextureDataOrder {
81 LayerMajor,
82 MipMajor,
83}
84
85impl 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
101impl SerializedImage {
102 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 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 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 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)]
152mod 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}