Giter Site home page Giter Site logo

Engine update thread about ouzel HOT 14 CLOSED

elnormous avatar elnormous commented on May 13, 2024
Engine update thread

from ouzel.

Comments (14)

elnormous avatar elnormous commented on May 13, 2024 1

Yes, I have seen this article quoted many times and I have implemented a similar logic in my game, but it doesn't answer the question, how to fix the update rate of the game thread to the one the user wants (e.g. 15 Hz). As I mentioned above, using sleep is not an option. That is why I created a while loop and user can do whatever he wants in it. He can add an update callback to the engine and put a sleep in it if he wants to save resources. But I don't think this is something that has to go into the engine. Maybe you have better ideas?

from ouzel.

danielytics avatar danielytics commented on May 13, 2024

@wenq1 this is typical in games. Usually you want to use all available CPU because you're busy updating graphics, physics, ai, game logic and so on.

Having said that, it might be a good addition to provide this as an option in case you want to enable sleeping to lower power consumption and make a non-fullscreen game play nicer with the rest of the system.

from ouzel.

wenq1 avatar wenq1 commented on May 13, 2024

@danielytics Not on mobile I believe. Busy loops means a huge deal for battery life. Nowadays even eglSwapBuffers () are vsync-ed to avoid extensive battery usage.

from ouzel.

danielytics avatar danielytics commented on May 13, 2024

@wenq1 ah, of course, its much more important for mobile. I wasn't thinking clearly ;-)

Does EGL vsync for battery conservation purposes, rather than to avoid visual tearing?

from ouzel.

wenq1 avatar wenq1 commented on May 13, 2024

Visual tearing will never occur on double-buffer backed systems. Reading and writing are always on complete buffers, never on buffers in progress. Performance-wise lockless double buffers are invented to address the issue.

Question asked here is of another scope. When you have a thread spawned (especially on mobile devices), you almost always need a handler based pattern to block somewhere, or you manually insert sleeps between loop iterations. Otherwise batteries will be tortured or considered fully utilized as a cookware.

from ouzel.

danielytics avatar danielytics commented on May 13, 2024

You still need to wait for vsync before swapping the buffers to avoid tearing. Otherwise you may still have part of the screen rendered from one buffer and the rest from another. My question was whether vsync is also done because of battery, or if thats just a happy side-effect. Probably a mixture of the two. Anyway, I've taken this ticket off topic enough.. apologies!

Sure, that makes sense and I guess that's why mobile apps are inherently event-based (doing little or nothing until the user does something). Could ouzel perhaps get a little closer to this by providing configurable fixed timesteps (eg so that the developer can decide how often rendering (and ideally independently, game logic) updates are run)? Eg, if you could say "render at 60 Hz and update game logic at 15 Hz". Not quite event-triggered of course, but still a lot more control over battery use than currently. Maybe I'm talking BS though ;-)

from ouzel.

elnormous avatar elnormous commented on May 13, 2024

There is no way to reliably fix the update thread to 15 Hz. I was considering that (and if you look at the commit history, it was implemented 2 years ago) a fixed update with sleeps, but sleeps are unreliable. They guarantee a minimum amount of time to sleep, but not maximum. For example, my game is updating all the logic at 60 Hz. I tried to add a sleep to force the update thread to run at 100 Hz and I got inconsistent update rate, that affected my game dramatically. Syncing the update thread with the render thread (vsync) is also a no-go, because every device can have its own refresh rate and usually it is not precisely 60 (I got 60.1 on some and 59.9 on others). If you are updating your physics exactly 60 times a second and you get a refresh rate that is something around 60, you will get have a double-update once in a while and that makes the game feel really glitchy.

from ouzel.

wenq1 avatar wenq1 commented on May 13, 2024

"Otherwise you may still have part of the screen rendered from one buffer and the rest from another" - No that should never happen in double buffered systems, Otherwise either locks screwed up on single-buffered system or poor logic is in charge in multi-buffer backed systems.

Interesting read here: http://stackoverflow.com/questions/23666069/single-producer-single-consumer-data-structure-with-double-buffer-in-c

Completely off-topic above. Ignore me..

Fixed step rendering is .... yet another thing. Check this out: http://gafferongames.com/game-physics/fix-your-timestep/. It is a game-loop design pattern that makes physics more predictable, irrelevant of your implementation.

