Skip to content
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
4 changes: 3 additions & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
[target.wasm32-unknown-unknown]
runner = "wasm-server-runner"
runner = "wasm-server-runner"
# Needed for getrandom/uuid: https://github.com/uuid-rs/uuid/issues/792
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']
6 changes: 3 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
sweep-cache: true

- name: Run clippy lints
run: SLANG_DIR=$SLANG_DIR cargo clippy --locked --workspace --all-targets -- --deny warnings
run: SLANG_DIR=$SLANG_DIR cargo clippy --locked --workspace --all-targets --features runtime -- --deny warnings

# Check documentation.
doc:
Expand Down Expand Up @@ -128,7 +128,7 @@ jobs:
sweep-cache: true

- name: Check documentation
run: SLANG_DIR=$SLANG_DIR cargo doc --locked --workspace --document-private-items --no-deps
run: SLANG_DIR=$SLANG_DIR cargo doc --locked --workspace --document-private-items --no-deps --features runtime
# Testing.
test:
needs: setup-slang # Depends on setup-slang
Expand Down Expand Up @@ -159,4 +159,4 @@ jobs:
sweep-cache: true
- name: Run Cargo Tests
run: |
SLANG_DIR=$SLANG_DIR cargo test --verbose
SLANG_DIR=$SLANG_DIR cargo test --verbose --features runtime
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ In order to compile and run any slang project, be sure to define the `SLANG_DIR`

**slang-hal** exposes a unified API for interacting with the GPU in a backend-agnostic way.

| Backend | Shader compilation | Compute pipelines | Render pipelines | Buffer read/write | Non-Pod types | Indirect dispatch | GPU timestamps | Link-time specialization |
|---------|--------------------|-------------------|------------------|---------------------|---------------|-------------------|----------------|------------------------|
| WebGpu | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Cuda | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ |
| Vulkan | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Metal | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| DirectX | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| CPU | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| PyTorch | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| OptiX | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| OpenCL | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Backend | Shader compilation | Compute pipelines | Render pipelines | Buffer read/write | Non-Pod types | Indirect dispatch | GPU timestamps | Link-time specialization | Comptime |
|---------|--------------------|-------------------|------------------|---------------------|---------------|-------------------|----------------|------------------------|----------|
| WebGpu | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| Cuda | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
| Vulkan | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Metal | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| DirectX | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| CPU | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| PyTorch | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| OptiX | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| OpenCL | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |

### Other features

Expand Down
2 changes: 1 addition & 1 deletion crates/minislang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "minislang"
authors = ["Sébastien Crozet <[email protected]>"]
description = "Small wrapper around the shader-slang binding"
repository = "https://github.com/dimforge/slang-hal"
version = "0.2.0"
version = "0.3.0"
edition = "2024"
license = "MIT OR Apache-2.0"

Expand Down
6 changes: 6 additions & 0 deletions crates/minislang/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ pub struct SlangCompiler {
tmp: TempDir,
}

impl Default for SlangCompiler {
fn default() -> Self {
Self::new(vec![])
}
}

