mirror of
https://github.com/visgl/luma.gl.git
synced 2025-12-08 17:36:19 +00:00
176 lines
5.4 KiB
Markdown
176 lines
5.4 KiB
Markdown
# Understanding Bindings
|
|
|
|
luma.gl offers support for setting up ("binding") data required by the GPU during shader execution, including:
|
|
- attribute buffers
|
|
- bindings (uniform buffers, textures, samplers, ...)
|
|
- uniforms
|
|
|
|
## Background
|
|
|
|
A key responsibility of any GPU framework is to make enable the application to
|
|
set up (or "bind") data so that it can be accessed by shader code running on the GPU.
|
|
|
|
Shaders contain declarations of external inputs such as attributes, uniform blocks, samplers etc.
|
|
Collectively, these inputs define data that the CPU (the application) needs to be provide to the GPU
|
|
(typically by "binding" data to the right "locations").
|
|
## Shader Layout
|
|
|
|
luma.gl needs a certain amount of metadata describing what bindings a specific shader (or pair of vertex and fragment shaders) expects.
|
|
|
|
luma.gl expects this metadata to be conform to the `ShaderLayout` type, and a `ShaderLayout`-conforming object
|
|
is required when creating a `RenderPipeline` or `ComputePipeline`.
|
|
Note that while `ShaderLayout`s must be created manually for WebGPU devices,
|
|
luma.gl can generate them automatically on WebGL devices (using WebGL program introspection APIs).
|
|
|
|
Shaders expose numeric bindings, however in applications, named bindings tend to be more convenient,
|
|
and the ShaderLayout does include information on both names, locations and formats.
|
|
|
|
|
|
```typescript
|
|
type ShaderLayout = {
|
|
attributes: {
|
|
{name: 'instancePositions', location: 0, format: 'float32x2', stepMode: 'instance'},
|
|
{name: 'instanceVelocities', location: 1, format: 'float32x2', stepMode: 'instance'},
|
|
{name: 'vertexPositions', location: 2, format: 'float32x2', stepMode: 'vertex'}
|
|
},
|
|
|
|
bindings: {
|
|
{name: 'projectionUniforms', location: 0, type: 'uniforms'},
|
|
{name: 'textureSampler', location: 1, type: 'sampler'},
|
|
{name: 'texture', location: 2, type: 'texture'}
|
|
}
|
|
}
|
|
|
|
device.createRenderPipeline({
|
|
layout,
|
|
attributes,
|
|
bindings
|
|
});
|
|
```
|
|
|
|
### Attribute Layout
|
|
|
|
```typescript
|
|
const shaderLayout: ShaderLayout = {
|
|
attributes: [
|
|
{name: 'instancePositions', location: 0, format: 'float32x2', stepMode: 'instance'},
|
|
{name: 'instanceVelocities', location: 1, format: 'float32x2', stepMode: 'instance'},
|
|
{name: 'vertexPositions', location: 2, format: 'float32x2', stepMode: 'vertex'}
|
|
],
|
|
...
|
|
};
|
|
```
|
|
|
|
### Buffer Mapping
|
|
|
|
For many use cases, supplying a single, "canonically" formatted buffer per attribute is sufficient.
|
|
However, sometimes an application may want to use more sophisticated GPU buffer layouts,
|
|
controlling GPU buffer offsets, strides, interleaving etc.
|
|
|
|
Buffer mapping is an optional feature enabling custom buffer layouts and buffer interleaving.
|
|
|
|
Note that buffer mappings need to be defined when a pipeline is created,
|
|
and all buffers subsequently supplied to that pipeline need to conform to the buffer mapping.
|
|
|
|
Example: The `bufferLayout` field in the example below specifies that both the
|
|
`instancePositions` and `instanceVelocities` attributes should be read from a single,
|
|
interleaved buffer. In this example, since no strides are provided, supplied buffers are assumed to be "packed",
|
|
with alternating "position" and "velocity" values with no padding in between.
|
|
|
|
```typescript
|
|
device.createRenderPipeline({
|
|
shaderLayout: {
|
|
attributes: [
|
|
{name: 'instancePositions', location: 0, format: 'float32x2', stepMode: 'instance'},
|
|
{name: 'instanceVelocities', location: 1, format: 'float32x2', stepMode: 'instance'},
|
|
{name: 'vertexPositions', location: 2, format: 'float32x2', stepMode: 'vertex'}
|
|
],
|
|
...
|
|
},
|
|
// We want to use "non-standard" buffers: two attributes interleaved in same buffer
|
|
bufferLayout: [
|
|
{name: 'particles', attributes: [
|
|
{name: 'instancePositions'},
|
|
{name: 'instanceVelocities'}
|
|
]
|
|
],
|
|
attributes: {
|
|
particles: device.createBuffer(...)
|
|
},
|
|
bindings: {}
|
|
});
|
|
```
|
|
|
|
## Model usage
|
|
|
|
```typescript
|
|
new Model(device, {
|
|
shaderLayout: {
|
|
attributes: {
|
|
instancePositions: {location: 0, format: 'float32x2', stepMode: 'instance'},
|
|
instanceVelocities: {location: 1, format: 'float32x2', stepMode: 'instance'},
|
|
vertexPositions: {location: 2, format: 'float32x2', stepMode: 'vertex'}
|
|
}
|
|
}
|
|
});
|
|
```
|
|
|
|
## Types
|
|
|
|
### `ShaderLayout`
|
|
|
|
```typescript
|
|
export type ShaderLayout = {
|
|
attributes: AttributeLayout[];
|
|
bindings: BindingLayout[];
|
|
}
|
|
```
|
|
|
|
### `AttributeLayout`
|
|
|
|
- name = `string`
|
|
- location - `number`
|
|
- format - `VertexFormat`
|
|
- stepMode - `'vertex' \| 'instance'`
|
|
|
|
|
|
## Advanced Example
|
|
|
|
WGSL vertex shader
|
|
|
|
```rust
|
|
struct Uniforms {
|
|
modelViewProjectionMatrix : mat4x4<f32>;
|
|
};
|
|
[[binding(0), group(0)]] var<uniform> uniforms : Uniforms; // BINDING 0
|
|
|
|
struct VertexOutput {
|
|
[[builtin(position)]] Position : vec4<f32>;
|
|
[[location(0)]] fragUV : vec2<f32>;
|
|
[[location(1)]] fragPosition: vec4<f32>;
|
|
};
|
|
|
|
[[stage(vertex)]]
|
|
fn main([[location(0)]] position : vec4<f32>,
|
|
[[location(1)]] uv : vec2<f32>) -> VertexOutput {
|
|
var output : VertexOutput;
|
|
output.Position = uniforms.modelViewProjectionMatrix * position;
|
|
output.fragUV = uv;
|
|
output.fragPosition = 0.5 * (position + vec4<f32>(1.0, 1.0, 1.0, 1.0));
|
|
return output;
|
|
}
|
|
```
|
|
|
|
WGSL Fragment Shader
|
|
|
|
```rust
|
|
[[group(0), binding(1)]] var mySampler: sampler; // BINDING 1
|
|
[[group(0), binding(2)]] var myTexture: texture_2d<f32>; // BINDING 2
|
|
|
|
[[stage(fragment)]]
|
|
fn main([[location(0)]] fragUV: vec2<f32>,
|
|
[[location(1)]] fragPosition: vec4<f32>) -> [[location(0)]] vec4<f32> {
|
|
return textureSample(myTexture, mySampler, fragUV) * fragPosition;
|
|
}
|
|
```
|