bevy_render/texture/
gpu_image.rs1use crate::{
2 render_asset::{PrepareAssetError, RenderAsset, RenderAssetUsages},
3 render_resource::{DefaultImageSampler, Sampler, Texture, TextureView},
4 renderer::{RenderDevice, RenderQueue},
5};
6use bevy_asset::AssetId;
7use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem};
8use bevy_image::{Image, ImageSampler};
9use bevy_math::{AspectRatio, UVec2};
10use wgpu::{Extent3d, TextureFormat, TextureViewDescriptor};
11
12#[derive(Debug, Clone)]
15pub struct GpuImage {
16 pub texture: Texture,
17 pub texture_view: TextureView,
18 pub texture_format: TextureFormat,
19 pub sampler: Sampler,
20 pub size: Extent3d,
21 pub mip_level_count: u32,
22}
23
24impl RenderAsset for GpuImage {
25 type SourceAsset = Image;
26 type Param = (
27 SRes<RenderDevice>,
28 SRes<RenderQueue>,
29 SRes<DefaultImageSampler>,
30 );
31
32 #[inline]
33 fn asset_usage(image: &Self::SourceAsset) -> RenderAssetUsages {
34 image.asset_usage
35 }
36
37 #[inline]
38 fn byte_len(image: &Self::SourceAsset) -> Option<usize> {
39 image.data.as_ref().map(Vec::len)
40 }
41
42 fn prepare_asset(
44 image: Self::SourceAsset,
45 _: AssetId<Self::SourceAsset>,
46 (render_device, render_queue, default_sampler): &mut SystemParamItem<Self::Param>,
47 ) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
48 let texture = if let Some(ref data) = image.data {
49 render_device.create_texture_with_data(
50 render_queue,
51 &image.texture_descriptor,
52 wgpu::util::TextureDataOrder::default(),
54 data,
55 )
56 } else {
57 render_device.create_texture(&image.texture_descriptor)
58 };
59
60 let texture_view = texture.create_view(
61 image
62 .texture_view_descriptor
63 .or_else(|| Some(TextureViewDescriptor::default()))
64 .as_ref()
65 .unwrap(),
66 );
67 let sampler = match image.sampler {
68 ImageSampler::Default => (***default_sampler).clone(),
69 ImageSampler::Descriptor(descriptor) => {
70 render_device.create_sampler(&descriptor.as_wgpu())
71 }
72 };
73
74 Ok(GpuImage {
75 texture,
76 texture_view,
77 texture_format: image.texture_descriptor.format,
78 sampler,
79 size: image.texture_descriptor.size,
80 mip_level_count: image.texture_descriptor.mip_level_count,
81 })
82 }
83}
84
85impl GpuImage {
86 #[inline]
88 pub fn aspect_ratio(&self) -> AspectRatio {
89 AspectRatio::try_from_pixels(self.size.width, self.size.height).expect(
90 "Failed to calculate aspect ratio: Image dimensions must be positive, non-zero values",
91 )
92 }
93
94 #[inline]
96 pub fn size_2d(&self) -> UVec2 {
97 UVec2::new(self.size.width, self.size.height)
98 }
99}