Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Mar 1, 2024
1 parent 64ebd52 commit 3d6c289
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 112 deletions.
111 changes: 111 additions & 0 deletions docs/api-reference/engine/computation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Computation

The `Computation` class is a high-level class in the luma.gl API. It brings together all GPU functionality needed to run GPU compute shaders, in a single, easy-to-use interface.

`Computation` manages the following responsibilities:
- **bindings** these can reference textures and uniform buffers
- **shader module injection**
- **shader transpilation****
- **debugging** - Detailed debug logging of draw calls

The `Computation` class integrates with
- The `@luma.gl/shadertools` shader module system: [see `Shader Assembly`]( /docs/api-reference/shadertools/shader-assembler).

## Usage

```typescript
import {Computation} from `@luma.gl/engine`;
```

One of the simplest way to provide attribute data is by using a Geometry object.

Create model object by passing shaders, uniforms, geometry and render it by passing updated uniforms.

```typescript
import {Computation} from `@luma.gl/engine`;
// construct the model.
const model = new Computation(device, {
source: COMPUTE_SHADER,
bindings: {
uSampler: texture
},
})
```

### Provide attribute data using Buffer

When using `Buffer` objects, data remains on GPU and same `Buffer` object can be shared between multiple models.

```typescript
// construct the model.
const model = new Computation(device, {
source: COMPUTE_SHADER,
attributes: {
attributeName1: bufferObject,
attributeName2: device.createBuffer(new Float32Array(...))
},
uniforms: {uSampler: texture},
})
```

On each frame, call the `model.draw()` function after updating any uniforms (typically matrices).

```ts
model.setUniforms({
uPMatrix: currentProjectionMatrix,
uMVMatrix: current ComputationViewMatrix
});
model.draw();
```

Debug shader source (even when shader successful)
```ts
// construct the model.
const model = new Computation(device, {
source: COMPUTE_SHADER,
debugShaders: true
});
```

## Types

### `ComputationProps`

| Property | Type | Description |
| ------------------ | ---------------------------------------------- | --------------------------------------------------------------------------------- |
| `source` | `Shader` \| _string_ | A vertex shader object, or source as a string. |
| `modules` | | shader modules to be applied (shadertools). |
| `pipelineFactory?` | | `PipelineFactory` to use for program creation and caching. |
| `debugShaders?` | `'error' \| 'never' \| 'warnings' \| 'always'` | Specify in what triggers the display shader compilation log (default: `'error'`). |

`ComputationProps` also include `ComputePipelineProps`, which are passed through to the `ComputePipeline` constructor, e.g:

| Property | Type | Description |
| ----------------- | -------------------------- | --------------------------------------------------------------------------------------- |
| `layout` | `ShaderLayout` | Describes how shader attributes and bindings are laid out. |
| `bindings?` | `Record<string, any>` | |


## Fields

### `pipeline: ComputePipeline`

The model's `ComputePipeline` instance

## Methods

### `constructor(device: Device, props: ComputationProps)`

The constructor for the Computation class. Use this to create a new Computation.

### `destroy(): void`

Free GPU resources associated with this model immediately, instead of waiting for garbage collection.

### `dispatch(pass: ComputePass, x, y, z)`

Renders the model with provided uniforms, attributes and samplers

```typescript
computation.dispatch(computePass, 1);
```
1 change: 1 addition & 0 deletions docs/sidebar.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
"api-reference/engine/model",
"api-reference/engine/pipeline-factory",
"api-reference/engine/shader-factory",
"api-reference/engine/computation",
"api-reference/engine/transform",
"api-reference/engine/transform/buffer-transform",
"api-reference/engine/transform/texture-transform",
Expand Down
5 changes: 3 additions & 2 deletions docs/whats-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ To accelerate WebGPU development, luma.gl v9 drops support for legacy functional

**`@luma.gl/engine`**

