Skip to content
Snippets Groups Projects
Commit 44902223 authored by Alexander Rose's avatar Alexander Rose
Browse files

optimized render-item program update

parent 6efa624e
Branches
Tags
No related merge requests found
......@@ -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))
......
......@@ -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}`
}
......
......@@ -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() }
)
......
......@@ -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
})
})
......
......@@ -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(),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment