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

GPUDevice.createShaderModule()

Methode

Erstellt aus WGSL-Quellcode ein <code>GPUShaderModule</code>, das sich in Render- und Compute-Pipelines als Vertex-, Fragment- oder Compute-Shader einsetzen lässt.

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

Signatur

GPUDevice.prototype.createShaderModule(descriptor)

Beschreibung

createShaderModule() ist die Methode, mit der Shader-Code an die GPU übergeben wird. Der Quelltext ist in der WebGPU Shading Language (WGSL) geschrieben und wird der Methode als String im Feld code übergeben. Zurück kommt ein GPUShaderModule, das eine oder mehrere Einstiegsfunktionen enthalten kann (markiert mit @vertex, @fragment oder @compute).

Das Modul allein führt noch nichts aus. Du referenzierst es später beim Erstellen einer Pipeline, etwa über createRenderPipeline() im Feld vertex.module bzw. fragment.module oder über createComputePipeline() im Feld compute.module. Zusätzlich gibst du dort den entryPoint an. Hat das Modul nur einen Einstiegspunkt der passenden Stufe, darfst du ihn weglassen.

Die Methode arbeitet synchron und wirft bei Syntaxfehlern keine Ausnahme. Stattdessen entsteht ein ungültiges Modul und es wird ein Validierungsfehler erzeugt, den du mit pushErrorScope()/popErrorScope() oder über das Event uncapturederror abfängst. Detaillierte Diagnosen mit Zeilen- und Spaltenangaben liefert GPUShaderModule.getCompilationInfo().

Parameter

Name Typ Default Beschreibung
$descriptor Pflicht GPUShaderModuleDescriptor Objekt, das das Shader-Modul beschreibt. Enthält die folgenden Felder.
$descriptor.code Pflicht string Der WGSL-Quellcode des Moduls.
$descriptor.label string "" Name zur Fehlersuche. Er erscheint in Fehlermeldungen und in Entwicklerwerkzeugen.
$descriptor.compilationHints Array<{entryPoint: string, layout?: GPUPipelineLayout | "auto"}> [] Optionale Hinweise, mit welchen Einstiegspunkten und Pipeline-Layouts das Modul später genutzt wird. Damit kann der Browser früher kompilieren.
$descriptor.sourceMap object Optionale Source Map (Format v3) für die Fehlersuche. Browser dürfen sie ignorieren.

Rückgabewert

Typ
GPUShaderModule
Beschreibung
Ein GPUShaderModule-Objekt. Bei Fehlern im WGSL-Code ist es ungültig und verursacht Validierungsfehler, sobald eine Pipeline es verwendet.

Beispiele

Vertex- und Fragment-Shader für ein Dreieck

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

const shaderModule = device.createShaderModule({
  label: 'Dreieck-Shader',
  code: /* wgsl */ `
    @vertex
    fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
      var pos = array<vec2f, 3>(
        vec2f( 0.0,  0.5),
        vec2f(-0.5, -0.5),
        vec2f( 0.5, -0.5)
      );
      return vec4f(pos[i], 0.0, 1.0);
    }

    @fragment
    fn fs_main() -> @location(0) vec4f {
      return vec4f(1.0, 0.4, 0.0, 1.0);
    }
  `
});

const pipeline = device.createRenderPipeline({
  layout: 'auto',
  vertex: { module: shaderModule, entryPoint: 'vs_main' },
  fragment: {
    module: shaderModule,
    entryPoint: 'fs_main',
    targets: [{ format: navigator.gpu.getPreferredCanvasFormat() }]
  },
  primitive: { topology: 'triangle-list' }
});
console.log(shaderModule.label);
Dreieck-Shader

Compute-Shader: Array-Werte verdoppeln

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const module = device.createShaderModule({
  label: 'Verdoppler',
  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] = data[id.x] * 2.0;
      }
    }
  `
});

// entryPoint darf fehlen, weil es nur einen @compute-Einstiegspunkt gibt
const pipeline = device.createComputePipeline({
  layout: 'auto',
  compute: { module }
});
console.log(pipeline instanceof GPUComputePipeline);
true

Kompilierfehler mit getCompilationInfo() auswerten

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

device.pushErrorScope('validation');
const module = device.createShaderModule({
  label: 'Fehlerhafter Shader',
  code: `@fragment fn main() -> @location(0) vec4f { return vec4f(1.0) }` // Semikolon fehlt
});
const error = await device.popErrorScope();
if (error) console.warn('Validierungsfehler:', error.message);

const info = await module.getCompilationInfo();
for (const msg of info.messages) {
  console.log(`${msg.type} in Zeile ${msg.lineNum}:${msg.linePos} – ${msg.message}`);
}
Validierungsfehler: ... error in Zeile 1:62 – expected ';' for return statement

// Wichtig · Fallstricke

  • Keine Ausnahme bei Fehlern: Fehlerhafter WGSL-Code bringt das Skript nicht zum Absturz. Er erzeugt nur einen Validierungsfehler, der ohne Error-Scope oder uncapturederror-Handler lediglich in der Konsole erscheint. Wenn Pipelines unerklärlich ungültig sind, prüfe getCompilationInfo().
  • Nur WGSL: Anders als bei WebGL gibt es kein GLSL und kein SPIR-V. Bestehende Shader musst du übersetzen, z. B. mit Tools wie naga oder Tint.
  • Leistung: Die Kompilierung kann aufwendig sein. Erzeuge Module einmal und verwende sie wieder, statt sie in jedem Frame neu anzulegen. Für nicht blockierende Pipeline-Erstellung gibt es createRenderPipelineAsync() bzw. createComputePipelineAsync().
  • Sicherheit: Baue WGSL-Code nicht ungeprüft aus Benutzereingaben zusammen. Der Browser prüft zwar Speicherzugriffe, aber manipulierter Code kann trotzdem Denial-of-Service auslösen, z. B. durch Endlosschleifen, die zum Geräteverlust führen.
  • Kompatibilität: WebGPU gibt es nur in sicheren Kontexten und noch nicht in allen Browsern bzw. auf allen Plattformen. Prüfe vorher navigator.gpu und das Ergebnis von requestAdapter(). Das Feld compilationHints wird nicht überall ausgewertet.