RenderAssetPersistencePolicy → RenderAssetUsages (#11399)

# Objective

Right now, all assets in the main world get extracted and prepared in
the render world (if the asset's using the RenderAssetPlugin). This is
unfortunate for two cases:

1. **TextureAtlas** / **FontAtlas**: This one's huge. The individual
`Image` assets that make up the atlas are cloned and prepared
individually when there's no reason for them to be. The atlas textures
are built on the CPU in the main world. *There can be hundreds of images
that get prepared for rendering only not to be used.*
2. If one loads an Image and needs to transform it in a system before
rendering it, kind of like the [decompression
example](https://github.com/bevyengine/bevy/blob/main/examples/asset/asset_decompression.rs#L120),
there's a price paid for extracting & preparing the asset that's not
intended to be rendered yet.

------

* References #10520
* References #1782

## Solution

This changes the `RenderAssetPersistencePolicy` enum to bitflags. I felt
that the objective with the parameter is so similar in nature to wgpu's
[`TextureUsages`](https://docs.rs/wgpu/latest/wgpu/struct.TextureUsages.html)
and
[`BufferUsages`](https://docs.rs/wgpu/latest/wgpu/struct.BufferUsages.html),
that it may as well be just like that.

```rust
// This asset only needs to be in the main world. Don't extract and prepare it.
RenderAssetUsages::MAIN_WORLD

// Keep this asset in the main world and  
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD

// This asset is only needed in the render world. Remove it from the asset server once extracted.
RenderAssetUsages::RENDER_WORLD
```

### Alternate Solution

I considered introducing a third field to `RenderAssetPersistencePolicy`
enum:
```rust
enum RenderAssetPersistencePolicy {
    /// Keep the asset in the main world after extracting to the render world.
    Keep,
    /// Remove the asset from the main world after extracting to the render world.
    Unload,
    /// This doesn't need to be in the render world at all.
    NoExtract, // <-----
}
```
Functional, but this seemed like shoehorning. Another option is renaming
the enum to something like:
```rust
enum RenderAssetExtractionPolicy {
    /// Extract the asset and keep it in the main world.
    Extract,
    /// Remove the asset from the main world after extracting to the render world.
    ExtractAndUnload,
    /// This doesn't need to be in the render world at all.
    NoExtract,
}
```
I think this last one could be a good option if the bitflags are too
clunky.

## Migration Guide

* `RenderAssetPersistencePolicy::Keep` → `RenderAssetUsage::MAIN_WORLD |
RenderAssetUsage::RENDER_WORLD` (or `RenderAssetUsage::default()`)
* `RenderAssetPersistencePolicy::Unload` →
`RenderAssetUsage::RENDER_WORLD`
* For types implementing the `RenderAsset` trait, change `fn
persistence_policy(&self) -> RenderAssetPersistencePolicy` to `fn
asset_usage(&self) -> RenderAssetUsages`.
* Change any references to `cpu_persistent_access`
(`RenderAssetPersistencePolicy`) to `asset_usage` (`RenderAssetUsage`).
This applies to `Image`, `Mesh`, and a few other types.
This commit is contained in:
Brian Reavis 2024-01-30 05:22:10 -08:00 committed by GitHub
parent d7c65e40ee
commit 6b40b6749e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 247 additions and 143 deletions

View file

@ -6,7 +6,7 @@ use bevy_reflect::Reflect;
use bevy_render::camera::Camera; use bevy_render::camera::Camera;
use bevy_render::extract_component::{ExtractComponent, ExtractComponentPlugin}; use bevy_render::extract_component::{ExtractComponent, ExtractComponentPlugin};
use bevy_render::extract_resource::{ExtractResource, ExtractResourcePlugin}; use bevy_render::extract_resource::{ExtractResource, ExtractResourcePlugin};
use bevy_render::render_asset::{RenderAssetPersistencePolicy, RenderAssets}; use bevy_render::render_asset::{RenderAssetUsages, RenderAssets};
use bevy_render::render_resource::binding_types::{ use bevy_render::render_resource::binding_types::{
sampler, texture_2d, texture_3d, uniform_buffer, sampler, texture_2d, texture_3d, uniform_buffer,
}; };
@ -360,7 +360,7 @@ fn setup_tonemapping_lut_image(bytes: &[u8], image_type: ImageType) -> Image {
CompressedImageFormats::NONE, CompressedImageFormats::NONE,
false, false,
image_sampler, image_sampler,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
) )
.unwrap() .unwrap()
} }
@ -386,6 +386,6 @@ pub fn lut_placeholder() -> Image {
}, },
sampler: ImageSampler::Default, sampler: ImageSampler::Default,
texture_view_descriptor: None, texture_view_descriptor: None,
cpu_persistent_access: RenderAssetPersistencePolicy::Unload, asset_usage: RenderAssetUsages::RENDER_WORLD,
} }
} }

View file

