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

HIGH energy consumption and GPU load on empty cocos2d-x starter project for iPhone6/6+. Probably more models affected. #18020

Open
kyriakos89 opened this issue Jul 2, 2017 · 21 comments
Assignees
Labels
Milestone

Comments

@kyriakos89
Copy link

Test Specs:

  • cocos2d-x version: 3.15.1
  • devices test on: iphone 6, iphone6+
  • developing environments
    • Xcode version:8.3.3 (8E3004b) but probably any version will have the same results.
    • iOS 10.x

Steps to Reproduce:

  1. Download the latest Cocos2d-x v3.15.1

  2. Run the cpp-empty-test iOS on iPhone 6 or iPhone 6+.

  3. It should be at running at 60fps with 72 GL vests, 3 GL calls
    19688534_10154865388471872_951622678_o

  4. Checking energy consumption using xCode. You will notice around 15% CPU (not an issue), that GPU is being used and a report for high energy consumption.
    iphone high energy

  5. Repeat the test on iPad 3 or iPad mini. The energy consumption should be low and GPU is not being used.
    ipad low energy

Users have reported that phones are heating up while playing games powered by Cocos2d-x.

@gestern
Copy link
Contributor

gestern commented Jul 7, 2017

Any news with the issue?

@kyriakos89
Copy link
Author

kyriakos89 commented Jul 7, 2017

Hi @gestern . We noticed a post you made in the past regarding a similar issue. And we remember that nobody replied. :) Yes, we have some more info. We created a new cocos2d-x empty project and we noticed low energy consumption on the above devices. After some comparison between an new cocos2d-x project and cpp-empty-test iOS, the difference was the surface size of the phone. In new project, the phone is using the provided launch images and a much lower resolution instead of the phones native resolution. On cpp-empty-test iOS and in our project, cocos2d-x has a surface size of the native resolution of the phone which is much higher. The only way to force a lower resolution is to not specific launch images for iphone 6 and 6+ which in our case is not an option, so we have yet to find a solution. What we want is to provide the launch images but use a lower surface resolution with scaling. The way we provide launch images is through a storyboard launch screen where we use 1 image and center it on all devices.

No help from coco2d-x team. We are a bit disappointed. It seems that cocos2d-x cant handle high resolution which is sad. Except if the cause is something else. At least we have gathered a lot of info so that someone more expert in the matter can have a look.

@minggo
Copy link
Contributor

minggo commented Jul 13, 2017

Oh, i haven't noticed it. It seems it is a tricky issue since all the codes are the same.

@kyriakos89
Copy link
Author

@minggo - Is there any way to change cocos2d-x surface size? Even if device has a bigger surface size. Let's say force it /2 so there are 50% less pixels to render on screen.

@minggo
Copy link
Contributor

minggo commented Jul 17, 2017

currently, retina is enabled by default, you may disable it but it may cause problem.

@xxy8075
Copy link

xxy8075 commented Mar 24, 2018

@minggo This problem is very serious,our game have 1500w downloads,Many users report that power consumption is serious,We will never use cocos2d-x again

@kkafas
Copy link

kkafas commented Mar 24, 2018

We managed to solve partially the issue by modyfing internally cocos2d-x. A static boolean variable controls cocos main draw function and is set as false by default. It is set to true only if some label, sprite, node etc must be drawn. e.g. to achieve this for a sprite we set variable to true if its position, opacity, color etc change in the respective setter functions. It’s a big change as many functions in many classes must be modified. However, this solution works if u have states in ur application with 0 animation. If you have ongoing animation, this solution is useless to you.

@trimax-items
Copy link

This is serious. It may even lead to a ban of cocos2d-x games by apple.

@slackmoehrle
Copy link
Contributor

slackmoehrle commented Mar 25, 2018

@kkafas can you share what you modified so I can take a look? And did you test with 3.16 or the latest from master and is utilization less now from your screenshots above?

@koalli
Copy link

