Alexander Rose пре 7 година
родитељ
комит
1ec3141951

+ 1 - 1
src/mol-gl/renderable/mesh.ts

@@ -60,7 +60,7 @@ namespace Mesh {
                 console.log('Updating mesh renderable')
             },
             dispose: () => {
-                renderItem.dispose()
+                renderItem.destroy()
             }
         }
     }

+ 1 - 1
src/mol-gl/renderable/point.ts

@@ -62,7 +62,7 @@ namespace Point {
                 console.log('Updating point renderable')
             },
             dispose: () => {
-                renderItem.dispose()
+                renderItem.destroy()
             }
         }
     }

+ 12 - 6
src/mol-gl/renderer.ts

@@ -13,11 +13,12 @@ import { Context } from './webgl/context';
 import { Mat4, Vec3 } from 'mol-math/linear-algebra';
 
 export interface RendererStats {
-    elementsCount: number
+    renderableCount: number
+    programCount: number
+    shaderCount: number
     bufferCount: number
     textureCount: number
-    shaderCount: number
-    renderableCount: number
+    vaoCount: number
 }
 
 interface Renderer {
@@ -98,10 +99,15 @@ namespace Renderer {
                 Viewport.copy(viewport, newViewport)
                 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height)
             },
-            get stats() {
+            get stats(): RendererStats {
                 return {
-                    renderableCount: scene.count
-                } as any
+                    renderableCount: scene.count,
+                    programCount: ctx.programCache.count,
+                    shaderCount: ctx.shaderCache.count,
+                    bufferCount: ctx.bufferCount,
+                    textureCount: ctx.textureCount,
+                    vaoCount: ctx.vaoCount,
+                }
             },
             dispose: () => {
                 scene.clear()

+ 6 - 0
src/mol-gl/webgl/buffer.ts

@@ -105,6 +105,9 @@ export function createBuffer(ctx: Context, array: ArrayType, itemSize: BufferIte
     }
     updateData(array)
 
+    let destroyed = false
+    ctx.bufferCount += 1
+
     return {
         _buffer,
         _usageHint,
@@ -119,10 +122,13 @@ export function createBuffer(ctx: Context, array: ArrayType, itemSize: BufferIte
         },
 
         destroy: () => {
+            if (destroyed) return
             gl.bindBuffer(_bufferType, _buffer)
             // set size to 1 before deleting
             gl.bufferData(_bufferType, 1, _usageHint)
             gl.deleteBuffer(_buffer)
+            destroyed = true
+            ctx.bufferCount -= 1
         }
     }
 }

+ 13 - 10
src/mol-gl/webgl/context.ts

@@ -7,14 +7,6 @@
 import { createProgramCache, ProgramCache } from './program'
 import { createShaderCache, ShaderCache } from './shader'
 
-// const extensions = [
-//     'OES_element_index_uint',
-//     'ANGLE_instanced_arrays'
-// ]
-// const optionalExtensions = [
-//     'EXT_disjoint_timer_query'
-// ]
-
 function unbindResources (gl: WebGLRenderingContext) {
     // bind null to all texture units
     const maxTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)
@@ -50,6 +42,9 @@ export interface Context {
     extensions: Extensions
     shaderCache: ShaderCache
     programCache: ProgramCache
+    bufferCount: number
+    textureCount: number
+    vaoCount: number
     destroy: () => void
 }
 
@@ -67,13 +62,21 @@ export function createContext(gl: WebGLRenderingContext): Context {
         console.log('Could not get "OES_vertex_array_object" extension')
     }
 
+    const shaderCache = createShaderCache()
+    const programCache = createProgramCache()
+
     return {
         gl,
         extensions: { angleInstancedArrays, oesElementIndexUint, oesVertexArrayObject },
-        shaderCache: createShaderCache(),
-        programCache: createProgramCache(),
+        shaderCache,
+        programCache,
+        bufferCount: 0,
+        textureCount: 0,
+        vaoCount: 0,
         destroy: () => {
             unbindResources(gl)
+            programCache.dispose()
+            shaderCache.dispose()
             // TODO destroy buffers and textures
         }
     }

+ 21 - 3
src/mol-gl/webgl/render-item.ts