@ -66,8 +66,7 @@ use bevy_reflect::TypePath;
use bevy_render::{ use bevy_render::{
extract_component::{ComponentUniforms, DynamicUniformIndex, UniformComponentPlugin}, extract_component::{ComponentUniforms, DynamicUniformIndex, UniformComponentPlugin},
render_asset::{ render_asset::{
PrepareAssetError, RenderAsset, RenderAssetPersistencePolicy, RenderAssetPlugin, PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssetUsages, RenderAssets,
RenderAssets,
}, },
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass}, render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
render_resource::{ render_resource::{
@ -316,8 +315,8 @@ impl RenderAsset for LineGizmo {
type PreparedAsset = GpuLineGizmo; type PreparedAsset = GpuLineGizmo;
type Param = SRes<RenderDevice>; type Param = SRes<RenderDevice>;
fn persistence_policy(&self) -> RenderAssetPersistencePolicy { fn asset_usage(&self) -> RenderAssetUsages {
RenderAssetPersistencePolicy::Keep RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD
} }
fn prepare_asset( fn prepare_asset(

View file

@ -22,7 +22,7 @@ use bevy_render::{
}, },
prelude::SpatialBundle, prelude::SpatialBundle,
primitives::Aabb, primitives::Aabb,
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Face, PrimitiveTopology}, render_resource::{Face, PrimitiveTopology},
texture::{ texture::{
CompressedImageFormats, Image, ImageAddressMode, ImageFilterMode, ImageLoaderSettings, CompressedImageFormats, Image, ImageAddressMode, ImageFilterMode, ImageLoaderSettings,
@ -393,7 +393,7 @@ async fn load_gltf<'a, 'b, 'c>(
let primitive_label = primitive_label(&gltf_mesh, &primitive); let primitive_label = primitive_label(&gltf_mesh, &primitive);
let primitive_topology = get_primitive_topology(primitive.mode())?; let primitive_topology = get_primitive_topology(primitive.mode())?;
let mut mesh = Mesh::new(primitive_topology, RenderAssetPersistencePolicy::Keep); let mut mesh = Mesh::new(primitive_topology, RenderAssetUsages::default());
// Read vertex attributes // Read vertex attributes
for (semantic, accessor) in primitive.attributes() { for (semantic, accessor) in primitive.attributes() {
@ -437,7 +437,7 @@ async fn load_gltf<'a, 'b, 'c>(
let morph_target_image = MorphTargetImage::new( let morph_target_image = MorphTargetImage::new(
morph_target_reader.map(PrimitiveMorphAttributesIter), morph_target_reader.map(PrimitiveMorphAttributesIter),
mesh.count_vertices(), mesh.count_vertices(),
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
)?; )?;
let handle = let handle =
load_context.add_labeled_asset(morph_targets_label, morph_target_image.0); load_context.add_labeled_asset(morph_targets_label, morph_target_image.0);
@ -744,7 +744,7 @@ async fn load_image<'a, 'b>(
supported_compressed_formats, supported_compressed_formats,
is_srgb, is_srgb,
ImageSampler::Descriptor(sampler_descriptor), ImageSampler::Descriptor(sampler_descriptor),
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
)?; )?;
Ok(ImageOrPath::Image { Ok(ImageOrPath::Image {
image, image,
@ -766,7 +766,7 @@ async fn load_image<'a, 'b>(
supported_compressed_formats, supported_compressed_formats,
is_srgb, is_srgb,
ImageSampler::Descriptor(sampler_descriptor), ImageSampler::Descriptor(sampler_descriptor),
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
)?, )?,
label: texture_label(&gltf_texture), label: texture_label(&gltf_texture),
}) })

View file

@ -6,7 +6,7 @@ pub use wgpu::PrimitiveTopology;
use crate::{ use crate::{
prelude::Image, prelude::Image,
primitives::Aabb, primitives::Aabb,
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPersistencePolicy, RenderAssets}, render_asset::{PrepareAssetError, RenderAsset, RenderAssetUsages, RenderAssets},
render_resource::{Buffer, TextureView, VertexBufferLayout}, render_resource::{Buffer, TextureView, VertexBufferLayout},
renderer::RenderDevice, renderer::RenderDevice,
}; };
@ -49,10 +49,10 @@ pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
/// ``` /// ```
/// # use bevy_render::mesh::{Mesh, Indices}; /// # use bevy_render::mesh::{Mesh, Indices};
/// # use bevy_render::render_resource::PrimitiveTopology; /// # use bevy_render::render_resource::PrimitiveTopology;
/// # use bevy_render::render_asset::RenderAssetPersistencePolicy; /// # use bevy_render::render_asset::RenderAssetUsages;
/// fn create_simple_parallelogram() -> Mesh { /// fn create_simple_parallelogram() -> Mesh {
/// // Create a new mesh using a triangle list topology, where each set of 3 vertices composes a triangle. /// // Create a new mesh using a triangle list topology, where each set of 3 vertices composes a triangle.
/// Mesh::new(PrimitiveTopology::TriangleList, RenderAssetPersistencePolicy::Unload) /// Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default())
/// // Add 4 vertices, each with its own position attribute (coordinate in /// // Add 4 vertices, each with its own position attribute (coordinate in
/// // 3D space), for each of the corners of the parallelogram. /// // 3D space), for each of the corners of the parallelogram.
/// .with_inserted_attribute( /// .with_inserted_attribute(
@ -123,7 +123,7 @@ pub struct Mesh {
indices: Option<Indices>, indices: Option<Indices>,
morph_targets: Option<Handle<Image>>, morph_targets: Option<Handle<Image>>,
morph_target_names: Option<Vec<String>>, morph_target_names: Option<Vec<String>>,
pub cpu_persistent_access: RenderAssetPersistencePolicy, pub asset_usage: RenderAssetUsages,
} }
impl Mesh { impl Mesh {
@ -184,17 +184,14 @@ impl Mesh {
/// Construct a new mesh. You need to provide a [`PrimitiveTopology`] so that the /// Construct a new mesh. You need to provide a [`PrimitiveTopology`] so that the
/// renderer knows how to treat the vertex data. Most of the time this will be /// renderer knows how to treat the vertex data. Most of the time this will be
/// [`PrimitiveTopology::TriangleList`]. /// [`PrimitiveTopology::TriangleList`].
pub fn new( pub fn new(primitive_topology: PrimitiveTopology, asset_usage: RenderAssetUsages) -> Self {
primitive_topology: PrimitiveTopology,
cpu_persistent_access: RenderAssetPersistencePolicy,
) -> Self {
Mesh { Mesh {
primitive_topology, primitive_topology,
attributes: Default::default(), attributes: Default::default(),
indices: None, indices: None,
morph_targets: None, morph_targets: None,
morph_target_names: None, morph_target_names: None,
cpu_persistent_access, asset_usage,
} }
} }
@ -1148,8 +1145,8 @@ impl RenderAsset for Mesh {
type PreparedAsset = GpuMesh; type PreparedAsset = GpuMesh;
type Param = (SRes<RenderDevice>, SRes<RenderAssets<Image>>); type Param = (SRes<RenderDevice>, SRes<RenderAssets<Image>>);
fn persistence_policy(&self) -> RenderAssetPersistencePolicy { fn asset_usage(&self) -> RenderAssetUsages {
self.cpu_persistent_access self.asset_usage
} }
/// Converts the extracted mesh a into [`GpuMesh`]. /// Converts the extracted mesh a into [`GpuMesh`].
@ -1317,7 +1314,7 @@ fn generate_tangents_for_mesh(mesh: &Mesh) -> Result<Vec<[f32; 4]>, GenerateTang
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Mesh; use super::Mesh;
use crate::render_asset::RenderAssetPersistencePolicy; use crate::render_asset::RenderAssetUsages;
use wgpu::PrimitiveTopology; use wgpu::PrimitiveTopology;
#[test] #[test]
@ -1325,7 +1322,7 @@ mod tests {
fn panic_invalid_format() { fn panic_invalid_format() {
let _mesh = Mesh::new( let _mesh = Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::default(),
) )
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0, 0.0]]); .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0, 0.0]]);
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::Mesh, mesh::Mesh,
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat}, render_resource::{Extent3d, TextureDimension, TextureFormat},
texture::Image, texture::Image,
}; };
@ -68,7 +68,7 @@ impl MorphTargetImage {
pub fn new( pub fn new(
targets: impl ExactSizeIterator<Item = impl Iterator<Item = MorphAttributes>>, targets: impl ExactSizeIterator<Item = impl Iterator<Item = MorphAttributes>>,
vertex_count: usize, vertex_count: usize,
cpu_persistent_access: RenderAssetPersistencePolicy, asset_usage: RenderAssetUsages,
) -> Result<Self, MorphBuildError> { ) -> Result<Self, MorphBuildError> {
let max = MAX_TEXTURE_WIDTH; let max = MAX_TEXTURE_WIDTH;
let target_count = targets.len(); let target_count = targets.len();
@ -108,7 +108,7 @@ impl MorphTargetImage {
TextureDimension::D3, TextureDimension::D3,
data, data,
TextureFormat::R32Float, TextureFormat::R32Float,
cpu_persistent_access, asset_usage,
); );
Ok(MorphTargetImage(image)) Ok(MorphTargetImage(image))
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::{Indices, Mesh}, mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
}; };
use super::Meshable; use super::Meshable;
@ -161,7 +161,7 @@ impl EllipseMeshBuilder {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals) .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
@ -220,7 +220,7 @@ impl Meshable for Triangle2d {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_indices(Some(indices)) .with_indices(Some(indices))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
@ -252,7 +252,7 @@ impl Meshable for Rectangle {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_indices(Some(indices)) .with_indices(Some(indices))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::{Indices, Mesh}, mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
}; };
use bevy_math::{Vec2, Vec3}; use bevy_math::{Vec2, Vec3};
use wgpu::PrimitiveTopology; use wgpu::PrimitiveTopology;
@ -369,7 +369,7 @@ impl From<Capsule> for Mesh {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vs) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vs)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vns) .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vns)

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::{Indices, Mesh}, mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
}; };
use wgpu::PrimitiveTopology; use wgpu::PrimitiveTopology;
@ -123,7 +123,7 @@ impl From<Cylinder> for Mesh {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_indices(Some(Indices::U32(indices))) .with_indices(Some(Indices::U32(indices)))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::{Indices, Mesh}, mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
}; };
use hexasphere::shapes::IcoSphere; use hexasphere::shapes::IcoSphere;
use thiserror::Error; use thiserror::Error;
@ -108,7 +108,7 @@ impl TryFrom<Icosphere> for Mesh {
Ok(Mesh::new( Ok(Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_indices(Some(indices)) .with_indices(Some(indices))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, points) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, points)

View file

@ -1,4 +1,4 @@
use crate::render_asset::RenderAssetPersistencePolicy; use crate::render_asset::RenderAssetUsages;
use super::{Indices, Mesh}; use super::{Indices, Mesh};
use bevy_math::*; use bevy_math::*;
@ -124,7 +124,7 @@ impl From<Box> for Mesh {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals) .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
@ -179,7 +179,7 @@ impl From<Quad> for Mesh {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_indices(Some(indices)) .with_indices(Some(indices))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
@ -263,7 +263,7 @@ impl From<Plane> for Mesh {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_indices(Some(Indices::U32(indices))) .with_indices(Some(Indices::U32(indices)))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::{Indices, Mesh}, mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
}; };
use wgpu::PrimitiveTopology; use wgpu::PrimitiveTopology;
@ -60,7 +60,7 @@ impl From<RegularPolygon> for Mesh {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals) .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::{Indices, Mesh}, mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
}; };
use bevy_math::Vec3; use bevy_math::Vec3;
use wgpu::PrimitiveTopology; use wgpu::PrimitiveTopology;
@ -89,7 +89,7 @@ impl From<Torus> for Mesh {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_indices(Some(Indices::U32(indices))) .with_indices(Some(Indices::U32(indices)))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)