Ouzel chooses to use multithreading to implement game update part of the rendering. It is the cpu-hogging behaviour itself that incurred the question.

from ouzel.

danielytics avatar danielytics commented on May 13, 2024

I was thinking something like this http://gafferongames.com/game-physics/fix-your-timestep/ where it makes a best effort to fix the timestep, but also allows multiple updates when enough "missed time" is accumulated. They did it for the purpose of physics, maybe its not suitable here. I know that getting it to be exactly X Hz is impossible...

EDIT:
hah, posted the same link at almost the same time :D

No that should never happen in double buffered systems

Do you mean with hardware double buffering? Presumably that's because they will always wait for vsync, no?

If software double buffering is used (which, granted, in this day and age shouldn't be necessary), you still need to synchronise: when you SwapBuffers the screen might be halfway through the screen and it will start pushing pixels to the screen. The top half of the screen will still show the previous frames graphics. It would be corrected next time the screen starts from pixel 0, but unless you have some way of making sure every pixel was read from the buffer before swapping, you could end up with the same situation again and again. Even the wikipedia page on multi-buffering says that modern systems synchronise between swaps. (Going by your SO link: I'm not saying that "you" are drawing part into one buffer and part into the other; I'm saying that the GPU is drawing part of one buffer to the screen and part of the other buffer to the screen, causing the screen to contain a mix of buffers; the buffers themselves may be properly locked and this could still happen).

I would expect this to all be happening in hardware, but at least with my experience with OpenGL, when I set it up with double buffering, I still have to tell it I want vsync for it to use vsync and if I do not, I get tearing. (Maybe ES always does vsync, I have no experience with ES)

from ouzel.

danielytics avatar danielytics commented on May 13, 2024

@elnormous Am I correct in saying that the problem you hit was that its impossible to remove jitter?

either

  • slow frames mean you get lower Hz

or

  • you do what the article does and it means that you might get two updates in one "tick" when enough extra time has been accumulated?

There's obviously no way to guarantee that the timestep will always be exactly what you want, but if I read the article correctly (but maybe I didn't!) it sounds like the idea is to make sure that the same number of updates happen in a given timeframe. That is, you might not get 1 update every 16.6ms, but you will get exactly two in 33.2ms (more or less). Best effort kinda thing. But I'm not experienced enough to discuss beyond this. You have more experience than I do, so if it didn't work, then...

EDIT: Reading comprehension failure on my part, sorry! You already said:

you will get have a double-update once in a while and that makes the game feel really glitchy

How do you handle it in your game? I assume you're not using a physics engine that requires a fixed timestep. What happens if the framerate drops really low? Even if using purely time-based update logic, there will be jumps in this case. Are they less "glitchy" than with double-updates in the fixed timestep approach?

from ouzel.

wenq1 avatar wenq1 commented on May 13, 2024

Say if you want 15hz update (66ms intervals), sleeping 80ms will be ok, and then just update (66ms) at a time. When deviations accumulates, say, you have slept for 3 times, you update once more at the last sleep. You'll get jitter surely.

Sleeping less, for example 10ms will give you smoother outcome and less jitter. Never sleep at close to the update rate or otherwise you might or might not get the extra update at some point in time.

To overcome the jitter issue, sleep a variable amount of time depending on the designed next (fraction of) frame time, say 60fps. This gives most predictable results when drawing occurs at a constant rate, say vsynced. When the framerate drops, the frame time will depart from the design, but with multi-threaded CPU-side updating will this ever happen?

from ouzel.

zerodarkzone avatar zerodarkzone commented on May 13, 2024

Hi,
you could read this thread from the cocos2d-x forum which is related
http://discuss.cocos2d-x.org/t/cocos2d-x-windows-performance-issues-examined/27915
Leaving a game use 100% of the CPU is not good from my point of view, you're killing mobile and laptop batteries. Lots of game engines offer a kind of fixed update rate so even if it is difficult it is not impossible to implement it.

from ouzel.

elnormous avatar elnormous commented on May 13, 2024

I will add an option to run the game thread in one of the two modes:

  1. Run as often as possible (current way)
  2. Run only once per v-sync

from ouzel.

elnormous avatar elnormous commented on May 13, 2024

I added a oneUpdatePerFrame (the name could change) attribute (false by default) to the Engine class. Now the game thread will sleep until the next frame (so it will not run on 100% anymore).
f2f29de

from ouzel.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.