koalli commented Mar 30, 2018

@kyriakos89 Do you have any idea how to change cocos2d-x surface size now? After cocos2d-x use Storyboard as launch screen #18276 to compatible with iPhoneX, we face the same problem with you. It's a very serious problem and we will lost many users because of it.

@minggo @dumganhar Can anybody help us?

@gestern
Copy link
Contributor

gestern commented Apr 2, 2018

@koalli
Despite the fact that your question does not concern the performance problem in cocos2d-x that is discussed here. I'll try to suggest a workaround with your problem with iPhoneX, so you have to stop using storyboard with loading screen and start using static way with Static Launch Screen. This approach will deprive you of most bugs with dynamic orientation (for example the call applicationScreenSizeChanged() is absolutely useless if you using dynamic way with storyboard ) that were never described here. So, try to use "Static Launch Screen" which linked above, and avoid using stroyboards way while you support iPhoneX

@drelaptop drelaptop added this to the 3.18 milestone May 22, 2018
@andres-blanco
Copy link

andres-blanco commented Oct 16, 2018

@kkafas can you share what you modified so I can take a look? And did you test with 3.16 or the latest from master and is utilization less now from your screenshots above?

I've just tested with 3.17 and the problem still persists. This is very serious

@drelaptop was there any progress in finding/fixing this issue?

@minggo
Copy link
Contributor

minggo commented Oct 24, 2018

Yep, the energy is high, it clears frame buffer many times which is not needed. I sent a PR to fix it #19131.

You can see that the energy of cpp-empty-test is still high. It is because:

  • the FPS is 60
  • it draws a full screen sprite
  • it draws fps info in bottom left
  • it draws a safe range area
  • it draw a button in upper right

If you change to 30 FPS and don't draw the full screen sprite, then the energy will be slow.

@minggo minggo assigned minggo and unassigned PatriceJiang Oct 24, 2018
@minggo
Copy link
Contributor

minggo commented Oct 24, 2018

In theory, if the content of a scene is static(not changed), then should not redraw. As cocos2d-x doesn't consider it at first, so can not implement it easily.

@kyriakos89
Copy link
Author

kyriakos89 commented Oct 24, 2018

"In theory, if the content of a scene is static(not changed), then should not redraw. "-> This is true. Our solution is not drawing the scene unless there is a change. However, our game has long static screens while user is not interacting. If you have continuous drawing, this solution is useless. Only dropping FPS might help.

In case you are interested about this solution i can provide some guidance but not the whole solution as it is now part of commercial product. Be warned, this solution is very huge and involves changes almost every cocos2d-x class.

  1. In void Director::drawScene(), it should draw only when our custom flag is set to true. Initially its set to true. After every draw, it is set back to false. it will get true again, only when something will change position, color, scale etc.