View file

@ -2,7 +2,7 @@ use wgpu::PrimitiveTopology;
use crate::{ use crate::{
mesh::{Indices, Mesh}, mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
}; };
use std::f32::consts::PI; use std::f32::consts::PI;
@ -85,7 +85,7 @@ impl From<UVSphere> for Mesh {
Mesh::new( Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::default(),
) )
.with_indices(Some(Indices::U32(indices))) .with_indices(Some(Indices::U32(indices)))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)

View file

@ -7,7 +7,11 @@ use bevy_ecs::{
system::{StaticSystemParam, SystemParam, SystemParamItem, SystemState}, system::{StaticSystemParam, SystemParam, SystemParamItem, SystemState},
world::{FromWorld, Mut}, world::{FromWorld, Mut},
}; };
use bevy_reflect::Reflect; use bevy_reflect::{
utility::{reflect_hasher, NonGenericTypeInfoCell},
FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, Typed,
ValueInfo,
};
use bevy_utils::{thiserror::Error, HashMap, HashSet}; use bevy_utils::{thiserror::Error, HashMap, HashSet};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::marker::PhantomData; use std::marker::PhantomData;
@ -35,7 +39,7 @@ pub trait RenderAsset: Asset + Clone {
type Param: SystemParam; type Param: SystemParam;
/// Whether or not to unload the asset after extracting it to the render world. /// Whether or not to unload the asset after extracting it to the render world.
fn persistence_policy(&self) -> RenderAssetPersistencePolicy; fn asset_usage(&self) -> RenderAssetUsages;
/// Prepares the asset for the GPU by transforming it into a [`RenderAsset::PreparedAsset`]. /// Prepares the asset for the GPU by transforming it into a [`RenderAsset::PreparedAsset`].
/// ///
@ -46,19 +50,120 @@ pub trait RenderAsset: Asset + Clone {
) -> Result<Self::PreparedAsset, PrepareAssetError<Self>>; ) -> Result<Self::PreparedAsset, PrepareAssetError<Self>>;
} }
/// Whether or not to unload the [`RenderAsset`] after extracting it to the render world. bitflags::bitflags! {
/// /// Defines where the asset will be used.
/// Unloading the asset saves on memory, as for most cases it is no longer necessary to keep ///
/// it in RAM once it's been uploaded to the GPU's VRAM. However, this means you can no longer /// If an asset is set to the `RENDER_WORLD` but not the `MAIN_WORLD`, the asset will be
/// access the asset from the CPU (via the `Assets<T>` resource) once unloaded (without re-loading it). /// unloaded from the asset server once it's been extracted and prepared in the render world.
/// ///
/// If you never need access to the asset from the CPU past the first frame it's loaded on, /// Unloading the asset saves on memory, as for most cases it is no longer necessary to keep
/// or only need very infrequent access, then set this to Unload. Otherwise, set this to Keep. /// it in RAM once it's been uploaded to the GPU's VRAM. However, this means you can no longer
#[derive(Reflect, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default, Debug)] /// access the asset from the CPU (via the `Assets<T>` resource) once unloaded (without re-loading it).
pub enum RenderAssetPersistencePolicy { ///
Unload, /// If you never need access to the asset from the CPU past the first frame it's loaded on,
#[default] /// or only need very infrequent access, then set this to `RENDER_WORLD`. Otherwise, set this to
Keep, /// `RENDER_WORLD | MAIN_WORLD`.
///
/// If you have an asset that doesn't actually need to end up in the render world, like an Image
/// that will be decoded into another Image asset, use `MAIN_WORLD` only.
#[repr(transparent)]
#[derive(Serialize, TypePath, Deserialize, Hash, Clone, Copy, PartialEq, Eq, Debug)]
pub struct RenderAssetUsages: u8 {
const MAIN_WORLD = 1 << 0;
const RENDER_WORLD = 1 << 1;
}
}
impl Default for RenderAssetUsages {
/// Returns the default render asset usage flags:
/// `RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD`
///
/// This default configuration ensures the asset persists in the main world, even after being prepared for rendering.
///
/// If your asset does not change, consider using `RenderAssetUsages::RENDER_WORLD` exclusively. This will cause
/// the asset to be unloaded from the main world once it has been prepared for rendering. If the asset does not need
/// to reach the render world at all, use `RenderAssetUsages::MAIN_WORLD` exclusively.
fn default() -> Self {
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD
}
}
impl Reflect for RenderAssetUsages {
fn get_represented_type_info(&self) -> Option<&'static bevy_reflect::TypeInfo> {
Some(<Self as Typed>::type_info())
}
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
self
}
fn as_reflect(&self) -> &dyn Reflect {
self
}
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
fn apply(&mut self, value: &dyn Reflect) {
let value = value.as_any();
if let Some(&value) = value.downcast_ref::<Self>() {
*self = value;
} else {
panic!("Value is not a {}.", Self::type_path());
}
}
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
*self = value.take()?;
Ok(())
}
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
ReflectRef::Value(self)
}
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
ReflectMut::Value(self)
}
fn reflect_owned(self: Box<Self>) -> bevy_reflect::ReflectOwned {
ReflectOwned::Value(self)
}
fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(*self)
}
fn reflect_hash(&self) -> Option<u64> {
use std::hash::Hash;
use std::hash::Hasher;
let mut hasher = reflect_hasher();
Hash::hash(&std::any::Any::type_id(self), &mut hasher);
Hash::hash(self, &mut hasher);
Some(hasher.finish())
}
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
let value = value.as_any();
if let Some(value) = value.downcast_ref::<Self>() {
Some(std::cmp::PartialEq::eq(self, value))
} else {
Some(false)
}
}
}
impl FromReflect for RenderAssetUsages {
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
let raw_value = *reflect.as_any().downcast_ref::<u8>()?;
Self::from_bits(raw_value)
}
}
impl Typed for RenderAssetUsages {
fn type_info() -> &'static TypeInfo {
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::<Self>()))
}
} }
/// This plugin extracts the changed assets from the "app world" into the "render world" /// This plugin extracts the changed assets from the "app world" into the "render world"
@ -224,12 +329,15 @@ fn extract_render_asset<A: RenderAsset>(mut commands: Commands, mut main_world:
let mut extracted_assets = Vec::new(); let mut extracted_assets = Vec::new();
for id in changed_assets.drain() { for id in changed_assets.drain() {
if let Some(asset) = assets.get(id) { if let Some(asset) = assets.get(id) {
if asset.persistence_policy() == RenderAssetPersistencePolicy::Unload { let asset_usage = asset.asset_usage();
if let Some(asset) = assets.remove(id) { if asset_usage.contains(RenderAssetUsages::RENDER_WORLD) {
extracted_assets.push((id, asset)); if asset_usage == RenderAssetUsages::RENDER_WORLD {
if let Some(asset) = assets.remove(id) {
extracted_assets.push((id, asset));
}
} else {
extracted_assets.push((id, asset.clone()));
} }
} else {
extracted_assets.push((id, asset.clone()));
} }
} }
} }

View file

@ -56,7 +56,7 @@ impl AssetSaver for CompressedImageSaver {
format: ImageFormatSetting::Format(ImageFormat::Basis), format: ImageFormatSetting::Format(ImageFormat::Basis),
is_srgb, is_srgb,
sampler: image.sampler.clone(), sampler: image.sampler.clone(),
cpu_persistent_access: image.cpu_persistent_access, asset_usage: image.asset_usage,
}) })
} }
.boxed() .boxed()

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
texture::{Image, TextureFormatPixelInfo}, texture::{Image, TextureFormatPixelInfo},
}; };
use bevy_asset::{ use bevy_asset::{
@ -18,7 +18,7 @@ pub struct ExrTextureLoader;
#[derive(Serialize, Deserialize, Default, Debug)] #[derive(Serialize, Deserialize, Default, Debug)]
pub struct ExrTextureLoaderSettings { pub struct ExrTextureLoaderSettings {
pub cpu_persistent_access: RenderAssetPersistencePolicy, pub asset_usage: RenderAssetUsages,
} }
/// Possible errors that can be produced by [`ExrTextureLoader`] /// Possible errors that can be produced by [`ExrTextureLoader`]
@ -72,7 +72,7 @@ impl AssetLoader for ExrTextureLoader {
TextureDimension::D2, TextureDimension::D2,
buf, buf,
format, format,
settings.cpu_persistent_access, settings.asset_usage,
)) ))
}) })
} }

