Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize spine memory leak & optimize. #16384

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 23 additions & 37 deletions cocos/spine/assembler/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
THE SOFTWARE.
*/

import { UIRenderable } from '../../2d';
import { IAssembler } from '../../2d/renderer/base';

import { Batcher2D } from '../../2d/renderer/batcher-2d';
Expand Down Expand Up @@ -58,6 +57,8 @@ const _byteStrideTwoColor = getAttributeStride(vfmtPosUvTwoColor4B);
const DEBUG_TYPE_REGION = 0;
const DEBUG_TYPE_MESH = 1;

const tempVecPos = new Vec3(0, 0, 0);

function _getSlotMaterial (blendMode: number, comp: Skeleton): MaterialInstance {
let src: BlendFactor;
let dst: BlendFactor;
Expand All @@ -84,12 +85,6 @@ function _getSlotMaterial (blendMode: number, comp: Skeleton): MaterialInstance
}

export const simple: IAssembler = {
fillBuffers (render: UIRenderable, batcher: Batcher2D) {

},
updateColor (render: UIRenderable) {

},
vCount: 32767,
ensureAccessor (useTint: boolean) {
let accessor = useTint ? _tintAccessor : _accessor;
Expand Down Expand Up @@ -141,70 +136,62 @@ function updateComponentRenderData (comp: Skeleton, batcher: Batcher2D): void {
}
const rd = comp.renderData!;
const accessor = _useTint ? _tintAccessor : _accessor;
comp.syncAttachedNode();
if (rd.vertexCount > 0 || rd.indexCount > 0) accessor.getMeshBuffer(rd.chunk.bufferId).setDirty();
}

function realTimeTraverse (comp: Skeleton): void {
const floatStride = (_useTint ? _byteStrideTwoColor : _byteStrideOneColor) / Float32Array.BYTES_PER_ELEMENT;
const floatStride = (comp.useTint ? _byteStrideTwoColor : _byteStrideOneColor) / Float32Array.BYTES_PER_ELEMENT;
const model = comp.updateRenderData();
if (!model) return;
const vc = model.vCount as number;
const ic = model.iCount as number;
const rd = comp.renderData!;
if (vc < 1 || ic < 1) return;

const rd = comp.renderData!;
if (rd.vertexCount !== vc || rd.indexCount !== ic) {
rd.resize(vc, ic);
rd.indices = new Uint16Array(ic);
comp._vLength = vc * Float32Array.BYTES_PER_ELEMENT * floatStride;
comp._vBuffer = new Uint8Array(rd.chunk.vb.buffer, rd.chunk.vb.byteOffset, Float32Array.BYTES_PER_ELEMENT * rd.chunk.vb.length);
comp._iLength = Uint16Array.BYTES_PER_ELEMENT * ic;
comp._iBuffer = new Uint8Array(rd.indices.buffer);
}
if (vc < 1 || ic < 1) return;

const vbuf = rd.chunk.vb;
const vUint8Buf = new Uint8Array(vbuf.buffer, vbuf.byteOffset, Float32Array.BYTES_PER_ELEMENT * vbuf.length);

const vPtr = model.vPtr;
const vLength = vc * Float32Array.BYTES_PER_ELEMENT * floatStride;
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
const vData = spine.wasmUtil.wasm.HEAPU8.subarray(vPtr, vPtr + vLength);
vUint8Buf.set(vData as TypedArray);

const iPtr = model.iPtr;
const ibuf = rd.indices!;
const iLength = Uint16Array.BYTES_PER_ELEMENT * ic;
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
const iData = spine.wasmUtil.wasm.HEAPU8.subarray(iPtr, iPtr + iLength);
const iUint8Buf = new Uint8Array(ibuf.buffer);
iUint8Buf.set(iData as TypedArray);
const HEAPU8 = spine.wasmUtil.wasm.HEAPU8;

comp._vBuffer?.set(HEAPU8.subarray(vPtr, vPtr + comp._vLength), 0);
comp._iBuffer?.set(HEAPU8.subarray(iPtr, iPtr + comp._iLength), 0);
const chunkOffset = rd.chunk.vertexOffset;
for (let i = 0; i < ic; i++) {
ibuf[i] += chunkOffset;
}
for (let i = 0; i < ic; i++) ibuf[i] += chunkOffset;

const meshes = model.getMeshes();
const count = meshes.size();
const data = model.getData();
const count = data.size();
let indexOffset = 0;
let indexCount = 0;
for (let i = 0; i < count; i++) {
const mesh = meshes.get(i);
const material = _getSlotMaterial(mesh.blendMode as number, comp);
const textureID = mesh.textureID as number;
indexCount = mesh.iCount;
for (let i = 0; i < count; i += 6) {
indexCount = data.get(i + 3);
const material = _getSlotMaterial(data.get(i + 4), comp);
const textureID: number = data.get(i + 5);
comp.requestDrawData(material, textureID, indexOffset, indexCount);
indexOffset += indexCount;
}

// if enableBatch apply worldMatrix
if (comp.enableBatch) {
const worldMat = comp.node.worldMatrix;
let index = 0;
const tempVecPos = new Vec3(0, 0, 0);
for (let i = 0; i < vc; i++) {
index = i * floatStride;
tempVecPos.x = vbuf[index];
tempVecPos.y = vbuf[index + 1];
tempVecPos.z = 0;
dumganhar marked this conversation as resolved.
Show resolved Hide resolved
tempVecPos.transformMat4(worldMat);
vbuf[index] = tempVecPos.x;
vbuf[index + 1] = tempVecPos.y;
vbuf[index + 2] = tempVecPos.z;
vbuf[index + 2] = 0;
}
}

Expand Down Expand Up @@ -341,7 +328,6 @@ function cacheTraverse (comp: Skeleton): void {
if (comp.enableBatch) {
const worldMat = comp.node.worldMatrix;
let index = 0;
const tempVecPos = new Vec3(0, 0, 0);
for (let i = 0; i < vc; i++) {
index = i * floatStride;
tempVecPos.x = vbuf[index];
Expand Down
96 changes: 41 additions & 55 deletions cocos/spine/attach-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { Mat4 } from '../core';
import { Skeleton } from './skeleton';
import { Node } from '../scene-graph';
import spine from './lib/spine-core';
import { FrameBoneInfo } from './skeleton-cache';

const tempMat4 = new Mat4();

Expand All @@ -35,75 +36,60 @@ const tempMat4 = new Mat4();
* @class sp.AttachUtil
*/
export class AttachUtil {
protected _inited = false;
protected _skeleton: spine.Skeleton | null = null;
protected _skeletonNode: Node|null = null;
protected _skeletonComp: Skeleton|null = null;
protected _isInitialized = false;
protected _skeletonBones: spine.Bone[] | FrameBoneInfo[] | null = null;
protected _socketNodes: Map<number, Node> | null = null;
private _keysToDelete: number[] = [];

constructor () {
this._inited = false;
this._skeleton = null;
this._skeletonNode = null;
this._skeletonComp = null;
this._isInitialized = false;
}

init (skeletonComp: Skeleton): void {
this._inited = true;
this._skeleton = skeletonComp._skeleton;
this._skeletonNode = skeletonComp.node;
this._skeletonComp = skeletonComp;
this._isInitialized = false;
if (!skeletonComp || skeletonComp.socketNodes?.size === 0) return;
const isCached = skeletonComp.isAnimationCached();
this._skeletonBones = isCached && skeletonComp._curFrame ? skeletonComp._curFrame.boneInfos : skeletonComp._skeleton.bones;
if (!this._skeletonBones || this._skeletonBones.length < 1) return;
this._socketNodes = skeletonComp.socketNodes;
if (!this._socketNodes || this._socketNodes.size <= 0) return;
this._isInitialized = true;
this._syncAttachedNode();
}

reset (): void {
this._inited = false;
this._skeleton = null;
this._skeletonNode = null;
this._skeletonComp = null;
this._isInitialized = false;
this._skeletonBones = null;
this._socketNodes = null;
this._keysToDelete.length = 0;
}

_syncAttachedNode (): void {
if (!this._inited) return;

const socketNodes = this._skeletonComp!.socketNodes;
if (socketNodes.size === 0) return;

let boneInfos;
const isCached = this._skeletonComp!.isAnimationCached();
if (isCached && this._skeletonComp!._curFrame) {
boneInfos = this._skeletonComp!._curFrame.boneInfos;
} else {
boneInfos = this._skeleton!.bones;
}

if (!boneInfos || boneInfos.length < 1) return;

const matrixHandle = (node: Node, bone: any): void => {
const tm = tempMat4;
tm.m00 = bone.a;
tm.m01 = bone.c;
tm.m04 = bone.b;
tm.m05 = bone.d;
tm.m12 = bone.worldX;
tm.m13 = bone.worldY;
node.matrix = tempMat4;
};

for (const boneIdx of socketNodes.keys()) {
const boneNode = socketNodes.get(boneIdx);
// Node has been destroy
if (!this._isInitialized) return;
const socketNodes = this._socketNodes!;
for (const [boneIdx, boneNode] of socketNodes) {
if (!boneNode || !boneNode.isValid) {
socketNodes.delete(boneIdx);
this._keysToDelete.push(boneIdx);
continue;
}
const bone = boneInfos[boneIdx];
// Bone has been destroy
if (!bone) {
boneNode.removeFromParent();
boneNode.destroy();
socketNodes.delete(boneIdx);
continue;
}
matrixHandle(boneNode, bone);
const bone = this._skeletonBones![boneIdx];
if (bone) this.matrixHandle(boneNode, bone);
}
if (this._keysToDelete.length <= 0) return;
for (const boneIdx of this._keysToDelete) {
socketNodes.delete(boneIdx);
}
this._keysToDelete.length = 0;
}

matrixHandle (node: Node, bone: any): void {
const tm = tempMat4;
tm.m00 = bone.a;
tm.m01 = bone.c;
tm.m04 = bone.b;
tm.m05 = bone.d;
tm.m12 = bone.worldX;
tm.m13 = bone.worldY;
node.matrix = tempMat4;
}
}
29 changes: 27 additions & 2 deletions cocos/spine/lib/spine-core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@
/* eslint @typescript-eslint/no-explicit-any: "off" */

declare namespace spine {

class String {
length: number;
isEmpty: boolean;
strPtr: number;
str: string;
}

class SPVectorFloat {
size(): number;
resize(newSize: number, defaultValue: number);
set(index: number, value: number);
get(index: number): number;
delete();
}

class Animation {
constructor(name: string, timelines: Array<Timeline>, duration: number);
duration: number;
Expand Down Expand Up @@ -555,7 +571,6 @@ declare namespace spine {
transformConstraints: Array<TransformConstraint>;
pathConstraints: Array<PathConstraint>;
_updateCache: Updatable[];
updateCacheReset: Updatable[];
skin: Skin;
color: Color;
time: number;
Expand Down Expand Up @@ -685,7 +700,7 @@ declare namespace spine {
scale: number;
private linkedMeshes;
constructor(attachmentLoader: AttachmentLoader);
readSkeletonData(json: string | any): SkeletonData;
readSkeletonData(json: any): SkeletonData;
readAttachment(map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment;
readVertices(map: any, attachment: VertexAttachment, verticesLength: number): void;
readAnimation(map: any, name: string, skeletonData: SkeletonData): void;
Expand Down Expand Up @@ -1163,7 +1178,17 @@ declare namespace spine {
end(): void;
}

class SkeletonSystem {
public static updateAnimation(deltaTime: number): void;
public static updateRenderData(): void;
public static getCount(): number;
}

class SkeletonInstance {
dtRate: number;
isCache: boolean;
isDelete: boolean;
enable: boolean;
initSkeleton(data: SkeletonData);
getAnimationState();
setAnimation(trackIndex: number, name: string, loop: boolean): spine.TrackEntry | null;
Expand Down
Loading
Loading