mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 12:19:19 +02:00
Merge branch 'milek-dev' into gfx-work
This commit is contained in:
80
PyInt.cpp
80
PyInt.cpp
@@ -27,12 +27,11 @@ void render_task::run() {
|
||||
if( output != nullptr ) {
|
||||
auto *outputwidth { PyObject_CallMethod( m_renderer, "get_width", nullptr ) };
|
||||
auto *outputheight { PyObject_CallMethod( m_renderer, "get_height", nullptr ) };
|
||||
opengl_texture &tex = GfxRenderer.Texture( m_target );
|
||||
// upload texture data
|
||||
if( ( outputwidth != nullptr )
|
||||
&& ( outputheight != nullptr )
|
||||
&& tex.id != -1) {
|
||||
::glBindTexture( GL_TEXTURE_2D, tex.id );
|
||||
&& m_target != -1) {
|
||||
::glBindTexture( GL_TEXTURE_2D, m_target );
|
||||
|
||||
int w = PyInt_AsLong( outputwidth );
|
||||
int h = PyInt_AsLong( outputheight );
|
||||
@@ -108,8 +107,6 @@ auto python_taskqueue::init() -> bool {
|
||||
PyObject *stringioclassname { nullptr };
|
||||
PyObject *stringioobject { nullptr };
|
||||
|
||||
// save a pointer to the main PyThreadState object
|
||||
m_mainthread = PyThreadState_Get();
|
||||
// do the setup work while we hold the lock
|
||||
m_main = PyImport_ImportModule("__main__");
|
||||
if (m_main == nullptr) {
|
||||
@@ -135,8 +132,8 @@ auto python_taskqueue::init() -> bool {
|
||||
|
||||
if( false == run_file( "abstractscreenrenderer" ) ) { goto release_and_exit; }
|
||||
|
||||
// release the lock
|
||||
PyEval_ReleaseLock();
|
||||
// release the lock, save the state for future use
|
||||
m_mainthread = PyEval_SaveThread();
|
||||
|
||||
WriteLog( "Python Interpreter setup complete" );
|
||||
|
||||
@@ -144,12 +141,11 @@ auto python_taskqueue::init() -> bool {
|
||||
for( auto &worker : m_workers ) {
|
||||
|
||||
auto *openglcontextwindow { Application.window( -1 ) };
|
||||
worker =
|
||||
std::make_unique<std::thread>(
|
||||
&python_taskqueue::run, this,
|
||||
openglcontextwindow, std::ref( m_tasks ), std::ref( m_condition ), std::ref( m_exit ) );
|
||||
worker = std::thread(
|
||||
&python_taskqueue::run, this,
|
||||
openglcontextwindow, std::ref( m_tasks ), std::ref( m_condition ), std::ref( m_exit ) );
|
||||
|
||||
if( worker == nullptr ) { return false; }
|
||||
if( false == worker.joinable() ) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -168,9 +164,8 @@ void python_taskqueue::exit() {
|
||||
m_exit = true;
|
||||
m_condition.notify_all();
|
||||
// let them free up their shit before we proceed
|
||||
for( auto const &worker : m_workers ) {
|
||||
if (worker && worker->joinable())
|
||||
worker->join();
|
||||
for( auto &worker : m_workers ) {
|
||||
worker.join();
|
||||
}
|
||||
// get rid of the leftover tasks
|
||||
// with the workers dead we don't have to worry about concurrent access anymore
|
||||
@@ -178,8 +173,7 @@ void python_taskqueue::exit() {
|
||||
task->cancel();
|
||||
}
|
||||
// take a bow
|
||||
PyEval_AcquireLock();
|
||||
PyThreadState_Swap( m_mainthread );
|
||||
acquire_lock();
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
@@ -188,7 +182,7 @@ auto python_taskqueue::insert( task_request const &Task ) -> bool {
|
||||
|
||||
if( ( Task.renderer.empty() )
|
||||
|| ( Task.input == nullptr )
|
||||
|| ( Task.target == null_handle ) ) { return false; }
|
||||
|| ( Task.target == 0 ) ) { return false; }
|
||||
|
||||
auto *renderer { fetch_renderer( Task.renderer ) };
|
||||
if( renderer == nullptr ) { return false; }
|
||||
@@ -202,11 +196,11 @@ auto python_taskqueue::insert( task_request const &Task ) -> bool {
|
||||
for( auto &task : m_tasks.data ) {
|
||||
if( task->target() == Task.target ) {
|
||||
// replace pending task in the slot with the more recent one
|
||||
PyEval_AcquireLock();
|
||||
acquire_lock();
|
||||
{
|
||||
task->cancel();
|
||||
}
|
||||
PyEval_ReleaseLock();
|
||||
release_lock();
|
||||
task = newtask;
|
||||
newtaskinserted = true;
|
||||
break;
|
||||
@@ -240,6 +234,18 @@ auto python_taskqueue::run_file( std::string const &File, std::string const &Pat
|
||||
return true;
|
||||
}
|
||||
|
||||
// acquires the python gil and sets the main thread as current
|
||||
void python_taskqueue::acquire_lock() {
|
||||
|
||||
PyEval_RestoreThread( m_mainthread );
|
||||
}
|
||||
|
||||
// releases the python gil and swaps the main thread out
|
||||
void python_taskqueue::release_lock() {
|
||||
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
|
||||
auto python_taskqueue::fetch_renderer( std::string const Renderer ) ->PyObject * {
|
||||
|
||||
auto const lookup { m_renderers.find( Renderer ) };
|
||||
@@ -250,17 +256,15 @@ auto python_taskqueue::fetch_renderer( std::string const Renderer ) ->PyObject *
|
||||
auto const path { substr_path( Renderer ) };
|
||||
auto const file { Renderer.substr( path.size() ) };
|
||||
PyObject *renderer { nullptr };
|
||||
PyObject *rendererarguments { nullptr };
|
||||
PyObject *renderername { nullptr };
|
||||
|
||||
PyEval_AcquireLock();
|
||||
|
||||
if( m_main == nullptr ) {
|
||||
ErrorLog( "Python Renderer: __main__ module is missing" );
|
||||
goto cache_and_return;
|
||||
}
|
||||
|
||||
PyObject *rendererarguments { nullptr };
|
||||
PyObject *renderername { nullptr };
|
||||
acquire_lock();
|
||||
{
|
||||
if( m_main == nullptr ) {
|
||||
ErrorLog( "Python Renderer: __main__ module is missing" );
|
||||
goto cache_and_return;
|
||||
}
|
||||
|
||||
if( false == run_file( file, path ) ) {
|
||||
goto cache_and_return;
|
||||
}
|
||||
@@ -287,7 +291,7 @@ cache_and_return:
|
||||
Py_DECREF( rendererarguments );
|
||||
}
|
||||
}
|
||||
PyEval_ReleaseLock();
|
||||
release_lock();
|
||||
// cache the failures as well so we don't try again on subsequent requests
|
||||
m_renderers.emplace( Renderer, renderer );
|
||||
return renderer;
|
||||
@@ -320,14 +324,14 @@ void python_taskqueue::run( GLFWwindow *Context, rendertask_sequence &Tasks, thr
|
||||
}
|
||||
if( task != nullptr ) {
|
||||
// swap in my thread state
|
||||
PyEval_AcquireLock();
|
||||
PyThreadState_Swap( threadstate );
|
||||
// execute python code
|
||||
task->run();
|
||||
error();
|
||||
PyEval_RestoreThread( threadstate );
|
||||
{
|
||||
// execute python code
|
||||
task->run();
|
||||
error();
|
||||
}
|
||||
// clear the thread state
|
||||
PyThreadState_Swap( nullptr );
|
||||
PyEval_ReleaseLock();
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
// TBD, TODO: add some idle time between tasks in case we're on a single thread cpu?
|
||||
} while( task != nullptr );
|
||||
|
||||
Reference in New Issue
Block a user