bevy_render/texture/
gpu_image.rs

1use crate::{
2    render_asset::{PrepareAssetError, RenderAsset, RenderAssetUsages},
3    render_resource::{DefaultImageSampler, Sampler, Texture, TextureView},
4    renderer::{RenderDevice, RenderQueue},
5};
6use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem};
7use bevy_image::{Image, ImageSampler};
8use bevy_math::UVec2;
9use wgpu::{TextureFormat, TextureViewDescriptor};
10
11/// The GPU-representation of an [`Image`].
12/// Consists of the [`Texture`], its [`TextureView`] and the corresponding [`Sampler`], and the texture's size.
13#[derive(Debug, Clone)]
14pub struct GpuImage {
15    pub texture: Texture,
16    pub texture_view: TextureView,
17    pub texture_format: TextureFormat,
18    pub sampler: Sampler,
19    pub size: UVec2,
20    pub mip_level_count: u32,
21}
22
23impl RenderAsset for GpuImage {
24    type SourceAsset = Image;
25    type Param = (
26        SRes<RenderDevice>,
27        SRes<RenderQueue>,
28        SRes<DefaultImageSampler>,
29    );
30
31    #[inline]
32    fn asset_usage(image: &Self::SourceAsset) -> RenderAssetUsages {
33        image.asset_usage
34    }
35
36    #[inline]
37    fn byte_len(image: &Self::SourceAsset) -> Option<usize> {
38        Some(image.data.len())
39    }
40
41    /// Converts the extracted image into a [`GpuImage`].
42    fn prepare_asset(
43        image: Self::SourceAsset,
44        (render_device, render_queue, default_sampler): &mut SystemParamItem<Self::Param>,
45    ) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
46        let texture = render_device.create_texture_with_data(
47            render_queue,
48            &image.texture_descriptor,
49            // TODO: Is this correct? Do we need to use `MipMajor` if it's a ktx2 file?
50            wgpu::util::TextureDataOrder::default(),
51            &image.data,
52        );
53
54        let size = image.size();
55        let texture_view = texture.create_view(
56            image
57                .texture_view_descriptor
58                .or_else(|| Some(TextureViewDescriptor::default()))
59                .as_ref()
60                .unwrap(),
61        );
62        let sampler = match image.sampler {
63            ImageSampler::Default => (***default_sampler).clone(),
64            ImageSampler::Descriptor(descriptor) => {
65                render_device.create_sampler(&descriptor.as_wgpu())
66            }
67        };
68
69        Ok(GpuImage {
70            texture,
71            texture_view,
72            texture_format: image.texture_descriptor.format,
73            sampler,
74            size,
75            mip_level_count: image.texture_descriptor.mip_level_count,
76        })
77    }
78}