Skip to content
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

RenderAssetUsages::RENDER_WORLD assets are not cleaned when their handles are dropped #13500

Closed
mockersf opened this issue May 25, 2024 · 3 comments · Fixed by #13609
Closed
Labels
A-Assets Load files from disk to use for things like images, models, and sounds A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior S-Needs-Investigation This issue requires detective work to figure out what's going wrong
Milestone

Comments

@mockersf
Copy link
Member

mockersf commented May 25, 2024

Bevy version

0.13 and main

What you did

load many images, set them as RenderAssetUsages::RENDER_WORLD, display them then drop them

What went wrong

GPU memory is not freed

Additional information

first video
images are loaded as RenderAssetUsages::all(), all displayed, then all the entities are despawned, there are no strong handles left
CPU and GPU memory are freed, as can be seen in the metal HUD

assets-both.mp4

second video
images are loaded as RenderAssetUsages:: RENDER_WORLD, all displayed, then all the entities are despawned, there are no strong handles left
CPU memory is freed as soon as the images are sent to the GPU, GPU memory is never freed

assets-render.mp4
Example code this example loads all the images in the Bevy repo
use bevy::{
    prelude::*,
    render::{render_asset::RenderAssetUsages, texture::ImageLoaderSettings},
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, (drop_handles, update_asset_count))
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle { ..default() });
    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Percent(100.0),
                height: Val::Percent(100.0),
                align_items: AlignItems::End,
                justify_content: JustifyContent::Center,
                ..default()
            },
            ..default()
        })
        .with_children(|parent| {
            parent.spawn(TextBundle::from_section(
                "image assets",
                TextStyle {
                    font_size: 100.0,
                    ..default()
                },
            ));
        });

    ALL_IMAGES.into_iter().enumerate().for_each(|(i, p)| {
        let handle = asset_server.load_with_settings(p, |s: &mut _| {
            *s = ImageLoaderSettings {
                asset_usage: RenderAssetUsages::all(),
                // asset_usage: RenderAssetUsages::RENDER_WORLD,
                ..default()
            };
        });

        commands.spawn(SpriteBundle {
            texture: handle,
            transform: Transform::from_xyz(
                (i % 20) as f32 * 10.0 - 5.0,
                (i / 20) as f32 * 10.0,
                0.0,
            )
            .with_scale(Vec3::splat(0.1)),
            ..default()
        });
    });
}

fn drop_handles(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut commands: Commands,
    images: Query<Entity, With<Handle<Image>>>,
) {
    if keyboard_input.just_pressed(KeyCode::Space) {
        for entity in &images {
            commands.entity(entity).despawn();
        }
    }
}

fn update_asset_count(mut text: Query<&mut Text>, images: Res<Assets<Image>>) {
    text.single_mut().sections[0].value = format!("CPU side: {} assets", images.len());
}

