Skip to content

Only one BindlessMaterial gets rendered at a time when sharing image handles. #18968

Open
@herbertgithubaccount

Description

@herbertgithubaccount

Bevy version

0.16

[Optional] Relevant system information

SystemInfo { os: "macOS 15.3.2 Sequoia", kernel: "24.3.0", cpu: "Apple M1 Pro", core_count: "10", memory: "16.0 GiB" }    
AdapterInfo { name: "Apple M1 Pro", vendor: 0, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "", backend: Metal }

Rust version: cargo 1.88.0-nightly (d811228b1 2025-04-15)

What you did

  • I tried to re-use the same texture handle in multiple BindlessMaterials.
  • This was done by modifying the setup function in the texture_binding_array example to:
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<BindlessMaterial>>,
    asset_server: Res<AssetServer>,
) {
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(0.0, 0.0, 20.0).looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
    ));

    // load 16 textures
    let textures: Vec<Handle<Image>> = TILE_ID
        .iter()
        .map(|id| asset_server.load(format!("textures/rpg/tiles/generic-rpg-tile{id:0>2}.png")))
        .collect();

    let original_material = materials.add(BindlessMaterial {
        textures: textures.clone(),
    });
    let mesh = meshes.add(Cuboid::default());

    const MAKE_NEW_MATERIAL: bool = true;

    for x in -3..=3 {
        for y in -3..=3 {
            let material = if MAKE_NEW_MATERIAL {
                // make a new material for each cube
                materials.add(BindlessMaterial {
                    textures: textures.clone(),
                })
            } else {
                // use the same material for all cubes
                original_material.clone()
            };
            commands.spawn((
                Mesh3d(mesh.clone()),
                MeshMaterial3d(material),
                Transform::from_xyz(x as f32, y as f32, -1.0),
            ));
        }
    }
}

What went wrong

  • Only one of the resulting meshes can be displayed a time. (See pictures.)
    • Moving the camera can change which of the meshes is visible, but only one is ever displayed at any given time.

Additional information

  • In the above code snippet, setting MAKE_NEW_MATERIAL = false results in all cubes being rendered consistently.
    • This makes me think that the bug is caused by different bindless materials using the same image handles.
  • This issue does not happen in Bevy 0.15. (All cubes are always displayed, regardless of what the value of MAKE_NEW_MATERIAL is.)
  • It's possible that this bug is specific to macOS.

Pictures

  • MAKE_NEW_MATERIAL = true:
    Only one cube is visible when MAKE_NEW_MATERIAL is true
  • MAKE_NEW_MATERIAL = true, with wireframe enabled:
    Only one cube is visible, wireframe indicates all cubes exist.
  • MAKE_NEW_MATERIAL = false:
    All cubes are visible when MAKE_NEW_MATERIAL is false

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-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