@@ -55,7 +55,7 @@ export interface RenderItem {
     update: (state: RenderItemState) => void
 
     draw: () => void
-    dispose: () => void
+    destroy: () => void
 }
 
 export function createRenderItem(ctx: Context, props: RenderItemProps, state: RenderItemState): RenderItem {
@@ -77,6 +77,7 @@ export function createRenderItem(ctx: Context, props: RenderItemProps, state: Re
         vertexArray = oesVertexArrayObject.createVertexArrayOES()
         oesVertexArrayObject.bindVertexArrayOES(vertexArray)
         program.bindAttributes(attributeBuffers)
+        ctx.vaoCount += 1
     }
 
     let elementsBuffer: ElementsBuffer
@@ -84,7 +85,13 @@ export function createRenderItem(ctx: Context, props: RenderItemProps, state: Re
         elementsBuffer = createElementsBuffer(ctx, elements)
     }
 
+    // needs to come after elements buffer creation to include it in the vao
+    if (oesVertexArrayObject) {
+        oesVertexArrayObject.bindVertexArrayOES(null!)
+    }
+
     let { drawCount, instanceCount } = state
+    let destroyed = false
 
     return {
         hash,
@@ -97,6 +104,7 @@ export function createRenderItem(ctx: Context, props: RenderItemProps, state: Re
                 oesVertexArrayObject.bindVertexArrayOES(vertexArray)
             } else {
                 program.bindAttributes(attributeBuffers)
+                elementsBuffer.bind()
             }
             program.bindTextures(textures)
             if (elementsBuffer) {
@@ -113,9 +121,19 @@ export function createRenderItem(ctx: Context, props: RenderItemProps, state: Re
                 if (value !== undefined) attributeBuffers[k].updateData(value)
             })
         },
-        dispose: () => {
-            // TODO
+        destroy: () => {
+            if (destroyed) return
             programRef.free()
+            Object.keys(textures).forEach(k => textures[k].destroy())
+            Object.keys(attributeBuffers).forEach(k => attributeBuffers[k].destroy())
+            if (elements && elementsKind) {
+                elementsBuffer.destroy()
+            }
+            if (oesVertexArrayObject) {
+                oesVertexArrayObject.deleteVertexArrayOES(vertexArray)
+                ctx.vaoCount -= 1
+            }
+            destroyed = true
         }
     }
 }

+ 11 - 0
src/mol-gl/webgl/texture.ts

@@ -11,6 +11,7 @@ export interface Texture {
     load: (image: TextureImage) => void
     bind: (id: TextureId) => void
     unbind: (id: TextureId) => void
+    destroy: () => void
 }
 
 export type TextureId = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
@@ -33,6 +34,9 @@ export function createTexture(ctx: Context): Texture {
     const _format = gl.RGB
     const _arrayType = gl.UNSIGNED_BYTE
 
+    let destroyed = false
+    ctx.textureCount += 1
+
     return {
         load: (image: TextureImage) => {
             const { array, width, height } = image
@@ -54,6 +58,13 @@ export function createTexture(ctx: Context): Texture {
         unbind: (id: TextureId) => {
             gl.activeTexture(gl.TEXTURE0 + id)
             gl.bindTexture(_textureType, null)
+        },
+
+        destroy: () => {
+            if (destroyed) return
+            gl.deleteTexture(texture)
+            destroyed = true
+            ctx.textureCount -= 1
         }
     }
 }

+ 6 - 2
src/mol-util/reference-cache.ts

@@ -28,11 +28,12 @@ export interface ReferenceCache<T, P, C> {
     get: (ctx: C, props: P) => ReferenceItem<T>
     clear: () => void
     count: number
+    dispose: () => void
 }
 
 export function createReferenceCache<T, P, C>(hashFn: (props: P) => string, ctor: (ctx: C, props: P) => T, deleteFn: (v: T) => void): ReferenceCache<T, P, C> {
     const map: Map<string, Reference<T>> = new Map()
-    
+
     return {
         get: (ctx: C, props: P) => {
             const id = hashFn(props)
@@ -56,6 +57,9 @@ export function createReferenceCache<T, P, C>(hashFn: (props: P) => string, ctor
         },
         get count () {
             return map.size
-        }
+        },
+        dispose: () => {
+            map.forEach(ref => deleteFn(ref.value))
+        },
     }
 }