Skip to content

Commit 50736ce

Browse files
authored
Disable rendering (to release graphics related memory) when EngineHook unmounts (#120)
1 parent 4494dbc commit 50736ce

File tree

11 files changed

+64
-3
lines changed

11 files changed

+64
-3
lines changed

Modules/@babylonjs/react-native/BabylonModule.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,27 @@ import { NativeEngine } from '@babylonjs/core';
33

44
// This global object is part of Babylon Native.
55
declare const _native: {
6-
graphicsInitializationPromise: Promise<void>;
6+
whenGraphicsReady: () => Promise<void>;
77
engineInstance: NativeEngine;
88
}
99

1010
const NativeBabylonModule: {
1111
initialize(): Promise<boolean>;
1212
whenInitialized(): Promise<boolean>;
13+
reset(): Promise<boolean>;
1314
} = NativeModules.BabylonModule;
1415

1516
export const BabylonModule = {
1617
initialize: async () => {
1718
const initialized = await NativeBabylonModule.initialize();
1819
if (initialized) {
19-
await _native.graphicsInitializationPromise;
20+
await _native.whenGraphicsReady();
2021
}
2122
return initialized;
2223
},
2324

2425
whenInitialized: NativeBabylonModule.whenInitialized,
26+
reset: NativeBabylonModule.reset,
2527

2628
createEngine: () => {
2729
const engine = new NativeEngine();

Modules/@babylonjs/react-native/EngineHook.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export function useEngine(): Engine | undefined {
8383
if (engine) {
8484
DisposeEngine(engine);
8585
}
86+
BabylonModule.reset();
8687
setEngine(undefined);
8788
};
8889
}, []);

Modules/@babylonjs/react-native/android/src/main/cpp/BabylonNativeInterop.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ namespace Babylon
8585
auto height = static_cast<size_t>(ANativeWindow_getHeight(windowPtr));
8686
m_graphics->UpdateWindow<void*>(windowPtr);
8787
m_graphics->UpdateSize(width, height);
88+
m_graphics->EnableRendering();
89+
}
90+
91+
void Reset()
92+
{
93+
m_graphics->DisableRendering();
8894
}
8995

9096
void SetPointerButtonState(uint32_t pointerId, uint32_t buttonId, bool isDown, uint32_t x, uint32_t y)
@@ -166,6 +172,12 @@ extern "C" JNIEXPORT void JNICALL Java_com_babylonreactnative_BabylonNativeInter
166172
native->SetPointerPosition(static_cast<uint32_t>(pointerId), static_cast<uint32_t>(x), static_cast<uint32_t>(y));
167173
}
168174

