Skip to content

Android - Wrong FPS/update on high rate devices #2129

Closed
@AlexandreK38

Description

@AlexandreK38

Environment:

  • axmol version: Latest 2.1.5
  • devices test on: Pixel 6, Samsung S8

Issue:

Hi,
I use scheduleUpdate() so that my code is updated on each frame drawn. If I set the frame interval to 1/60s I expect the update() to be called once every 1/60s, but on my Pixel 6 it will be called twice.
So the issue occurs on high rate devices (120FPS) like the Pixel 6.
The code itself tells they are not handled:

@Override
    public void onDrawFrame(final GL10 gl) {
        /*
         * Fix 60fps limiting doesn't work when high-end device is working in 120fps mode.
         */
        if (AxmolRenderer.sAnimationInterval <= 1.0f / 1200.0f * AxmolRenderer.NANOSECONDSPERSECOND) {
            AxmolRenderer.nativeRender();
        } else {
            final long now = System.nanoTime();
            final long interval = now - this.mLastTickInNanoSeconds;

            /*
             * Render time MUST be counted in, or the FPS will slower than appointed.
            */
            this.mLastTickInNanoSeconds = now;
            AxmolRenderer.nativeRender();

            if (interval < AxmolRenderer.sAnimationInterval) {
                try {
                    Thread.sleep((AxmolRenderer.sAnimationInterval - interval) / AxmolRenderer.NANOSECONDSPERMICROSECOND);
                } catch (final Exception e) {
                }
            }
        }
    }

A possible fix to this is this following code:

@Override
    public void onDrawFrame(final GL10 gl) {
        /*
         * Fix 60fps limiting doesn't work when high-end device is working in 120fps mode.
         */
        if (AxmolRenderer.sAnimationInterval <= 1.0f / 1200.0f * AxmolRenderer.NANOSECONDSPERSECOND) {
            AxmolRenderer.nativeRender();
        } else {
            /*
             * Render time MUST be counted in, or the FPS will slower than appointed.
            */
            this.mLastTickInNanoSeconds = System.nanoTime();
            AxmolRenderer.nativeRender();

            final long interval = System.nanoTime() - this.mLastTickInNanoSeconds;

            if (interval < AxmolRenderer.sAnimationInterval) {
                try {
                    Thread.sleep((AxmolRenderer.sAnimationInterval - interval) / AxmolRenderer.NANOSECONDSPERMICROSECOND);
                } catch (final Exception e) {
                }
            }
        }
    }

It works, but in any case (current and possible fix) the UI rendering seems a bit laggy because the renderer is using RENDERMODE_CONTINUOUSLY mode meaning it's the java thread that triggers the call periodically and sleeping in the onDrawFrame() might cause troubles to it.

I explored this solution and a new one using our own thread to trigger manually the rendering (see PR #2125) and the thread solution was giving better performance, overall when you do much work at each frame.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions