sceneform-android: [Critical] [Bug] Memory leaks [SOLUTION INCLUDED] [FIXED]
@ThomasGorisse Sorry to worry You, but I have a huge problem with memory.
I’m trying everything, but nothing works.
private fun reclaimReleasedResources() {
SceneView.reclaimReleasedResources()
Renderer.reclaimReleasedResources()
ResourceManager
.getInstance()
.reclaimReleasedResources()
ResourceManager
.getInstance()
.destroyAllResources()
}
arSceneView?.apply {
scene?.callOnHierarchy { node ->
try {
node.parent = null
if (node is AnchorNode) {
TimberLog.e("[CLEAN_UP] Detach: $node")
node.renderableInstance?.clear()
node.anchor?.apply {
detach()
}
}
} catch (e: UnsupportedOperationException) {
TimberLog.e("[CLEAN_UP] Error: ${e.message}")
}
}
destroySession()
}
arCharactersViewModel.getArCharacters().forEach { character ->
character.apply {
animationController.clear()
cloud.node.renderableInstance.clear()
distance.node.renderableInstance.clear()
arCharacterNode.renderableInstance.clear()
}
}
EngineInstance
.getEngine()
.filamentEngine
.flushAndWait()
locationArScene.clearRouteSteps()
locationArScene.clearArObjects()
locationArScene.stopLocationScene()
fun RenderableInstance.clear() {
filamentAsset?.releaseSourceData()
detachFromRenderer()
destroy()
}
What else can I do? I can’t migrate to sceneview as my project is too large at this point.
Each session (for example navigation to arFragment, add ± 100mb to memory stack. So after 10-15 sessions app crashes due to memory usage. Is anything I can do?
Some code with load AR models:
try {
getModelRenderable(
path,
context
)?.thenAccept { renderable ->
interaction.locations.forEach { location ->
viewModelScope.launch(Dispatchers.Main) {
val touch = ViewRenderable.builder()
.setView(context.get(), R.layout.view_character_touch)
.setAsyncLoadEnabled(true)
.await()
.apply {
isShadowCaster = false
isShadowReceiver = false
}
val interactionView = ViewRenderable.builder()
.setView(context.get(), R.layout.view_character_interaction)
.setAsyncLoadEnabled(true)
.await()
.apply {
isShadowCaster = false
isShadowReceiver = false
}
val distance = ViewRenderable.builder()
.setView(context.get(), R.layout.view_distance)
.setAsyncLoadEnabled(true)
.await()
.apply {
isShadowCaster = false
isShadowReceiver = false
}
val cloud = ViewRenderable.builder()
.setView(context.get(), R.layout.navigation_cloud)
.setAsyncLoadEnabled(true)
.await()
.apply {
isShadowCaster = false
isShadowReceiver = false
}
val transformableNode = TransformableNode(transformation).apply {
this.renderable = renderable
}
val nodeCloud = getNode(cloud)
val distanceCloud = getNode(distance)
transformableNode.renderableInstance.setCulling(false)
_arCharacterObjects.add(
ArCharacter(
renderState = RenderState.NONE,
width = interaction.arObject.metadata.width,
height = interaction.arObject.metadata.height,
depth = interaction.arObject.metadata.depth,
arObjectCourse = interaction.arObject.arObjectCourse,
characterId = RandomString.invoke(),
interactionEntity = interaction,
viewAboveCharacter = interactionView,
touch = touch,
location = location,
interactionStarted = false,
arCharacterNode = transformableNode,
animationController = AnimationStateController(
renderableInstance = transformableNode.renderableInstance
),
name = interaction.name,
description = interaction.description,
manualPlacementAllowed = interaction.manualPlacementAllowed,
manualPlacementRadius = interaction.manualPlacementRadius,
modelVisibilityRadius = interaction.modelVisibilityRadius,
cloud = buildArObject(
location.lat,
location.long,
1.5f,
nodeCloud,
NavigationArObject.RotationMode.FACE_USER,
NavigationArObject.ScalingMode.GRADUAL,
objectType = ObjectType.Cloud
),
distance = buildArObject(
location.lat,
location.long,
1.5f,
distanceCloud,
NavigationArObject.RotationMode.FACE_USER,
NavigationArObject.ScalingMode.GRADUAL,
objectType = ObjectType.Cloud
)
)
)
TimberLog.d("[PERFORMANCE_LOCATION_MARKER] Added character.")
}
}
}
TimberLog.d("[PERFORMANCE_LOCATION_MARKER] Finished creating objects. Size: ${_arCharacterObjects.size}")
} catch (e: Exception) {
TimberLog.e("[LOCATION_MARKER] Error while loading character: $e")
}
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 16
@kustraslawomir hello, Look at RenderableInstance#createFilamentAssetModelInstance(). Free up FilamentAssets. like this, use RenderableInstance#destroyGltfAsset()
@kustraslawomir The earlier version I used. The method of destroyGltfAsset was I added. You can refer it.