pub struct SlangProgram {
#[allow(dead_code)]
session: shader_slang::Session,
Expand Down
13 changes: 13 additions & 0 deletions crates/slang-hal-build/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "slang-hal-build"
authors = ["Sébastien Crozet <[email protected]>"]
description = "Build script utilities for compile-time Slang shader compilation"
repository = "https://github.com/dimforge/slang-hal"
version = "0.3.0"
edition = "2024"
license = "MIT OR Apache-2.0"

[dependencies]
minislang = { version = "0.3", path = "../minislang" }
include_dir = "0.7"
walkdir = "2"
123 changes: 123 additions & 0 deletions crates/slang-hal-build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# slang-hal-build

Build script utilities for compile-time Slang shader compilation.

This crate provides utilities to compile Slang shaders at build time when using the `comptime` feature of `slang-hal`. This eliminates the need for runtime Slang compiler dependency, making it possible to:

- Deploy applications without bundling the Slang compiler
- Support WebAssembly targets
- Reduce application startup time
- Reduce binary dependencies

## Usage

### 1. Add dependencies to your `Cargo.toml`:

```toml
[dependencies]
slang-hal = { version = "0.2", features = ["derive", "comptime"] }

[build-dependencies]
slang-hal-build = "0.2"
```

### 2. Create a `build.rs` file:

```rust
use slang_hal_build::ShaderCompiler;
use std::env;

fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create shader compiler with output directory
let out_dir = env::var("OUT_DIR")?;
let mut compiler = ShaderCompiler::new(vec![], out_dir);

// Optional: Add shader include directories
const SHADER_DIR: include_dir::Dir<'_> =
include_dir::include_dir!("$CARGO_MANIFEST_DIR/shaders");
compiler.add_dir(SHADER_DIR);

// Compile your shaders
// The shader path should be relative to CARGO_MANIFEST_DIR
compiler.compile_shader("shaders/add.slang", "add_assign", &[])?;

// With link-time specialization:
// compiler.compile_shader("shaders/matmul.slang", "matmul", &["specialization::module".to_string()])?;

Ok(())
}
```

### 3. Use the shaders in your code:

```rust
use slang_hal::{Shader, backend::WebGpu};
use slang_hal::function::GpuFunction;
use minislang::SlangCompiler;

#[derive(Shader)]
#[shader(module = "add")]
pub struct GpuAdd<B: Backend> {
add_assign: GpuFunction<B>,
}

#[async_std::main]
async fn main() {
let backend = WebGpu::default().await.unwrap();

// When comptime is enabled, the compiler parameter is not used
// (but still required for API compatibility)
let compiler = SlangCompiler::new(vec![]);

// The shader is loaded from precompiled data embedded in the binary
let add = GpuAdd::from_backend(&backend, &compiler).unwrap();

// Use the shader as normal...
}
```

## How It Works

1. **Build Time**: The build script compiles shaders for all enabled backends (WebGPU, Metal, Vulkan, CUDA, CPU) based on your Cargo features.

2. **Generated Files**: For each shader entry point, the build script generates:
- Compiled shader source or bytecode (`.wgsl`, `.metal`, `.spv`, `.ptx`, `.dll`)
- Reflection metadata (Rust source files with shader parameter info)

3. **Compile Time**: The `#[derive(Shader)]` macro generates code that uses `include_bytes!()` and `include!()` to embed the precompiled shader data directly into your binary.

4. **Runtime**: Shaders are loaded instantly from embedded data, with no need to invoke the Slang compiler.

## Backend-Specific Compilation

The build script automatically compiles shaders only for backends enabled via Cargo features:

```toml
[dependencies]
slang-hal = { version = "0.2", features = ["derive", "comptime", "metal", "vulkan"] }
```

This will compile shaders for WebGPU (default), Metal, and Vulkan, but not CUDA or CPU.

## Limitations

- **No runtime specialization**: When `comptime` is enabled, you cannot use runtime shader specialization via `Shader::with_specializations()`. Link-time specialization specified in the `#[shader(specialize = [...])]` attribute is still supported.

- **Larger binaries**: Since shader bytecode for all enabled backends is embedded in the binary, this increases binary size compared to runtime compilation.

- **Longer compile times**: Shaders are compiled during your project's build process, which increases build time.

## WebAssembly Support

The primary motivation for the `comptime` feature is to enable WebAssembly support. The Slang compiler has native dependencies that are difficult to compile for WASM targets. With `comptime`, your WASM binary contains only the precompiled WGSL shaders, eliminating the need for the Slang compiler at runtime.

```toml
[dependencies]
slang-hal = { version = "0.2", features = ["derive", "comptime"] }
```

Then build for WASM:

```bash
cargo build --target wasm32-unknown-unknown
```
Loading
Loading