Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.deleteShader()

WebGLRenderingContext.deleteShader()

Methode

Markiert ein <code>WebGLShader</code>-Objekt zur Löschung. Der GPU-Speicher wird freigegeben, sobald der Shader an kein Programm mehr angehängt ist.

seit JavaScript WebGL 1.0 – Baseline: alle Browser Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.deleteShader(shader)

Beschreibung

deleteShader() gibt ein Shader-Objekt frei, das vorher mit createShader() erzeugt wurde. Der Shader wird dabei zur Löschung markiert. Ist er noch an ein oder mehrere WebGLProgram-Objekte angehängt (attachShader()), wird er erst dann tatsächlich gelöscht, wenn er von allen Programmen gelöst wurde (detachShader()) oder diese Programme selbst gelöscht werden.

Üblicherweise geht man so vor: Shader kompilieren, an ein Programm anhängen, Programm mit linkProgram() linken und danach die Shader lösen und löschen. Das gelinkte Programm enthält den ausführbaren Code bereits, die einzelnen Shader-Objekte braucht man danach nicht mehr. So sammeln sich in langlebigen Anwendungen oder beim erneuten Laden von Shadern (Hot-Reload) keine ungenutzten Objekte an.

Auch wenn das Kompilieren fehlschlägt, sollte man den Shader nach dem Auslesen des Fehlerprotokolls mit getShaderInfoLog() löschen. Ob ein Shader zur Löschung markiert ist, lässt sich mit gl.getShaderParameter(shader, gl.DELETE_STATUS) abfragen.

Parameter

Name Typ Default Beschreibung
$shader Pflicht WebGLShader | null Das zu löschende Shader-Objekt aus gl.createShader(). Bei null oder einem bereits gelöschten Shader passiert nichts.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Shader nach dem Linken aufräumen

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

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

const vs = compile(gl.VERTEX_SHADER, `
  attribute vec4 aPos;
  void main() { gl_Position = aPos; }`);
const fs = compile(gl.FRAGMENT_SHADER, `
  precision mediump float;
  void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }`);

const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);

// Shader werden nach dem Linken nicht mehr benötigt
gl.detachShader(program, vs);
gl.detachShader(program, fs);
gl.deleteShader(vs);
gl.deleteShader(fs);

console.log(gl.getProgramParameter(program, gl.LINK_STATUS));
true

Fehlgeschlagene Kompilierung sauber behandeln

const gl = document.createElement('canvas').getContext('webgl');

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

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    const log = gl.getShaderInfoLog(shader);
    gl.deleteShader(shader); // Speicher trotz Fehler freigeben
    throw new Error(`Shader-Fehler: ${log}`);
  }
  return shader;
};

try {
  createShader(gl.FRAGMENT_SHADER, 'void main() { gl_FragColor = vec4(1.0) }');
} catch (err) {
  console.error(err.message);
}
Shader-Fehler: ERROR: 0:1: '}' : syntax error

Verzögerte Löschung über DELETE_STATUS prüfen

const gl = document.createElement('canvas').getContext('webgl');

const shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, 'void main() { gl_Position = vec4(0.0); }');
gl.compileShader(shader);

const program = gl.createProgram();
gl.attachShader(program, shader);

gl.deleteShader(shader);
// Noch angehängt: nur markiert, nicht wirklich gelöscht
console.log(gl.getShaderParameter(shader, gl.DELETE_STATUS));

gl.detachShader(program, shader); // erst jetzt tatsächlich freigegeben
console.log(gl.isShader(shader));
true false

// Wichtig · Fallstricke

  • Verzögerte Löschung: Solange der Shader an ein Programm angehängt ist, wird er nur markiert. Wer Speicher wirklich freigeben will, muss ihn zusätzlich mit detachShader() lösen oder das Programm mit deleteProgram() löschen.
  • Ein gelöschter Shader darf nicht mehr benutzt werden: Aufrufe wie shaderSource() oder attachShader() mit einem gelöschten Shader erzeugen den Fehler INVALID_VALUE (abfragbar über gl.getError()).
  • Wird ein Shader übergeben, der zu einem anderen WebGL-Kontext gehört, entsteht ein INVALID_OPERATION-Fehler.
  • Einige Entwicklertools und Treiber zeigen den Quelltext gelöschter Shader nicht mehr an. Für die Fehlersuche kann es daher sinnvoll sein, das Löschen im Entwicklungsmodus vorübergehend abzuschalten.
  • Geht der Kontext verloren (webglcontextlost), werden alle Objekte automatisch ungültig. deleteShader() ist dann nicht nötig.
  • In allen Browsern mit WebGL-Unterstützung verfügbar, ebenso in WebGL2RenderingContext.