texture recovery

Started by raft, December 21, 2010, 03:20:37 PM

Previous topic - Next topic

raft

after GL context is lost and recreated (for example after pressing home button and returning back to activity), textures are re-uploaded to gpu automatically when they are needed. this is great but has a side effect, we got a delay.

in my game, i use android widgets for in game gui (not for the overlays and in-game buttons but for paused menu etc). when user returns the activity, paused menu instantly appears (since it's android gui) with a black background, this lasts a few seconds (most textures are re-uploaded), then game is rendered in background, when user presses resume button, then another delay happens (this time overlay textures are re-uploaded, they werent rendered in paused state). not a nice experience for user. i'm not sure how to cope with this

* leave it as it's :)
* adding a method to TextureManager to manually force all textures re-upload may help.

EgonOlsen

I could add a method which forces all known textures to be uploaded in the next render cycle. But that wouldn't affect blitted ones unless they are known to the TextureManager. Is that a problem? Have you tried to create the mipmaps on the cpu? Maybe that's faster?

raft

No it wont be a problem. I can add blitted textures to TextureManager too.

so this method wont be synchronous and can be called in any thread. is it possible to make it synchronous or have some mechanism to notify when it finishes?

I havent tried cpu mipmapping but mipmapping seems fast. below is the output at this recovery stage. there are many garbage collections taking time. not sure if triggered by jPCT. i guess uncompressing take quite a time. maybe you can print out uncompres time too.

I/jPCT-AE (30203): Memory usage after compacting: 5877 KB used out of 14151 KB
I/jPCT-AE (30203): OpenGL vendor:     Qualcomm
I/jPCT-AE (30203): OpenGL renderer:   Adreno
I/jPCT-AE (30203): OpenGL version:    OpenGL ES-CM 1.1
I/jPCT-AE (30203): OpenGL renderer initialized (using 2 texture stages)
D/dalvikvm(30203): GC freed 67 objects / 348960 bytes in 44ms
I/jPCT-AE (30203): Uncompressed 172106 bytes to 1048576 bytes!
D/dalvikvm(30203): GC freed 10 objects / 688904 bytes in 41ms
D/dalvikvm(30203): GC freed 16 objects / 664 bytes in 41ms
D/dalvikvm(30203): GC freed 9 objects / 2428136 bytes in 41ms
D/dalvikvm(30203): GC freed 17 objects / 2097712 bytes in 45ms
D/dalvikvm(30203): GC freed 3 objects / 362744 bytes in 40ms
I/jPCT-AE (30203): Uncompressed 181335 bytes to 1048576 bytes!
D/dalvikvm(30203): GC freed 10 objects / 726944 bytes in 41ms
D/dalvikvm(30203): GC freed 4 objects / 192 bytes in 41ms
D/dalvikvm(30203): GC freed 9 objects / 2503216 bytes in 41ms
D/dalvikvm(30203): GC freed 16 objects / 2097664 bytes in 45ms
D/dalvikvm(30203): GC freed 3 objects / 366944 bytes in 41ms
I/jPCT-AE (30203): Uncompressed 183437 bytes to 1048576 bytes!
D/dalvikvm(30203): GC freed 10 objects / 735608 bytes in 42ms
D/dalvikvm(30203): GC freed 4 objects / 192 bytes in 41ms
D/dalvikvm(30203): GC freed 15 objects / 2521016 bytes in 106ms
D/dalvikvm(12048): GC freed 2972 objects / 129872 bytes in 120ms
D/dalvikvm(30203): GC freed 10 objects / 2097488 bytes in 41ms
D/dalvikvm(30203): GC freed 3 objects / 402048 bytes in 41ms
I/jPCT-AE (30203): Uncompressed 200990 bytes to 1048576 bytes!
D/dalvikvm(30203): GC freed 10 objects / 806216 bytes in 44ms
D/dalvikvm(30203): GC freed 4 objects / 192 bytes in 43ms
D/dalvikvm(30203): GC freed 15 objects / 2661336 bytes in 45ms
D/dalvikvm(30203): GC freed 10 objects / 2097488 bytes in 41ms
D/dalvikvm(30203): GC freed 3 objects / 493328 bytes in 49ms
I/jPCT-AE (30203): Uncompressed 246627 bytes to 1048576 bytes!
D/dalvikvm(30203): GC freed 10 objects / 988192 bytes in 54ms
D/dalvikvm(30203): GC freed 4 objects / 192 bytes in 43ms
D/dalvikvm(30203): GC freed 15 objects / 3025696 bytes in 46ms
D/dalvikvm(30203): GC freed 12 objects / 2359296 bytes in 44ms
I/jPCT-AE (30203): Uncompressed 130872 bytes to 1048576 bytes!
D/dalvikvm(30203): GC freed 10 objects / 524568 bytes in 44ms
D/dalvikvm(30203): GC freed 4 objects / 192 bytes in 41ms
D/dalvikvm(30203): GC freed 15 objects / 2098792 bytes in 44ms
I/jPCT-AE (30203): Uncompressed 4449 bytes to 16384 bytes!
I/jPCT-AE (30203): Mipmaps generated by the GPU in 1ms
I/jPCT-AE (30203): Uncompressed 37889 bytes to 65536 bytes!
I/jPCT-AE (30203): Mipmaps generated by the GPU in 2ms
I/jPCT-AE (30203): Uncompressed 37675 bytes to 65536 bytes!
I/jPCT-AE (30203): Mipmaps generated by the GPU in 2ms
I/jPCT-AE (30203): Uncompressed 4388 bytes to 16384 bytes!
I/jPCT-AE (30203): Mipmaps generated by the GPU in 1ms
I/jPCT-AE (30203): Uncompressed 11064 bytes to 16384 bytes!
I/jPCT-AE (30203): Mipmaps generated by the GPU in 1ms
I/jPCT-AE (30203): Uncompressed 12737 bytes to 65536 bytes!
D/dalvikvm(30203): GC freed 165 objects / 2954000 bytes in 43ms
I/jPCT-AE (30203): Mipmaps generated by the GPU in 2ms
D/dalvikvm(28069): GC freed 87 objects / 3000 bytes in 147ms
I/jPCT-AE (30203): Uncompressed 74187 bytes to 524288 bytes!
D/dalvikvm(30203): GC freed 734 objects / 773696 bytes in 42ms
D/dalvikvm(30203): GC freed 31 objects / 1122560 bytes in 41ms
I/jPCT-AE (30203): Uncompressed 17132 bytes to 131072 bytes!
I/jPCT-AE (30203): Uncompressed 5760 bytes to 131072 bytes!
D/dalvikvm(30203): GC freed 76 objects / 2496424 bytes in 41ms
I/jPCT-AE (30203): Uncompressed 10807 bytes to 131072 bytes!
D/dalvikvm(28314): GC freed 2454 objects / 110688 bytes in 102ms

EgonOlsen

Uncompressing uses ByteArrayXXXputStreams and such...so yes, i guess it will create some garbage. Looking at the code of desktop jPCT, i noticed a method in TextureManager called preWarm(<FrameBuffer>); which wasn't present in jPCT-AE. I decided to add it and put the texture upload stuff in there. The method doesn't guarantee that anything useful happens when you call it (it's like System.gc() in that respect), so i can get away with doing nothing where i actually would have to do some asynchronous stuff in desktop jPCT. In AE, everything is synchronous, so if you call it, all known textures should be uploaded if needed.
I've also added the timing output to the uncompression code. Hope this helps.

http://www.jpct.net/jpct-ae/download/alpha/jpct_ae.jar

raft

thanks ;D does it matter calling preWarm in GL thread or not ?

EgonOlsen

The gl context should be valid when called from other threads IMHO. However, you should take care that it doesn't interfere with the rendering itself or you'll screw up OpenGL states badly.

EgonOlsen


raft

it works. uncompressing takes quite a time as seen in logs, but still gc takes more time.

I/jPCT-AE ( 4510): OpenGL renderer initialized (using 2 texture stages)
D/dalvikvm( 4510): GC freed 74 objects / 349216 bytes in 62ms
I/jPCT-AE ( 4510): Uncompressed 172106 bytes to 1048576 bytes in 131ms!
D/dalvikvm( 4510): GC freed 13 objects / 689080 bytes in 48ms
D/dalvikvm( 4510): GC freed 4 objects / 240 bytes in 57ms
D/dalvikvm( 4510): GC freed 21 objects / 2428640 bytes in 61ms
D/dalvikvm( 4510): GC freed 16 objects / 2097696 bytes in 49ms
D/dalvikvm( 4510): GC freed 3 objects / 362744 bytes in 57ms
I/jPCT-AE ( 4510): Uncompressed 181335 bytes to 1048576 bytes in 202ms!
D/dalvikvm( 4510): GC freed 13 objects / 727120 bytes in 62ms
D/dalvikvm( 4510): GC freed 4 objects / 240 bytes in 57ms
D/dalvikvm( 2168): GC freed 2615 objects / 112712 bytes in 171ms
D/dalvikvm( 4510): GC freed 9 objects / 2503208 bytes in 62ms
D/dalvikvm( 4510): GC freed 15 objects / 2097640 bytes in 61ms
D/dalvikvm( 4510): GC freed 3 objects / 366944 bytes in 57ms
I/jPCT-AE ( 4510): Uncompressed 183437 bytes to 1048576 bytes in 201ms!
D/dalvikvm( 4510): GC freed 13 objects / 735784 bytes in 58ms
D/dalvikvm( 4510): GC freed 4 objects / 240 bytes in 62ms
D/dalvikvm( 4510): GC freed 14 objects / 2520984 bytes in 58ms
D/dalvikvm( 4510): GC freed 10 objects / 2097496 bytes in 57ms
D/dalvikvm( 4510): GC freed 3 objects / 402048 bytes in 58ms
I/jPCT-AE ( 4510): Uncompressed 200990 bytes to 1048576 bytes in 181ms!
D/dalvikvm( 4510): GC freed 13 objects / 806392 bytes in 62ms
D/dalvikvm( 4510): GC freed 4 objects / 240 bytes in 57ms
D/dalvikvm( 4510): GC freed 14 objects / 2661304 bytes in 57ms
D/dalvikvm( 4510): GC freed 10 objects / 2097488 bytes in 59ms
D/dalvikvm( 4510): GC freed 3 objects / 493328 bytes in 59ms
I/jPCT-AE ( 4510): Uncompressed 246627 bytes to 1048576 bytes in 200ms!
D/dalvikvm( 4510): GC freed 13 objects / 988368 bytes in 60ms
D/dalvikvm( 4510): GC freed 4 objects / 240 bytes in 60ms
D/dalvikvm( 4510): GC freed 14 objects / 3025664 bytes in 49ms
I/ActivityManager( 2168): Process com.android.settings (pid 4928) has died.
D/dalvikvm( 4510): GC freed 12 objects / 2359312 bytes in 57ms
I/jPCT-AE ( 4510): Uncompressed 130872 bytes to 1048576 bytes in 109ms!
D/dalvikvm( 4510): GC freed 13 objects / 524744 bytes in 62ms
D/dalvikvm( 4510): GC freed 4 objects / 240 bytes in 57ms
D/dalvikvm( 4510): GC freed 14 objects / 2098760 bytes in 58ms
I/jPCT-AE ( 4510): Uncompressed 4449 bytes to 16384 bytes in 1ms!
I/jPCT-AE ( 4510): Mipmaps generated by the GPU in 0ms


but i couldnt find a proper place to prewarm yet. i've tried something like:
renderer.prewarmTextures = true;
while (renderer.prewarmTextures) {
    Log.v(LOG_TAG, "waiting for prewarm complete");
    Thread.sleep(500);
}


the thing is, if i do this in ui thread (onCreate() for example), renderer never starts and hence onCreate() never returns. if i do this in a background thread, results are somewhat unstable. for example, if i turn off screen while game is running, Android creates another Activity instance, resumes and pauses it (no kidding, wtf?) so i end up with a background thread that never completes ???

another thing is, this way initial loading time increased up to 17-18 secs on Nexus One. which may give users the idea that program hanged.

btw, is there a side effect of calling preWarm more than once?

EgonOlsen

18 secs....wow, that's a huge increase. How comes? Are you using so many textures that are uploaded during the game otherwise?
Calling it multiple times shouldn't hurt. It only uploads a texture if it hasn't been uploaded already. At least it's supposed to work that way. You can check this by looking at the log messages about mipmap creation and such. They shouldn't appear on subsequent calls.

raft

preWarm takes 5-11 secs, depends on what i dont now. i have six 512x512 textures for sky box. loading and compressing them takes most of the time. they need to be large otherwise (as skybox occupies all screen) they seem blurry on screen. i tried 256x256 but didnt look nice

raft

seems as the right place to put preWarm is onSurfaceChanged(..) armed with a synchronized block to ensure always called after textures are loaded. this way i can be sure that i left no thread behind.

initial loading time is ~15 secs with skybox textures compressed and ~10 secs uncompressed.

raft

i guess this is worth sharing:

i've made some debugging and trials on how GLSurfaceView's internal thread (GLThread) behaves. it's the thread which does the rendering and calls methods in GLSurfaceView.Renderer.

if i get the subject correct, GL context is valid while SurfaceView is valid. but seems as GLThread creates GL context unnecessarily at every call to GLSurfaceView.onResume(). for example, some application popups infront of the game, your activity pauses and then resumes and you call GLSurfaceView.onPause() and GLSurfaceView.onResume() respectively. GLSurfaceView.onResume() results in recreating GL context but it's still valid indeed. normally this wont matter too much, but if your textures are large as mine, then you got an unnecessary delay of seconds.

raft