Skip to content

Commit

Permalink
RenderAssetPersistencePolicy → RenderAssetUsages (bevyengine#11399)
Browse files Browse the repository at this point in the history
# 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 bevyengine#10520
* References bevyengine#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.
  • Loading branch information
brianreavis authored and tjamaan committed Feb 6, 2024
1 parent ddf9ce9 commit 1db333e
Show file tree
Hide file tree
Showing 36 changed files with 247 additions and 143 deletions.
6 changes: 3 additions & 3 deletions crates/bevy_core_pipeline/src/tonemapping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use bevy_reflect::Reflect;
use bevy_render::camera::Camera;
use bevy_render::extract_component::{ExtractComponent, ExtractComponentPlugin};
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::{
sampler, texture_2d, texture_3d, uniform_buffer,
};
Expand Down Expand Up @@ -360,7 +360,7 @@ fn setup_tonemapping_lut_image(bytes: &[u8], image_type: ImageType) -> Image {
CompressedImageFormats::NONE,
false,
image_sampler,
RenderAssetPersistencePolicy::Unload,
RenderAssetUsages::RENDER_WORLD,
)
.unwrap()
}
Expand All @@ -386,6 +386,6 @@ pub fn lut_placeholder() -> Image {
},
sampler: ImageSampler::Default,
texture_view_descriptor: None,
cpu_persistent_access: RenderAssetPersistencePolicy::Unload,
asset_usage: RenderAssetUsages::RENDER_WORLD,
}
}
7 changes: 3 additions & 4 deletions crates/bevy_gizmos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ use bevy_reflect::TypePath;
use bevy_render::{
extract_component::{ComponentUniforms, DynamicUniformIndex, UniformComponentPlugin},
render_asset::{
PrepareAssetError, RenderAsset, RenderAssetPersistencePolicy, RenderAssetPlugin,
RenderAssets,
PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssetUsages, RenderAssets,
},
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
render_resource::{
Expand Down Expand Up @@ -316,8 +315,8 @@ impl RenderAsset for LineGizmo {
type PreparedAsset = GpuLineGizmo;
type Param = SRes<RenderDevice>;

fn persistence_policy(&self) -> RenderAssetPersistencePolicy {
RenderAssetPersistencePolicy::Keep
fn asset_usage(&self) -> RenderAssetUsages {
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD
}

fn prepare_asset(
Expand Down
10 changes: 5 additions & 5 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use bevy_render::{
},
prelude::SpatialBundle,
primitives::Aabb,
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
render_resource::{Face, PrimitiveTopology},
texture::{
CompressedImageFormats, Image, ImageAddressMode, ImageFilterMode, ImageLoaderSettings,
Expand Down Expand Up @@ -393,7 +393,7 @@ async fn load_gltf<'a, 'b, 'c>(
let primitive_label = primitive_label(&gltf_mesh, &primitive);
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
for (semantic, accessor) in primitive.attributes() {
Expand Down Expand Up @@ -437,7 +437,7 @@ async fn load_gltf<'a, 'b, 'c>(
let morph_target_image = MorphTargetImage::new(
morph_target_reader.map(PrimitiveMorphAttributesIter),
mesh.count_vertices(),
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)?;
let handle =
load_context.add_labeled_asset(morph_targets_label, morph_target_image.0);
Expand Down Expand Up @@ -744,7 +744,7 @@ async fn load_image<'a, 'b>(
supported_compressed_formats,
is_srgb,
ImageSampler::Descriptor(sampler_descriptor),
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)?;
Ok(ImageOrPath::Image {
image,
Expand All @@ -766,7 +766,7 @@ async fn load_image<'a, 'b>(
supported_compressed_formats,
is_srgb,
ImageSampler::Descriptor(sampler_descriptor),
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)?,
label: texture_label(&gltf_texture),
})
Expand Down
23 changes: 10 additions & 13 deletions crates/bevy_render/src/mesh/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub use wgpu::PrimitiveTopology;
use crate::{
prelude::Image,
primitives::Aabb,
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPersistencePolicy, RenderAssets},
render_asset::{PrepareAssetError, RenderAsset, RenderAssetUsages, RenderAssets},
render_resource::{Buffer, TextureView, VertexBufferLayout},
renderer::RenderDevice,
};
Expand Down Expand Up @@ -49,10 +49,10 @@ pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
/// ```
/// # use bevy_render::mesh::{Mesh, Indices};
/// # use bevy_render::render_resource::PrimitiveTopology;
/// # use bevy_render::render_asset::RenderAssetPersistencePolicy;
/// # use bevy_render::render_asset::RenderAssetUsages;
/// fn create_simple_parallelogram() -> Mesh {
/// // 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
/// // 3D space), for each of the corners of the parallelogram.
/// .with_inserted_attribute(
Expand Down Expand Up @@ -123,7 +123,7 @@ pub struct Mesh {
indices: Option<Indices>,
morph_targets: Option<Handle<Image>>,
morph_target_names: Option<Vec<String>>,
pub cpu_persistent_access: RenderAssetPersistencePolicy,
pub asset_usage: RenderAssetUsages,
}

impl Mesh {
Expand Down Expand Up @@ -184,17 +184,14 @@ impl Mesh {
/// 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
/// [`PrimitiveTopology::TriangleList`].
pub fn new(
primitive_topology: PrimitiveTopology,
cpu_persistent_access: RenderAssetPersistencePolicy,
) -> Self {
pub fn new(primitive_topology: PrimitiveTopology, asset_usage: RenderAssetUsages) -> Self {
Mesh {
primitive_topology,
attributes: Default::default(),
indices: None,
morph_targets: None,
morph_target_names: None,
cpu_persistent_access,
asset_usage,
}
}

Expand Down Expand Up @@ -1148,8 +1145,8 @@ impl RenderAsset for Mesh {
type PreparedAsset = GpuMesh;
type Param = (SRes<RenderDevice>, SRes<RenderAssets<Image>>);

fn persistence_policy(&self) -> RenderAssetPersistencePolicy {
self.cpu_persistent_access
fn asset_usage(&self) -> RenderAssetUsages {
self.asset_usage
}

/// Converts the extracted mesh a into [`GpuMesh`].
Expand Down Expand Up @@ -1317,15 +1314,15 @@ fn generate_tangents_for_mesh(mesh: &Mesh) -> Result<Vec<[f32; 4]>, GenerateTang
#[cfg(test)]
mod tests {
use super::Mesh;
use crate::render_asset::RenderAssetPersistencePolicy;
use crate::render_asset::RenderAssetUsages;
use wgpu::PrimitiveTopology;

#[test]
#[should_panic]
fn panic_invalid_format() {
let _mesh = Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Unload,
RenderAssetUsages::default(),
)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, vec![[0.0, 0.0, 0.0]]);
}
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_render/src/mesh/morph.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
mesh::Mesh,
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat},
texture::Image,
};
Expand Down Expand Up @@ -68,7 +68,7 @@ impl MorphTargetImage {
pub fn new(
targets: impl ExactSizeIterator<Item = impl Iterator<Item = MorphAttributes>>,
vertex_count: usize,
cpu_persistent_access: RenderAssetPersistencePolicy,
asset_usage: RenderAssetUsages,
) -> Result<Self, MorphBuildError> {
let max = MAX_TEXTURE_WIDTH;
let target_count = targets.len();
Expand Down Expand Up @@ -108,7 +108,7 @@ impl MorphTargetImage {
TextureDimension::D3,
data,
TextureFormat::R32Float,
cpu_persistent_access,
asset_usage,
);
Ok(MorphTargetImage(image))
}
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_render/src/mesh/primitives/dim2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
};

use super::Meshable;
Expand Down Expand Up @@ -161,7 +161,7 @@ impl EllipseMeshBuilder {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
Expand Down Expand Up @@ -220,7 +220,7 @@ impl Meshable for Triangle2d {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_indices(Some(indices))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
Expand Down Expand Up @@ -252,7 +252,7 @@ impl Meshable for Rectangle {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_indices(Some(indices))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/mesh/shape/capsule.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
};
use bevy_math::{Vec2, Vec3};
use wgpu::PrimitiveTopology;
Expand Down Expand Up @@ -369,7 +369,7 @@ impl From<Capsule> for Mesh {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vs)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, vns)
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/mesh/shape/cylinder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
};
use wgpu::PrimitiveTopology;

Expand Down Expand Up @@ -123,7 +123,7 @@ impl From<Cylinder> for Mesh {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_indices(Some(Indices::U32(indices)))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/mesh/shape/icosphere.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
};
use hexasphere::shapes::IcoSphere;
use thiserror::Error;
Expand Down Expand Up @@ -108,7 +108,7 @@ impl TryFrom<Icosphere> for Mesh {

Ok(Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_indices(Some(indices))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, points)
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_render/src/mesh/shape/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::render_asset::RenderAssetPersistencePolicy;
use crate::render_asset::RenderAssetUsages;

use super::{Indices, Mesh};
use bevy_math::*;
Expand Down Expand Up @@ -124,7 +124,7 @@ impl From<Box> for Mesh {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
Expand Down Expand Up @@ -179,7 +179,7 @@ impl From<Quad> for Mesh {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_indices(Some(indices))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
Expand Down Expand Up @@ -263,7 +263,7 @@ impl From<Plane> for Mesh {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_indices(Some(Indices::U32(indices)))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/mesh/shape/regular_polygon.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
};
use wgpu::PrimitiveTopology;

Expand Down Expand Up @@ -60,7 +60,7 @@ impl From<RegularPolygon> for Mesh {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/mesh/shape/torus.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
};
use bevy_math::Vec3;
use wgpu::PrimitiveTopology;
Expand Down Expand Up @@ -89,7 +89,7 @@ impl From<Torus> for Mesh {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_indices(Some(Indices::U32(indices)))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/mesh/shape/uvsphere.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use wgpu::PrimitiveTopology;

use crate::{
mesh::{Indices, Mesh},
render_asset::RenderAssetPersistencePolicy,
render_asset::RenderAssetUsages,
};
use std::f32::consts::PI;

Expand Down Expand Up @@ -85,7 +85,7 @@ impl From<UVSphere> for Mesh {

Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetPersistencePolicy::Keep,
RenderAssetUsages::default(),
)
.with_indices(Some(Indices::U32(indices)))
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
Expand Down
Loading

0 comments on commit 1db333e

Please sign in to comment.