- NEW: Scenegraph classes: `ModelNode`, `GroupNode`, `ScenegraphNode`. (Moved from `@luma.gl/experimental`).
- NEW: Scenegraph classes: `ModelNode`, `GroupNode`, `ScenegraphNode`, moved from `@luma.gl/experimental`.
- NEW: `ShaderInputs` - Class that manages uniform buffers for a `Model`
- NEW: `ShaderFactory` - Creates and caches reusable `Shader` resources
- NEW: `AnimationLoopTemplate` - Small helper class that can help write cleaner demos and applications in TypeScript.
- NEW: `AnimationLoopTemplate` - Helper class for writing cleaner demos and applications in TypeScript.
- New `Computation` - Class that manages a `ComputePipeline` similar to `Model` and `Transform`.

**`@luma.gl/gltf`**

Expand Down
8 changes: 7 additions & 1 deletion modules/core/src/adapter/resources/compute-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Copyright (c) vis.gl contributors

import {Resource, ResourceProps} from './resource';
import type {ComputeShaderLayout} from '../types/shader-layout';
import type {ComputeShaderLayout, Binding} from '../types/shader-layout';
import type {Device} from '../device';
import type {Shader} from './shader';

Expand Down Expand Up @@ -43,4 +43,10 @@ export abstract class ComputePipeline extends Resource<ComputePipelineProps> {
constructor(device: Device, props: ComputePipelineProps) {
super(device, props, ComputePipeline.defaultProps);
}

/**
* @todo Use renderpass.setBindings() ?
* @todo Do we want to expose BindGroups in the API and remove this?
*/
abstract setBindings(bindings: Record<string, Binding>): void;
}
26 changes: 13 additions & 13 deletions modules/engine/src/computation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class Computation {
private _destroyed = false;

constructor(device: Device, props: ComputationProps) {
if (this.device.info.type !== 'webgpu') {
if (device.info.type !== 'webgpu') {
throw new Error('Computation is only supported in WebGPU');
}

Expand Down Expand Up @@ -160,7 +160,7 @@ export class Computation {
destroy(): void {
if (this._destroyed) return;
this.pipelineFactory.release(this.pipeline);
this.shaderFactory.release(this.pipeline.shader);
this.shaderFactory.release(this.shader);
this._uniformStore.destroy();
this._destroyed = true;
}
Expand All @@ -182,7 +182,9 @@ export class Computation {

// Set pipeline state, we may be sharing a pipeline so we need to set all state on every draw
// Any caching needs to be done inside the pipeline functions
// this.pipeline.setBindings(this.bindings);
this.pipeline.setBindings(this.bindings);
computePass.setPipeline(this.pipeline);
// @ts-expect-error
computePass.setBindings([]);

computePass.dispatch(x, y, z);
Expand Down Expand Up @@ -263,23 +265,21 @@ export class Computation {
1,
`Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`
)();
prevShader = this.pipeline.shader;
prevShader = this.shader;
}

this._pipelineNeedsUpdate = false;

const shader = this.shader
? this.shaderFactory.createShader({
id: `${this.id}-fragment`,
stage: 'compute',
source: this.source,
debug: this.props.debugShaders
})
: null;
this.shader = this.shaderFactory.createShader({
id: `${this.id}-fragment`,
stage: 'compute',
source: this.source,
debug: this.props.debugShaders
});

this.pipeline = this.pipelineFactory.createComputePipeline({
...this.props,
shader
shader: this.shader
});

if (prevShader) {
Expand Down
6 changes: 6 additions & 0 deletions modules/shadertools/src/lib/shader-assembly/select-shaders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export type AssembleShaderProps = Omit<AssembleShaderOptions, 'vs' | 'fs'> & {
* @returns
*/
export function selectShaders(props: AssembleShaderProps): AssembleShaderOptions {
// If we have a source field, we have a single unified shader source
if (props.source) {
const propsCopy: AssembleShaderOptions = {...props, vs: undefined, fs: undefined};
return propsCopy;
}

if (!props.vs) {
throw new Error('no vertex shader');
}
Expand Down
Loading

0 comments on commit 3d6c289

Please sign in to comment.