Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port the high-level Blade engine from RayCraft #62

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,34 +40,44 @@ readme = "docs/README.md"
[features]

[dependencies]
blade-asset = { version = "0.2.0", path = "blade-asset" }
blade-egui = { version = "0.2.0", path = "blade-egui" }
blade-macros = { version = "0.2.1", path = "blade-macros" }
blade-graphics = { version = "0.3.0", path = "blade-graphics" }
blade-render = { version = "0.2.0", path = "blade-render" }
blade-asset = { version = "0.2", path = "blade-asset" }
blade-egui = { version = "0.2", path = "blade-egui" }
blade-graphics = { version = "0.3", path = "blade-graphics" }
blade-render = { version = "0.2", path = "blade-render" }
choir = { workspace = true }
colorsys = "0.6"
egui = { workspace = true }
nalgebra = { version = "0.32", features = ["mint"] }
log = { workspace = true }
mint = { workspace = true, features = ["serde"] }
num_cpus = "1"
profiling = { workspace = true }
rapier3d = { version = "0.17", features = ["debug-render"] }
serde = { version = "1", features = ["serde_derive"] }
slab = "0.4"
strum = { workspace = true }
winit = "0.28"

[dev-dependencies]
blade-macros = { version = "0.2", path = "blade-macros" }
bytemuck = { workspace = true }
choir = { workspace = true }
egui = { workspace = true }
del-msh = "0.1"
egui-gizmo = "0.12"
egui_plot = "0.23"
egui-winit = "0.23"
env_logger = "0.10"
# https://github.com/nobuyuki83/del-msh/issues/1
del-msh = "=0.1.17"
glam = { workspace = true }
log = { workspace = true }
mint = { workspace = true, features = ["serde"] }
naga = { workspace = true }
nanorand = { version = "0.7", default-features = false, features = ["wyrand"] }
num_cpus = "1"
profiling = { workspace = true }
ron = "0.8"
serde = { version = "1", features = ["serde_derive"] }
strum = { workspace = true }
winit = "0.28"

[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
egui-winit = "0.23"
egui_plot = "0.23"
egui-gizmo = "0.12"
env_logger = "0.10"

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
console_error_panic_hook = "0.1.7"
Expand Down
3 changes: 3 additions & 0 deletions blade-asset/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Blade Asset Pipeline

[![Docs](https://docs.rs/blade-asset/badge.svg)](https://docs.rs/blade-asset)
[![Crates.io](https://img.shields.io/crates/v/blade-asset.svg?maxAge=2592000)](https://crates.io/crates/blade-asset)

This is an abstract library for defininig the pipeline of asset processing.
It's tightly integrated with [Choir](https://github.com/kvark/choir) but otherwise doesn't know about GPUs and such.

Expand Down
20 changes: 20 additions & 0 deletions blade-egui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Blade EGUI

[![Docs](https://docs.rs/blade-egui/badge.svg)](https://docs.rs/blade-egui)
[![Crates.io](https://img.shields.io/crates/v/blade-egui.svg?maxAge=2592000)](https://crates.io/crates/blade-egui)

[EGUI](https://www.egui.rs/) support for [Blade-graphics](https://crates.io/crates/blade-graphics).

![scene editor](etc/scene-editor.jpg)

## Instructions

Just the usual :crab: workflow. E.g. to run the bunny-mark benchmark run:
```bash
cargo run --release --example bunnymark
```

## Platforms

The full-stack Blade Engine can only run on Vulkan with hardware Ray Tracing support.
However, on secondary platforms, such as Metal and GLES/WebGL2, one can still use Blde-Graphics and Blade-Egui.
File renamed without changes
52 changes: 52 additions & 0 deletions blade-graphics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Blade Graphics

[![Docs](https://docs.rs/blade-graphics/badge.svg)](https://docs.rs/blade-graphics)
[![Crates.io](https://img.shields.io/crates/v/blade-graphics.svg?maxAge=2592000)](https://crates.io/crates/blade-graphics)

Blade-graphics is a lean and mean [GPU abstraction](https://youtu.be/63dnzjw4azI?t=623) aimed at ergonomics and fun. See [motivation](etc/motivation.md), [FAQ](etc/FAQ.md), and [performance](etc/performance.md) for details.

## Examples

![ray-query example](etc/ray-query.gif)
![particles example](etc/particles.png)

## Platforms

The backend is selected automatically based on the host platform:
- *Vulkan* on desktop Linux, Windows, and Android
- *Metal* on desktop macOS, and iOS
- *OpenGL ES3* on the Web

| Feature | Vulkan | Metal | GLES |
| ------- | ------ | ----- | ---- |
| compute | :white_check_mark: | :white_check_mark: | |
| ray tracing | :white_check_mark: | | |

### OpenGL ES

GLES is also supported at a basic level. It's enabled for `wasm32-unknown-unknown` target, and can also be force-enabled on native:
```bash
RUSTFLAGS="--cfg gles" CARGO_TARGET_DIR=./target-gl cargo test
```

This path can be activated on all platforms via Angle library.
For example, on macOS it's sufficient to place `libEGL.dylib` and `libGLESv2.dylib` in the working directory.

### WebGL2

Following command will start a web server offering the `bunnymark` example:
```bash
cargo run-wasm --example bunnymark
```

### Vulkan Portability

First, ensure to load the environment from the Vulkan SDK:
```bash
cd /opt/VulkanSDK && source setup-env.sh
```

Vulkan backend can be forced on using "vulkan" config flag. Example invocation that produces a vulkan (portability) build into another target folder:
```bash
RUSTFLAGS="--cfg vulkan" CARGO_TARGET_DIR=./target-vk cargo test
```
44 changes: 22 additions & 22 deletions docs/FAQ.md → blade-graphics/etc/FAQ.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# Frequency Asked Questions

## When should I *not* use Blade?

- When you *target the Web*. Blade currently has no Web backends supported. Targeting WebGPU is desired, but will not be as performant as native.
- Similarly, when you target the *low-end GPUs* or old drivers. Blade has no OpenGL/D3D11 support, and it requires fresh drivers on Vulkan.
- When you render with 10K or *more draw calls*. State switching has overhead with Blade, and it is lower in GPU abstractions/libraries that have barriers and explicit bind groups.
- When you need something *off the shelf*. Blade is experimental and young, it assumes you'll be customizing it.

## Why investing into this when there is `wgpu`?

`wgpu` is becoming a standard solution for GPU access in Rust and beyond. It's wonderful, and by any means just use it if you have any doubts. It's a strong local maxima in a chosen space of low-level portability. It may very well be the global maxima as well, but we don't know this until we explore the *other* local maximas. Blade is an attempt to strike where `wgpu` can't reach, it makes a lot of the opposite design solutions. Try it and see.

## Isn't this going to be slow?

Blade creating a descriptor set (in Vulkan) for each draw call. It doesn't care about pipeline compatibility to preserve the bindings. How is this fast?

Short answer is - yes, it's unlikely going to be faster than wgpu-hal. Long answer is - slow doesn't matter here.

Take a look at Vulkan [performance](performance.md) numbers. wgpu-hal can get 60K bunnies on a slow machine, which is pretty much the maximum. Both wgpu and blade can reach about 20K. Honestly, if you are relying on 20K unique draw calls being fast, you are in a strange place. Generally, developers should switch to instancing or other batching methods whenever the object count grows above 100, not to mention a 1000.

Similar reasoning goes to pipeline switches. If you are relying on many pipeline switches done efficiently, then it's good to reconsider your shaders, perhaps turning into the megashader alley a bit. In D3D12, a pipeline change requires all resources to be rebound anyway (and this is what wgpu-hal/dx12 does regardless of the pipeline compatibility), so this is fine in Blade.
# Frequency Asked Questions
## When should I *not* use Blade?
- When you *target the Web*. Blade currently has no Web backends supported. Targeting WebGPU is desired, but will not be as performant as native.
- Similarly, when you target the *low-end GPUs* or old drivers. Blade has no OpenGL/D3D11 support, and it requires fresh drivers on Vulkan.
- When you render with 10K or *more draw calls*. State switching has overhead with Blade, and it is lower in GPU abstractions/libraries that have barriers and explicit bind groups.
- When you need something *off the shelf*. Blade is experimental and young, it assumes you'll be customizing it.
## Why investing into this when there is `wgpu`?
`wgpu` is becoming a standard solution for GPU access in Rust and beyond. It's wonderful, and by any means just use it if you have any doubts. It's a strong local maxima in a chosen space of low-level portability. It may very well be the global maxima as well, but we don't know this until we explore the *other* local maximas. Blade is an attempt to strike where `wgpu` can't reach, it makes a lot of the opposite design solutions. Try it and see.
## Isn't this going to be slow?
Blade creating a descriptor set (in Vulkan) for each draw call. It doesn't care about pipeline compatibility to preserve the bindings. How is this fast?
Short answer is - yes, it's unlikely going to be faster than wgpu-hal. Long answer is - slow doesn't matter here.
Take a look at Vulkan [performance](performance.md) numbers. wgpu-hal can get 60K bunnies on a slow machine, which is pretty much the maximum. Both wgpu and blade can reach about 20K. Honestly, if you are relying on 20K unique draw calls being fast, you are in a strange place. Generally, developers should switch to instancing or other batching methods whenever the object count grows above 100, not to mention a 1000.
Similar reasoning goes to pipeline switches. If you are relying on many pipeline switches done efficiently, then it's good to reconsider your shaders, perhaps turning into the megashader alley a bit. In D3D12, a pipeline change requires all resources to be rebound anyway (and this is what wgpu-hal/dx12 does regardless of the pipeline compatibility), so this is fine in Blade.
Loading
Loading