Skip to content

bevy async compute broke by MSAA in 0.15, 0.16, and 0.17 #20355

@Saratii

Description

@Saratii

Bevy version

0.14.1 and 0.16.1

[Optional] Relevant system information

8 core processor

What you did

I copied the unofficial example from here. https://bevy-cheatbook.github.io/fundamentals/async-compute.html
I found that it didnt actually work. I minimized it to the provided file down below and it still didn't work. I then copied the official example and the only thing i had to change to break it was adding a camera

In every scenerio described the main thread hangs itself and the app crashes. I believe this is due to the weird programming going on in the bevy TaskPool or including the main thread in the compute thread pool which allows it no CPU time when I create expensive computations.

What went wrong

I expect bevy async compute to not block main and not hang the app.

Additional information

Image Here is minimal code that breaks the unoffical example
use bevy::prelude::*;
use bevy::tasks::{AsyncComputeTaskPool, Task, TaskPoolBuilder};
use std::collections::HashMap;

#[derive(Resource, Default)]
struct MyMapGenTasks {
    generating_chunks: HashMap<usize, Task<()>>,
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .insert_resource(MyMapGenTasks::default())
        .add_systems(Startup, setup)
        .add_systems(Update, begin_generating_map_chunks)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera3d::default());
    AsyncComputeTaskPool::get_or_init(|| {
        TaskPoolBuilder::new()
            .num_threads(2)
            .stack_size(16 * 1024 * 1024)
            .build()
    });
}

fn generate_map_chunk() {
    let mut sum = 0.0;
    for j in 1..u32::MAX {
        sum += (j as f32).sin().cos().tan().sqrt() + j as f32 * 0.0001;
    }
    println!("sum: {}", sum);
}

fn begin_generating_map_chunks(mut my_tasks: ResMut<MyMapGenTasks>) {
    let task_pool: &'static AsyncComputeTaskPool = AsyncComputeTaskPool::get();
    for chunk_coord in 0..1000 {
        if my_tasks.generating_chunks.contains_key(&chunk_coord) {
            continue;
        }
        let task = task_pool.spawn(async move { generate_map_chunk() });
        my_tasks.generating_chunks.insert(chunk_coord, task);
    }
}```



And there is code replacement that breaks the official example
```rs
// Pretend this is a time-intensive function. :)
                    async fn generate_map_chunk() {
                        let mut sum = 0.0;
                        for j in 1..u32::MAX {
                            sum += (j as f32).sin().cos().tan().sqrt() + j as f32 * 0.0001;
                        }
                        println!("sum: {}", sum);
                    }
                    generate_map_chunk().await;``` 
(i also tried a non async generate_map_chunk function. 

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-TasksTools for parallel and async workC-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