Efficient Rendering

Started by
9 comments, last by aevanthony 15 years, 12 months ago
Hmm, This application I tested with has a 128x128 texture, and the shader I'm using just does a glFragColor = texture2d...etc, a simple color assignment. Now when I scale the window up very large, my entire system suffers performance problems, mostly... actually more specifically, audio playback gets very bad and CPU shoots up. So I was wondering... what does OpenGL in place of when no shader programs are created? What's the default behavior? Maybe even... would it be a good idea to disable the shader program entirely when OpenGL is rendering a texture to the window, and just have it active while the FBO is rendering to the texture?
Advertisement
I created a new Shader program, assigned it NO shader. I used glUseProgram(textureProgram); before the FBO rendered to a texture, I used; glUseProgram(DoNothing) after.

On my current PC, CPU usage while scaling my applications window during run time. With a 256x256 texture rendered to a window scaled up to 1680x1050; CPU from ~30% to ~8%

Mmmm... that's like what, 60-75% less cpu usage? Much better, can't wait to see how this runs on a slower gpu/system.

That'll go a long way to broaden the range of GPU's that will smoothly run this program I'm sure. Mmmmm.

:) I'll have to test it all out more and all that mess, but so far happy.
Are you rendering with an infinite loop? In that case, with a single core CPU, it should use 100% CPU if vsync is off. If on, it will be like 1 to 5%.
With dual core, instead of 100%, it would be somewhere around 50%.
With dual core and if you have vsync on, it would be 1 to 5%.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Hmm, is there another way to achieve this which won't use 100% CPU for those cases? Is there some other recommended approach to this?
The other way is to render when the OS sends a notification because you window has been exposed or needs a refresh for some reason. On Windows, it sends a WM_PAINT message.
If you are using GLUT, then get rid of glutIdleFunc. Your render functions gets called when GLUT received a notification from the OS.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
When removing that idle function nothing redraws to the screen.

Just to add, I made sure vsync was forced... on both machines, but based on some reading in to Vista there's problems with vsync overall. In any case, I haven't seen anything near 50% usage on either machine. Well, except on this FX5200... but that's before and after glUseProgram.

When I swap the programs and set glUseProgram to use the program with no shader attached on this machine with a FX5200 it doesn't seem to take effect. The visual display doesn't render as if the texture is scaled, it still looks like the fragment shader is executing per pixel... using a program where no shader is attached!! Ironically the card I don't even need for did as I expected... (x1950pro) /ultra-sigh.

That's perplexing, I can't seem to figure out why that is, every thing's the same as the machine I ran this on last night on my ATI box.

Is it possible this FX card is ignoring glUseProgram calls I'm using per frame? Any other ideas? Can you think of something else?

I mean the only thing I did was akin to;

1. glUseProgram(p) // fun stuff
2. FBO render to texture. // receives fun stuff
3. glUseProgram(p2) // do no more fun stuff
4. Render texture to window. // texture rendered without extra fun stuff

*Kicks a bucket*
Post some minimilistic code that's causing the high CPU usage.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
The CPU rises only really* when I scale up, *only on this machine (of the two I tested). It's as if the glUseProgram(p2) doesn't do what it should. (Use a program which has no shader associated with it, to prevent a fragment shader from doing anything to every pixel. Hence more efficient, the goal is to force only* the texture to be processed with my fragment shader.)

This is the significant portion of the rendering loop.


	static float da = 1.0;	glUseProgram(p); // ENABLE SHADER PROGRAM	glBindTexture(GL_TEXTURE_2D, FBOTex[TexRenderWrite]);	GLint TexLoc = glGetUniformLocation(p, "tex"); glUniform1i(TexLoc, 0);	vLoc = glGetUniformLocation(p, "aL"); glUniform1f(vLoc, u0);	vLoc = glGetUniformLocation(p, "aR"); glUniform1f(vLoc, u1);	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);	glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT);	glViewport(0, 0, SD, SD);	glDrawBuffer(AttchPoint[TexRenderRead]);	glActiveTexture(GL_TEXTURE0 + TexRenderRead);	glPushMatrix();	glBegin(GL_QUADS);		glTexCoord2f(0.0, 0.0); glVertex3f(-da, -da,  0.0);		glTexCoord2f(0.0, 1.0); glVertex3f(-da,  da,  0.0);		glTexCoord2f(1.0, 1.0); glVertex3f( da,  da,  0.0);		glTexCoord2f(1.0, 0.0); glVertex3f( da, -da,  0.0);	glEnd();	glPopMatrix();	glPopAttrib();	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);	TexRenderRead = (TexRenderRead + 1)%2;	TexRenderWrite = (TexRenderWrite + 1)%2;	glUseProgram(p2); // DISABLE SHADER PROGRAM	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	glLoadIdentity();	glPushMatrix();	glBegin(GL_QUADS);		glTexCoord2f(0.0, 0.0); glVertex3f(-da, -da,  0.0);		glTexCoord2f(0.0, 1.0); glVertex3f(-da,  da,  0.0);		glTexCoord2f(1.0, 1.0); glVertex3f( da,  da,  0.0);		glTexCoord2f(1.0, 0.0); glVertex3f( da, -da,  0.0);	glEnd();	glPopMatrix();	glutSwapBuffers();	Sleep(1);
I fixed it, after researching I came across the fact that I should have done this instead to disable my fragment shader for rendering to the window;

Reference the above code and do this instead;
glUseProgram(p2) -> glUseProgram(0)



I can scale my window without a dramatic performance hit! it's a lot better. I need to do better still, it still uses too much(maybe) CPU. ~35% when scaled to over 800x600... maybe it's the best I can get though, even WinAmp has a comparable CPU usage on this machine, so maybe this is what I've been looking for.

Vista apparently has problems with vsync. Is there a way through OpenGL I can force vsync?

[Edited by - aevanthony on April 24, 2008 3:51:09 PM]
If your driver offers http://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt
then wglGetSwapIntervalEXT(0) disables and wglGetSwapIntervalEXT(1) enables it.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

This topic is closed to new replies.

Advertisement