const ALL_IMAGES: [&str; 221] = [
    "textures/simplespace/ship_C.png",
    "textures/simplespace/enemy_B.png",
    "textures/simplespace/enemy_A.png",
    "textures/rpg/ui/generic-rpg-ui-inventario.png",
    "textures/rpg/ui/generic-rpg-ui-text-box.png",
    "textures/rpg/ui/generic-rpg-ui-inventario01.png",
    "textures/rpg/ui/generic-rpg-ui-inventario03.png",
    "textures/rpg/ui/generic-rpg-ui-inventario02.png",
    "textures/rpg/ui/generic-rpg-ui-inventario04.png",
    "textures/rpg/mobs/worm-run-idle.png",
    "textures/rpg/mobs/slime-blue.png",
    "textures/rpg/mobs/boss_bee.png",
    "textures/rpg/mobs/fox-run.png",
    "textures/rpg/mobs/slime-green.png",
    "textures/rpg/mobs/slime-orange.png",
    "textures/rpg/mobs/kobold-idle.png",
    "textures/rpg/props/generic-rpg-board02.png",
    "textures/rpg/props/generic-rpg-barrel02.png",
    "textures/rpg/props/generic-rpg-grass02.png",
    "textures/rpg/props/generic-rpg-barrel03.png",
    "textures/rpg/props/generic-rpg-board03.png",
    "textures/rpg/props/generic-rpg-treasure-closed.png",
    "textures/rpg/props/generic-rpg-board01.png",
    "textures/rpg/props/generic-rpg-barrel01.png",
    "textures/rpg/props/generic-rpg-grass01.png",
    "textures/rpg/props/generic-rpg-board04.png",
    "textures/rpg/props/generic-rpg-flowers.png",
    "textures/rpg/props/generic-rpg-fence-raw03.png",
    "textures/rpg/props/generic-rpg-fence-raw17.png",
    "textures/rpg/props/generic-rpg-rock01.png",
    "textures/rpg/props/generic-rpg-loot01.png",
    "textures/rpg/props/generic-rpg-fence-raw16.png",
    "textures/rpg/props/generic-rpg-fence-raw02.png",
    "textures/rpg/props/generic-rpg-fence-raw14.png",
    "textures/rpg/props/generic-rpg-loot03.png",
    "textures/rpg/props/generic-rpg-rock03.png",
    "textures/rpg/props/generic-rpg-rock02.png",
    "textures/rpg/props/generic-rpg-loot02.png",
    "textures/rpg/props/generic-rpg-fence-raw01.png",
    "textures/rpg/props/generic-rpg-fence-raw15.png",
    "textures/rpg/props/generic-rpg-fence-raw11.png",
    "textures/rpg/props/generic-rpg-fence-raw05.png",
    "textures/rpg/props/generic-rpg-rock06.png",
    "textures/rpg/props/generic-rpg-rod.png",
    "textures/rpg/props/generic-rpg-fence-raw04.png",
    "textures/rpg/props/generic-rpg-fence-raw10.png",
    "textures/rpg/props/generic-rpg-bridge.png",
    "textures/rpg/props/generic-rpg-fence-raw06.png",
    "textures/rpg/props/generic-rpg-fence-raw12.png",
    "textures/rpg/props/generic-rpg-loot05.png",
    "textures/rpg/props/generic-rpg-rock05.png",
    "textures/rpg/props/generic-rpg-fence08.png",
    "textures/rpg/props/generic-rpg-fence09.png",
    "textures/rpg/props/generic-rpg-rock04.png",
    "textures/rpg/props/generic-rpg-loot04.png",
    "textures/rpg/props/generic-rpg-fence-raw13.png",
    "textures/rpg/props/generic-rpg-fence-raw07.png",
    "textures/rpg/props/generic-rpg-fence-raw22.png",
    "textures/rpg/props/generic-rpg-fence04.png",
    "textures/rpg/props/generic-rpg-fence10.png",
    "textures/rpg/props/generic-rpg-fence11.png",
    "textures/rpg/props/generic-rpg-fence05.png",
    "textures/rpg/props/generic-rpg-flower01.png",
    "textures/rpg/props/generic-rpg-fence-raw23.png",
    "textures/rpg/props/generic-rpg-fence-raw21.png",
    "textures/rpg/props/generic-rpg-fence-raw09.png",
    "textures/rpg/props/generic-rpg-flower03.png",
    "textures/rpg/props/generic-rpg-fence-complete.png",
    "textures/rpg/props/generic-rpg-fence13.png",
    "textures/rpg/props/generic-rpg-fence07.png",
    "textures/rpg/props/generic-rpg-fence06.png",
    "textures/rpg/props/generic-rpg-fence12.png",
    "textures/rpg/props/generic-rpg-flower02.png",
    "textures/rpg/props/generic-rpg-fence-raw08.png",
    "textures/rpg/props/generic-rpg-fence-raw20.png",
    "textures/rpg/props/generic-rpg-tree02.png",
    "textures/rpg/props/generic-rpg-fence-raw18.png",
    "textures/rpg/props/generic-rpg-fence-raw24.png",
    "textures/rpg/props/generic-rpg-fence02.png",
    "textures/rpg/props/generic-rpg-fence03.png",
    "textures/rpg/props/generic-rpg-fence-raw25.png",
    "textures/rpg/props/generic-rpg-fence-raw19.png",
    "textures/rpg/props/generic-rpg-tree01.png",
    "textures/rpg/props/generic-rpg-house-inn.png",
    "textures/rpg/props/generic-rpg-fence01.png",
    "textures/rpg/props/generic-rpg-fence14.png",
    "textures/rpg/props/generic-rpg-crate02.png",
    "textures/rpg/props/generic-rpg-crate03.png",
    "textures/rpg/props/generic-rpg-crate01.png",
    "textures/rpg/props/generic-rpg-fish04.png",
    "textures/rpg/props/generic-rpg-mini-lake.png",
    "textures/rpg/props/generic-rpg-fish01.png",
    "textures/rpg/props/generic-rpg-fish02.png",
    "textures/rpg/props/generic-rpg-fish03.png",
    "textures/rpg/props/generic-rpg-trasure-open.png",
    "textures/rpg/chars/sensei/sensei.png",
    "textures/rpg/chars/mani/mani-idle-run.png",
    "textures/rpg/chars/hat-guy/hat-guy.png",
    "textures/rpg/chars/vendor/generic-rpg-vendor.png",
    "textures/rpg/chars/gabe/gabe-idle-run.png",
    "textures/rpg/tiles/generic-rpg-tile35.png",
    "textures/rpg/tiles/generic-rpg-tile21.png",
    "textures/rpg/tiles/generic-rpg-tile09.png",
    "textures/rpg/tiles/generic-rpg-tile08.png",
    "textures/rpg/tiles/generic-rpg-tile20.png",
    "textures/rpg/tiles/generic-rpg-tile34.png",
    "textures/rpg/tiles/generic-rpg-tile22.png",
    "textures/rpg/tiles/generic-rpg-tile37.png",
    "textures/rpg/tiles/generic-rpg-tile23.png",
    "textures/rpg/tiles/generic-rpg-tile27.png",
    "textures/rpg/tiles/generic-rpg-tile33.png",
    "textures/rpg/tiles/generic-rpg-tile32.png",
    "textures/rpg/tiles/generic-rpg-tile26.png",
    "textures/rpg/tiles/generic-rpg-tile18.png",
    "textures/rpg/tiles/generic-rpg-tile30.png",
    "textures/rpg/tiles/generic-rpg-tile24.png",
    "textures/rpg/tiles/generic-rpg-tile25.png",
    "textures/rpg/tiles/generic-rpg-tile31.png",
    "textures/rpg/tiles/generic-rpg-tile19.png",
    "textures/rpg/tiles/generic-rpg-tile56.png",
    "textures/rpg/tiles/generic-rpg-tile42.png",
    "textures/rpg/tiles/generic-rpg-tile43.png",
    "textures/rpg/tiles/generic-rpg-tile57.png",
    "textures/rpg/tiles/generic-rpg-tile41.png",
    "textures/rpg/tiles/generic-rpg-tile55.png",
    "textures/rpg/tiles/generic-rpg-tile69.png",
    "textures/rpg/tiles/generic-rpg-tile68.png",
    "textures/rpg/tiles/generic-rpg-tile54.png",
    "textures/rpg/tiles/generic-rpg-tile40.png",
    "textures/rpg/tiles/generic-rpg-tile44.png",
    "textures/rpg/tiles/generic-rpg-tile50.png",
    "textures/rpg/tiles/generic-rpg-tile51.png",
    "textures/rpg/tiles/generic-rpg-tile45.png",
    "textures/rpg/tiles/generic-rpg-tile53.png",
    "textures/rpg/tiles/generic-rpg-tile47.png",
    "textures/rpg/tiles/generic-rpg-tile46.png",
    "textures/rpg/tiles/generic-rpg-tile52.png",
    "textures/rpg/tiles/generic-rpg-tile63.png",
    "textures/rpg/tiles/generic-rpg-tile-waterfall01.png",
    "textures/rpg/tiles/generic-rpg-tile62.png",
    "textures/rpg/tiles/generic-rpg-tile60.png",
    "textures/rpg/tiles/generic-rpg-tile48.png",
    "textures/rpg/tiles/generic-rpg-tile-waterfall02.png",
    "textures/rpg/tiles/generic-rpg-tile-waterfall03.png",
    "textures/rpg/tiles/generic-rpg-tile49.png",
    "textures/rpg/tiles/generic-rpg-tile61.png",
    "textures/rpg/tiles/generic-rpg-tile59.png",
    "textures/rpg/tiles/generic-rpg-tile65.png",
    "textures/rpg/tiles/generic-rpg-tile71.png",
    "textures/rpg/tiles/generic-rpg-tile-waterfall07.png",
    "textures/rpg/tiles/generic-rpg-tile-waterfall06.png",
    "textures/rpg/tiles/generic-rpg-tile70.png",
    "textures/rpg/tiles/generic-rpg-tile64.png",
    "textures/rpg/tiles/generic-rpg-tile58.png",
    "textures/rpg/tiles/generic-rpg-tile66.png",
    "textures/rpg/tiles/generic-rpg-tile-waterfall04.png",
    "textures/rpg/tiles/generic-rpg-tile-waterfall05.png",
    "textures/rpg/tiles/generic-rpg-tile67.png",
    "textures/rpg/tiles/generic-rpg-tile14.png",
    "textures/rpg/tiles/generic-rpg-tile28.png",
    "textures/rpg/tiles/generic-rpg-tile29.png",
    "textures/rpg/tiles/generic-rpg-tile01.png",
    "textures/rpg/tiles/generic-rpg-tile15.png",
    "textures/rpg/tiles/generic-rpg-tile03.png",
    "textures/rpg/tiles/generic-rpg-tile17.png",
    "textures/rpg/tiles/generic-rpg-tile16.png",
    "textures/rpg/tiles/generic-rpg-tile02.png",
    "textures/rpg/tiles/generic-rpg-tile06.png",
    "textures/rpg/tiles/generic-rpg-tile12.png",
    "textures/rpg/tiles/generic-rpg-tile13.png",
    "textures/rpg/tiles/generic-rpg-tile07.png",
    "textures/rpg/tiles/generic-rpg-tile39.png",
    "textures/rpg/tiles/generic-rpg-tile11.png",
    "textures/rpg/tiles/generic-rpg-tile05.png",
    "textures/rpg/tiles/generic-rpg-tile04.png",
    "textures/rpg/tiles/generic-rpg-tile10.png",
    "textures/rpg/tiles/generic-rpg-tile38.png",
    "textures/rpg/tiles/generic-rpg-Slice.png",
    "textures/fantasy_ui_borders/panel-border-015.png",
    "textures/fantasy_ui_borders/panel-border-010.png",
    "textures/fantasy_ui_borders/border_sheet.png",
    "textures/fantasy_ui_borders/panel-border-010-repeated.png",
    "textures/slice_square.png",
    "textures/BlueNoise-Normal.png",
    "textures/parallax_example/cube_color.png",
    "textures/parallax_example/cube_normal.png",
    "textures/parallax_example/cube_depth.png",
    "textures/Ryfjallet_cubemap.png",
    "textures/slice_square_2.png",
    "textures/ScratchedGold-Normal.png",
    "textures/array_texture.png",
    "textures/basic_metering_mask.png",
    "textures/Game Icons/exitRight.png",
    "textures/Game Icons/wrench.png",
    "textures/Game Icons/right.png",
    "branding/icon.png",
    "branding/banner.png",
    "branding/bevy_logo_dark_big.png",
    "branding/bevy_logo_light.png",
    "branding/bevy_bird_dark.png",
    "branding/bevy_logo_dark.png",
    "models/TonemappingTest/TestPattern.png",
    "models/FlightHelmet/FlightHelmet_Materials_GlassPlasticMat_BaseColor.png",
    "models/FlightHelmet/FlightHelmet_Materials_LeatherPartsMat_OcclusionRoughMetal.png",
    "models/FlightHelmet/FlightHelmet_Materials_RubberWoodMat_Normal.png",
    "models/FlightHelmet/FlightHelmet_Materials_LensesMat_OcclusionRoughMetal.png",
    "models/FlightHelmet/FlightHelmet_Materials_GlassPlasticMat_OcclusionRoughMetal.png",
    "models/FlightHelmet/FlightHelmet_Materials_LensesMat_BaseColor.png",
    "models/FlightHelmet/FlightHelmet_Materials_LeatherPartsMat_Normal.png",
    "models/FlightHelmet/FlightHelmet_Materials_RubberWoodMat_BaseColor.png",
    "models/FlightHelmet/FlightHelmet_Materials_GlassPlasticMat_Normal.png",
    "models/FlightHelmet/FlightHelmet_Materials_RubberWoodMat_OcclusionRoughMetal.png",
    "models/FlightHelmet/FlightHelmet_Materials_LeatherPartsMat_BaseColor.png",
    "models/FlightHelmet/FlightHelmet_Materials_MetalPartsMat_OcclusionRoughMetal.png",
    "models/FlightHelmet/FlightHelmet_Materials_MetalPartsMat_Normal.png",
    "models/FlightHelmet/FlightHelmet_Materials_MetalPartsMat_BaseColor.png",
    "models/FlightHelmet/FlightHelmet_Materials_LensesMat_Normal.png",
    "docs/Mesh.png",
    "pixel/bevy_pixel_dark.png",
    "pixel/bevy_pixel_light.png",
    "android-res/mipmap-mdpi/ic_launcher.png",
];
@mockersf mockersf added C-Bug An unexpected or incorrect behavior A-Rendering Drawing game state to the screen A-Assets Load files from disk to use for things like images, models, and sounds labels May 25, 2024
@JMS55
Copy link
Contributor

