Skip to content

Updating a spawned mesh asset requires RenderAssetUsages::default() in 0.16.0-rc.5 #18864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
oliver-dew opened this issue Apr 16, 2025 · 2 comments
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior P-Regression Functionality that used to work but no longer does. Add a test for this! S-Needs-Design This issue requires design work to think about how it would best be accomplished
Milestone

Comments

@oliver-dew
Copy link

Bevy version

0.16.0-rc.5

[Optional] Relevant system information

If you cannot get Bevy to build or run on your machine, please include:

  • Rust 1.85.1
  • SystemInfo { os: "Linux (Ubuntu 24.04)", kernel: "6.11.0-21-generic", cpu: "AMD Ryzen 7 5825U with Radeon Graphics", core_count: "8", memory: "28.3 GiB" }

If your bug is rendering-related, copy the adapter info that appears when you run Bevy.

AdapterInfo { name: "AMD Radeon Graphics (RADV RENOIR)", vendor: 4098, device: 5607, device_type: IntegratedGpu, driver: "radv", driver_info: "Mesa 24.2.8-1ubuntu1~24.04.1", backend: Vulkan }

What you did

I have a mesh generated procedurally on the CPU, that has been spawned, perhaps several instances. I want to update/ replace the mesh (again procedurally on the CPU), by calling meshes.insert(handle, new_mesh). In 0.16, this only works if I set RenderAssetUsages::default() on the mesh asset. If instead I use RenderAssetUsages::RENDER_WORLD, spawned meshes update sporadically, after a few minutes.

MWE:

use bevy::{
    asset::RenderAssetUsages,
    input::keyboard::KeyboardInput,
    prelude::*,
    render::mesh::{Indices, PrimitiveTopology},
};
use rand::Rng;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, spawn_scene)
        .add_systems(Update, update_mesh_asset.run_if(on_event::<KeyboardInput>))
        .run();
}

fn spawn_scene(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(2.0, 2.0, 4.0).looking_at(Vec3::ZERO, Vec3::Y),
    ));

    let mesh = meshes.add(create_cube_mesh(Vec3::ONE));
    commands.spawn((
        Mesh3d(mesh),
        MeshMaterial3d(materials.add(StandardMaterial::default())),
    ));
}

// Press any key to update the mesh
fn update_mesh_asset(
    keys: Res<ButtonInput<KeyCode>>,
    mut meshes: ResMut<Assets<Mesh>>,
    query: Query<&Mesh3d>,
) {
    if keys.get_just_pressed().next().is_none() {
        return;
    };
    let Ok(mesh) = query.get_single() else { return };
    let handle = mesh.id();//0.clone();
    let mut rng = rand::rng();
    let cube = create_cube_mesh(Vec3::new(
        rng.random_range(0.5..1.5),
        rng.random_range(0.5..1.5),
        rng.random_range(0.5..1.5),
    ));
    meshes.insert(handle, cube);
}

