Skip to content
Snippets Groups Projects
Commit d722d17a authored by David Sehnal's avatar David Sehnal
Browse files

mol-gl: partial scene commit support

parent 522d929f
No related branches found
No related tags found
No related merge requests found
...@@ -294,14 +294,13 @@ namespace Canvas3D { ...@@ -294,14 +294,13 @@ namespace Canvas3D {
cameraResetRequested = false; cameraResetRequested = false;
} }
let isDirty = false; const sceneCommitTimeoutMs = 250;
function commitScene() { function commitScene() {
if (!isDirty) return; if (!scene.needsCommit) return;
scene.syncCommit(); const allCommited = scene.commit(sceneCommitTimeoutMs);
if (debugHelper.isEnabled) debugHelper.update(); if (debugHelper.isEnabled) debugHelper.update();
reprCount.next(reprRenderObjects.size); if (allCommited) reprCount.next(reprRenderObjects.size);
isDirty = false;
} }
function add(repr: Representation.Any) { function add(repr: Representation.Any) {
...@@ -322,7 +321,6 @@ namespace Canvas3D { ...@@ -322,7 +321,6 @@ namespace Canvas3D {
reprRenderObjects.set(repr, newRO) reprRenderObjects.set(repr, newRO)
scene.update(repr.renderObjects, false) scene.update(repr.renderObjects, false)
isDirty = true;
} }
function remove(repr: Representation.Any) { function remove(repr: Representation.Any) {
...@@ -333,7 +331,6 @@ namespace Canvas3D { ...@@ -333,7 +331,6 @@ namespace Canvas3D {
renderObjects.forEach(o => scene.remove(o)) renderObjects.forEach(o => scene.remove(o))
reprRenderObjects.delete(repr) reprRenderObjects.delete(repr)
scene.update(repr.renderObjects, false, true) scene.update(repr.renderObjects, false, true)
isDirty = true;
} }
} }
......
...@@ -82,7 +82,7 @@ export class BoundingSphereHelper { ...@@ -82,7 +82,7 @@ export class BoundingSphereHelper {
}) })
this.scene.update(void 0, false) this.scene.update(void 0, false)
this.scene.syncCommit() this.scene.commit()
} }
syncVisibility() { syncVisibility() {
......
...@@ -121,7 +121,7 @@ describe('renderer', () => { ...@@ -121,7 +121,7 @@ describe('renderer', () => {
const points = createPoints() const points = createPoints()
scene.add(points) scene.add(points)
scene.syncCommit() scene.commit()
expect(ctx.stats.resourceCounts.attribute).toBe(4); expect(ctx.stats.resourceCounts.attribute).toBe(4);
expect(ctx.stats.resourceCounts.texture).toBe(5); expect(ctx.stats.resourceCounts.texture).toBe(5);
expect(ctx.stats.resourceCounts.vertexArray).toBe(5); expect(ctx.stats.resourceCounts.vertexArray).toBe(5);
...@@ -129,7 +129,7 @@ describe('renderer', () => { ...@@ -129,7 +129,7 @@ describe('renderer', () => {
expect(ctx.stats.resourceCounts.shader).toBe(10); expect(ctx.stats.resourceCounts.shader).toBe(10);
scene.remove(points) scene.remove(points)
scene.syncCommit() scene.commit()
expect(ctx.stats.resourceCounts.attribute).toBe(0); expect(ctx.stats.resourceCounts.attribute).toBe(0);
expect(ctx.stats.resourceCounts.texture).toBe(0); expect(ctx.stats.resourceCounts.texture).toBe(0);
expect(ctx.stats.resourceCounts.vertexArray).toBe(0); expect(ctx.stats.resourceCounts.vertexArray).toBe(0);
......
/**
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { LinkedList } from '../mol-data/generic'
import { GraphicsRenderObject } from './render-object'
type N = LinkedList.Node<GraphicsRenderObject>
export class CommitQueue {
private removeList = LinkedList<GraphicsRenderObject>();
private removeMap = new Map<GraphicsRenderObject, N>();
private addList = LinkedList<GraphicsRenderObject>();
private addMap = new Map<GraphicsRenderObject, N>();
get isEmpty() {
return this.removeList.count === 0 && this.addList.count === 0;
}
add(o: GraphicsRenderObject) {
if (this.removeMap.has(o)) {
const a = this.removeMap.get(o)!;
this.removeMap.delete(o);
this.removeList.remove(a);
}
if (this.addMap.has(o)) return;
const b = this.addList.addLast(o);
this.addMap.set(o, b);
}
remove(o: GraphicsRenderObject) {
if (this.addMap.has(o)) {
const a = this.addMap.get(o)!;
this.addMap.delete(o);
this.addList.remove(a);
}
if (this.removeMap.has(o)) return;
const b = this.removeList.addLast(o);
this.removeMap.set(o, b);
}
tryGetRemove() {
const o = this.removeList.removeFirst();
if (o) this.removeMap.delete(o);
return o;
}
tryGetAdd() {
const o = this.addList.removeFirst();
if (o) this.addMap.delete(o);
return o;
}
}
...@@ -13,7 +13,9 @@ import { Object3D } from './object3d'; ...@@ -13,7 +13,9 @@ import { Object3D } from './object3d';
import { Sphere3D } from '../mol-math/geometry'; import { Sphere3D } from '../mol-math/geometry';
import { Vec3 } from '../mol-math/linear-algebra'; import { Vec3 } from '../mol-math/linear-algebra';
import { BoundaryHelper } from '../mol-math/geometry/boundary-helper'; import { BoundaryHelper } from '../mol-math/geometry/boundary-helper';
import { arraySetAdd, arraySetRemove } from '../mol-util/array'; import { CommitQueue } from './commit-queue';
import { now } from '../mol-util/now';
import { arraySetRemove } from '../mol-util/array';
const boundaryHelper = new BoundaryHelper(); const boundaryHelper = new BoundaryHelper();
function calculateBoundingSphere(renderables: Renderable<RenderableValues & BaseValues>[], boundingSphere: Sphere3D): Sphere3D { function calculateBoundingSphere(renderables: Renderable<RenderableValues & BaseValues>[], boundingSphere: Sphere3D): Sphere3D {
...@@ -56,13 +58,12 @@ interface Scene extends Object3D { ...@@ -56,13 +58,12 @@ interface Scene extends Object3D {
readonly count: number readonly count: number
readonly renderables: ReadonlyArray<Renderable<RenderableValues & BaseValues>> readonly renderables: ReadonlyArray<Renderable<RenderableValues & BaseValues>>
readonly boundingSphere: Sphere3D readonly boundingSphere: Sphere3D
// readonly isCommiting: boolean
update: (objects: ArrayLike<GraphicsRenderObject> | undefined, keepBoundingSphere: boolean, isRemoving?: boolean) => void update: (objects: ArrayLike<GraphicsRenderObject> | undefined, keepBoundingSphere: boolean, isRemoving?: boolean) => void
add: (o: GraphicsRenderObject) => void // Renderable<any> add: (o: GraphicsRenderObject) => void // Renderable<any>
remove: (o: GraphicsRenderObject) => void remove: (o: GraphicsRenderObject) => void
syncCommit: () => void commit: (maxTimeMs?: number) => boolean
// commit: () => Task<void> readonly needsCommit: boolean
has: (o: GraphicsRenderObject) => boolean has: (o: GraphicsRenderObject) => boolean
clear: () => void clear: () => void
forEach: (callbackFn: (value: Renderable<RenderableValues & BaseValues>, key: GraphicsRenderObject) => void) => void forEach: (callbackFn: (value: Renderable<RenderableValues & BaseValues>, key: GraphicsRenderObject) => void) => void
...@@ -78,7 +79,7 @@ namespace Scene { ...@@ -78,7 +79,7 @@ namespace Scene {
const object3d = Object3D.create() const object3d = Object3D.create()
const add = (o: GraphicsRenderObject) => { function add(o: GraphicsRenderObject) {
if (!renderableMap.has(o)) { if (!renderableMap.has(o)) {
const renderable = createRenderable(ctx, o) const renderable = createRenderable(ctx, o)
renderables.push(renderable) renderables.push(renderable)
...@@ -91,18 +92,43 @@ namespace Scene { ...@@ -91,18 +92,43 @@ namespace Scene {
} }
} }
const remove = (o: GraphicsRenderObject) => { function remove(o: GraphicsRenderObject) {
const renderable = renderableMap.get(o) const renderable = renderableMap.get(o)
if (renderable) { if (renderable) {
renderable.dispose() renderable.dispose()
renderables.splice(renderables.indexOf(renderable), 1) arraySetRemove(renderables, renderable);
renderableMap.delete(o) renderableMap.delete(o)
boundingSphereDirty = true boundingSphereDirty = true
} }
} }
const toAdd: GraphicsRenderObject[] = [] const commitBulkSize = 100;
const toRemove: GraphicsRenderObject[] = [] function commit(maxTimeMs: number) {
const start = now();
let i = 0;
while (true) {
const o = commitQueue.tryGetRemove();
if (!o) break;
remove(o);
if (++i % commitBulkSize === 0 && now() - start > maxTimeMs) return false;
}
while (true) {
const o = commitQueue.tryGetAdd();
if (!o) break;
add(o);
if (++i % commitBulkSize === 0 && now() - start > maxTimeMs) return false;
}
renderables.sort(renderableSort)
return true;
}
// const toAdd: GraphicsRenderObject[] = []
// const toRemove: GraphicsRenderObject[] = []
const commitQueue = new CommitQueue();
return { return {
get view () { return object3d.view }, get view () { return object3d.view },
...@@ -126,21 +152,10 @@ namespace Scene { ...@@ -126,21 +152,10 @@ namespace Scene {
} }
if (!keepBoundingSphere) boundingSphereDirty = true if (!keepBoundingSphere) boundingSphereDirty = true
}, },
add: (o: GraphicsRenderObject) => { add: (o: GraphicsRenderObject) => commitQueue.add(o),
arraySetAdd(toAdd, o); remove: (o: GraphicsRenderObject) => commitQueue.remove(o),
arraySetRemove(toRemove, o); commit: (maxTime = Number.MAX_VALUE) => commit(maxTime),
}, get needsCommit() { return !commitQueue.isEmpty; },
remove: (o: GraphicsRenderObject) => {
arraySetAdd(toRemove, o);
arraySetRemove(toAdd, o);
},
syncCommit: () => {
for (let i = 0, il = toRemove.length; i < il; ++i) remove(toRemove[i])
toRemove.length = 0
for (let i = 0, il = toAdd.length; i < il; ++i) add(toAdd[i])
toAdd.length = 0
renderables.sort(renderableSort)
},
has: (o: GraphicsRenderObject) => { has: (o: GraphicsRenderObject) => {
return renderableMap.has(o) return renderableMap.has(o)
}, },
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment