Start · Sprachen · JavaScript · Referenz · GPUDevice.createPipelineLayout()

GPUDevice.createPipelineLayout()

Methode

Erstellt ein <code>GPUPipelineLayout</code>, das festlegt, welche <code>GPUBindGroupLayout</code>-Objekte eine Render- oder Compute-Pipeline an welchen Gruppen-Indizes erwartet.

seit JavaScript WebGPU – Chrome/Edge 113+, Safari 26+, Firefox 141 Kategorie: webapi

Signatur

GPUDevice.prototype.createPipelineLayout(descriptor)

Beschreibung

createPipelineLayout() erzeugt ein explizites Pipeline-Layout. Es beschreibt die Schnittstelle zwischen Shader-Ressourcen und Pipeline: Das Array bindGroupLayouts ordnet jedem @group(n)-Index im WGSL-Shader ein GPUBindGroupLayout zu. Das Ergebnis übergibt man anschließend als layout-Eigenschaft an createRenderPipeline() oder createComputePipeline().

Alternativ kann man layout: "auto" verwenden; dann leitet WebGPU das Layout aus dem Shader ab. Das ist bequem, hat aber einen Nachteil: Automatisch erzeugte Bind-Group-Layouts sind an genau eine Pipeline gebunden, und Bind Groups lassen sich nicht zwischen Pipelines teilen. Ein explizites Layout lohnt sich daher immer, wenn mehrere Pipelines dieselben Bind Groups nutzen sollen (z. B. eine gemeinsame Kamera-/Szenen-Gruppe an @group(0)), oder wenn Ressourcen eingebunden werden, die der Shader aktuell gar nicht verwendet.

Die Methode arbeitet synchron und liefert sofort ein Objekt zurück. Validierungsfehler (etwa zu viele Bind Groups oder Überschreitung der Geräte-Limits) werfen keine Ausnahme, sondern erzeugen einen GPU-Validierungsfehler und ein ungültiges Layout. Solche Fehler fängt man mit pushErrorScope()/popErrorScope() oder dem uncapturederror-Ereignis ab.

Parameter

Name Typ Default Beschreibung
$descriptor Pflicht GPUPipelineLayoutDescriptor Konfigurationsobjekt mit den folgenden Eigenschaften.
$descriptor.bindGroupLayouts Pflicht Array<GPUBindGroupLayout | null> Liste der Bind-Group-Layouts; der Array-Index entspricht dem @group(n)-Index im Shader. Die Länge darf device.limits.maxBindGroups (mindestens 4) nicht überschreiten. Neuere Implementierungen erlauben null-Einträge für ungenutzte Gruppen.
$descriptor.label string "" Optionaler Name zur Identifikation in Fehlermeldungen und Debugging-Werkzeugen.

Rückgabewert

Typ
GPUPipelineLayout
Beschreibung
Ein neues GPUPipelineLayout-Objekt, das als layout an createRenderPipeline(), createRenderPipelineAsync(), createComputePipeline() oder createComputePipelineAsync() übergeben wird.

Beispiele

Compute-Pipeline mit explizitem Layout

const adapter = await navigator.gpu?.requestAdapter();
if (!adapter) throw new Error('WebGPU wird nicht unterstützt');
const device = await adapter.requestDevice();

const shader = device.createShaderModule({
  code: `
    @group(0) @binding(0) var<storage, read_write> data: array<f32>;
    @compute @workgroup_size(64)
    fn main(@builtin(global_invocation_id) id: vec3u) {
      if (id.x < arrayLength(&data)) { data[id.x] *= 2.0; }
    }`
});

// Layout der Gruppe 0 beschreiben
const bindGroupLayout = device.createBindGroupLayout({
  label: 'Daten-Gruppe',
  entries: [{
    binding: 0,
    visibility: GPUShaderStage.COMPUTE,
    buffer: { type: 'storage' }
  }]
});

// Pipeline-Layout: Index 0 -> @group(0)
const pipelineLayout = device.createPipelineLayout({
  label: 'Verdopplungs-Layout',
  bindGroupLayouts: [bindGroupLayout]
});

const pipeline = device.createComputePipeline({
  layout: pipelineLayout,
  compute: { module: shader, entryPoint: 'main' }
});

console.log(pipelineLayout.label);
Verdopplungs-Layout

Gemeinsame Bind Group für mehrere Render-Pipelines

// Annahme: device, shaderModule und format existieren bereits
const sceneLayout = device.createBindGroupLayout({
  entries: [{
    binding: 0,
    visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
    buffer: { type: 'uniform' }
  }]
});

const materialLayout = device.createBindGroupLayout({
  entries: [
    { binding: 0, visibility: GPUShaderStage.FRAGMENT, sampler: {} },
    { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: {} }
  ]
});

// Beide Pipelines teilen sich Gruppe 0 (Szene) und Gruppe 1 (Material)
const sharedLayout = device.createPipelineLayout({
  label: 'Szene+Material',
  bindGroupLayouts: [sceneLayout, materialLayout]
});

const makePipeline = (fragmentEntry) => device.createRenderPipeline({
  layout: sharedLayout,
  vertex: { module: shaderModule, entryPoint: 'vs_main' },
  fragment: {
    module: shaderModule,
    entryPoint: fragmentEntry,
    targets: [{ format }]
  }
});

const opaquePipeline = makePipeline('fs_opaque');
const unlitPipeline = makePipeline('fs_unlit');
// Eine mit sceneLayout erstellte Bind Group funktioniert nun in beiden Pipelines.

Validierungsfehler abfangen

device.pushErrorScope('validation');

// Absichtlich zu viele Gruppen
const tooMany = Array.from(
  { length: device.limits.maxBindGroups + 1 },
  () => device.createBindGroupLayout({ entries: [] })
);
device.createPipelineLayout({ bindGroupLayouts: tooMany });

const error = await device.popErrorScope();
console.log(error ? `Fehler: ${error.message}` : 'Layout gültig');
Fehler: ... (Meldung abhängig vom Browser)

// Wichtig · Fallstricke

  • Keine Ausnahmen: Ungültige Deskriptoren führen zu einem GPU-Validierungsfehler und einem ungültigen Objekt. Der Fehler zeigt sich oft erst beim Erstellen der Pipeline. Mit pushErrorScope('validation') prüfen.
  • Index = Gruppennummer: Die Reihenfolge im Array bindGroupLayouts muss zu den @group(n)-Angaben im Shader passen. Die Bindings des Shaders müssen in Typ und visibility mit den Layout-Einträgen übereinstimmen, sonst schlägt die Pipeline-Erstellung fehl.
  • Limits: Die Anzahl der Gruppen ist durch device.limits.maxBindGroups begrenzt (Standard: 4). Auch die Gesamtzahl bestimmter Ressourcen pro Shaderstufe (z. B. maxStorageBuffersPerShaderStage) wird über alle Gruppen hinweg geprüft.
  • "auto" vs. explizit: Bind Groups, die mit pipeline.getBindGroupLayout(n) aus einem "auto"-Layout erstellt wurden, sind nicht mit anderen Pipelines kompatibel. Für wiederverwendbare Ressourcen daher explizite Layouts nutzen.
  • Kompatibilität: WebGPU ist nur in sicheren Kontexten (HTTPS/localhost) verfügbar und noch nicht auf allen Plattformen aktiviert. Immer vorher navigator.gpu und das Ergebnis von requestAdapter() prüfen. null-Einträge in bindGroupLayouts sind eine neuere Ergänzung der Spezifikation und werden nicht überall unterstützt.