Bladeren bron

optimized render-item program update

Alexander Rose 6 jaren geleden
bovenliggende
commit
4490222302
5 gewijzigde bestanden met toevoegingen van 40 en 18 verwijderingen
  1. 2 2
      src/mol-gl/scene.ts
  2. 17 8
      src/mol-gl/shader-code.ts
  3. 13 3
      src/mol-gl/webgl/program.ts
  4. 6 4
      src/mol-gl/webgl/render-item.ts
  5. 2 1
      src/mol-view/viewer.ts

+ 2 - 2
src/mol-gl/scene.ts

@@ -60,10 +60,10 @@ namespace Scene {
 
             update: () => {
                 update()
-                renderableMap.forEach((o, r) => o.update())
+                renderableMap.forEach(o => o.update())
                 boundingSphere = undefined
             },
-            
+
             add: (o: RenderObject) => {
                 if (!renderableMap.has(o)) {
                     renderableMap.set(o, createRenderable(ctx, o))

+ 17 - 8
src/mol-gl/shader-code.ts

@@ -6,25 +6,33 @@
  */
 
 import { ValueCell } from 'mol-util';
+import { idFactory } from 'mol-util/id-factory';
 
 export type DefineKind = 'boolean' | 'string'
 export type DefineType = boolean | string
 export type DefineValues = { [k: string]: ValueCell<DefineType> }
 
+const shaderCodeId = idFactory()
+
 export interface ShaderCode {
+    id: number
     vert: string
     frag: string
 }
 
-export const PointShaderCode: ShaderCode = {
-    vert: require('mol-gl/shader/point.vert'),
-    frag: require('mol-gl/shader/point.frag')
+export function ShaderCode(vert: string, frag: string): ShaderCode {
+    return { id: shaderCodeId(), vert, frag }
 }
 
-export const MeshShaderCode: ShaderCode = {
-    vert: require('mol-gl/shader/mesh.vert'),
-    frag: require('mol-gl/shader/mesh.frag')
-}
+export const PointShaderCode = ShaderCode(
+    require('mol-gl/shader/point.vert'),
+    require('mol-gl/shader/point.frag')
+)
+
+export const MeshShaderCode = ShaderCode(
+    require('mol-gl/shader/mesh.vert'),
+    require('mol-gl/shader/mesh.frag')
+)
 
 export type ShaderDefines = {
     [k: string]: ValueCell<DefineType>
@@ -47,9 +55,10 @@ function getDefinesCode (defines: ShaderDefines) {
     return lines.join('\n') + '\n'
 }
 
-export function addShaderDefines(defines: ShaderDefines, shaders: ShaderCode) {
+export function addShaderDefines(defines: ShaderDefines, shaders: ShaderCode): ShaderCode {
     const header = getDefinesCode(defines)
     return {
+        id: shaderCodeId(),
         vert: `${header}${shaders.vert}`,
         frag: `${header}${shaders.frag}`
     }

+ 13 - 3
src/mol-gl/webgl/program.ts

@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { ShaderCode } from '../shader-code'
+import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code'
 import { Context } from './context';
 import { getUniformUpdaters, getTextureUniformUpdaters, UniformValues } from './uniform';
 import { AttributeBuffers } from './buffer';
@@ -12,6 +12,7 @@ import { TextureId, Textures } from './texture';
 import { createReferenceCache, ReferenceCache } from 'mol-util/reference-cache';
 import { idFactory } from 'mol-util/id-factory';
 import { RenderableSchema } from '../renderable/schema';
+import { hashFnv32a, hashString } from 'mol-data/util';
 
 const getNextProgramId = idFactory()
 
@@ -46,19 +47,21 @@ function getAttributeLocations(ctx: Context, program: WebGLProgram, schema: Rend
 }
 
 export interface ProgramProps {
+    defineValues: DefineValues,
     shaderCode: ShaderCode,
     schema: RenderableSchema
 }
 
 export function createProgram(ctx: Context, props: ProgramProps): Program {
     const { gl, shaderCache } = ctx
-    const { shaderCode, schema } = props
+    const { defineValues, shaderCode: _shaderCode, schema } = props
 
     const program = gl.createProgram()
     if (program === null) {
         throw new Error('Could not create WebGL program')
     }
 
+    const shaderCode = addShaderDefines(defineValues, _shaderCode)
     const vertShaderRef = shaderCache.get(ctx, { type: 'vert', source: shaderCode.vert })
     const fragShaderRef = shaderCache.get(ctx, { type: 'frag', source: shaderCode.frag })
 
@@ -113,7 +116,14 @@ export type ProgramCache = ReferenceCache<Program, ProgramProps, Context>
 
 export function createProgramCache(): ProgramCache {
     return createReferenceCache(
-        (props: ProgramProps) => JSON.stringify(props),
+        (props: ProgramProps) => {
+            const array = [props.shaderCode.id]
+            Object.keys(props.defineValues).forEach(k => {
+                const v = props.defineValues[k].ref.value
+                array.push(hashString(k), typeof v === 'boolean' ? v ? 1 : 0 : hashString(v))
+            })
+            return hashFnv32a(array).toString()
+        },
         (ctx: Context, props: ProgramProps) => createProgram(ctx, props),
         (program: Program) => { program.destroy() }
     )

+ 6 - 4
src/mol-gl/webgl/render-item.ts

@@ -7,7 +7,7 @@
 import { createAttributeBuffers, createElementsBuffer, ElementsBuffer, createAttributeBuffer, ArrayKind } from './buffer';
 import { createTextures } from './texture';
 import { Context } from './context';
-import { ShaderCode, addShaderDefines } from '../shader-code';
+import { ShaderCode } from '../shader-code';
 import { Program } from './program';
 import { RenderableSchema, RenderableValues, AttributeSpec, getValueVersions, splitValues, Values } from '../renderable/schema';
 import { idFactory } from 'mol-util/id-factory';
@@ -74,7 +74,8 @@ export function createRenderItem(ctx: Context, drawMode: DrawMode, shaderCode: S
     Object.keys(RenderVariantDefines).forEach(k => {
         const variantDefineValues: Values<RenderableSchema> = (RenderVariantDefines as any)[k]
         programs[k] = programCache.get(ctx, {
-            shaderCode: addShaderDefines({ ...defineValues, ...variantDefineValues }, shaderCode),
+            defineValues: { ...defineValues, ...variantDefineValues },
+            shaderCode,
             schema
         })
     })
@@ -117,7 +118,7 @@ export function createRenderItem(ctx: Context, drawMode: DrawMode, shaderCode: S
             program.setUniforms(uniformValues)
             if (oesVertexArrayObject && vertexArray) {
                 oesVertexArrayObject.bindVertexArrayOES(vertexArray)
-                // TODO need to bind elements buffer explicitely since it is not always recorded in the VAO
+                // need to bind elements buffer explicitely since it is not always recorded in the VAO
                 if (elementsBuffer) elementsBuffer.bind()
             } else {
                 if (elementsBuffer) elementsBuffer.bind()
@@ -147,7 +148,8 @@ export function createRenderItem(ctx: Context, drawMode: DrawMode, shaderCode: S
                     const variantDefineValues: Values<RenderableSchema> = (RenderVariantDefines as any)[k]
                     programs[k].free()
                     programs[k] = programCache.get(ctx, {
-                        shaderCode: addShaderDefines({ ...defineValues, ...variantDefineValues }, shaderCode),
+                        defineValues: { ...defineValues, ...variantDefineValues },
+                        shaderCode,
                         schema
                     })
                 })

+ 2 - 1
src/mol-view/viewer.ts

@@ -175,7 +175,6 @@ namespace Viewer {
             let didRender = false
             controls.update()
             camera.update()
-            scene.update()
             if (force || !Mat4.areEqual(camera.projectionView, prevProjectionView, EPSILON.Value) || !Mat4.areEqual(scene.view, prevSceneView, EPSILON.Value)) {
                 // console.log('foo', force, prevSceneView, scene.view)
                 Mat4.copy(prevProjectionView, camera.projectionView)
@@ -274,6 +273,7 @@ namespace Viewer {
                 }
                 reprMap.set(repr, newRO)
                 reprCount.next(reprMap.size)
+                scene.update()
             },
             remove: (repr: Representation<any>) => {
                 const renderObjectSet = reprMap.get(repr)
@@ -281,6 +281,7 @@ namespace Viewer {
                     renderObjectSet.forEach(o => scene.remove(o))
                     reprMap.delete(repr)
                     reprCount.next(reprMap.size)
+                    scene.update()
                 }
             },
             update: () => scene.update(),