2014-05-11 6 views
8

Wie bereinigen Sie ein WebGL-Kontext-Programm und entladen Sie das Programm, Puffer und alles aus der GPU und dom-Element?Wie säubere und lösche ich einen WebGL-Canvas-Kontext nach der Verwendung von der GPU?

Ich würde gerne sicherstellen, dass wir nicht verunreinigt sind.

Auch wäre es schön, die Leinwand wenn möglich wieder zu verwenden (und ich weiß nicht, ob es 2d oder webgl Kontext wäre).

+0

stack.gl ein nettes Paket hat gl-Reset genannt. Es bereinigt den Webgl-Kontext für die Wiederverwendung. – walteronassis

Antwort

13

Sie können einfach jeden Verweis auf Ihren gl-Kontext und alle gl-Objekte und die Zeichenfläche verlieren und die Zeichenfläche aus dem DOM entfernen. Leider, weil JavaScript Müll ist, gibt es keine Ahnung, wann der Browser tatsächlich den Speicher freigeben wird. Es gibt einige Konformitätstests, um zu testen, dass sie das richtig machen, aber wenn Sie nicht nur hoffen und beten möchten ...

Um alle Ihre Ressourcen zu befreien, indem Sie gl.deleteXXX auf alles, was Sie erstellt und alle Bind zu lösen Punkte. Das bedeutet, dass gl.bindTexture für alle Textureinheiten auf allen Zielen mit null aufgerufen wird, dasselbe gilt für Arrays, Framebuffer und Renderbuffer.

var numTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); 
for (var unit = 0; unit < numTextureUnits; ++unit) { 
    gl.activeTexture(gl.TEXTURE0 + unit); 
    gl.bindTexture(gl.TEXTURE_2D, null); 
    gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); 
} 
gl.bindBuffer(gl.ARRAY_BUFFER, null); 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 
gl.bindRenderbuffer(gl.RENDERBUFFER, null); 
gl.bindFramebuffer(gl.FRAMEBUFFER, null); 

// Delete all your resources 
// Note!!!: You'd have to change this code to delete the resources YOU created. 
gl.deleteTexture(someTexture); 
gl.deleteTexture(someOtherTexture); 
gl.deleteBuffer(someBuffer); 
gl.deleteBuffer(someOtherBuffer); 
gl.deleteRenderbuffer(someRenderbuffer); 
gl.deleteFramebuffer(someFramebuffer); 

Weil Sie nicht null auf ein Attribut binden, können Sie die Größe aller Ihrer Puffer auf 1 gesetzt könnte (Null ist nicht erlaubt), bevor Sie sie löschen. Entweder das oder erstelle einen neuen Puffer und weise ihn allen Attributen zu.

Beispiel des ersten

// set a buffer to 1 byte before deleting 
// NOTE: You'd need to do this for ALL BUFFERS you created. 
gl.bindBuffer(gl.ARRAY_BUFFER, someArrayBuffer); 
gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW); 
gl.deleteBuffer(someArrayBuffer); 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, someElementArrayBuffer); 
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 1, gl.STATIC_DRAW); 
gl.deleteBuffer(someElementArrayBuffer); 

Oder einen neuen Puffer machen und es zuweisen, um alle

var buf = gl.createBuffer(); 
gl.bindBuffer(gl.ARRAY_BUFFER, buf); 
var numAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); 
for (var attrib = 0; attrib < numAttributes; ++attrib) { 
    gl.vertexAttribPointer(attrib, 1, gl.FLOAT, false, 0, 0); 
} 

Attribute Dadurch werden die alten Puffer aus den Attributen entbinden.

Abschließend legen Sie die Leinwandgröße auf 1x1 Pixel.

gl.canvas.width = 1; 
gl.canvas.height = 1; 

Es ist keine perfekte Lösung, aber es wird sofort alle, aber ein paar k Speicher sofort frei, keine Wartezeiten für die Garbage Collection, die außerhalb Ihrer Kontrolle ist.

Wie für die Wiederverwendung der Leinwand von Grund auf neu können Sie nicht. Das Canvas wird immer den gleichen Kontext haben, in dem Sie es zuerst gefragt haben.

Siehe auch @ Johan Antwort über loseContext

+0

Cool, danke für die gründliche Antwort. Vielleicht könntest du für die Nachwelt ein Beispiel hinzufügen, wie 'gl.deleteXX' aussieht? – Bartvds

+0

Gute Erklärung, ich habe es benutzt, aber ich sehe immer noch, dass das Programm nicht freigegeben wird, wenn wir ein neues Bild in den Webgl-Kontext laden und neue Programme anhängen. Sie können es auf Firefox Shader-Editor betrachten – subhfyu546754

4

den Kontext zu verlieren, verwenden Sie die Erweiterung WEBGL_lose_context als

gl.getExtension('WEBGL_lose_context').loseContext(); 

Siehe https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context/loseContext

+3

Sie verbunden mit 'restoreContext()' anstelle von ['loseContext()'] (https://developer.mozilla.org/en-US/docs/Web/API/ WEBGL_lose_kontext/lossContext). Auch die ersten beiden Zeilen deuten darauf hin, dass dies nicht das tut, was Sie wollen: * "WEBGL_lose_context.Die Methode "loseContext()" ist Teil der WebGL-API und ermöglicht es Ihnen * *** simulate *** * den Kontext eines WebGLRenderingContext-Kontexts zu verlieren. Es löst die in der WebGL-Spezifikation beschriebenen Schritte zur Behandlung des verlorenen Kontexts aus. * *** Der Kontext bleibt solange bestehen, bis WEBGL_lose_context.restoreContext() aufgerufen wird. "*** – Job

+2

@Job spec ist nicht der Code, er kann interpretiert werden Es gibt jedoch auch die folgenden: _Implementations sollte den zugrunde liegenden Grafikkontext und alle Grafikressourcen zerstören, wenn diese Methode aufgerufen wird. ** Dies ist der empfohlene Mechanismus für Anwendungen, um ihre Verwendung der WebGL-API programmgesteuert zu stoppen das Wort _simulate_ - Ich vermute, es wurde gewählt, weil _Diese Erweiterung neue Funktionen enthält, die das Verlieren und Wiederherstellen des WebGL-Kontextes ** sogar auf Plattformen, wo der Kontext niemals verloren gehen kann, _ _ - dh Simulation findet statt, wenn das Zerstören unmöglich ist – Grief

+0

Danke zur Klärung! – Job

Verwandte Themen