Skip to content

noop system with commands argument added to Render schedule exhibits racing behavior #12498

@MeoMix

Description

@MeoMix

Bevy version

0.13

[Optional] Relevant system information

AdapterInfo { name: "D3D12 (NVIDIA GeForce GTX 1080 Ti)", vendor: 0, device: 0, device_type: Other, driver: "", driver_info: "", backend: Gl }
1.78.0-nightly (7065f0ef4 2024-03-12)

What you did

I updated to Bevy 0.13 from Bevy 0.12. I attempted to render a tilemap using bevy-ecs-tilemap in a WASM/singlethreaded environment.

What went wrong

Nothing rendered. The issue occurs approximately 1 in every 5 loads of the app.

Additional information

MRE: https://github.com/MeoMix/bevy_bug_example/blob/master/src/main.rs

// This code should draw a white square in the center of the window if it runs properly.
// One in every 5-10 runs no white square will render.
// If the `multithreaded` feature is enabled in bevy's Cargo.toml then the square "always" renders (if it's a timing issue it becomes sufficiently difficult to surface with multithreading)
use bevy::prelude::*;
use bevy::render::{Render, RenderApp, RenderSet};
use bevy_ecs_tilemap::prelude::*;

fn main() {
    App::new()
    .add_plugins((DefaultPlugins, TilemapPlugin))
    .add_systems(Startup, (spawn_camera, spawn_tilemap).chain())
    .add_plugins(ExamplePlugin)
    .run();
}

fn spawn_camera(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());
}

pub fn spawn_tilemap(mut commands: Commands) {
    let tilemap_entity = commands.spawn_empty().id();
    let map_size =  TilemapSize { x: 144, y: 144 };
    let mut tile_storage = TileStorage::empty(map_size);

    let tile_pos = TilePos { x: 0, y: 0 };

    let tile_entity = commands.spawn(TileBundle {
        position: tile_pos,
        tilemap_id: TilemapId(tilemap_entity),
        ..default()
    }).id();

    tile_storage.set(&tile_pos, tile_entity);

    commands.entity(tilemap_entity).insert(
        TilemapBundle {
            size: map_size,
            storage: tile_storage,
            tile_size: TilemapTileSize { x: 128.0, y: 128.0 },
            ..default()
        },
    );
}

pub struct ExamplePlugin;

impl Plugin for ExamplePlugin {
    fn build(&self, app: &mut App) {
    }

    fn finish(&self, app: &mut App) {
        if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
            render_app.add_systems(Render, test_system.in_set(RenderSet::Queue));
        }
    }
}

// IMPORTANT: need to have commands as an argument here or bug doesn't reproduce!
pub fn test_system(mut commands: Commands) {}

The crucial thing to note about the MRE is that test_system accepts mut commands: Commands but is otherwise empty. test_system is added to RenderApp in the set RenderSet::Queue.

The issue does not reproduce if I remove the unused argument.

I see that bevy-ecs-tilemap also inserts a system into the set RenderSet::Queue here: https://github.com/StarArawn/bevy_ecs_tilemap/blob/main/src/render/material.rs#L130

My assumption is that this bug relates to #9822 but only because I have awareness of this change and lack awareness of all changes made in Bevy 0.13.

Correct Output:
image

Incorrect Output:

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsA-RenderingDrawing game state to the screenC-BugAn unexpected or incorrect behaviorS-Needs-InvestigationThis issue requires detective work to figure out what's going wrong

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions