Skip to content

Commit

Permalink
SWIG: Python - allow releasing the GIL during swapBuffers
Browse files Browse the repository at this point in the history
  • Loading branch information
paroj committed Sep 15, 2024
1 parent 612de95 commit 7f0f99e
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 5 deletions.
21 changes: 20 additions & 1 deletion Docs/src/tutorials/numpy.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,23 @@ Now we can store the image to disk using pyplot.

@note There is also Ogre::RenderTarget::writeContentsToFile if you do not need the pixel data in Python.

![](numpy_final.png)
![](numpy_final.png)

## Background Threads {#python-background-threads}

By default, the Python bindings do not release the GIL (Global Interpreter Lock) during rendering, which means that no other Python code can run in parallel.
This is usually not a problem and constantly re-acquiring the GIL would reduce performance. However, this means that the following code will not work:

```py
import threading

def printer():
for _ in range(15):
print("Thread")

threading.Thread(target=printer).start()
root.startRendering()
```

The "printer" Thread will be blocked until the rendering is finished.
To allow background threads to run, you can use `root.allowPyThread()`, which will release the GIL during swapping, while rendering is waiting for vsync.
34 changes: 30 additions & 4 deletions OgreMain/include/Ogre.i
Original file line number Diff line number Diff line change
Expand Up @@ -924,12 +924,38 @@ SHARED_PTR(Mesh);
%ignore Ogre::Root::createSceneManager(uint16);
%ignore Ogre::Root::createSceneManager(uint16, const String&);
%ignore Ogre::Root::getMovableObjectFactoryIterator;
#ifdef SWIGPYTHON
%{
class ThreadAllowFrameListener : public Ogre::FrameListener {
PyThreadState* _save = 0;
public:
bool frameRenderingQueued(const Ogre::FrameEvent& evt)
{
if(!_save)
_save = PyEval_SaveThread();
return true;
}
bool frameEnded(const Ogre::FrameEvent& evt)
{
if(_save) {
PyEval_RestoreThread(_save);
_save = 0;
}
return true;
}
};
%}
%extend Ogre::Root {
void allowPyThread()
{
static ThreadAllowFrameListener listener;
$self->addFrameListener(&listener);
}
}
#endif
%include "OgreRoot.h"
// dont wrap: platform specific
// %include "OgreWindowEventUtilities.h"
// %include "OgreTimer.h"
// dont wrap: not useful in high level languages
// %include "OgreRadixSort.h"
// %include "OgreTimer.h"
// %include "OgreString.h"
// %include "OgreStringConverter.h"
// %include "OgreProfiler.h"

0 comments on commit 7f0f99e

Please sign in to comment.