const bool drawThisFrame = _runningScene ? _CustomWasUpdatedForDraw( _runningScene ) : true;
if( drawThisFrame ) {
_renderer->clear();
......

  1. _CustomWasUpdatedForDraw

bool _CustomWasUpdatedForDraw( Node * parent ) {
if( !parent->isVisible() ) {
return false;
}
bool res = false;
if( parent->_CustomWasUpdatedForDraw ) {
parent->_CustomWasUpdatedForDraw = false;
res = true;
}
for( auto& child : parent->getChildren() ) {
if( _CustomWasUpdatedForDraw( child ) ) {
res = true;
}
}
return res;
}

  1. For every class/object that is rendered on screen, you need to identify all cases that this item is updated and set this value to true. Examples of updates are position, scale, rotation, color, opacity etc. Since cocos2d-x uses very well inheritance, cocos2d-x team might find a better solution than ours. Example in Label.cpp:

void Label::updateColor()
{
if (_batchNodes.empty())
{
return;
}

Color4B color4( _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity );

........
_CustomWasUpdatedForDraw = true;
}

But as I said earlier, this will work in 1% of cases and will not help the majority of games except in scenes like a pause scene where no animation is done or if your game is liek a board game where nothing moves if user doesn't interact. Who all this info will help new ideas on the table.

@koalli
Copy link

koalli commented Nov 9, 2018

As @gestern said , I use a lower resolution LaunchImage instead of LaunchStoryboard, it can reduce the energy consumption in iPhone 6/7/8 plus obviously, this is a iOS screen compatibility mode since iPhone5 or iPhone6 I guess, it will create a smaller surface size. But we still cannot solve it in iPhone X because it will show black safe area in this mode.

In my test case, I found lower surface size also used lower energy. @kyriakos89 mention that changing surface size may reduce energy consumption, but disable retina is not a good solution. Maybe we can try to detect iPhoneX device and hardcode a lower contentScaleFactor in this code. But I have not idea what problem it will cause according to @minggo said, do you guys have any idea ?

@Izzyjm
Copy link

Izzyjm commented Nov 10, 2018

will cocos2d-x provide a fix to this my energyconsumption also just keeps going up , is at very high rightnow

@Izzyjm
Copy link

Izzyjm commented Nov 11, 2018

would anyone recommend releasing my game or wait until this issue is fixed ?

@stevetranby
Copy link
Contributor

stevetranby commented Nov 12, 2018

I would say yeah try releasing it.

Are you running the release build when testing? If not, do so.
What energy impact are you seeing on your own game? Make sure release build.
Are you able to play your game at 30fps? If so try changing the interval to 1/30 instead of 1/60. Half Energy :D (not actually, might be more or less).

You could also render at 60fps, but more manually manage your scheduled updates and animations/actions. Have your scene or root node schedule frame-based update, but then track elapsed time or frames and only call game play update functionality every .1s or every 3 frames or similar.

There are ways to render to a smaller framebuffer and then blit that framebuffer into a fullscreen quad with the simplest shader. Any non-simplest shaders will run on 1/4th the pixels if you render to a 1/2 screen width 1/2 screen height framebuffer, for example.
https://discuss.cocos2d-x.org/t/big-window-small-framebuffer/23711

@huachangmiao
Copy link
Contributor

huachangmiao commented Nov 14, 2018

I would say yeah try releasing it.

Are you running the release build when testing? If not, do so.
What energy impact are you seeing on your own game? Make sure release build.
Are you able to play your game at 30fps? If so try changing the interval to 1/30 instead of 1/60. Half Energy :D (not actually, might be more or less).

You could also render at 60fps, but more manually manage your scheduled updates and animations/actions. Have your scene or root node schedule frame-based update, but then track elapsed time or frames and only call game play update functionality every .1s or every 3 frames or similar.

There are ways to render to a smaller framebuffer and then blit that framebuffer into a fullscreen quad with the simplest shader. Any non-simplest shaders will run on 1/4th the pixels if you render to a 1/2 screen width 1/2 screen height framebuffer, for example.
https://discuss.cocos2d-x.org/t/big-window-small-framebuffer/23711

In fact, I have done this in my project.
It really can reduce energy consumption. But if you look closely, you will find that the pictures are not clear enough, especially the labels.
So I added a quality option for the players. The default selection is non-HD.
I think cocos2d-x' s developers should provide an API in the engine that can dynamically change the resolution.

@stevetranby
Copy link
Contributor

Curious what the resolution you're rendering at is and what the native resolution is of the device that's slow. Also, you could consider rendering labels at full resolution, especially if they're all in the UI layer allowing you to render them separately.

This has been common practice throughout video game history where games offer both resolution and quality settings. Players can start at max or medium and bump up/down as needed to hit certain frame rate (or in this case energy usage).

You could also offer 60 fps / 30 fps option, unless your game requires 60 for gameplay?

@drelaptop drelaptop modified the milestones: 3.17.1, next Nov 16, 2018
@minggo minggo modified the milestones: 3.17.2, next Apr 30, 2019
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