@@ -153,6 +153,22 @@ std::map<std::string, std::unique_ptr<Structure>>& getStructureMapCreateIfNeeded
153153 return state::structures[typeName];
154154}
155155
156+ void sleepForFramerate () {
157+ // If needed, block the program execution to hit the intended framerate
158+ // (if not used, the render loop may busy-run maxed out at 1000+ fps and waste resources)
159+ if (options::maxFPS != -1 ) {
160+ auto currTime = std::chrono::steady_clock::now ();
161+ long microsecPerLoop = 1000000 / options::maxFPS;
162+ microsecPerLoop = (95 * microsecPerLoop) / 100 ; // give a little slack so we actually hit target fps
163+ while (std::chrono::duration_cast<std::chrono::microseconds>(currTime - lastMainLoopIterTime).count () <
164+ microsecPerLoop) {
165+ std::this_thread::yield ();
166+ currTime = std::chrono::steady_clock::now ();
167+ }
168+ }
169+ lastMainLoopIterTime = std::chrono::steady_clock::now ();
170+ }
171+
156172} // namespace
157173
158174// === Core global functions
@@ -239,19 +255,7 @@ void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI) {
239255 size_t currentContextStackSize = contextStack.size ();
240256 while (contextStack.size () >= currentContextStackSize) {
241257
242- // The windowing system will let the main loop busy-loop on some platforms. Make sure that doesn't happen.
243- if (options::maxFPS != -1 ) {
244- auto currTime = std::chrono::steady_clock::now ();
245- long microsecPerLoop = 1000000 / options::maxFPS;
246- microsecPerLoop = (95 * microsecPerLoop) / 100 ; // give a little slack so we actually hit target fps
247- while (std::chrono::duration_cast<std::chrono::microseconds>(currTime - lastMainLoopIterTime).count () <
248- microsecPerLoop) {
249- std::this_thread::yield ();
250- currTime = std::chrono::steady_clock::now ();
251- }
252- }
253- lastMainLoopIterTime = std::chrono::steady_clock::now ();
254-
258+ sleepForFramerate ();
255259 mainLoopIteration ();
256260
257261 // auto-exit if the window is closed
@@ -305,9 +309,29 @@ void frameTick() {
305309 // Make sure we're visible
306310 render::engine->showWindow ();
307311
308- // All-imporant main loop iteration
312+ bool savedVsyncValue = false ; // see below
313+ bool needToRestoreVSyncValue =
314+ false ; // we need this as a saved bool, because the setting could change during mainLoopIteration()
315+ if (options::frameTickLimitFPS) {
316+ sleepForFramerate ();
317+ } else {
318+ // Ugly workaround to preserve the API:
319+ // We want vsync to be disabled unless frameTick(limitFPS=True), so that we don't slow down user's application.
320+ // But it's currently a bool read in the render call and I don't want to change that API. So we temporarily set
321+ // it to false and restore the value after.
322+ // ONEDAY: when we have a major version update, change the API on the vsync setting to make this unecessary
323+ savedVsyncValue = options::enableVSync;
324+ options::enableVSync = false ;
325+ needToRestoreVSyncValue = true ;
326+ }
327+
309328 mainLoopIteration ();
310329
330+ if (needToRestoreVSyncValue) {
331+ // restore saved value, see note above
332+ options::enableVSync = savedVsyncValue;
333+ }
334+
311335 frameTickStack--;
312336}
313337
@@ -705,6 +729,15 @@ void buildPolyscopeGui() {
705729 ImGui::Text (" Last: %.1f ms/frame (%.1f fps)" , ImGui::GetIO ().DeltaTime * 1000 .f , 1 .f / ImGui::GetIO ().DeltaTime );
706730
707731 ImGui::PushItemWidth (40 * options::uiScale);
732+
733+ bool isFrameTickShow = frameTickStack > 0 ;
734+ if (isFrameTickShow) {
735+ ImGui::Checkbox (" limit fps" , &options::frameTickLimitFPS);
736+ ImGui::SameLine ();
737+ }
738+
739+ ImGui::BeginDisabled (isFrameTickShow && !options::frameTickLimitFPS);
740+
708741 if (ImGui::InputInt (" max fps" , &options::maxFPS, 0 )) {
709742 if (options::maxFPS < 1 && options::maxFPS != -1 ) {
710743 options::maxFPS = -1 ;
@@ -715,6 +748,8 @@ void buildPolyscopeGui() {
715748 ImGui::SameLine ();
716749 ImGui::Checkbox (" vsync" , &options::enableVSync);
717750
751+ ImGui::EndDisabled ();
752+
718753 ImGui::TreePop ();
719754 }
720755
0 commit comments