bevyengine / bevyengine/bevy

Compute World: a new world for GPGPU

Open
#8,440 3 comments 12 reactions 0 assignees View on GitHub
A-ECS A-Rendering C-Feature C-Performance
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

# Rethinking the way we handle Compute Shaders and GPGPU

_I understand that this is a very controversal topic. I think it might be a good idea to have an issue for us to discuss it and its design._

## The problem to solve

The use of compute shaders for massively parallel GPGPU (General-purpose computing on graphics processing units) algorithms or to speed up parts of rendering is more and more requested by game developers or graphics programmers in general.

Bevy's current API for compute shader is very much rendering centered and that makes it quite hard and boilerplaty to work with. In addition, it's also very hard to get data back from the GPU once your compute shader have finished running.

## What solution would you like?

I think there's quite a few way to improve the API for compute shaders some of them are the following:

**1.** Having a new World, namely GPGPU World of Compute World, running aside from App World and Render World, and being in charge of GPGPU algorithms. This would allow us to keep having a clear boundary between Render World and the two others. To show this, we can find of going from this:

![Current Worlds](https://user-images.githubusercontent.com/105886300/232919746-ab947d3c-ade4-4999-af83-a578539ad2bf.jpg)

to this:

![New Worlds](https://user-images.githubusercontent.com/105886300/232919745-c05c5364-0184-47a4-9b20-b6902d442642.jpg)

The `Inject` phase show above is mainly to emphasize on the fact that data is flowing from Compute World to App World. In practice, I think we can integrate this logic to `Extract`.

App World in frame N would have read access to data from Compute World N - 1 and can write for Compute World N + 1.

![Data Flow](https://user-images.githubusercontent.com/105886300/232919742-e1e52960-fded-4127-858a-a1d7d90c217f.jpg)

**2.** Being able to handle compute shader's logic from App World. (like I did in [bevy_app_compute](https://github.com/Kjolnyr/bevy_app_compute)) The main issue I see with this approach is that it's really hard to know where in the underlying WGPU queue we are injecting new `submit()` calls.

**3.** Keep the current Compute Shader implementation, but improve the API by using derive macros like `AsBindGroup` for example, and functions to handle it from App World. The main issue with this method, is to get data back from the GPU as we can only talk to Render World in the `Extract` phase.

for the last two options, we could imagine defining our Compute structs like that:

```rust
/// Extending the current `AsBindGroup` macro to support COPY_SRC + COPY_DST buffers and staging buffers
#[derive(AsBindGroup)]
struct MyCompute {
#[uniform(0)]
foo: f32,

/// we have CPU read access to bar
#[storage(1), staging]
bar: Vec,

/// We can copy from rw to other storage buffers
#[storage(2), copy_src]
rw: Velocity
}

/// Having a helper trait working like `Material`
impl Compute for MyCompute {
fn compute_shader() -> ShaderRef {
/// ...
}
/// Some more functions to configure our shader
}

```

Maybe we can also exploit `wgpu`'s reflection system in some way to be more flexible and dynamic about our compute shader logic since we don't have to make a layout necessarily, but I think that's to be discussed in another issue.

**I'm leaning toward option no. 1.**

### Known limitation

The current implementation of `wgpu` only has one interal queue for `submit()` calls. Therefore, we still have to know where and when to put our compute `submit()` calls, as they will run sequentially with the render queue. I know that `vulkan` has a separate compute queue, and I'm hoping that one day, `wgpu` will too. I just don't know how feasible / mature this multi-queue system is for other backends `wgpu` implements.

## What alternative(s) have you considered?

As written before, option 2. and 3. are the current alternatives.

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.