JMS55 commented May 25, 2024

Assuming it's not a wgpu issue (e.g. gfx-rs/wgpu#5707, which I'm not sure if it applies to 0.19 or not), this PR #12459 probably broke it.

Can you run a git bisect and see if it worked before #12459?

EDIT: Also try adding a print statement here and seeing if assets are properly dropped.

EDIT2: Could also have been #12827 breaking something.

@JMS55 JMS55 added this to the 0.14 milestone May 25, 2024
@alice-i-cecile alice-i-cecile added the S-Needs-Investigation This issue requires detective work to figure out what's going wrong label May 26, 2024
@JMS55
Copy link
Contributor

JMS55 commented May 31, 2024

I added a Drop impl to GpuImage and ran the example. I see all the images being dropped. If there's memory leaks, I think it's on wgpu's side.

@mockersf
Copy link
Member Author

@JMS55 the GpuUimage is dropped, but the bind group was kept, keeping the memory used. #13609 fixes that

github-merge-queue bot pushed a commit that referenced this issue May 31, 2024
# Objective

- Fixes #13500
- Images that are `RenderAssetUsages::RENDER_WORLD` don't free their
memory when they are no longer used

## Solution

- Remove their bind group when the handles are unused
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Assets Load files from disk to use for things like images, models, and sounds A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior S-Needs-Investigation This issue requires detective work to figure out what's going wrong
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants