ZhouWeikuan / cocos2d

cocos2d for android, based on cocos2d-android-0.82, and now ported from cocos2d-iphone 0.99.4. The googlecode address is here: http://code.google.com/p/cocos2d-android-1/ . There are several demos to watch.
610 stars 291 forks source link

libgdx update and native buffers for particle effects #33

Closed dustinanon closed 12 years ago

dustinanon commented 13 years ago

Updated libgdx and implemented native buffer copies for particle effects. This has a dramatic performance increase.

Check http://www.badlogicgames.com/wiki/index.php/Direct_Bulk_FloatBuffer.put_is_slow for more information.

dustinanon commented 13 years ago

There we go, here's further optimizations to reduce gc while the particle system is running. Also made some optimizations to initParticle to reduce the recycle time for a particle.

dustinanon commented 13 years ago

For my case, I also just fixed all of my white texture issues. Please try the last commit and tell me if it works for you too!

opengenius commented 13 years ago

http://www.image-share.com/ipng-889-228.html http://www.image-share.com/ipng-889-229.html

this happens after Particle demo starts, and dissapeares after 10 minutes only. HTC sensation with android 2.3.4.

also in our project i have UnsatisfiedLinkError exception.

java.lang.UnsatisfiedLinkError: copyJni at com.badlogic.gdx.utils.BufferUtils.copyJni(Native Method) at com.badlogic.gdx.utils.BufferUtils.copy(BufferUtils.java:153) at org.cocos2d.particlesystem.CCQuadParticleSystem.initTexCoordsWithRect(CCQuadParticleSystem.java:171) at org.cocos2d.particlesystem.CCQuadParticleSystem.(CCQuadParticleSystem.java:74)

dustinanon commented 13 years ago

As for the UnsatisfiedLinkError, either the libgdx.so is out of date (I provided an updated 0.9.1 version somewhere in all these commits, lol) or you didn't load the jni.

What I saw was that System.loadLibrary("gdx") was only being called from on a per Test basis (in fact, I think it was only called on the Box2D test, since the only JNI that was being used was for physics), but what I did was go ahead and load the Library in Cocos2D.java, that way all child activities will also have access to libgdx.

dustinanon commented 13 years ago

As for that issue with the HTC Sensation... well.. wow, haha. I haven't seen that! At work I have a Motorola Motoroi (Korean version of the Motorola Droid), that's running 2.1, a Samsung Galaxy Tab that's running 2.2, a Barnes & Noble NookColor that's running 2.2, and another Samsung Galaxy Tab that's running 2.3.4.

I tested on each platform before committing (these are the devices our clients have requested, so we bought one of each for testing our own implementation), and the code worked well on each of them. I wonder if there's anyway that I can set up the emulator to behave like your Sensation?..

If it's a problem with the direct buffers being copied by JNI... well, see if you can view the EffectsAdvancedTest, that uses CCGrid3D which I also updated to use the JNI Buffer Copy. Maybe we can pin down what's happening to either using JNI for buffer copies, or something that's going on specifically within the particlesystem?

dustinanon commented 13 years ago

I found a couple of links, maybe the HTC Sensation has a bug with it's graphics drivers, or maybe something with the SD Card loader, or maybe lack of support for qHD (whatever that is???)

http://support.t-mobile.com/thread/1501 http://forum.xda-developers.com/showthread.php?t=1169704 http://forum.xda-developers.com/showthread.php?p=15190722 http://support.t-mobile.com/message/12431

I don't know if these are the same thing, but I guess we could check?

opengenius commented 13 years ago

EffectsAdvancedTest seems to run fine.

opengenius commented 13 years ago

cocos2d samples are installed into internal memory. I've tried with removed SD, but artifacts haven't missed.

dustinanon commented 13 years ago

wow, that's really bizarre... if the JNI Copy works for EffectsAdvancedTest, then I guess it's something that is explicit to the Particle Test... my guess is that OpenGL does something in particle effects that it doesn't do in EffectsAdvancedTest and your phone doesn't like it. I'll have to see what the differences is.

opengenius commented 13 years ago

updateQuad(CCParticle p, CGPoint newPos) { // place vertices and colos in array final int base = particleIdx * ccPointSprite.spriteSize; vert_arr[base + 0] = newPos.x; vert_arr[base + 0] = newPos.y;
vert_arr[base + 0] = p.color.r; vert_arr[base + 0] = p.color.g; vert_arr[base + 0] = p.color.b; vert_arr[base + 0] = p.color.a;

looks like +0 was copypasted in CCPointParticleSystem

opengenius commented 13 years ago

int base; float size_2, x, y, r, cr, sr;

local variables are outside of method body in CCQuadParticleSystem.

dustinanon commented 13 years ago

yeah, I pulled them out because creating the floats and deleting them was causing the GC to go crazy and caused the framerate to stutter. By having them outside the method body, we utilize an extra 224bits per particle that persists outside of the method, but it's much better than allocating those 224 bits inside the method, then releasing them every time the you update the quad, on every particle.

My garbage collector was clearing ~38,000 objects once every 700 ~ 1000 ms before I pulled those out.

As for CCPointParticleSystem... ahem.. .whoops :P

I did that at 3AM, my mistake! It should be base + 0, base + 1, etc.,

opengenius commented 13 years ago

ints and floats are primitive types and they are allocated in stack memory, GC doesn't track them, please read something about memory in Java.

dustinanon commented 13 years ago

Then you put those back in, run the particlesystem, and watch logcat.

I know about that, I've read that about it, but if I had to make a guess at what was happening, I would say that dalvik handles primitives a little differently than Sun/Oracle's JVM.

All I know is that I tested it, and that's what I observed.

Edit: Okay, my mistake there. Perhaps I got a little overzealous with pulling shit out of the method call. I put them back in, tested, and it was even faster than having them declared as a member field.

Sorry that I was a little offended, it's just that your comment came off as somewhat crass. I'm just trying to get performance on lesser devices because we're trying to get a cocos2d application to run on android phones with the same speed that our iOS version runs on the iPhone.

That means that I have to optimize some of this code as best as I can, under deadline, with $1000s at risk. Forgive me if I make a poor choice every now and then :-/