View file

@ -1,6 +1,4 @@
use crate::{ use crate::{render_asset::RenderAssetUsages, render_resource::*, texture::DefaultImageSampler};
render_asset::RenderAssetPersistencePolicy, render_resource::*, texture::DefaultImageSampler,
};
use bevy_derive::{Deref, DerefMut}; use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{ use bevy_ecs::{
prelude::{FromWorld, Res, ResMut}, prelude::{FromWorld, Res, ResMut},
@ -83,7 +81,7 @@ fn fallback_image_new(
image_dimension, image_dimension,
&data, &data,
format, format,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
) )
} else { } else {
let mut image = Image::default(); let mut image = Image::default();

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
texture::{Image, TextureFormatPixelInfo}, texture::{Image, TextureFormatPixelInfo},
}; };
use bevy_asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext}; use bevy_asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext};
@ -13,7 +13,7 @@ pub struct HdrTextureLoader;
#[derive(Serialize, Deserialize, Default, Debug)] #[derive(Serialize, Deserialize, Default, Debug)]
pub struct HdrTextureLoaderSettings { pub struct HdrTextureLoaderSettings {
pub cpu_persistent_access: RenderAssetPersistencePolicy, pub asset_usage: RenderAssetUsages,
} }
#[non_exhaustive] #[non_exhaustive]
@ -68,7 +68,7 @@ impl AssetLoader for HdrTextureLoader {
TextureDimension::D2, TextureDimension::D2,
rgba_data, rgba_data,
format, format,
settings.cpu_persistent_access, settings.asset_usage,
)) ))
}) })
} }

View file

@ -6,7 +6,7 @@ use super::dds::*;
use super::ktx2::*; use super::ktx2::*;
use crate::{ use crate::{
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPersistencePolicy}, render_asset::{PrepareAssetError, RenderAsset, RenderAssetUsages},
render_resource::{Sampler, Texture, TextureView}, render_resource::{Sampler, Texture, TextureView},
renderer::{RenderDevice, RenderQueue}, renderer::{RenderDevice, RenderQueue},
texture::BevyDefault, texture::BevyDefault,
@ -110,7 +110,7 @@ pub struct Image {
/// The [`ImageSampler`] to use during rendering. /// The [`ImageSampler`] to use during rendering.
pub sampler: ImageSampler, pub sampler: ImageSampler,
pub texture_view_descriptor: Option<TextureViewDescriptor<'static>>, pub texture_view_descriptor: Option<TextureViewDescriptor<'static>>,
pub cpu_persistent_access: RenderAssetPersistencePolicy, pub asset_usage: RenderAssetUsages,
} }
/// Used in [`Image`], this determines what image sampler to use when rendering. The default setting, /// Used in [`Image`], this determines what image sampler to use when rendering. The default setting,
@ -467,7 +467,7 @@ impl Default for Image {
}, },
sampler: ImageSampler::Default, sampler: ImageSampler::Default,
texture_view_descriptor: None, texture_view_descriptor: None,
cpu_persistent_access: RenderAssetPersistencePolicy::Keep, asset_usage: RenderAssetUsages::default(),
} }
} }
} }
@ -483,7 +483,7 @@ impl Image {
dimension: TextureDimension, dimension: TextureDimension,
data: Vec<u8>, data: Vec<u8>,
format: TextureFormat, format: TextureFormat,
cpu_persistent_access: RenderAssetPersistencePolicy, asset_usage: RenderAssetUsages,
) -> Self { ) -> Self {
debug_assert_eq!( debug_assert_eq!(
size.volume() * format.pixel_size(), size.volume() * format.pixel_size(),
@ -497,7 +497,7 @@ impl Image {
image.texture_descriptor.dimension = dimension; image.texture_descriptor.dimension = dimension;
image.texture_descriptor.size = size; image.texture_descriptor.size = size;
image.texture_descriptor.format = format; image.texture_descriptor.format = format;
image.cpu_persistent_access = cpu_persistent_access; image.asset_usage = asset_usage;
image image
} }
@ -511,12 +511,12 @@ impl Image {
dimension: TextureDimension, dimension: TextureDimension,
pixel: &[u8], pixel: &[u8],
format: TextureFormat, format: TextureFormat,
cpu_persistent_access: RenderAssetPersistencePolicy, asset_usage: RenderAssetUsages,
) -> Self { ) -> Self {
let mut value = Image::default(); let mut value = Image::default();
value.texture_descriptor.format = format; value.texture_descriptor.format = format;
value.texture_descriptor.dimension = dimension; value.texture_descriptor.dimension = dimension;
value.cpu_persistent_access = cpu_persistent_access; value.asset_usage = asset_usage;
value.resize(size); value.resize(size);
debug_assert_eq!( debug_assert_eq!(
@ -637,9 +637,7 @@ impl Image {
} }
_ => None, _ => None,
}) })
.map(|(dyn_img, is_srgb)| { .map(|(dyn_img, is_srgb)| Self::from_dynamic(dyn_img, is_srgb, self.asset_usage))
Self::from_dynamic(dyn_img, is_srgb, self.cpu_persistent_access)
})
} }
/// Load a bytes buffer in a [`Image`], according to type `image_type`, using the `image` /// Load a bytes buffer in a [`Image`], according to type `image_type`, using the `image`
@ -650,7 +648,7 @@ impl Image {
#[allow(unused_variables)] supported_compressed_formats: CompressedImageFormats, #[allow(unused_variables)] supported_compressed_formats: CompressedImageFormats,
is_srgb: bool, is_srgb: bool,
image_sampler: ImageSampler, image_sampler: ImageSampler,
cpu_persistent_access: RenderAssetPersistencePolicy, asset_usage: RenderAssetUsages,
) -> Result<Image, TextureError> { ) -> Result<Image, TextureError> {
let format = image_type.to_image_format()?; let format = image_type.to_image_format()?;
@ -679,7 +677,7 @@ impl Image {
reader.set_format(image_crate_format); reader.set_format(image_crate_format);
reader.no_limits(); reader.no_limits();
let dyn_img = reader.decode()?; let dyn_img = reader.decode()?;
Self::from_dynamic(dyn_img, is_srgb, cpu_persistent_access) Self::from_dynamic(dyn_img, is_srgb, asset_usage)
} }
}; };
image.sampler = image_sampler; image.sampler = image_sampler;
@ -819,8 +817,8 @@ impl RenderAsset for Image {
SRes<DefaultImageSampler>, SRes<DefaultImageSampler>,
); );
fn persistence_policy(&self) -> RenderAssetPersistencePolicy { fn asset_usage(&self) -> RenderAssetUsages {
self.cpu_persistent_access self.asset_usage
} }
/// Converts the extracted image into a [`GpuImage`]. /// Converts the extracted image into a [`GpuImage`].
@ -926,7 +924,7 @@ impl CompressedImageFormats {
mod test { mod test {
use super::*; use super::*;
use crate::render_asset::RenderAssetPersistencePolicy; use crate::render_asset::RenderAssetUsages;
#[test] #[test]
fn image_size() { fn image_size() {
@ -940,7 +938,7 @@ mod test {
TextureDimension::D2, TextureDimension::D2,
&[0, 0, 0, 255], &[0, 0, 0, 255],
TextureFormat::Rgba8Unorm, TextureFormat::Rgba8Unorm,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::MAIN_WORLD,
); );
assert_eq!( assert_eq!(
Vec2::new(size.width as f32, size.height as f32), Vec2::new(size.width as f32, size.height as f32),

View file

@ -3,7 +3,7 @@ use bevy_ecs::prelude::{FromWorld, World};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
renderer::RenderDevice, renderer::RenderDevice,
texture::{Image, ImageFormat, ImageType, TextureError}, texture::{Image, ImageFormat, ImageType, TextureError},
}; };
@ -58,7 +58,7 @@ pub struct ImageLoaderSettings {
pub format: ImageFormatSetting, pub format: ImageFormatSetting,
pub is_srgb: bool, pub is_srgb: bool,
pub sampler: ImageSampler, pub sampler: ImageSampler,
pub cpu_persistent_access: RenderAssetPersistencePolicy, pub asset_usage: RenderAssetUsages,
} }
impl Default for ImageLoaderSettings { impl Default for ImageLoaderSettings {
@ -67,7 +67,7 @@ impl Default for ImageLoaderSettings {
format: ImageFormatSetting::default(), format: ImageFormatSetting::default(),
is_srgb: true, is_srgb: true,
sampler: ImageSampler::Default, sampler: ImageSampler::Default,
cpu_persistent_access: RenderAssetPersistencePolicy::Keep, asset_usage: RenderAssetUsages::default(),
} }
} }
} }
@ -107,7 +107,7 @@ impl AssetLoader for ImageLoader {
self.supported_compressed_formats, self.supported_compressed_formats,
settings.is_srgb, settings.is_srgb,
settings.sampler.clone(), settings.sampler.clone(),
settings.cpu_persistent_access, settings.asset_usage,
) )
.map_err(|err| FileTextureError { .map_err(|err| FileTextureError {
error: err, error: err,

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
texture::{Image, TextureFormatPixelInfo}, texture::{Image, TextureFormatPixelInfo},
}; };
use image::{DynamicImage, ImageBuffer}; use image::{DynamicImage, ImageBuffer};
@ -11,7 +11,7 @@ impl Image {
pub fn from_dynamic( pub fn from_dynamic(
dyn_img: DynamicImage, dyn_img: DynamicImage,
is_srgb: bool, is_srgb: bool,
cpu_persistent_access: RenderAssetPersistencePolicy, asset_usage: RenderAssetUsages,
) -> Image { ) -> Image {
use bevy_core::cast_slice; use bevy_core::cast_slice;
let width; let width;
@ -158,7 +158,7 @@ impl Image {
TextureDimension::D2, TextureDimension::D2,
data, data,
format, format,
cpu_persistent_access, asset_usage,
) )
} }
@ -222,7 +222,7 @@ mod test {
use image::{GenericImage, Rgba}; use image::{GenericImage, Rgba};
use super::*; use super::*;
use crate::render_asset::RenderAssetPersistencePolicy; use crate::render_asset::RenderAssetUsages;
#[test] #[test]
fn two_way_conversion() { fn two_way_conversion() {
@ -230,8 +230,7 @@ mod test {
let mut initial = DynamicImage::new_rgba8(1, 1); let mut initial = DynamicImage::new_rgba8(1, 1);
initial.put_pixel(0, 0, Rgba::from([132, 3, 7, 200])); initial.put_pixel(0, 0, Rgba::from([132, 3, 7, 200]));
let image = let image = Image::from_dynamic(initial.clone(), true, RenderAssetUsages::RENDER_WORLD);
Image::from_dynamic(initial.clone(), true, RenderAssetPersistencePolicy::Unload);
// NOTE: Fails if `is_srbg = false` or the dynamic image is of the type rgb8. // NOTE: Fails if `is_srbg = false` or the dynamic image is of the type rgb8.
assert_eq!(initial, image.try_into_dynamic().unwrap()); assert_eq!(initial, image.try_into_dynamic().unwrap());

View file

@ -14,7 +14,7 @@ use wgpu::{
use crate::{ use crate::{
prelude::{Image, Shader}, prelude::{Image, Shader},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{ render_resource::{
binding_types::texture_2d, BindGroup, BindGroupLayout, BindGroupLayoutEntries, Buffer, binding_types::texture_2d, BindGroup, BindGroupLayout, BindGroupLayoutEntries, Buffer,
CachedRenderPipelineId, FragmentState, PipelineCache, RenderPipelineDescriptor, CachedRenderPipelineId, FragmentState, PipelineCache, RenderPipelineDescriptor,
@ -364,7 +364,7 @@ pub(crate) fn collect_screenshots(world: &mut World) {
wgpu::TextureDimension::D2, wgpu::TextureDimension::D2,
result, result,
texture_format, texture_format,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
)); ));
}; };

View file

@ -2,7 +2,7 @@ use crate::TextureAtlasLayout;
use bevy_asset::{Assets, Handle}; use bevy_asset::{Assets, Handle};
use bevy_math::{IVec2, Rect, Vec2}; use bevy_math::{IVec2, Rect, Vec2};
use bevy_render::{ use bevy_render::{
render_asset::RenderAssetPersistencePolicy, render_asset::{RenderAsset, RenderAssetUsages},
texture::{Image, TextureFormatPixelInfo}, texture::{Image, TextureFormatPixelInfo},
}; };
use guillotiere::{size2, Allocation, AtlasAllocator}; use guillotiere::{size2, Allocation, AtlasAllocator};
@ -30,10 +30,11 @@ impl DynamicTextureAtlasBuilder {
} }
} }
/// Add a new texture to `atlas_layout` /// Add a new texture to `atlas_layout`.
/// It is the user's responsibility to pass in the correct [`TextureAtlasLayout`] ///
/// and that `atlas_texture_handle` has [`Image::cpu_persistent_access`] /// It is the user's responsibility to pass in the correct [`TextureAtlasLayout`].
/// set to [`RenderAssetPersistencePolicy::Keep`] /// Also, the asset that `atlas_texture_handle` points to must have a usage matching
/// [`RenderAssetUsages::MAIN_WORLD`].
/// ///
/// # Arguments /// # Arguments
/// ///
@ -54,9 +55,11 @@ impl DynamicTextureAtlasBuilder {
)); ));
if let Some(allocation) = allocation { if let Some(allocation) = allocation {
let atlas_texture = textures.get_mut(atlas_texture_handle).unwrap(); let atlas_texture = textures.get_mut(atlas_texture_handle).unwrap();
assert_eq!( assert!(
atlas_texture.cpu_persistent_access, atlas_texture
RenderAssetPersistencePolicy::Keep .asset_usage()
.contains(RenderAssetUsages::MAIN_WORLD),
"The asset at atlas_texture_handle must have the RenderAssetUsages::MAIN_WORLD usage flag set"
); );
self.place_texture(atlas_texture, allocation, texture); self.place_texture(atlas_texture, allocation, texture);

View file

@ -2,7 +2,7 @@ use bevy_asset::AssetId;
use bevy_log::{debug, error, warn}; use bevy_log::{debug, error, warn};
use bevy_math::{Rect, UVec2, Vec2}; use bevy_math::{Rect, UVec2, Vec2};
use bevy_render::{ use bevy_render::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat}, render_resource::{Extent3d, TextureDimension, TextureFormat},
texture::{Image, TextureFormatPixelInfo}, texture::{Image, TextureFormatPixelInfo},
}; };
@ -241,7 +241,7 @@ impl<'a> TextureAtlasBuilder<'a> {
self.format.pixel_size() * (current_width * current_height) as usize self.format.pixel_size() * (current_width * current_height) as usize
], ],
self.format, self.format,
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
); );
Some(rect_placements) Some(rect_placements)
} }