175+
extern "C" JNIEXPORT void JNICALL Java_com_babylonreactnative_BabylonNativeInterop_reset(JNIEnv* env, jclass obj, jlong instanceRef)
176+
{
177+
auto native = reinterpret_cast<Babylon::Native*>(instanceRef);
178+
native->Reset();
179+
}
180+
169181
extern "C" JNIEXPORT void JNICALL Java_com_babylonreactnative_BabylonNativeInterop_destroy(JNIEnv* env, jclass obj, jlong instanceRef)
170182
{
171183
auto native = reinterpret_cast<Babylon::Native*>(instanceRef);

Modules/@babylonjs/react-native/android/src/main/java/com/babylonreactnative/BabylonModule.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,12 @@ public void initialize(Promise promise) {
3939
public void whenInitialized(Promise promise) {
4040
BabylonNativeInterop.whenInitialized(this.getReactApplicationContext()).thenAccept(instanceRef -> promise.resolve(instanceRef != 0));
4141
}
42+
43+
@ReactMethod
44+
public void reset(Promise promise) {
45+
this.getReactApplicationContext().runOnJSQueueThread(() -> {
46+
BabylonNativeInterop.reset(this.getReactApplicationContext());
47+
promise.resolve(null);
48+
});
49+
}
4250
}

Modules/@babylonjs/react-native/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ final class BabylonNativeInterop {
3535
private static native void refresh(long instanceRef, Surface surface);
3636
private static native void setPointerButtonState(long instanceRef, int pointerId, int buttonId, boolean isDown, int x, int y);
3737
private static native void setPointerPosition(long instanceRef, int pointerId, int x, int y);
38+
private static native void reset(long instanceRef);
3839
private static native void destroy(long instanceRef);
3940

4041
// Must be called from the Android UI thread
@@ -137,6 +138,17 @@ static void deinitialize() {
137138
BabylonNativeInterop.destroyOldNativeInstances(null);
138139
}
139140

141+
static void reset(ReactContext reactContext) {
142+
JavaScriptContextHolder jsContext = reactContext.getJavaScriptContextHolder();
143+
CompletableFuture<Long> instanceRefFuture = BabylonNativeInterop.nativeInstances.get(jsContext);
144+
if (instanceRefFuture != null) {
145+
Long instanceRef = instanceRefFuture.getNow(null);
146+
if (instanceRef != null) {
147+
BabylonNativeInterop.reset(instanceRef);
148+
}
149+
}
150+
}
151+
140152
private static CompletableFuture<Long> getOrCreateFuture(ReactContext reactContext) {
141153
JavaScriptContextHolder jsContext = reactContext.getJavaScriptContextHolder();
142154
CompletableFuture<Long> instanceRefFuture = BabylonNativeInterop.nativeInstances.get(jsContext);

Modules/@babylonjs/react-native/ios/BabylonModule.mm

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
#import "BabylonNativeInterop.h"
22

33
#import <React/RCTBridgeModule.h>
4+
#import <ReactCommon/CallInvoker.h>
45

56
#import <Foundation/Foundation.h>
67

8+
@interface RCTBridge (RCTTurboModule)
9+
- (std::shared_ptr<facebook::react::CallInvoker>)jsCallInvoker;
10+
@end
11+
712
@interface BabylonModule : NSObject <RCTBridgeModule>
813
@end
914

@@ -21,4 +26,11 @@ @implementation BabylonModule
2126
[BabylonNativeInterop whenInitialized:self.bridge resolve:resolve];
2227
}
2328

29+
RCT_EXPORT_METHOD(reset:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
30+
self.bridge.jsCallInvoker->invokeAsync([resolve]() {
31+
[BabylonNativeInterop reset];
32+
resolve([NSNull null]);
33+
});
34+
}
35+
2436
@end

Modules/@babylonjs/react-native/ios/BabylonNative.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,19 @@ namespace Babylon
8787
{
8888
m_impl->graphics->UpdateWindow<void*>(windowPtr);
8989
m_impl->graphics->UpdateSize(width, height);
90+
m_impl->graphics->EnableRendering();
9091
}
9192

9293
void Native::Resize(size_t width, size_t height)
9394
{
9495
m_impl->graphics->UpdateSize(width, height);
9596
}
9697

98+
void Native::Reset()
99+
{
100+
m_impl->graphics->DisableRendering();
101+
}
102+
97103
void Native::SetPointerButtonState(uint32_t pointerId, uint32_t buttonId, bool isDown, uint32_t x, uint32_t y)
98104
{
99105
if (isDown)

Modules/@babylonjs/react-native/ios/BabylonNative.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace Babylon
1313
~Native();
1414
void Refresh(void* windowPtr, size_t width, size_t height);
1515
void Resize(size_t width, size_t height);
16+
void Reset();
1617
void SetPointerButtonState(uint32_t pointerId, uint32_t buttonId, bool isDown, uint32_t x, uint32_t y);
1718
void SetPointerPosition(uint32_t pointerId, uint32_t x, uint32_t y);
1819

Modules/@babylonjs/react-native/ios/BabylonNativeInterop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
+ (void)setView:(RCTBridge*)bridge jsRunLoop:(NSRunLoop*)jsRunLoop mktView:(MTKView*)mtkView;
88
+ (void)reportTouchEvent:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event;
99
+ (void)whenInitialized:(RCTBridge*)bridge resolve:(RCTPromiseResolveBlock)resolve;
10+
+ (void)reset;
1011
@end

Modules/@babylonjs/react-native/ios/BabylonNativeInterop.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ + (void)whenInitialized:(RCTBridge*)bridge resolve:(RCTPromiseResolveBlock)resol
115115
}
116116
}
117117

118+
+ (void)reset {
119+
if (currentNativeInstance) {
120+
currentNativeInstance->Reset();
121+
}
122+
}
123+
118124
+ (void)setCurrentView:(MTKView*)mtkView {
119125
currentView = mtkView;
120126
activeTouches = [NSMutableArray new];

0 commit comments

Comments
 (0)