fn create_cube_mesh(size: Vec3) -> Mesh {
    // Prior to 0.16, `RenderAssetUsages::RENDER_WORLD` works for every key press
    // In 0.16.0-rc.5, you need to use `RenderAssetUsages::default()`
    let mut mesh = Mesh::new(
        PrimitiveTopology::TriangleList,
        RenderAssetUsages::RENDER_WORLD,
    );
    mesh.insert_attribute(
        Mesh::ATTRIBUTE_POSITION,
        vec![
            // top (facing towards +y)
            [-0.5, 0.5, -0.5], // vertex with index 0
            [0.5, 0.5, -0.5],  // vertex with index 1
            [0.5, 0.5, 0.5],   // etc. until 23
            [-0.5, 0.5, 0.5],
            // bottom   (-y)
            [-0.5, -0.5, -0.5],
            [0.5, -0.5, -0.5],
            [0.5, -0.5, 0.5],
            [-0.5, -0.5, 0.5],
            // right    (+x)
            [0.5, -0.5, -0.5],
            [0.5, -0.5, 0.5],
            [0.5, 0.5, 0.5], // This vertex is at the same position as vertex with index 2, but they'll have different UV and normal
            [0.5, 0.5, -0.5],
            // left     (-x)
            [-0.5, -0.5, -0.5],
            [-0.5, -0.5, 0.5],
            [-0.5, 0.5, 0.5],
            [-0.5, 0.5, -0.5],
            // back     (+z)
            [-0.5, -0.5, 0.5],
            [-0.5, 0.5, 0.5],
            [0.5, 0.5, 0.5],
            [0.5, -0.5, 0.5],
            // forward  (-z)
            [-0.5, -0.5, -0.5],
            [-0.5, 0.5, -0.5],
            [0.5, 0.5, -0.5],
            [0.5, -0.5, -0.5],
        ]
        .iter()
        .map(|v| [v[0] * size.x, v[1] * size.y, v[2] * size.z])
        .collect::<Vec<[f32; 3]>>(),
    );
    mesh.insert_attribute(
        Mesh::ATTRIBUTE_UV_0,
        vec![
            // Assigning the UV coords for the top side.
            [0.0, 0.2],
            [0.0, 0.0],
            [1.0, 0.0],
            [1.0, 0.2],
            // Assigning the UV coords for the bottom side.
            [0.0, 0.45],
            [0.0, 0.25],
            [1.0, 0.25],
            [1.0, 0.45],
            // Assigning the UV coords for the right side.
            [1.0, 0.45],
            [0.0, 0.45],
            [0.0, 0.2],
            [1.0, 0.2],
            // Assigning the UV coords for the left side.
            [1.0, 0.45],
            [0.0, 0.45],
            [0.0, 0.2],
            [1.0, 0.2],
            // Assigning the UV coords for the back side.
            [0.0, 0.45],
            [0.0, 0.2],
            [1.0, 0.2],
            [1.0, 0.45],
            // Assigning the UV coords for the forward side.
            [0.0, 0.45],
            [0.0, 0.2],
            [1.0, 0.2],
            [1.0, 0.45],
        ],
    );
    mesh.insert_attribute(
        Mesh::ATTRIBUTE_NORMAL,
        vec![
            // Normals for the top side (towards +y)
            [0.0, 1.0, 0.0],
            [0.0, 1.0, 0.0],
            [0.0, 1.0, 0.0],
            [0.0, 1.0, 0.0],
            // Normals for the bottom side (towards -y)
            [0.0, -1.0, 0.0],
            [0.0, -1.0, 0.0],
            [0.0, -1.0, 0.0],
            [0.0, -1.0, 0.0],
            // Normals for the right side (towards +x)
            [1.0, 0.0, 0.0],
            [1.0, 0.0, 0.0],
            [1.0, 0.0, 0.0],
            [1.0, 0.0, 0.0],
            // Normals for the left side (towards -x)
            [-1.0, 0.0, 0.0],
            [-1.0, 0.0, 0.0],
            [-1.0, 0.0, 0.0],
            [-1.0, 0.0, 0.0],
            // Normals for the back side (towards +z)
            [0.0, 0.0, 1.0],
            [0.0, 0.0, 1.0],
            [0.0, 0.0, 1.0],
            [0.0, 0.0, 1.0],
            // Normals for the forward side (towards -z)
            [0.0, 0.0, -1.0],
            [0.0, 0.0, -1.0],
            [0.0, 0.0, -1.0],
            [0.0, 0.0, -1.0],
        ],
    );
    mesh.insert_indices(Indices::U32(vec![
        0, 3, 1, 1, 3, 2, // triangles making up the top (+y) facing side.
        4, 5, 7, 5, 6, 7, // bottom (-y)
        8, 11, 9, 9, 11, 10, // right (+x)
        12, 13, 15, 13, 14, 15, // left (-x)
        16, 19, 17, 17, 19, 18, // back (+z)
        20, 21, 23, 21, 22, 23, // forward (-z)
    ]));
    mesh
}

What went wrong

If it's not clear, break this out into:

  • what were you expecting?
    In 0.16 I expect to be able to update a spawned mesh that has the usage RenderAssetUsages::RENDER_WORLD , as was possible prior to 0.16
  • what actually happened?
    The asset updates, but only sporadically, after a few minutes. To get the old behaviour back, I need to set RenderAssetUsages::default() on the mesh asset
@oliver-dew oliver-dew added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Apr 16, 2025
@tychedelia tychedelia added this to the 0.16.1 milestone Apr 16, 2025
@hukasu
Copy link
Contributor

hukasu commented Apr 17, 2025

there was an pr that made it so some render assets be unloaded from Assets after they were extracted to the render world when they have RenderAssetUsage::RENDER_WORLD, and it's been some time already, so to my understanding, Assets should return None when trying to fetch an asset that is RenderAssetUsage::RENDER_WORLD IIRC

@hukasu
Copy link
Contributor

hukasu commented Apr 17, 2025

oh, you are not using get_mut you are completely replacing the mesh, i don't know what should be the behavior when doing this

@janhohenheim janhohenheim added A-Rendering Drawing game state to the screen P-Regression Functionality that used to work but no longer does. Add a test for this! S-Needs-Design This issue requires design work to think about how it would best be accomplished and removed S-Needs-Triage This issue needs to be labelled labels Apr 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior P-Regression Functionality that used to work but no longer does. Add a test for this! S-Needs-Design This issue requires design work to think about how it would best be accomplished
Projects
None yet
Development

No branches or pull requests

4 participants