(pipeline-layout …)
Composes an ordered list of (bind-group-layout …)
into an explicit GPUPipelineLayout that a
(render-pipeline …) or
(compute-pipeline …) names as its
:layout instead of auto-deriving its layout from the WGSL.
This is the only way to bind @group(0), @group(1), … to distinct explicit
layouts, pinning per-group binding visibility and buffer-binding types that the
shader alone doesn’t determine. Otherwise a pipeline states :layout auto, whose
single implicit layout is inferred from shader usage.
Syntax
Section titled “Syntax”(pipeline-layout :name pl :bind-group-layouts [bgl0 bgl1])| Key | Type | Required | Description |
|---|---|---|---|
:name |
symbol | Yes | Unique pipeline-layout name |
:bind-group-layouts |
reference list | Yes | Declared (bind-group-layout …) names at @group 0, 1, … in order (at least one) |
Example
Section titled “Example”(shader-module :name mod :code """ @group(0) @binding(0) var<uniform> tint: vec4f; @group(1) @binding(0) var<uniform> xform: vec4f; @vertex fn vs() -> @builtin(position) vec4f { return vec4f(xform.xy, 0, 1); } @fragment fn fs() -> @location(0) vec4f { return tint; }""")
(buffer :name colorBuf :size 16 :usage [uniform copy-dst])(buffer :name xformBuf :size 16 :usage [uniform copy-dst])
(bind-group-layout :name bglColor (entry :binding 0 :visibility [fragment] (buffer :type uniform)))(bind-group-layout :name bglXform (entry :binding 0 :visibility [vertex] (buffer :type uniform)))
; @group(0) = bglColor, @group(1) = bglXform(pipeline-layout :name pl :bind-group-layouts [bglColor bglXform])
(render-pipeline :name pipe :layout pl (vertex :module mod :entry vs) (fragment :module mod :entry fs (target :format bgra8unorm)))
; Bind groups take their per-group layout from the pipeline:(bind-group :name gColor :layout pipe :group 0 (entry :binding 0 :buffer colorBuf))(bind-group :name gXform :layout pipe :group 1 (entry :binding 0 :buffer xformBuf)):layoutis one required key on both(render-pipeline …)and(compute-pipeline …), mirroringGPUPipelineDescriptorBase.layout, which is one required member. Its value is eitherautoor the name of a(pipeline-layout …), never both and never neither.autois read as the builtin wherever it appears, so a(pipeline-layout …)cannot claim that name. Declaring one is a located compile error.- A
:bind-group-layoutsentry must cross-reference a declared(bind-group-layout …); a dangling name is anot_cross_refvalidation error. - Bind groups reference the pipeline (
:layout pipe :group N), so each group resolves topipeline.getBindGroupLayout(N), the matching entry of the explicit layout. This is equivalent across the browser runtime, native wgpu, and the--htmlexport.
Validation Rules
Section titled “Validation Rules”| Rule | Error |
|---|---|
| Name must be unique across every form kind | located message, no code (see below) |
:bind-group-layouts is required |
missing_required_key |
:bind-group-layouts may not be empty |
vector_too_short |
| Each referenced bind-group-layout must exist | not_cross_ref |
A pipeline layout is its own cross-reference target: only a pipeline’s
:layout names one. (A (bind-group …) names a render pipeline, a compute
pipeline or a bind-group layout, which is why those three share a target group
and collide as duplicate_cross_ref_target.) A pipeline-layout name that
another form already uses, whatever its kind, is the compiler’s located
message with no code: duplicate name 'pipe': already declared as a (pipeline-layout …) at line 3.
WebGPU Mapping
Section titled “WebGPU Mapping”Maps to GPUPipelineLayout via:
const pl = device.createPipelineLayout({ bindGroupLayouts: [bgl0, bgl1], // @group 0, 1});const pipe = device.createRenderPipeline({ layout: pl, /* … */ });Related
Section titled “Related”(bind-group-layout …)- The composed layouts(render-pipeline …)- Names it as:layout(compute-pipeline …)- Names it as:layout(bind-group …)- Bind resources to the layout’s groups