The Lifecycle of a ModernGL Object#
From moderngl 5.7 we support three different garbage collection modes.
This should be configured using the
preferably right after the context is created.
The current supported modes are:
None: (default) No garbage collection is performed. Objects needs to to be manually released like in previous versions of moderngl.
"context_gc": Dead objects are collected in
Context.objects. These can periodically be released using
"auto": Dead objects are destroyed automatically like we would expect in python.
It’s important to realize here that garbage collection is not about the python objects itself, but the underlying OpenGL objects. ModernGL operates in many different environments were garbage collection can be a challenge. This depends on factors like who is controlling the existence of the OpenGL context and challenges around threading in python.
Standalone / Headless Context#
In this instance we control when the context is created and destroyed.
"auto" garbage collection is perfectly reasonable in this
When detecting an existing context from some window library we have no
direct control over the existence of the context. Using
is dangerous can can cause crashes especially on application exit.
The window and context is destroyed and closed, then moderngl will
try to destroy resources in a context that no longer exists.
"context_gc" mode to avoid this.
It can be possible to switch the
the window is closed. This can still be a problem if you have
race conditions due to resources being created in the render loop.
The Threading Issue#
When using threads in python the garbage collector can run in any thread.
This is a problem for OpenGL because only the main thread is allowed
to interact with the context. When using threads in your application
you should be using
"context_gc" mode and periodically call
for example during every frame swap.
Manually Releasing Objects#
Objects in moderngl don’t automatically release the OpenGL resources when
gc_mode=None is used.
Each type has a
release() method that needs to be called to properly clean
# Create a texture texture = ctx.texture((10, 10), 4) # Properly release the opengl resources texture.release()
Detecting Released Objects#
If you for some reason need to detect if a resource was released it can be done
by checking the type of the internal moderngl object (
>> import moderngl >> ctx = moderngl.create_standalone_context() >> buffer = ctx.buffer(reserve=1024) >> type(buffer.mglo) <class 'mgl.Buffer'> >> buffer.release() >> type(buffer.mglo) <class '_moderngl.InvalidObject'> >> type(buffer.mglo) == moderngl.mgl.InvalidObject True