View file

@ -2,7 +2,7 @@ use ab_glyph::{FontArc, FontVec, InvalidFont, OutlinedGlyph};
use bevy_asset::Asset; use bevy_asset::Asset;
use bevy_reflect::TypePath; use bevy_reflect::TypePath;
use bevy_render::{ use bevy_render::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat}, render_resource::{Extent3d, TextureDimension, TextureFormat},
texture::Image, texture::Image,
}; };
@ -45,7 +45,9 @@ impl Font {
.flat_map(|a| vec![255, 255, 255, (*a * 255.0) as u8]) .flat_map(|a| vec![255, 255, 255, (*a * 255.0) as u8])
.collect::<Vec<u8>>(), .collect::<Vec<u8>>(),
TextureFormat::Rgba8UnormSrgb, TextureFormat::Rgba8UnormSrgb,
RenderAssetPersistencePolicy::Unload, // This glyph image never needs to reach the render world because it's placed
// into a font texture atlas that'll be used for rendering.
RenderAssetUsages::MAIN_WORLD,
) )
} }
} }

View file

@ -2,7 +2,7 @@ use ab_glyph::{GlyphId, Point};
use bevy_asset::{Assets, Handle}; use bevy_asset::{Assets, Handle};
use bevy_math::Vec2; use bevy_math::Vec2;
use bevy_render::{ use bevy_render::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat}, render_resource::{Extent3d, TextureDimension, TextureFormat},
texture::Image, texture::Image,
}; };
@ -63,7 +63,7 @@ impl FontAtlas {
&[0, 0, 0, 0], &[0, 0, 0, 0],
TextureFormat::Rgba8UnormSrgb, TextureFormat::Rgba8UnormSrgb,
// Need to keep this image CPU persistent in order to add additional glyphs later on // Need to keep this image CPU persistent in order to add additional glyphs later on
RenderAssetPersistencePolicy::Keep, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
)); ));
let texture_atlas = TextureAtlasLayout::new_empty(size); let texture_atlas = TextureAtlasLayout::new_empty(size);
Self { Self {

View file

@ -10,7 +10,7 @@ use bevy::{
prelude::*, prelude::*,
render::{ render::{
mesh::{Indices, MeshVertexAttribute}, mesh::{Indices, MeshVertexAttribute},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_asset::RenderAssets, render_asset::RenderAssets,
render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline}, render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline},
render_resource::{ render_resource::{
@ -48,12 +48,12 @@ fn star(
// We will specify here what kind of topology is used to define the mesh, // We will specify here what kind of topology is used to define the mesh,
// that is, how triangles are built from the vertices. We will use a // that is, how triangles are built from the vertices. We will use a
// triangle list, meaning that each vertex of the triangle has to be // triangle list, meaning that each vertex of the triangle has to be
// specified. We set `cpu_persistent_access` to unload, meaning this mesh // specified. We set `RenderAssetUsages::RENDER_WORLD`, meaning this mesh
// will not be accessible in future frames from the `meshes` resource, in // will not be accessible in future frames from the `meshes` resource, in
// order to save on memory once it has been uploaded to the GPU. // order to save on memory once it has been uploaded to the GPU.
let mut star = Mesh::new( let mut star = Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
); );
// Vertices need to have a position attribute. We will use the following // Vertices need to have a position attribute. We will use the following

View file

@ -6,7 +6,7 @@ use std::f32::consts::PI;
use bevy::{ use bevy::{
prelude::*, prelude::*,
render::{ render::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat}, render_resource::{Extent3d, TextureDimension, TextureFormat},
}, },
}; };
@ -120,6 +120,6 @@ fn uv_debug_texture() -> Image {
TextureDimension::D2, TextureDimension::D2,
&texture_data, &texture_data,
TextureFormat::Rgba8UnormSrgb, TextureFormat::Rgba8UnormSrgb,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
) )
} }

