Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stats showing actually rendered frames #1082

Closed
j3k0 opened this issue Dec 2, 2020 · 8 comments
Closed

Stats showing actually rendered frames #1082

j3k0 opened this issue Dec 2, 2020 · 8 comments
Labels

Comments

@j3k0
Copy link

j3k0 commented Dec 2, 2020

I don't know if that would make sense, I found it more interesting in my app to know the actual number of frames rendered per seconds by Starling (not including the skipped frames).

This allows me to better optimize for letting starling skip frames. My real case example, rounding all angles and alpha value to "0.01" my in-game screen went from 6 real fps to 2 real fps (i.e. not counting skipped frame). This information I can't know from the green color alone.

I can make a proper PR, here's the diff (I wasn't working from the git repo)

diff --git a/starling/src/starling/core/StatsDisplay.as b/starling/src/starling/core/StatsDisplay.as
--- a/starling/src/starling/core/StatsDisplay.as
+++ b/starling/src/starling/core/StatsDisplay.as
@@ -38,6 +38,9 @@ package starling.core
         private var _frameCount:int = 0;
         private var _totalTime:Number = 0;

+        /** Frames actually rendered per seconds (not counting skipped frames) */
+        private var _rfps:Number = 0;
+        /** Frames per seconds (including skipped frames) */
         private var _fps:Number = 0;
         private var _memory:Number = 0;
         private var _gpuMemory:Number = 0;
@@ -108,10 +111,11 @@ package starling.core
         {
             _background.color = _skipCount > _frameCount / 2 ? 0x003F00 : 0x0;
             _fps = _totalTime > 0 ? _frameCount / _totalTime : 0;
+            _rfps = _totalTime > 0 ? (_frameCount - _skipCount) / _totalTime : 0;
             _memory = System.totalMemory * B_TO_MB;
             _gpuMemory = supportsGpuMem ? Starling.context['totalGPUMemory'] * B_TO_MB : -1;

-            var fpsText:String = _fps.toFixed(_fps < 100 ? 1 : 0);
+            var fpsText:String = _rfps.toFixed(_rfps < 10 ? 1 : 0);
             var memText:String = _memory.toFixed(_memory < 100 ? 1 : 0);
             var gpuMemText:String = _gpuMemory.toFixed(_gpuMemory < 100 ? 1 : 0);
             var drwText:String = (_totalTime > 0 ? _drawCount-2 : _drawCount).toString(); // ignore self
@PrimaryFeather
Copy link
Contributor

Thanks a lot for the suggestion, Jean-Christophe! I agree – in some situations, it would be more useful to see the actual frame count without the skipped frames. I think my reasoning behind the green color (vs. showing the actual number) was that I thought it would be sufficient in most cases, while not distracting as much from the pure "how many frames are there" information you typically need. If the FPS number had suddenly shown, say, 20, while you target 60 fps, it would have been confusing for users.

What we could also do, along the lines of your idea, is to add a new line that counts only the skipped frames. So, a game targeting 60 fps would still show "60" in the FPS line, but e.g. "40" as "skipped frames/sec".

What do you think of that?

@j3k0
Copy link
Author

j3k0 commented Dec 7, 2020

add a new line that counts only the skipped frames

Yes, more stats sounds even better.


Along with the idea, I was looking into a way to get the data from Starling about rendering stats, without hacking into Starling source code. It would be useful, for example, to get full performance data into my analytics.

There is an Event.RENDER event. It is only triggered when a frame is not skipped, so doesn't give the actual FPS (one might assume Event.RENDER is triggered when render() is called).

I could add events Event.SKIP_FRAME (and Event.DRAW_FRAME which would be more explicit, but would do the same as Event.RENDER).

Or/and add skipCount to the Painter? So it exposes both frameCount and skipCount.

Or/and add a function get stats():Stats with class Stats { ...data from StatsDisplay... }.

@PrimaryFeather
Copy link
Contributor

skipped

What do you think of that?

I also really liked your proposal of adding a new SKIP_FRAME event, so I added that, too. Thanks so much for the suggestion!

@PrimaryFeather
Copy link
Contributor

Note that "skipped/sec" is typically two frames lower than the "frames/sec" – that's because the stats display renders two times per second. 😉

@j3k0
Copy link
Author

j3k0 commented Jan 12, 2021

What do you think of that?

Great!

"skipped/sec" is typically two frames lower than the "frames/sec"

OK, so that's only when the stats are displayed, good to know. I assumed there was a built in minimum of the refresh rate.

Maybe there is a way to know the frame was only drawn because of the stats display? This way it could still counts as a skipped frame. No need to over-complicate things just for that though.

@PrimaryFeather
Copy link
Contributor

Thanks for your quick review, Jean-Christophe! 😄

Maybe there is a way to know the frame was only drawn because of the stats display? This way it could still counts as a skipped frame. No need to over-complicate things just for that though.

Mhm, I thought about that, too; just as the number of draw calls shown ignores those of the stats display, it would be great if the "skipped frames" count would take the stats display itself into account. However, it's not so easy, because I don't know who or what is responsible for a draw call. E.g. there could be a TextField on the stage displaying the current time, updating in sync with the stats display. With the stats display enabled, it wouldn't even change the skip count.

So I guess all I can do is document this behavior, but keep it as is. 😉

@j3k0
Copy link
Author

j3k0 commented Jan 12, 2021

Just a random thought I got on that.

Assuming displayObject.requiresRedraw indicates that a given DisplayObject is to be redrawn.

It might be relatively easy to implement (pseudo code).

/// @internal
DisplayObject.dirtyList(): Array<DisplayObject> {
  if (this.requiresRedraw) return [ this ] else return [];
}

/// @internal
DisplayObjectContainer.dirtyList(): Array<DisplayObject> {
  const ret = [];
  for (const obj of this.children)
    ret = ret.concat(obj.dirtyList());
  return ret;
}

That gives the list of objects that need redraw:

  • good for debugging which object is responsible for redrawing the scene (when trying to improve that)
  • allows starling check that only the stats display is responsible (when showing it).

@PrimaryFeather
Copy link
Contributor

Thanks for the suggestion, Jean-Christophe! You're right, it might be useful to add such functionality to be able to find out more about what's responsible for a redraw – and use that inside the stats display, too. I'll think about this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants