Start · Sprachen · JavaScript · Referenz · WEBGL_debug_shaders extension

WEBGL_debug_shaders extension

Schnittstelle

WebGL-Erweiterung, deren Methode <code>getTranslatedShaderSource()</code> den vom Treiber übersetzten Quelltext eines Shaders liefert – zum Debuggen von Shader-Problemen.

seit JavaScript WebGL 1 / WebGL 2 – Verfügbarkeit browserabhängig Kategorie: webapi

Signatur

interface WEBGL_debug_shaders

Beschreibung

Die Erweiterung WEBGL_debug_shaders gehört zur WebGL API und stellt genau eine Methode bereit: getTranslatedShaderSource(shader). Browser übersetzen GLSL-ES-Shader intern, bevor sie an den Grafiktreiber gehen – etwa mit ANGLE nach HLSL (Direct3D), in Desktop-GLSL oder nach Metal Shading Language. Die Methode gibt diesen übersetzten Quelltext zurück.

Nützlich ist das vor allem, wenn ein Shader auf bestimmten Plattformen anders rechnet, langsam läuft oder beim Linken scheitert, obwohl der GLSL-Code korrekt aussieht. Im übersetzten Code sieht man z. B. umbenannte Bezeichner (_u-Präfixe), eingefügte Begrenzungsprüfungen für Arrays oder aufgerollte Schleifen.

Weil der übersetzte Quelltext Rückschlüsse auf Treiber und Plattform erlaubt, also für Fingerprinting taugt, stellen viele Browser die Erweiterung nur in privilegierten Kontexten bereit (Erweiterungen, Entwicklerwerkzeuge) oder hinter einem Konfigurationsschalter. Deshalb immer prüfen, ob getExtension("WEBGL_debug_shaders") überhaupt ein Objekt zurückgibt.

Die Erweiterung ist sowohl für WebGLRenderingContext als auch für WebGL2RenderingContext vorgesehen.

Parameter

Name Typ Default Beschreibung
$shader Pflicht WebGLShader Parameter von getTranslatedShaderSource(): der Shader, dessen übersetzter Quelltext gelesen werden soll. Er sollte vorher mit gl.compileShader() kompiliert worden sein.

Rückgabewert

Typ
string
Beschreibung
Rückgabewert von getTranslatedShaderSource(): der übersetzte Shader-Quelltext. Bei nicht kompiliertem oder fehlerhaft kompiliertem Shader meist ein leerer String. Das Erweiterungsobjekt selbst bekommt man über gl.getExtension(); ist die Erweiterung nicht verfügbar, liefert dieser Aufruf null.

Beispiele

Erweiterung abfragen und Verfügbarkeit prüfen

const canvas = document.createElement("canvas");
const gl = canvas.getContext("webgl2") ?? canvas.getContext("webgl");

const debugExt = gl?.getExtension("WEBGL_debug_shaders");

if (debugExt) {
  console.log("WEBGL_debug_shaders verfügbar");
} else {
  console.log("Nicht verfügbar – evtl. nur in privilegierten Kontexten");
}
Nicht verfügbar – evtl. nur in privilegierten Kontexten

Übersetzten Quelltext eines Fragment-Shaders ausgeben

const gl = document.createElement("canvas").getContext("webgl");
const ext = gl.getExtension("WEBGL_debug_shaders");

const source = `
  precision mediump float;
  uniform vec4 uColor;
  void main() {
    gl_FragColor = uColor;
  }
`;

const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  console.error(gl.getShaderInfoLog(shader));
} else if (ext) {
  console.log(ext.getTranslatedShaderSource(shader));
}
// z. B. (ANGLE/HLSL, gekürzt): // uniform float4 _uColor : register(c0); // ...

Hilfsfunktion für Debug-Builds: GLSL vs. Übersetzung vergleichen

const compileWithDebug = (gl, type, source) => {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);

  const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  const ext = gl.getExtension("WEBGL_debug_shaders");

  console.groupCollapsed(`Shader (${ok ? "OK" : "Fehler"})`);
  console.log("Original:\n", source);
  if (!ok) console.warn(gl.getShaderInfoLog(shader));
  if (ext && ok) {
    console.log("Übersetzt:\n", ext.getTranslatedShaderSource(shader));
  }
  console.groupEnd();

  return ok ? shader : null;
};

const gl = document.createElement("canvas").getContext("webgl");
compileWithDebug(gl, gl.VERTEX_SHADER, `
  attribute vec2 aPos;
  void main() { gl_Position = vec4(aPos, 0.0, 1.0); }
`);
Shader (OK) Original: ... Übersetzt: ... (nur wenn Erweiterung verfügbar)

// Wichtig · Fallstricke

  • Datenschutz und Verfügbarkeit: Der übersetzte Code verrät Details über Backend und Treiber und eignet sich damit für Fingerprinting. Firefox stellt die Erweiterung deshalb nur privilegiertem Code bereit (bzw. über webgl.enable-privileged-extensions in about:config). Chromium-Browser und Safari handhaben das je nach Version unterschiedlich. Produktivcode darf nie von der Erweiterung abhängen.
  • Keine stabile Ausgabe: Format und Inhalt des übersetzten Codes hängen von Browser, Betriebssystem, GPU und Backend ab (HLSL, GLSL, MSL) und können sich mit jedem Update ändern. Die Ausgabe also nicht maschinell auswerten, sondern nur lesen.
  • Erst kompilieren: Vor dem Aufruf von gl.compileShader() oder nach einem Kompilierfehler kommt meist ein leerer String zurück. Für Fehlermeldungen ist gl.getShaderInfoLog() zuständig.
  • Kontextverlust: Nach webglcontextlost ist das Erweiterungsobjekt ungültig und muss nach der Wiederherstellung neu per getExtension() abgefragt werden.
  • Die verwandte Erweiterung WEBGL_debug_renderer_info liefert Hersteller- und Rendererangaben der GPU und unterliegt ähnlichen Datenschutz-Einschränkungen.