Bind Groups
A bind group is a collection of resources that are bound to a shader. These resources can be buffers, textures, or samplers. It’s a way to define what resources are available to a shader and how they are accessed.
import tgpu from 'typegpu';import * as d from 'typegpu/data';
// Defining the layout of resources we want the shader to// have access to.const fooLayout = tgpu.bindGroupLayout({ foo: { uniform: d.vec3f }, bar: { texture: 'float' },});
const fooBuffer = ...;const barTexture = ...;
// Create a bind group that can fulfill the required layout.const fooBindGroup = root.createBindGroup(fooLayout, { foo: fooBuffer, bar: barTexture,});
In this example, we create a bind group that contains a buffer and a texture. Binding indices are determined based on the order of properties in the layout.
Now, during command encoding, we can assign this bind group to a shader.
// Assuming group index is 0...pass.setBindGroup(0, root.unwrap(fooBindGroup));
Available resource types
Each property in the layout object represents a resource as seen by a shader. We recommend keeping the names of
these properties the same as the corresponding @group(...) @binding(...) ...;
statements in WGSL.
const fooLayout = tgpu.bindGroupLayout({ key0: { ... }, key1: { ... }, // ...});
Uniforms
To interpret a buffer as a uniform, create a property with the value matching:
{ uniform: d.AnyData;}
Simple example
const fooLayout = tgpu.bindGroupLayout({ luckyNumber: { uniform: d.f32 }, // ...});
Matching WGSL statement:
@group(...) @binding(0) var<uniform> luckyNumber: f32;// ...
Storage
To get readonly/mutable access to a buffer, create a property with the value matching:
{ storage: d.AnyData | ((n: number) => d.AnyData);
/** @default 'readonly' */ access?: 'readonly' | 'mutable';}
Simple example
const fooLayout = tgpu.bindGroupLayout({ counter: { storage: d.f32, access: 'mutable' }, // ...});
Matching WGSL statement:
@group(...) @binding(0) var<storage, read_write> counter: f32;// ...
Runtime-sized example
Apart from being able to specify any data type, we can signal that the shader is generalized to work on arbitrarily sized data by passing a function.
const Filter = (n: number) => d.struct({ clamp: d.f32, values: d.arrayOf(d.f32, n), });
const fooLayout = tgpu.bindGroupLayout({ factors: { storage: (n: number) => d.arrayOf(d.f32, n) }, filter: { storage: Filter }, // ...});
Matching WGSL code:
struct Filter { clamp: f32, values: array<f32>;}
@group(...) @binding(0) var<storage, read> factors: array<f32>;@group(...) @binding(1) var<storage, read> filter: Filter;// ...
Samplers
Samplers can be made accessible to shaders with a property that matches the following:
{ sampler: 'filtering' | 'non-filtering' | 'comparison';}
Textures
To be able to sample a texture in a shader, create a property with the value matching:
{ texture: 'float' | 'unfilterable-float' | 'depth' | 'sint' | 'uint';
/** @default '2d' */ viewDimension?: '1d' | '2d' | '2d-array' | 'cube' | 'cube-array' | '3d';
/** @default false */ multisampled?: boolean;}
Storage Textures
To be able to operate on textures more directly in a shader, create a property with the value matching:
{ storageTexture: StorageTextureTexelFormat;
/** @default 'writeonly' */ access?: 'readonly' | 'writeonly' | 'mutable';
/** @default '2d' */ viewDimension?: '1d' | '2d' | '2d-array' | '3d';}
You can see the list of supported storage texture formats here.
Bind Groups
Before execution of a pipeline, any bind group that matches a given layout can be put in its place and used by the shader.
To create a bind group, you can call the createBindGroup
method on the root object and associate each named key with
a proper resource.
const fooLayout = tgpu.bindGroupLayout({ key0: { ... }, key1: { ... }, // ...});
const fooBindGroup0 = root.createBindGroup(fooLayout, { key1: ..., key0: ..., // ...});
const fooBindGroup1 = root.createBindGroup(fooLayout, { key0: ..., key1: ..., // ...});
// ...
If you accidentally pass the wrong type of resource, the TypeScript compiler will catch the error at compile time.
- Uniform bindings with schema
TData
accept:TgpuBuffer<TData> & UniformFlag
- buffers of typeTData
with'uniform'
usage,GPUBuffer
- raw WebGPU buffers.
- Storage bindings with schema
TData
accept:TgpuBuffer<TData> & StorageFlag
- buffers of typeTData
with'storage'
usage,GPUBuffer
- raw WebGPU buffers.
- Texture bindings:
GPUTextureView
- views of raw WebGPU textures.
- Storage Texture bindings:
GPUTextureView
- views of raw WebGPU textures.
- Sampler bindings:
sampler === 'comparison'
GPUSampler
- raw WebGPU samplers created with acompare
function.
sampler === 'filtering'
orsampler === 'non-filtering'
GPUSampler
- raw WebGPU samplers created without acompare
function.