Skip to content

Commit

Permalink
fix: enhance perf of Text when fontSize changed in webgl #1422
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoiver committed Jul 20, 2023
1 parent 0e5ba2c commit 8cbcf8c
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 187 deletions.
5 changes: 0 additions & 5 deletions packages/g-plugin-device-renderer/src/meshes/Instanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,6 @@ export abstract class Instanced {

protected abstract createMaterial(objects: DisplayObject[]): void;

/**
* Get called when instance created or recreated.
*/
onCreate(object: DisplayObject) {}

get instance() {
return this.objects[0];
}
Expand Down
11 changes: 10 additions & 1 deletion packages/g-plugin-device-renderer/src/meshes/InstancedPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import {
VertexAttributeLocation,
} from './Instanced';
import { updateBuffer } from './Line';
import { RenderHelper } from '../render';
import { TexturePool } from '../TexturePool';
import { LightPool } from '../LightPool';

enum LineVertexAttributeBufferIndex {
PACKED = VertexAttributeBufferIndex.POSITION + 1,
Expand Down Expand Up @@ -50,7 +53,13 @@ export class InstancedPathMesh extends Instanced {
return false;
}

onCreate(object: DisplayObject) {
constructor(
protected renderHelper: RenderHelper,
protected texturePool: TexturePool,
protected lightPool: LightPool,
object: DisplayObject,
) {
super(renderHelper, texturePool, lightPool, object);
this.segmentNum = this.calcSegmentNum(object);
}

Expand Down
58 changes: 32 additions & 26 deletions packages/g-plugin-device-renderer/src/meshes/Text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import type GlyphAtlas from './symbol/GlyphAtlas';
import { BASE_FONT_WIDTH, GlyphManager } from './symbol/GlyphManager';
import { getGlyphQuads } from './symbol/SymbolQuad';
import { packUint8ToFloat } from '../utils/compression';
import { LightPool } from '../LightPool';
import { TexturePool } from '../TexturePool';
import { RenderHelper } from '../render';

enum TextVertexAttributeBufferIndex {
INSTANCED = VertexAttributeBufferIndex.POSITION + 1,
Expand Down Expand Up @@ -50,41 +53,46 @@ export class TextMesh extends Instanced {

private tmpMat4 = mat4.create();

shouldMerge(object: DisplayObject, index: number) {
const shouldMerge = super.shouldMerge(object, index);

if (!shouldMerge) {
return false;
}
private fontHash: string;

if (this.index !== index) {
return false;
}
constructor(
protected renderHelper: RenderHelper,
protected texturePool: TexturePool,
protected lightPool: LightPool,
object: DisplayObject,
) {
super(renderHelper, texturePool, lightPool, object);
this.fontHash = this.calcFontHash(object);
}

const instance = this.instance;
private calcFontHash(object: DisplayObject) {
const instancedAttributes = [
'fontSize',
'fontFamily',
'fontWeight',
'textBaseline',
'letterSpacing',
];
return (
object.parsedStyle.metrics.font +
instancedAttributes.reduce((prev, cur) => {
return prev + object.parsedStyle[cur];
}, '')
);
}

// fontStack & fontSize should be same
// if (instance.parsedStyle.fontSize !== object.parsedStyle.fontSize) {
// return false;
// }
shouldMerge(object: DisplayObject, index: number) {
const shouldMerge = super.shouldMerge(object, index);

if (
instance.parsedStyle.metrics.font !== object.parsedStyle.metrics.font ||
instancedAttributes.some(
(name) => instance.parsedStyle[name] !== object.parsedStyle[name],
)
) {
if (!shouldMerge) {
return false;
}

return true;
if (this.index !== index) {
return false;
}

return this.fontHash === this.calcFontHash(object);
}

createGeometry(objects: DisplayObject[]): void {
Expand Down Expand Up @@ -307,7 +315,6 @@ export class TextMesh extends Instanced {
name === 'lineHeight' ||
name === 'wordWrap' ||
name === 'textAlign' ||
name === 'visibility' ||
name === 'dx' ||
name === 'dy'
) {
Expand All @@ -323,6 +330,7 @@ export class TextMesh extends Instanced {
name === 'strokeOpacity' ||
name === 'opacity' ||
name === 'lineWidth' ||
name === 'visibility' ||
name === 'pointerEvents'
) {
const vertice = this.geometry.vertices[
Expand Down Expand Up @@ -370,10 +378,7 @@ export class TextMesh extends Instanced {
// @ts-ignore
object.renderable3D?.encodedPickingColor) || [0, 0, 0];

const modelMatrix =
name === 'modelMatrix'
? mat4.copy(this.tmpMat4, object.getWorldTransform())
: null;
const modelMatrix = mat4.copy(this.tmpMat4, object.getWorldTransform());

const [start, end] = this.packedBufferObjectMap.get(object);
const sliced = vertice.slice(start, end);
Expand Down Expand Up @@ -413,6 +418,7 @@ export class TextMesh extends Instanced {
sliced[i + 28] = encodedPickingColor[0];
sliced[i + 29] = encodedPickingColor[1];
sliced[i + 30] = encodedPickingColor[2];
// sliced[i + 31] = object.sortable.renderOrder * RENDER_ORDER_SCALE;
}

this.geometry.updateVertexBuffer(
Expand Down
78 changes: 41 additions & 37 deletions packages/g-plugin-device-renderer/src/renderer/BatchManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import type { Batch } from './Batch';

let stencilRefCounter = 1;

/**
* Create a new batch if the number of instances exceeds.
*/
const MAX_INSTANCES_PER_BATCH = 5000;

export type BatchContext = { device: Device } & RenderingPluginContext;
Expand Down Expand Up @@ -45,6 +48,7 @@ export class BatchManager {
objectIndices: number[];
name: string;
value: any;
// names: string[];
}
> = {};

Expand Down Expand Up @@ -114,8 +118,8 @@ export class BatchManager {
this.renderHelper,
this.texturePool,
this.lightPool,
object,
);
existedMesh.onCreate(object);
existedMesh.renderer = renderer;
existedMesh.index = i;
this.meshes.push(existedMesh);
Expand Down Expand Up @@ -202,11 +206,11 @@ export class BatchManager {
this.renderHelper,
this.texturePool,
this.lightPool,
object,
);
existedMesh.renderer = renderer;
existedMesh.index = i;
existedMesh.init(this.context);
existedMesh.onCreate(object);
this.meshes.push(existedMesh);
} else {
existedMesh.geometryDirty = true;
Expand All @@ -219,46 +223,46 @@ export class BatchManager {
}
}

if (
shouldSubmit &&
existedMesh &&
existedMesh.inited &&
!existedMesh.geometryDirty
) {
const shouldMerge = existedMesh.shouldMerge(object, i);
if (shouldMerge) {
const objectIdx = existedMesh.objects.indexOf(object);
if (immediately) {
object.parsedStyle[attributeName] = newValue;
existedMesh.updateAttribute(
[object],
objectIdx,
attributeName,
newValue,
);
} else {
const patchKey = existedMesh.id + attributeName;
if (!this.pendingUpdatePatches[patchKey]) {
this.pendingUpdatePatches[patchKey] = {
instance: existedMesh,
objectIndices: [],
name: attributeName,
value: newValue,
};
}
if (
this.pendingUpdatePatches[patchKey].objectIndices.indexOf(
objectIdx,
) === -1
) {
this.pendingUpdatePatches[patchKey].objectIndices.push(
if (shouldSubmit && existedMesh) {
if (existedMesh.inited && !existedMesh.geometryDirty) {
const shouldMerge = existedMesh.shouldMerge(object, i);
if (shouldMerge) {
const objectIdx = existedMesh.objects.indexOf(object);
if (immediately) {
object.parsedStyle[attributeName] = newValue;
existedMesh.updateAttribute(
[object],
objectIdx,
attributeName,
newValue,
);
} else {
const patchKey = existedMesh.id + attributeName;
if (!this.pendingUpdatePatches[patchKey]) {
this.pendingUpdatePatches[patchKey] = {
instance: existedMesh,
objectIndices: [],
name: attributeName,
value: newValue,
};
}
if (
this.pendingUpdatePatches[patchKey].objectIndices.indexOf(
objectIdx,
) === -1
) {
this.pendingUpdatePatches[patchKey].objectIndices.push(
objectIdx,
);
}
}
} else {
this.remove(object);
this.add(object);
}
} else {
existedMesh.geometryDirty = true;
existedMesh.onCreate(object);
this.remove(object);
this.add(object);
}
}
});
Expand Down
7 changes: 7 additions & 0 deletions site/examples/perf/animation/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
"zh": "移动大量节点",
"en": "Move nodes"
}
},
{
"filename": "webgl-text.js",
"title": {
"zh": "在 WebGL 中更新 Text 的位置",
"en": "Update position of Text in WebGL"
}
}
]
}
Loading

0 comments on commit 8cbcf8c

Please sign in to comment.