Skip to content

FrameTimeGraph, even disabled, crashes wasm on load (FrametimeGraphMaterial)Β #21362

@analytik

Description

@analytik

Bevy version and features

  • Bevy 0.17.1
  • Bevy CLI 0.1.0-alpha.2
  • default features plus bevy_dev_tools enabled

What I did + What went wrong

When adding FpsOverlayPlugin to a mostly-blank project, wasm builds break - that is, build completes, but throws an error in browser, and app doesn't show.

  • Using bevy run --release web --open -b --wasm-opt true
  • bug happens with/without wasm-opt, both dev/release
  • using Firefox stable, 143.0.3
  • commenting out whole bevy_dev_tools + the plugin fixes things
  • bug happens both when the graph part is turned on or off (i.e. FrameTimeGraphConfig { enabled: false, still triggers the bug
  • desktop (windows 10) build runs correctly with the graph turned on or off
  • When "forking" bevy_dev_tools locally and removing every mention of the graph, app runs correctly again in wasm
ERROR  Handling wgpu errors as fatal by default log.target = "wgpu::backend::wgpu_core";
log.module_path = "wgpu::backend::wgpu_core";
log.file = "C:\\Users\\redacted\\.cargo\\registry\\src\\index.crates.io-1949cf8c6b5b557f\\wgpu-26.0.1\\src\\backend\\wgpu_core.rs";
log.line = 1087;

panicked at C:\Users\redacted\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-26.0.1\src\backend\wgpu_core.rs:1087:26:
wgpu error: Validation Error

Caused by:
  In Device::create_bind_group_layout, label = 'FrametimeGraphMaterial'
    Binding 0 entry is invalid
      Downlevel flags DownlevelFlags(VERTEX_STORAGE) are required but not supported on the device.
This is not an invalid use of WebGPU: the underlying API or device does not support enough features to be a fully compliant implementation. A subset of the features can still be used. If you are running this program on native and not in a browser and wish to work around this issue, call Adapter::downlevel_properties or Device::downlevel_properties to get a listing of the features the current platform supports.



Stack:

__wbg_get_imports/imports.wbg.__wbg_new_8a6f238a6ece86ea@http://127.0.0.1:4000/build/katabevy4.js:1404:21
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[21430]:0x12168cb
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[42024]:0x143a2eb
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[5700]:0xc04e97
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[1039]:0x4acd97
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[3101]:0x9369f2
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[28542]:0x131f49c
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[62300]:0x14c01f7
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[2381]:0x82ddeb
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[545]:0x17ed37
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[777]:0x36577b
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[15170]:0x1076537
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[561]:0x1b8e34
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[2954]:0x904351
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[3278]:0x9733a4
@http://127.0.0.1:4000/build/katabevy4_bg.wasm:wasm-function[45470]:0x145c0fb
__wbg_adapter_6@http://127.0.0.1:4000/build/katabevy4.js:318:10
real@http://127.0.0.1:4000/build/katabevy4.js:261:20

The whole main.rs is mostly just copy-paste of the basic geometry shape example + framerate example.

use bevy::{
    dev_tools::fps_overlay::{FpsOverlayConfig, FpsOverlayPlugin, FrameTimeGraphConfig},
    prelude::*,
    text::FontSmoothing,
};

fn main() -> AppExit {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(FpsOverlayPlugin {
            config: FpsOverlayConfig {
                text_config: TextFont {
                    // Here we define size of our overlay
                    font_size: 42.0,
                    // If we want, we can use a custom font
                    font: default(),
                    // We could also disable font smoothing,
                    font_smoothing: FontSmoothing::default(),
                    ..default()
                },
                // We can also change color of the overlay
                text_color: Color::srgb_u8(10, 0, 1),
                // We can also set the refresh interval for the FPS counter
                refresh_interval: core::time::Duration::from_millis(100),
                enabled: true,
                frame_time_graph_config: FrameTimeGraphConfig {
                    enabled: false,
                    // The minimum acceptable fps
                    min_fps: 30.0,
                    // The target fps
                    target_fps: 60.0,
                },
            },
        })
        .insert_resource(GameData::new())
        .add_systems(Startup, setup)
        .add_systems(Update, on_update)
        .run()
}

const X_EXTENT: f32 = 1650.;

#[derive(Resource, Default)]
struct GameData {
    big_counter: u64,
    line_counter: u64,
}

impl GameData {
    pub fn new() -> Self {
        Self { ..default() }
    }
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    commands.spawn(Camera2d);

    let mut shapes = vec![];
    for _i in 0..600 {
        shapes.push(meshes.add(RegularPolygon::new(5.0, 4)));
    }
    
    let num_shapes = shapes.len();

    for (i, shape) in shapes.into_iter().enumerate() {
        let color = Color::oklch(0.25, 0.5, 360. * i as f32 / num_shapes as f32);
        commands.spawn((
            Mesh2d(shape),
            MeshMaterial2d(materials.add(color)),
            Transform::from_xyz(
                // Distribute shapes from -X_EXTENT/2 to +X_EXTENT/2.
                -X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * X_EXTENT,
                0.0,
                0.0,
            )
            .with_rotation(Quat::from_rotation_z(-0.5))
            .with_scale(Vec3::new(3.0, 500.0, 1.0)),
        ));
    }
}

fn on_update(
    mut gd: ResMut<GameData>,
    mut materials: ResMut<Assets<ColorMaterial>>,
    keyboard: Res<ButtonInput<KeyCode>>,
) {
    // first is probably background material
    let steps = materials.iter().count();
    if gd.big_counter == 0 {
        println!("Count of materials: {}", steps);
    }
    for i in 0..steps {
        let material_option = materials.iter_mut().nth(i);
        gd.line_counter += 1;
        if let Some(matt) = material_option {
            let hue: f32 = (155.0 + (gd.big_counter as f32 / 10.5) + (i as f32 / 24.0)) % 360.0;
            let light = 1.0_f32 - lfo_seesaw_norm_f32(gd.big_counter as u32, 950, 0.8)
                + lfo_seesaw_norm_f32(gd.line_counter as u32, 80000, 0.15)
                - ((i as f32) * 0.00025);
            let chrom = 0.05_f32 + lfo_seesaw_norm_f32(40_000 + gd.big_counter as u32, 2100, 0.7)
                - lfo_seesaw_norm_f32(gd.big_counter as u32, 1800, 0.4)
                + ((i as f32) * 0.00025);
            matt.1.color = Color::Oklcha(Oklcha::lch(light, chrom, hue));
        }
    }
    gd.big_counter += 1;
    if keyboard.just_pressed(KeyCode::Space) {
        println!("Space pressed {}", gd.big_counter);
    }
}

pub fn lfo_seesaw(n: u32, cycle: u32) -> u32 {
    let double_cycle = cycle * 2;
    let is_descending_or_peak = n % cycle < n % double_cycle;
    let is_peak = n % double_cycle == cycle;
    match (is_descending_or_peak, is_peak) {
        (true, false) => cycle - (n % (cycle)),
        (true, true) => cycle,
        (false, _) => n % cycle,
    }
}

pub fn lfo_seesaw_norm_f32(n: u32, cycle: u32, normalize: f32) -> f32 {
    let lfo = lfo_seesaw(n, cycle) as f32;
    lfo / cycle as f32 * normalize
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-Dev-ToolsTools used to debug Bevy applications.A-RenderingDrawing game state to the screenC-BugAn unexpected or incorrect behaviorO-WebSpecific to web (WASM) buildsP-CrashA sudden unexpected crashS-Needs-InvestigationThis issue requires detective work to figure out what's going wrong

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions