views:

1869

answers:

5

I'm testing my simple OpenGL ES implementation (a 2D game) on the iPhone and I notice a high render utilization while using the profiler. These are the facts:

  • I'm displaying only one preloaded large texture (512x512 pixels) at 60fps and the render utilization is around 40%.
  • My texture is blended using GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, the only GL function I'm using.
  • I've tried to make the texture smaller and tiling it, which made no difference.
  • I'm using a PNG texture atlas of 1024x1024 pixels

I find it very strange that this one texture is causing such an intense GPU usage.

Is this to be expected? What am I doing wrong?

EDIT: My code:

// OpenGL setup is identical to OpenGL ES template
// initState is called to setup
// timer is initialized, drawView is called by the timer

- (void) initState
{
    //usual init declarations have been omitted here     
    glEnable(GL_BLEND); 
    glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);     
    glEnableClientState (GL_VERTEX_ARRAY);
    glVertexPointer     (2,GL_FLOAT,sizeof(Vertex),&allVertices[0].x);      
    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer   (2,GL_FLOAT,sizeof(Vertex),&allVertices[0].tx);     
    glEnableClientState (GL_COLOR_ARRAY);
    glColorPointer      (4,GL_UNSIGNED_BYTE,sizeof(Vertex),&allVertices[0].r);    
}    
- (void) drawView
{       
    [EAGLContext setCurrentContext:context];
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity();

    GLfloat width  = backingWidth /2.f; 
    GLfloat height = backingHeight/2.f; 

    glOrthof(-width, width, -height, height, -1.f, 1.f);
    glMatrixMode(GL_MODELVIEW);
    glClearColor(0.f, 0.f, 0.f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT);     
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);     
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];     
    [self checkGLError];     
}

EDIT: I've made a couple of improvements, but none managed to lower the render utilization. I've divided the texture in parts of 32x32, changed the type of the coordinates and texture coordinates from GLfloat to GLshort and added extra vertices for degenerative triangles.

The updates are:

initState: (vertex and texture pointer are now GL_SHORT)

glMatrixMode(GL_TEXTURE);
glScalef(1.f / 1024.f, 1.f / 1024.f, 1.f / 1024.f);
glMatrixMode(GL_MODELVIEW);
glScalef(1.f / 16.f, 1.f/ 16.f, 1.f/ 16.f);

drawView:

glDrawArrays(GL_TRIANGLE_STRIP, 0, 1536); //(16*16 parts * 6 vertices)
+1  A: 

Read this post.

512x512 is probably a little over optimistic for the iPhone to deal with.

EDIT:

I assume you have already read this, but if not check Apples guide to optimal OpenGl ES performance on iPhone.

Serapth
I'm aware of the fact that 512x512 is large. The question you're referring to says that tiling did the trick.My implementation doesn't benefit from tiling at all. Besides that, what if my design doesn't give me the opportunity to tile?
Kriem
tiling would only help you if your objects are small, try to move the object far away from the camera is it still taking a lot of GPU?
Shay Erlichmen
Sorry, I forgot to mention it's a 2D game. So no depth buffering and no change in load.
Kriem
I had read it indeed. It says little about my case I think?
Kriem
I'm still not convinced the 512-ness of my image is the issue. Dividing it in little parts makes no difference. Plus, we're talking about ONLY that particular 2D quad(s). You'd think the iPhone should be able to handle that easily!
Kriem
After some intense research, I came to the conclusion it's inherent to the iPhone. It's fil rate is pretty bad. Check this: http://stackoverflow.com/questions/882408/glclearcolor-pushing-the-iphone-at-27-render-utilization
Kriem
I write graphics software for the iPhone and I regularly have 5 512x512 textures (4-channels each = 4MB textures) on the iPhone. The trick is using glScissor to avoid drawing the whole texture onto the screen and instead only pushing the parts of the texture that need to be redrawn. That optimization might not be possible in your case, but it's absolutely critical in my application!
Ben Gotow
A: 

What is exactly is the problem?
You're getting your 60fps, which is silky smooth.

Who cares if render utilization is 40%?

Rhythmic Fistman
I found it strange. I was wondering ifI might be doing something wrong. Killing such a performance hit could give me more visual options.
Kriem
I've noticed that a 256x512 RGBA texture with GL_LINEAR for min and mag filter costs about 15% GPU on an iPodtouch2G. That's a lot. I'm still trying to figure out what the device likes and doesn't like. There are some counter-intuitive results.
Rhythmic Fistman
+2  A: 

Hi Kriem,

I'm writing an app which displays five 512x512 textures on top of each other in a 2D environment using GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, and I can get about 14fps. Do you really need 60fps? For a game, I'd think 24-30 would be fine. Also, use PVR texture compression if at all possible. There's an example that does it included with the SDK.

Ben Gotow
Yes, I need as much frames per second as possible. I think that should be the goalof every game designer. The more fps., the smoother. Despite that, I agree with you that 30 fps is sufficient and passes quality requirement. The problem with PVR textures are the ugly compression artefacts. Especially with 2D sprites, these artifacts really pester the experience.
Kriem
A: 

The issue could be because of the iPhone's texture cache size. It may simply come down to how much of the texture is on each individual triangle, quad, or tristrip, depending on how you're setting state.

Try this: subdivide your quad and repeat your tests. So if you're 1 quad, make it 4. Then 16. and so on, and see if that helps. The key is to reduce the actual number of pixels that each primitive references.

When the texture cache gets blown, then the hardware will thrash texture lookups from main memory into whatever vram is set aside for the texture buffer for each pixel. This can kill performance mighty quick.

OR - I am completely wrong because I really don't know the iPhone hardware, and I also know that the PVR chip is a strange beast in comparison to what I'm used to (PS2, PSP). Still it's an easy test to try and I'm curious if it helps.

Ben Throop
It didn't help. My conclusion was - apparently correct - that the iPhone has a bad fill rate.
Kriem
Ah, well good to know. Does Apple publish fill rate specs? Would guess no from your response.
Ben Throop
A: 
  1. I hope you didn't forget to disable GL_BLEND when you don't need it already.
  2. You can make an attempt at memory bandwidth optimization - use 16 bpp formats or PVRTC. IMHO with your texture size texture cache doesn't help at all.
  3. Don't forget that your framebuffer is being used as texture by iPhone UI. If it is created as 32 bit RGBA it will be alpha-blended one more time. For optimal performance 16 bit 565 framebuffers are the best (but graphics quality suffers).

I don't know all the details, such as cache size, but, I suppose, textures pixels are already swizzled when uploaded into video memory and triangles are split by PVR tile engine. Therefore your own splitting appears to be redundant.

And finally. This is only a mobile low-power GPU, not designed for huge screens and high fillrates. Alpha-blending is costly, maybe 3-4 times difference on PowerVR chips.

P.S. sorry for my bad english

noop