• Advertisement
Sign in to follow this  

GLSL-PingPong-Rendering - strange performance issue

This topic is 1973 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there,

I do some calculations on the GPU by rendering a quad into a FBO. The result is subsequently submitted back to GPU for further processing.
The result looks fine but due to some strange mistake I seem to make, it runs very slow (below 1 fps). But when I include a "glReadPixels" call after rendering the quad, the performance goes up to 20 fps (the result of the calculation stays absolutely the same!). But since I don't want to access the data on CPU between the two shader calls, I don't need to acces the pixels and therefore there should be no need for a glReadPixels call. The result of the glReadPixels call is not even read by the program and I only need to read a one-pixel-region to get this effect (see comments below). I have no Idea how this strange behaviour could be explained.

The relevant code is posted below. I used an FBO without an attached depth buffer, only a rgba-texture. The functions "renderToFBO" and "submitToGPU" are called subsequently. If you are interested in initialzation code or something, please let me know. I figured out, that the performance issue is not related to the glsl-shader code.

Thanks for your answers.
[source lang="cpp"]// RenderTarget - Type:

typedef struct {
bool isAllocated;
bool hasDepthBuffer;
GLuint color_tex;
GLuint fb; // FBO
GLuint depthBuffer;
GLsizei width;
GLsizei height;
TextureType textureType;
} RenderTarget;

// ------------------ render to FBO ---------------------

void RenderTargetContainer :: renderToFBO(RenderTarget *rt) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, rt->fb);
glViewport(0,0, rt->width, rt->height);

glClear(GL_COLOR_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, rt->width, 0.0, rt->height);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glBegin(GL_QUADS);
glVertex2f(0.0, 0.0);
glVertex2f(static_cast <float> (rt->width), 0.0);
glVertex2f(static_cast <float> (rt->width),static_cast <float> (rt->height));
glVertex2f(0.0, static_cast <float> (rt->height));
glEnd();

// -- these two lines make it run fast
// -- although the visible result statys the same.
// -- "foo" will never be read.
// -- region needs to be at least 1 to get the speed up effect.
static float foo[4];
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, foo);
}

// ------------------ submit result to GPU ---------------------

void RenderTargetContainer :: submitToGPU(GLint shaderVarLocation, int textureUnit, RenderTarget *rt) {
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, rt->color_tex);
glUniform1i(shaderVarLocation, textureUnit);
}[/source]

Share this post


Link to post
Share on other sites
Advertisement
Oh sorry, I didnt... I was just checking for glsl errors...
What could it mean that i got an invalid operation error (0x502) at the very beginning of my Program?

[source lang="cpp"]int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
checkErr(); // GL_INVALID_OPERATION !!!!!!!!

MSG msg = {0};
WNDCLASSEX wcl = {0};

wcl.cbSize = sizeof(wcl);
wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wcl.lpfnWndProc = WindowProc;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hInstance = g_hInstance = hInstance;
wcl.hIcon = LoadIcon(0, IDI_APPLICATION);
wcl.hCursor = LoadCursor(0, IDC_ARROW);
wcl.hbrBackground = 0;
wcl.lpszMenuName = MAKEINTRESOURCE(MENU_FIXED_FUNC);
wcl.lpszClassName = "GLWindowClass";
wcl.hIconSm = 0;

if (!RegisterClassEx(&wcl))
return 0;
......[/source]

Share this post


Link to post
Share on other sites
Calling glGetError without a context is invalid, as it is a gl function and you should have the context before calling it. And have you tried calling glFinish() or glFlush() after the operations?

I'm also wondering what you mean by "submitting the results to GPU", if you never read back the texture data to CPU won't you just keep working on the same data? The piece of code you commented as submitting the results just binds another texture. Edited by powly k

Share this post


Link to post
Share on other sites
Thank you, calling glFinish() after rendering the quad made it run fast so that I don't need the glReadPixels-hack anymore! Seems like glReadPixels does something like glFinish internally.

(btw. Putting glGetError at locations behind context creation also removed any gl-errors smile.png )

I'm also wondering what you mean by "submitting the results to GPU", if you never read back the texture data to CPU won't you just keep working on the same data? The piece of code you commented as submitting the results just binds another texture.[/quote]
I'm not deep into that but I think it's like this:
The texture data doesn't need to be transferred to the CPU, since after rendering the quad the data is inside the texture memory on GPU - binding the texture and sending the texture unit via glUniform to the shader allows accessing the texture memory on GPU where the texture data still is.
(Is that right?) Edited by Mathias_L

Share this post


Link to post
Share on other sites
Oh, it's correct. The term "submit" was what alarmed me, but it's not totally wrong because even though you don't run your data through the CPU, you do tell where in VRAM the data will be found.

And glReadPixels ought to have a glFinish inside, otherwise it could read when the image is still being rendered and return very weird results :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement