Browse Source

renderItem.update tweaks

Alexander Rose 6 years ago
parent
commit
ce86231f41
2 changed files with 47 additions and 21 deletions
  1. 14 0
      src/mol-gl/renderable/schema.ts
  2. 33 21
      src/mol-gl/webgl/render-item.ts

+ 14 - 0
src/mol-gl/renderable/schema.ts

@@ -77,6 +77,20 @@ export function splitValues(schema: RenderableSchema, values: RenderableValues)
     return { attributeValues, defineValues, textureValues, uniformValues }
 }
 
+export function splitKeys(schema: RenderableSchema) {
+    const attributeKeys: string[] = []
+    const defineKeys: string[] = []
+    const textureKeys: string[] = []
+    const uniformKeys: string[] = []
+    Object.keys(schema).forEach(k => {
+        if (schema[k].type === 'attribute') attributeKeys.push(k)
+        if (schema[k].type === 'define') defineKeys.push(k)
+        if (schema[k].type === 'texture') textureKeys.push(k)
+        if (schema[k].type === 'uniform') uniformKeys.push(k)
+    })
+    return { attributeKeys, defineKeys, textureKeys, uniformKeys }
+}
+
 export type Versions<T extends RenderableValues> = { [k in keyof T]: number }
 export function getValueVersions<T extends RenderableValues>(values: T) {
     const versions: Versions<any> = {}

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

@@ -9,7 +9,7 @@ import { createTextures } from './texture';
 import { WebGLContext } from './context';
 import { ShaderCode } from '../shader-code';
 import { Program } from './program';
-import { RenderableSchema, RenderableValues, AttributeSpec, getValueVersions, splitValues, Values } from '../renderable/schema';
+import { RenderableSchema, RenderableValues, AttributeSpec, getValueVersions, splitValues, Values, splitKeys } from '../renderable/schema';
 import { idFactory } from 'mol-util/id-factory';
 import { deleteVertexArray, createVertexArray } from './vertex-array';
 import { ValueCell } from 'mol-util';
@@ -60,6 +60,22 @@ interface ValueChanges {
     textures: boolean
     uniforms: boolean
 }
+function createValueChanges() {
+    return {
+        attributes: false,
+        defines: false,
+        elements: false,
+        textures: false,
+        uniforms: false,
+    }
+}
+function resetValueChanges(valueChanges: ValueChanges) {
+    valueChanges.attributes = false
+    valueChanges.defines = false
+    valueChanges.elements = false
+    valueChanges.textures = false
+    valueChanges.uniforms = false
+}
 
 // TODO make `RenderVariantDefines` a parameter for `createRenderItem`
 
@@ -74,6 +90,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo
     const { instancedArrays, vertexArrayObject } = ctx.extensions
 
     const { attributeValues, defineValues, textureValues, uniformValues } = splitValues(schema, values)
+    const { attributeKeys, defineKeys, textureKeys } = splitKeys(schema)
     const versions = getValueVersions(values)
 
     const glDrawMode = getDrawMode(ctx, drawMode)
@@ -109,13 +126,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo
     ctx.instanceCount += instanceCount
     ctx.instancedDrawCount += instanceCount * drawCount
 
-    const valueChanges: ValueChanges = {
-        attributes: false,
-        defines: false,
-        elements: false,
-        textures: false,
-        uniforms: false
-    }
+    const valueChanges = createValueChanges()
 
     let destroyed = false
 
@@ -130,7 +141,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo
             program.setUniforms(uniformValues)
             if (vertexArrayObject && vertexArray) {
                 vertexArrayObject.bindVertexArray(vertexArray)
-                // need to bind elements buffer explicitely since it is not always recorded in the VAO
+                // need to bind elements buffer explicitly since it is not always recorded in the VAO
                 if (elementsBuffer) elementsBuffer.bind()
             } else {
                 if (elementsBuffer) elementsBuffer.bind()
@@ -144,15 +155,17 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo
             }
         },
         update: () => {
-            valueChanges.defines = false
-            Object.keys(defineValues).forEach(k => {
+            resetValueChanges(valueChanges)
+
+            for (let i = 0, il = defineKeys.length; i < il; ++i) {
+                const k = defineKeys[i]
                 const value = defineValues[k]
                 if (value.ref.version !== versions[k]) {
                     // console.log('define version changed', k)
                     valueChanges.defines = true
                     versions[k] = value.ref.version
                 }
-            })
+            }
 
             if (valueChanges.defines) {
                 // console.log('some defines changed, need to rebuild programs')
@@ -182,26 +195,25 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo
                 versions.instanceCount = values.instanceCount.ref.version
             }
 
-            valueChanges.attributes = false
-            Object.keys(attributeValues).forEach(k => {
+            for (let i = 0, il = attributeKeys.length; i < il; ++i) {
+                const k = attributeKeys[i]
                 const value = attributeValues[k]
                 if (value.ref.version !== versions[k]) {
                     const buffer = attributeBuffers[k]
                     if (buffer.length >= value.ref.value.length) {
                         // console.log('attribute array large enough to update', k, value.ref.id, value.ref.version)
-                        attributeBuffers[k].updateData(value.ref.value)
+                        buffer.updateData(value.ref.value)
                     } else {
                         // console.log('attribute array to small, need to create new attribute', k, value.ref.id, value.ref.version)
-                        attributeBuffers[k].destroy()
+                        buffer.destroy()
                         const { itemSize, divisor } = schema[k] as AttributeSpec<ArrayKind>
                         attributeBuffers[k] = createAttributeBuffer(ctx, value.ref.value, itemSize, divisor)
                         valueChanges.attributes = true
                     }
                     versions[k] = value.ref.version
                 }
-            })
+            }
 
-            valueChanges.elements = false
             if (elementsBuffer && values.elements.ref.version !== versions.elements) {
                 if (elementsBuffer.length >= values.elements.ref.value.length) {
                     // console.log('elements array large enough to update', values.elements.ref.id, values.elements.ref.version)
@@ -232,8 +244,8 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo
                 }
             }
 
-            valueChanges.textures = false
-            Object.keys(textureValues).forEach(k => {
+            for (let i = 0, il = textureKeys.length; i < il; ++i) {
+                const k = textureKeys[i]
                 const value = textureValues[k]
                 if (value.ref.version !== versions[k]) {
                     // update of textures with kind 'texture' is done externally
@@ -244,7 +256,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo
                         valueChanges.textures = true
                     }
                 }
-            })
+            }
 
             return valueChanges
         },