2014-05-11 7 views
8

Come si pulisce un programma di contesto WebGL e si scarica il programma, i buffer e tutto dalla GPU e dall'elemento dom?Come ripulire e scaricare un contesto canvas WebGL dalla GPU dopo l'uso?

Mi piacerebbe assicurarmi che non ci siano rifiuti.

Anche sarebbe bello riutilizzare la tela se possibile (e non so se sarebbe 2d o contesto webgl).

+0

stack.gl ha un bel pacchetto chiamato gl-reset. Pulisce il contesto webgl per il riutilizzo. – walteronassis

risposta

13

Puoi semplicemente perdere ogni riferimento al tuo contesto gl e tutti gli oggetti gl e la tela e rimuovere la tela dal DOM. Sfortunatamente, poiché JavaScript è garbage collection non si sa quando il browser libererà la memoria. Ci sono alcuni test di conformità per provare a farlo correttamente ma se non vuoi semplicemente sperare e pregare allora ...

Per liberare tutte le tue risorse chiamando lo gl.deleteXXX su tutto ciò che hai creato e non vincolante punti. Ciò significa che per ogni unità di texture chiamate gl.bindTexture su tutti i target con null, lo stesso con array, framebuffer e 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); 

Poiché non è possibile associare null per un attributo è possibile impostare le dimensioni di tutti i tamponi a 1 (zero non è consentito) prima di eliminarli. O quello o creare un nuovo buffer e assegnarlo a tutti gli attributi.

Esempio del primo

// 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); 

o fare un nuovo buffer e assegnare a tutti gli attributi

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); 
} 

Ciò separare i vecchi buffer dagli attributi.

Infine, imposta le dimensioni dell'area di lavoro su 1x1 pixel.

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

Non è una soluzione perfetta, ma lo farà subito libera tutti, ma alcuni k di memoria immediatamente, senza tempi di attesa per la raccolta dei rifiuti, che è fuori dal tuo controllo.

Per quanto riguarda il riutilizzo della tela da zero non è possibile. La tela avrà sempre lo stesso contesto per cui l'hai prima richiesta.

vedere anche @ risposta di Johan circa loseContext

+0

Cool, grazie per la risposta completa. Forse per i posteri potresti aggiungere un esempio di come appare "gl.deleteXX"? – Bartvds

+0

Una buona spiegazione, l'ho usato ma continuo a vedere il programma che non viene liberato quando carichiamo una nuova immagine sul contesto webgl e una nuova serie di programmi viene allegata. Puoi dare un'occhiata all'editor firefox shader – subhfyu546754

4

Per perdere contesto, utilizzare l'estensione WEBGL_lose_context come

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

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

+3

Sei collegato a 'restoreContext()' invece di ['loseContext()'] (https://developer.mozilla.org/en-US/docs/Web/API/ WEBGL_lose_context/loseContext). Inoltre, le prime due righe suggeriscono che questo non fa quello che vuoi: * "Il WEBGL_lose_context.Il metodo loseContext() è parte dell'API WebGL e consente di * * simulare *** * perdere il contesto di un contesto WebGLRenderingContext. Attiva i passaggi descritti nella specifica WebGL per la gestione del contesto perso. * *** Il contesto rimarrà perso fino a quando non verrà chiamato WEBGL_lose_context.restoreContext(). "*** – Job

+2

@Job spec non è il codice, può essere interpretato Tuttavia, vi è anche quanto segue: _Le implementazioni dovrebbero distruggere il contesto grafico sottostante e tutte le risorse grafiche quando viene chiamato questo metodo. ** Questo è il meccanismo consigliato per le applicazioni che bloccano a livello di programmazione l'utilizzo dell'API WebGL. ** _ Riguardo la parola _simola_ - Immagino sia stata scelta perché _Questa estensione espone nuove funzioni che simulano la perdita e il ripristino del contesto WebGL, ** anche su piattaforme in cui il contesto non può mai essere perso ** _ - cioè la simulazione avviene quando la distruzione è impossibile – Grief

+0

Grazie per il chiarimento! – Job

Problemi correlati