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

Fix memory leaks in Spine caused by not calling freeStoreMemory. #18018

Merged
merged 4 commits into from
Dec 12, 2024
Merged
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
3 changes: 2 additions & 1 deletion cocos/spine/lib/spine-core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@
duration: number;
name: string;
timelines: Array<Timeline>;
apply(skeleton: Skeleton, lastTime: number, time: number, loop: boolean, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 50 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 166. Maximum allowed is 150
hasTimeline(id: number): boolean;
}
interface Timeline {
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 54 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 151. Maximum allowed is 150
getPropertyId(): number;
}
enum MixBlend {
Expand Down Expand Up @@ -94,7 +94,7 @@
getCurveType(frameIndex: number): number;
setCurve(frameIndex: number, cx1: number, cy1: number, cx2: number, cy2: number): void;
getCurvePercent(frameIndex: number, percent: number): number;
abstract apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 97 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 160. Maximum allowed is 150
}
class RotateTimeline extends CurveTimeline {
static ENTRIES: number;
Expand All @@ -106,7 +106,7 @@
constructor(frameCount: number);
getPropertyId(): number;
setFrame(frameIndex: number, time: number, degrees: number): void;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 109 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 151. Maximum allowed is 150
}
class TranslateTimeline extends CurveTimeline {
static readonly ENTRIES: number;
Expand All @@ -114,17 +114,17 @@
constructor(frameCount: number);
getPropertyId(): number;
setFrame(frameIndex: number, time: number, x: number, y: number): void;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 117 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 151. Maximum allowed is 150
}
class ScaleTimeline extends TranslateTimeline {
constructor(frameCount: number);
getPropertyId(): number;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 122 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 151. Maximum allowed is 150
}
class ShearTimeline extends TranslateTimeline {
constructor(frameCount: number);
getPropertyId(): number;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 127 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 151. Maximum allowed is 150
}
class ColorTimeline extends CurveTimeline {
static ENTRIES: number;
Expand All @@ -135,7 +135,7 @@
getSlotIndex(): number;
setSlotIndex(inValue: number): void;
setFrame(frameIndex: number, time: number, r: number, g: number, b: number, a: number): void;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 138 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 151. Maximum allowed is 150
}
class TwoColorTimeline extends CurveTimeline {
static readonly ENTRIES: number;
Expand All @@ -146,7 +146,7 @@
getSlotIndex(): number;
setSlotIndex(inValue: number): void;
setFrame(frameIndex: number, time: number, r: number, g: number, b: number, a: number, r2: number, g2: number, b2: number): void;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 149 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 151. Maximum allowed is 150
}
class AttachmentTimeline implements Timeline {
slotIndex: number;
Expand All @@ -159,7 +159,7 @@
setSlotIndex(inValue: number): void;
getAttachmentNames(): Array<string>;
setFrame(frameIndex: number, time: number, attachmentName: string): void;
apply(skeleton: Skeleton, lastTime: number, time: number, events: Array<Event>, alpha: number, blend: MixBlend, direction: MixDirection): void;

Check warning on line 162 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 151. Maximum allowed is 150
}
class DeformTimeline extends CurveTimeline {
slotIndex: number;
Expand Down Expand Up @@ -781,7 +781,7 @@
MipMapNearestNearest = 9984,
MipMapLinearNearest = 9985,
MipMapNearestLinear = 9986,
MipMapLinearLinear = 9987

Check failure on line 784 in cocos/spine/lib/spine-core.d.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

Duplicate enum member value 9987
}
enum TextureWrap {
MirroredRepeat = 33648,
Expand Down Expand Up @@ -1214,7 +1214,8 @@
class wasmUtil {
static spineWasmInit(): void;
static spineWasmDestroy(): void;
static queryStoreMemory(size: number): number;
static freeStoreMemory(): void;
static createStoreMemory(size: number): number;
static querySpineSkeletonDataByUUID(uuid: string): SkeletonData;
static createSpineSkeletonDataWithJson(jsonStr: string, atlasText: string): SkeletonData;
static createSpineSkeletonDataWithBinary(byteSize: number, atlasText: string): SkeletonData;
Expand Down
3 changes: 2 additions & 1 deletion cocos/spine/skeleton-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,12 @@ export class SkeletonData extends Asset {
} else {
const rawData = new Uint8Array(this._nativeAsset);
const byteSize = rawData.length;
const ptr = spine.wasmUtil.queryStoreMemory(byteSize);
const ptr = spine.wasmUtil.createStoreMemory(byteSize);
const wasmMem = spine.wasmUtil.wasm.HEAPU8.subarray(ptr, ptr + byteSize);
wasmMem.set(rawData);
this._skeletonCache = spine.wasmUtil.createSpineSkeletonDataWithBinary(byteSize, this._atlasText);
spine.wasmUtil.registerSpineSkeletonDataWithUUID(this._skeletonCache, uuid);
spine.wasmUtil.freeStoreMemory();
}

return this._skeletonCache;
Expand Down
3 changes: 2 additions & 1 deletion native/cocos/editor-support/spine-wasm/spine-type-export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1382,7 +1382,8 @@ EMSCRIPTEN_BINDINGS(cocos_spine) {
class_<SpineWasmUtil>("SpineWasmUtil")
.class_function("spineWasmInit", &SpineWasmUtil::spineWasmInit)
.class_function("spineWasmDestroy", &SpineWasmUtil::spineWasmDestroy)
.class_function("queryStoreMemory", &SpineWasmUtil::queryStoreMemory)
.class_function("createStoreMemory", &SpineWasmUtil::createStoreMemory)
.class_function("freeStoreMemory", &SpineWasmUtil::freeStoreMemory)
.class_function("querySpineSkeletonDataByUUID", &SpineWasmUtil::querySpineSkeletonDataByUUID, allow_raw_pointers())
.class_function("createSpineSkeletonDataWithJson", &SpineWasmUtil::createSpineSkeletonDataWithJson, allow_raw_pointers())
.class_function("createSpineSkeletonDataWithBinary", &SpineWasmUtil::createSpineSkeletonDataWithBinary, allow_raw_pointers())
Expand Down
16 changes: 3 additions & 13 deletions native/cocos/editor-support/spine-wasm/spine-wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ EventType SpineWasmUtil::s_currentType = EventType_Event;
TrackEntry* SpineWasmUtil::s_currentEntry = nullptr;
Event* SpineWasmUtil::s_currentEvent = nullptr;
uint8_t* SpineWasmUtil::s_mem = nullptr;
uint32_t SpineWasmUtil::s_memSize = 0;

void SpineWasmUtil::spineWasmInit() {
// LogUtil::Initialize();
Expand Down Expand Up @@ -95,17 +94,9 @@ void SpineWasmUtil::destroySpineSkeleton(Skeleton* skeleton) {
}
}

uint32_t SpineWasmUtil::queryStoreMemory(uint32_t size) {
if (s_mem) {
if (s_memSize < size) {
delete[] s_mem;
s_mem = new uint8_t[size];
s_memSize = size;
}
} else {
s_mem = new uint8_t[size];
s_memSize = size;
}
uint32_t SpineWasmUtil::createStoreMemory(uint32_t size) {
s_mem = new uint8_t[size];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't have to delete previous memory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queryStoreMemory is responsible for allocation, while freeStoreMemory is responsible for deallocation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, why not rename to createStoreMemory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


return (uint32_t)s_mem;
}

Expand All @@ -114,7 +105,6 @@ void SpineWasmUtil::freeStoreMemory() {
delete[] s_mem;
s_mem = nullptr;
}
s_memSize = 0;
}

uint32_t SpineWasmUtil::getCurrentListenerID() {
Expand Down
3 changes: 1 addition & 2 deletions native/cocos/editor-support/spine-wasm/spine-wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class SpineWasmUtil {
public:
static void spineWasmInit();
static void spineWasmDestroy();
static uint32_t queryStoreMemory(uint32_t size);
static uint32_t createStoreMemory(uint32_t size);
static void freeStoreMemory();

static spine::SkeletonData* querySpineSkeletonDataByUUID(const spine::String& uuid);
Expand All @@ -28,5 +28,4 @@ class SpineWasmUtil {
static spine::Event* s_currentEvent;

static uint8_t* s_mem;
static uint32_t s_memSize;
};
Loading