View file

@ -13,7 +13,7 @@ use bevy::{
pbr::CascadeShadowConfigBuilder, pbr::CascadeShadowConfigBuilder,
prelude::*, prelude::*,
render::{ render::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat}, render_resource::{Extent3d, TextureDimension, TextureFormat},
texture::{ImageSampler, ImageSamplerDescriptor}, texture::{ImageSampler, ImageSamplerDescriptor},
}, },
@ -381,7 +381,7 @@ fn uv_debug_texture() -> Image {
TextureDimension::D2, TextureDimension::D2,
&texture_data, &texture_data,
TextureFormat::Rgba8UnormSrgb, TextureFormat::Rgba8UnormSrgb,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
); );
img.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor::default()); img.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor::default());
img img

View file

@ -4,7 +4,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::{ use bevy::render::{
mesh::{Indices, VertexAttributeValues}, mesh::{Indices, VertexAttributeValues},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::PrimitiveTopology, render_resource::PrimitiveTopology,
}; };
@ -123,7 +123,7 @@ fn input_handler(
#[rustfmt::skip] #[rustfmt::skip]
fn create_cube_mesh() -> Mesh { fn create_cube_mesh() -> Mesh {
// Keep the mesh data accessible in future frames to be able to mutate it in toggle_texture. // Keep the mesh data accessible in future frames to be able to mutate it in toggle_texture.
Mesh::new(PrimitiveTopology::TriangleList, RenderAssetPersistencePolicy::Keep) Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
.with_inserted_attribute( .with_inserted_attribute(
Mesh::ATTRIBUTE_POSITION, Mesh::ATTRIBUTE_POSITION,
// Each array is an [x, y, z] coordinate in local space. // Each array is an [x, y, z] coordinate in local space.

View file

@ -6,7 +6,7 @@ use bevy::{
reflect::TypePath, reflect::TypePath,
render::{ render::{
mesh::{MeshVertexBufferLayout, PrimitiveTopology}, mesh::{MeshVertexBufferLayout, PrimitiveTopology},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{ render_resource::{
AsBindGroup, PolygonMode, RenderPipelineDescriptor, ShaderRef, AsBindGroup, PolygonMode, RenderPipelineDescriptor, ShaderRef,
SpecializedMeshPipelineError, SpecializedMeshPipelineError,
@ -99,7 +99,7 @@ impl From<LineList> for Mesh {
// This tells wgpu that the positions are list of lines // This tells wgpu that the positions are list of lines
// where every pair is a start and end point // where every pair is a start and end point
PrimitiveTopology::LineList, PrimitiveTopology::LineList,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
) )
// Add the vertices positions as an attribute // Add the vertices positions as an attribute
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
@ -118,7 +118,7 @@ impl From<LineStrip> for Mesh {
// This tells wgpu that the positions are a list of points // This tells wgpu that the positions are a list of points
// where a line will be drawn between each consecutive point // where a line will be drawn between each consecutive point
PrimitiveTopology::LineStrip, PrimitiveTopology::LineStrip,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
) )
// Add the point positions as an attribute // Add the point positions as an attribute
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, line.points) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, line.points)

View file

@ -7,7 +7,7 @@ use bevy::{
prelude::*, prelude::*,
reflect::TypePath, reflect::TypePath,
render::{ render::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{AsBindGroup, Extent3d, ShaderRef, TextureDimension, TextureFormat}, render_resource::{AsBindGroup, Extent3d, ShaderRef, TextureDimension, TextureFormat},
texture::{ImageSampler, ImageSamplerDescriptor}, texture::{ImageSampler, ImageSamplerDescriptor},
view::ColorGrading, view::ColorGrading,
@ -691,7 +691,7 @@ fn uv_debug_texture() -> Image {
TextureDimension::D2, TextureDimension::D2,
&texture_data, &texture_data,
TextureFormat::Rgba8UnormSrgb, TextureFormat::Rgba8UnormSrgb,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
); );
img.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor::default()); img.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor::default());
img img

View file

@ -11,7 +11,7 @@ use bevy::{
skinning::{SkinnedMesh, SkinnedMeshInverseBindposes}, skinning::{SkinnedMesh, SkinnedMeshInverseBindposes},
Indices, PrimitiveTopology, VertexAttributeValues, Indices, PrimitiveTopology, VertexAttributeValues,
}, },
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
}, },
}; };
use rand::{rngs::StdRng, Rng, SeedableRng}; use rand::{rngs::StdRng, Rng, SeedableRng};
@ -56,7 +56,7 @@ fn setup(
// Create a mesh // Create a mesh
let mesh = Mesh::new( let mesh = Mesh::new(
PrimitiveTopology::TriangleList, PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
) )
// Set mesh vertex positions // Set mesh vertex positions
.with_inserted_attribute( .with_inserted_attribute(

View file

@ -7,7 +7,7 @@ use bevy::{
prelude::*, prelude::*,
render::{ render::{
extract_resource::{ExtractResource, ExtractResourcePlugin}, extract_resource::{ExtractResource, ExtractResourcePlugin},
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_asset::RenderAssets, render_asset::RenderAssets,
render_graph::{self, RenderGraph}, render_graph::{self, RenderGraph},
render_resource::*, render_resource::*,
@ -49,7 +49,7 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
TextureDimension::D2, TextureDimension::D2,
&[0, 0, 0, 255], &[0, 0, 0, 255],
TextureFormat::Rgba8Unorm, TextureFormat::Rgba8Unorm,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
); );
image.texture_descriptor.usage = image.texture_descriptor.usage =
TextureUsages::COPY_DST | TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING; TextureUsages::COPY_DST | TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING;

View file

@ -9,7 +9,7 @@ use bevy::{
diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
prelude::*, prelude::*,
render::{ render::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat}, render_resource::{Extent3d, TextureDimension, TextureFormat},
}, },
sprite::{MaterialMesh2dBundle, Mesh2dHandle}, sprite::{MaterialMesh2dBundle, Mesh2dHandle},
@ -547,7 +547,7 @@ fn init_textures(textures: &mut Vec<Handle<Image>>, args: &Args, images: &mut As
TextureDimension::D2, TextureDimension::D2,
&pixel, &pixel,
TextureFormat::Rgba8UnormSrgb, TextureFormat::Rgba8UnormSrgb,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
))); )));
} }
} }

View file

@ -16,7 +16,7 @@ use bevy::{
math::{DVec2, DVec3}, math::{DVec2, DVec3},
prelude::*, prelude::*,
render::{ render::{
render_asset::RenderAssetPersistencePolicy, render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat}, render_resource::{Extent3d, TextureDimension, TextureFormat},
}, },
window::{PresentMode, WindowPlugin, WindowResolution}, window::{PresentMode, WindowPlugin, WindowResolution},
@ -205,7 +205,7 @@ fn init_textures(args: &Args, images: &mut Assets<Image>) -> Vec<Handle<Image>>
TextureDimension::D2, TextureDimension::D2,
pixel, pixel,
TextureFormat::Rgba8UnormSrgb, TextureFormat::Rgba8UnormSrgb,
RenderAssetPersistencePolicy::Unload, RenderAssetUsages::RENDER_WORLD,
)) ))
}) })
.collect() .collect()