bevyengine / bevyengine/bevy

Allow user defined batches in `Query::par_iter_mut`

Open
#9,573 1 comment 2 reactions 0 assignees View on GitHub
A-ECS C-Usability
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## What problem does this solve or what need does it fill?
This would provide a functionality combination that is currently missing from the [Query Type](https://docs.rs/bevy/latest/bevy/ecs/prelude/struct.Query.html#)

- Accessing custom defined batches of Entities is possible currently via the `Query::(get_)many(_mut)` methods.
- Iterating over Query results in parallel is possible via `Query::par_iter(_mut)`
- There is some basic control over the batching via `QueryParIter::batching_strategy`

However, it is currently impossible to combine the features to allow parallel computation on multiple independent batches of entities.
## What solution would you like?
Extend the `Query` to allow paralellized iteration over user-defined batches.

I imagine something like this:
```rust
trait EntityBatch{
fn entities(&self)->Vec;
}

struct SomeBatchDef{
batches: [Entity;10],
}

impl EntityBatch for SomeBatchDef {
//[...]
}

fn system(mut some_query:Query<&mut XY>){

// just a bunch of batches (but this should allow batches of dynamic size, like `Query::iter_many`)
let batches:Vec = generate_batches();

some_query.par_iter_many_mut(
batches,
compute_batch
);
}

fn compute_batch(mut query:Query<&mut XY>,batch:SomeBatchDef) {
// here we can access the entities for the batch but also use Query::get() to get individual entities.
}
```
Its rather verbose, but offers the maximum level of flexibility I can think of.

### Considerations on Safety:
The batches must be non-overlapping, otherwise the mutable access is invalid. This should be checked by default (perhaps also have a unsafe `unchecked_par_iter_many_mut` method (oh boy, the name is getting long)).

### Ergonomics:
- internally, this should use the task pool managed by bevy.
- the function should get passed a `Query` struct and the current batch. Perhaps a dedicated trait (e.g. "EntityBatch") would be useful to pass an iterator of `EntityBatch` to have necessary information on the batch, while still keeping relevant information for the function to know which Entities to access.

## What alternative(s) have you considered?
Add a "grouping" feature to Queries that dispatches the same system multiple times for the different groups. This could then be parallelized by the default Query Scheduler. However I am not familiar enough with the internals to know if this is even possible.

```rust
#[derive(Debug,PartialEq)]
struct GroupingComponent(u8)

fn system(mut query:Query<&mut Component,_,GroupBy>)
```
## Additional context
I [asked on the Discord](https://discord.com/channels/691052431525675048/742569353878437978/1144226555296485386), but sadly got no answer, so I'm assuming there is currently no way to do this.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.