Hi,
there is another memory leak, this time related to rendering in combination with simulation.unload.
As a testing scene, I took the pygame example from SofaPython3 and added a reload to every tenth step.
import Sofa
import Sofa.Core
import Sofa.Simulation
import Sofa.SofaGL
import SofaRuntime
import os
sofa_directory = os.environ["SOFA_ROOT"]
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
display_size = (800, 600)
def init_display(node):
pygame.display.init()
pygame.display.set_mode(display_size, pygame.DOUBLEBUF | pygame.OPENGL)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_DEPTH_TEST)
Sofa.SofaGL.glewInit()
Sofa.Simulation.initVisual(node)
Sofa.Simulation.initTextures(node)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, (display_size[0] / display_size[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def simple_render(rootNode):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, (display_size[0] / display_size[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
cameraMVM = rootNode.camera.getOpenGLModelViewMatrix()
glMultMatrixd(cameraMVM)
Sofa.SofaGL.draw(rootNode)
pygame.display.get_surface().fill((0, 0, 0))
pygame.display.flip()
def createScene(root):
# Register all the common component in the factory.
SofaRuntime.PluginRepository.addFirstPath(os.path.join(sofa_directory, "bin"))
root.addObject("RequiredPlugin", name="SofaOpenglVisual") # visual stuff
root.addObject("RequiredPlugin", name="SofaLoader") # geometry loaders
root.addObject("RequiredPlugin", name="SofaSimpleFem") # diffusion fem
root.addObject("RequiredPlugin", name="SofaBoundaryCondition") # constraints
root.addObject("RequiredPlugin", name="SofaEngine") # Box Roi
root.addObject("RequiredPlugin", name="SofaImplicitOdeSolver") # implicit solver
root.addObject("RequiredPlugin", name="SofaMiscForceField") # meshmatrix
root.addObject("RequiredPlugin", name="SofaGeneralEngine") # TextureInterpolation
root.addObject("RequiredPlugin", name="CImgPlugin") # for loading a bmp image for texture
root.addObject("RequiredPlugin", name="SofaBaseLinearSolver")
root.addObject("RequiredPlugin", name="SofaGeneralVisual")
root.addObject("RequiredPlugin", name="SofaTopologyMapping")
root.addObject("RequiredPlugin", name="SofaGeneralTopology")
root.addObject("RequiredPlugin", name="SofaGeneralLoader")
### these are just some things that stay still and move around
# so you know the animation is actually happening
root.gravity = [0, -1.0, 0]
root.addObject("VisualStyle", displayFlags="showAll")
root.addObject("MeshGmshLoader", name="meshLoaderCoarse", filename="mesh/liver.msh")
root.addObject("MeshObjLoader", name="meshLoaderFine", filename="mesh/liver-smooth.obj")
root.addObject("EulerImplicitSolver")
root.addObject("CGLinearSolver", iterations="200", tolerance="1e-09", threshold="1e-09")
liver = root.addChild("liver")
liver.addObject("TetrahedronSetTopologyContainer", name="topo", src="@../meshLoaderCoarse")
liver.addObject("TetrahedronSetGeometryAlgorithms", template="Vec3d", name="GeomAlgo")
liver.addObject("MechanicalObject", template="Vec3d", name="MechanicalModel", showObject="1", showObjectScale="3")
liver.addObject("TetrahedronFEMForceField", name="fem", youngModulus="1000", poissonRatio="0.4", method="large")
liver.addObject("MeshMatrixMass", massDensity="1")
liver.addObject("FixedConstraint", indices="2 3 50")
visual = liver.addChild("visual")
visual.addObject("MeshObjLoader", name="meshLoader_0", filename="mesh/liver-smooth.obj", handleSeams="1")
visual.addObject("OglModel", name="VisualModel", src="@meshLoader_0", color="red")
visual.addObject("BarycentricMapping", input="@..", output="@VisualModel", name="visual mapping")
# place light and a camera
root.addObject("LightManager")
root.addObject("DirectionalLight", direction=[0, 1, 0])
root.addObject("InteractiveCamera", name="camera", position=[0, 15, 0], lookAt=[0, 0, 0], distance=37, fieldOfView=45, zNear=0.63, zFar=55.69)
if __name__ == "__main__":
root = Sofa.Core.Node("myroot")
createScene(root)
Sofa.Simulation.init(root)
with_window = True
if with_window:
init_display(root)
for i in range(300):
Sofa.Simulation.animate(root, root.getDt())
Sofa.Simulation.updateVisual(root)
if with_window:
simple_render(root)
if i % 10 == 0:
if with_window:
pygame.display.quit()
Sofa.Simulation.unload(root)
createScene(root)
Sofa.Simulation.init(root)
if with_window:
init_display(root)
The leak seems to be related to the OpenGL context, because for 31 init_display calls, I get and AddressSanitizer output of
Indirect leak of 59521240 byte(s) in 31 object(s) allocated from:
#0 0x7f8a1c4cf808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x7f8a0be337c3 in SDL_malloc_REAL /sdl_build/SDL2-2.0.16/src/stdlib/SDL_malloc.c:5388
that matches the lost amount of memory.
And it also veeeery closely matches the amount of memory required to store 31 RGBA buffers of the set image size. :D
>>> (600*800*4*31)/59521240
0.9999791671006854
If no display is created, there is no leak.
@fredroy Do you maybe know what could be the issue here?
Cheers,
Paul
Hi,
there is another memory leak, this time related to rendering in combination with
simulation.unload.As a testing scene, I took the pygame example from SofaPython3 and added a reload to every tenth step.
The leak seems to be related to the OpenGL context, because for
31init_displaycalls, I get and AddressSanitizer output ofthat matches the lost amount of memory.
And it also veeeery closely matches the amount of memory required to store 31 RGBA buffers of the set image size. :D
If no display is created, there is no leak.
@fredroy Do you maybe know what could be the issue here?
Cheers,
Paul