Attack of the Dreaded, Double-damned FloatBuffer

Posted by DesertFox on March 13, 2011, 1:38 a.m.

*sigh*

So one of the major irritations in game-development for the Android just reared-up and bit me in the ass - that of the Dreaded, Double-damned FloatBuffer.

What is a floatbuffer? Its a buffer of floats! Basically, its an array that you can put floats into singly, or in large chunks. What is it used for? OpenGL ES - you use floatbuffers to store mesh vertices and the like. What is the problem with it? Lets find out!

You would think that creating a floatbuffer, and adding in some float vertex data for batched drawing in OpenGL wouldn't be that annoying, especially when doing that with an IntBuffer or a ShortBuffer or a ByteBuffer takes practically zero time. In theory, adding something into a primitive buffer ought to take about as much time as assigning a value to an array. Maybe a bit slower, but not enough to be a problem.

Individual draw calls in OpenGL are sorta expensive, so batching draw calls is a good idea. Lets assume a particle system with 200 particles. Now, 200 draw calls in OpenGL ES would slow things down a bit (at least enough to be noticable), so batching is perfect here since you can store all the particle images on the same texture. 200 particles requires 4000 floats - 12 for vertex data, 8 for uv data, times 200. A sizeable array, certainly but not mindboggling.

Since the particles move, we have to clear the floatbuffer and rebuild it every frame, adding in the vertex data for every particle, and then drawing it all in one fell swoop. Since in theory, you would construct the floatbuffer from the array with one nice memory-copy operation, you'd think you would see a nice increase in performance.

Right?

What happens is a total snafu. You see, Android's implementation is completely fucked. And I mean completely. Instead of doing a memory copy like all of the other buffers, FloatBuffer wanders off, gets drunk, vomits, falls asleep in a gutter somewhere, and then finally in the morning hands you back your data. When you add something in to a floatbuffer, it does calculations on it for absolutely no reason. And they take forever.

That 4000-float floatbuffer? Clearing it and reloading it every frame, and doing nothing else gives me a whopping 8-ish frames per second. Maybe lower. Doing the same thing with an intbuffer wouldn't even register as a blip on the radar - because it is hundreds and hundreds of times faster, as is every other buffer type. This crippling bug has been around for ages

But wait! You can fix it! Just use goddamned JNI - which is basically saying "Here, you can fix this by writing something in C++ to construct a Java Floatbuffer for you!". Which totally bypasses the entire point of using java as the main development language for android for its ease of use.

So basically I said "Fuck it", and am using someone else's JNI replacement now. Now with the fast buffer replacement, I can batch my calls and draw a thousand particles if I want. Hooray!

Comments

Quietus 13 years, 7 months ago

that was quite the anticlimax.

Acid 13 years, 7 months ago

I concur.

Ferret 13 years, 7 months ago

I never knew there was such a problem with the android. How informative! :D

Zarniwooop 13 years, 7 months ago

I just lol'd when I saw your mp.

tylerthemiler 13 years, 7 months ago

That's really annoying :/ Why didn't they just port the Java version, since android uses a fair amount of the native java libraries right??

DesertFox 13 years, 7 months ago

@tyler - they *did* port the java version. They just fucked it up.