diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 7f2ad1010..a22370da8 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -23,6 +23,7 @@ #include "engine.h" #include "instrument.h" #include "safeReader.h" +#include "workPool.h" #include "../ta-log.h" #include "../fileutils.h" #ifdef HAVE_SDL2 @@ -3123,6 +3124,10 @@ bool DivEngine::switchMaster(bool full) { quitDispatch(); initDispatch(); } + if (renderPool!=NULL) { + delete renderPool; + renderPool=NULL; + } if (initAudioBackend()) { for (int i=0; i2.0f) metroVol=2.0f; + renderPoolThreads=getConfInt("renderPoolThreads",0); if (lowLatency) logI("using low latency mode."); diff --git a/src/engine/engine.h b/src/engine/engine.h index ba2cf567b..25add2069 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -487,6 +487,7 @@ class DivEngine { size_t totalProcessed; + unsigned int renderPoolThreads; DivWorkPool* renderPool; // MIDI stuff @@ -1264,6 +1265,8 @@ class DivEngine { metroAmp(0.0f), metroVol(1.0f), totalProcessed(0), + renderPoolThreads(0), + renderPool(NULL), curOrders(NULL), curPat(NULL), tempIns(NULL), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 0b21dc57f..5f06d31aa 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1790,8 +1790,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi std::chrono::steady_clock::time_point ts_processBegin=std::chrono::steady_clock::now(); if (renderPool==NULL) { - // TODO: test this - renderPool=new DivWorkPool(0); + renderPool=new DivWorkPool(renderPoolThreads); } // process MIDI events (TODO: everything) diff --git a/src/engine/workPool.cpp b/src/engine/workPool.cpp index b3610f74c..6a562bfe2 100644 --- a/src/engine/workPool.cpp +++ b/src/engine/workPool.cpp @@ -43,11 +43,14 @@ void DivWorkThread::run() { if (setFuckingPromise) { parent->notify.set_value(); setFuckingPromise=false; + std::this_thread::yield(); } if (terminate) { break; } - notify.wait(unique); + if (notify.wait_for(unique,std::chrono::milliseconds(100))==std::cv_status::timeout) { + logE("this task timed out!"); + } continue; } else { task=tasks.front(); @@ -128,7 +131,6 @@ bool DivWorkPool::busy() { void DivWorkPool::wait() { if (!threaded) return; - //std::unique_lock unique(selfLock); if (busyCount==0) { logV("nothing to do"); @@ -141,6 +143,7 @@ void DivWorkPool::wait() { for (unsigned int i=0; i0); + if (ImGui::Checkbox("Multi-threaded (EXPERIMENTAL)",&renderPoolThreadsB)) { + if (renderPoolThreadsB) { + settings.renderPoolThreads=2; + } else { + settings.renderPoolThreads=0; + } + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("runs chip emulation on separate threads.\nmay increase performance on multi-core CPUs.\n\nwarnings:\n- experimental! currently broken/not working well.\n- only useful on multi-chip songs."); + } + + if (renderPoolThreadsB) { + pushWarningColor(settings.renderPoolThreads>cpuCores,settings.renderPoolThreads>cpuCores); + if (ImGui::InputInt("Number of threads",&settings.renderPoolThreads)) { + if (settings.renderPoolThreads<2) settings.renderPoolThreads=2; + if (settings.renderPoolThreads>32) settings.renderPoolThreads=32; + } + if (settings.renderPoolThreads>=DIV_MAX_CHIPS) { + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("that's the limit!"); + } + } else if (settings.renderPoolThreads>cpuCores) { + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("it is a VERY bad idea to set this number higher than your CPU core count (%d)!",cpuCores); + } + } + popWarningColor(); + } + bool lowLatencyB=settings.lowLatency; if (ImGui::Checkbox("Low-latency mode",&lowLatencyB)) { settings.lowLatency=lowLatencyB; @@ -3284,6 +3314,7 @@ void FurnaceGUI::syncSettings() { settings.classicChipOptions=e->getConfInt("classicChipOptions",0); settings.wasapiEx=e->getConfInt("wasapiEx",0); settings.chanOscThreads=e->getConfInt("chanOscThreads",0); + settings.renderPoolThreads=e->getConfInt("renderPoolThreads",0); clampSetting(settings.mainFontSize,2,96); clampSetting(settings.headFontSize,2,96); @@ -3433,6 +3464,7 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.classicChipOptions,0,1); clampSetting(settings.wasapiEx,0,1); clampSetting(settings.chanOscThreads,0,256); + clampSetting(settings.renderPoolThreads,0,256); if (settings.exportLoops<0.0) settings.exportLoops=0.0; if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0; @@ -3689,6 +3721,7 @@ void FurnaceGUI::commitSettings() { e->setConf("classicChipOptions",settings.classicChipOptions); e->setConf("wasapiEx",settings.wasapiEx); e->setConf("chanOscThreads",settings.chanOscThreads); + e->setConf("renderPoolThreads",settings.renderPoolThreads); // colors for (int i=0; i