Simulate: move all glfw calls to main thread to fix MacOS

This commit is contained in:
Levi Burner
2022-06-03 10:21:08 -04:00
parent 62008a0e19
commit a526a6bd78
3 changed files with 39 additions and 50 deletions
+34 -25
View File
@@ -92,7 +92,7 @@ mjModel* LoadModel(const char* file, mj::Simulate& simulate) {
}
// simulate in background thread (while rendering in main thread)
void SimulateLoop(mj::Simulate& simulate) {
void PhysicsLoop(mj::Simulate& simulate) {
// cpu-sim syncronization point
double cpusync = 0;
mjtNum simsync = 0;
@@ -222,6 +222,31 @@ void SimulateLoop(mj::Simulate& simulate) {
}
} // end unnamed namespace
//---------------------------------- physics_thread ---------------------------------------
void PhysicsThread(mj::Simulate* simulate, const char* filename) {
// request loadmodel if file given (otherwise drag-and-drop)
if (filename != nullptr) {
m = LoadModel(filename, *simulate);
if (m) {
d = mj_makeData(m);
simulate->load(filename, m, d, true);
mj_forward(m, d);
// allocate ctrlnoise
free(ctrlnoise);
ctrlnoise = (mjtNum*) malloc(sizeof(mjtNum)*m->nu);
mju_zero(ctrlnoise, m->nu);
}
}
PhysicsLoop(*simulate);
// delete everything we allocated
free(ctrlnoise);
mj_deleteData(d);
mj_deleteModel(m);
}
//---------------------------------- main -------------------------------------------------
// run event loop
@@ -240,33 +265,17 @@ int main(int argc, const char** argv) {
mju_error("could not initialize GLFW");
}
// start simulation thread (this creates the UI)
simulate.startthread();
// request loadmodel if file given (otherwise drag-and-drop)
if (argc>1) {
m = LoadModel(argv[1], simulate);
if (m) {
d = mj_makeData(m);
simulate.load(argv[1], m, d, true);
mj_forward(m, d);
// allocate ctrlnoise
free(ctrlnoise);
ctrlnoise = (mjtNum*) malloc(sizeof(mjtNum)*m->nu);
mju_zero(ctrlnoise, m->nu);
}
const char* filename = nullptr;
if (argc > 1) {
filename = argv[1];
}
SimulateLoop(simulate);
// start physics thread
std::thread physicsthreadhandle = std::thread(&PhysicsThread, &simulate, filename);
// If simulate loop exited its time to stop the UI
simulate.stopthread();
// delete everything we allocated
free(ctrlnoise);
mj_deleteData(d);
mj_deleteModel(m);
// start simulation UI loop (blocking call)
simulate.renderloop();
physicsthreadhandle.join();
// terminate GLFW (crashes with Linux NVidia drivers)
#if defined(__APPLE__) || defined(_WIN32)
+1 -19
View File
@@ -1535,18 +1535,6 @@ namespace mju = ::mujoco::sample_util;
Simulate::Simulate(void) {
} // TODO constructor is now empty...
//------------------------ start the render thread -----------------------------
void Simulate::startthread(void) {
this->renderthreadhandle = std::thread(&Simulate::renderthread, this);
}
//------------------------ stop the render thread ------------------------------
void Simulate::stopthread(void) {
// stop simulation thread
this->exitrequest = 1;
this->renderthreadhandle.join();
}
//------------------------ apply pose perturbations ----------------------------
void Simulate::applyposepertubations(int flg_paused) {
if (this->m != nullptr) {
@@ -1798,7 +1786,7 @@ void Simulate::clearcallback(void) {
uiClearCallback(this->window);
}
void Simulate::renderthread(void) {
void Simulate::renderloop(void) {
// Set timer callback (milliseconds)
mjcb_time = timer;
@@ -1900,12 +1888,6 @@ void Simulate::renderthread(void) {
this->clearcallback();
mjv_freeScene(&this->scn);
mjr_freeContext(&this->con);
// terminate GLFW (crashes with Linux NVidia drivers)
// Must call terminate in this thread on Windows with NVidia drivers (Intel is fine)
#if defined(__APPLE__) || defined(_WIN32)
glfwTerminate();
#endif
}
} // namespace mujoco
+4 -6
View File
@@ -44,7 +44,7 @@ class MJSIMULATEAPI Simulate {
Simulate(void);
// Start the Simulate UI thread
void startthread(void);
// void startthread(void);
// Stop the Simulate UI thread
void stopthread(void);
@@ -72,15 +72,13 @@ class MJSIMULATEAPI Simulate {
// clear callbacks registered in external structures
void clearcallback(void);
// thread to render the UI
void renderthread(void);
// loop to render the UI (must be called from main thread because of MacOS)
// https://discourse.glfw.org/t/multithreading-glfw/573/5
void renderloop(void);
// constants
static constexpr int kMaxFilenameLength = 1000;
// the UI rendering thread
std::thread renderthreadhandle;
// model and data to be visualized
mjModel* mnew = nullptr;
mjData* dnew = nullptr;