1

I recently asked this question:

How to perform asynchronous off-screen queries?

What I've heard, but haven't been able to confirm yet, is that rendering to the window is more expensive than rendering to a framebuffer. First of all, can anyone comment on this? Can I draw multiple scenes to framebuffers faster than I can to the window? Are there other options, e.g., pbuffers or PBOs?

I have started playing around with framebuffers, but I have not been able to get the query to work. Here's some psuedo code for what I have set up so far:

glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
window = glfwCreateWindow(1, 1, "OpenGL", NULL, NULL);

glfwMakeContextCurrent(window);

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);

glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);

glEnable(GL_DEPTH_TEST);
glGenQueries(numberOfQueries, queries);

for (scene in scenesToRender)
{
    glClear(GL_DEPTH_BUFFER_BIT);


    glDepthFunc(GL_LESS);
    drawShadingObjects(scene);

    glBeginQuery(GL_SAMPLES_PASSED, queries[index]);

    glDepthFunc(GL_LEQUAL);
    drawShadedObject(scene);

    glEndQuery(GL_SAMPLES_PASSED);

}

collectQueryResults();

deleteBuffers();

So far everything runs, but all of the queries return "0". Is there something about querying when drawing to a framebuffer that is different than when drawing to the window buffer?

Again, my two questions are:

  1. Can I draw multiple scenes to framebuffers faster than I can to the window? Are there other options, e.g., pbuffers or PBOs?
  2. Is there something about querying when drawing to a framebuffer that is different than when drawing to the window buffer?
Community
  • 1
  • 1
Neal Kruis
  • 2,055
  • 3
  • 26
  • 49
  • So do you have one query or multiple queries? Your `glGenQueries()` and `glBeginQuery()` calls seem to disagree. – genpfault Jan 28 '14 at 19:12
  • oops. it should be multiple queries. I'll fix that. The idea is that there can be some number of asynchronous queries happening while other scenes are drawn. – Neal Kruis Jan 28 '14 at 19:26

1 Answers1

1

Try something like this:

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include <vector>
using namespace std;

const unsigned int sz = 1024;
void drawScene( unsigned int multiplier )
{
    glViewport( 0, 0, sz, sz );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glRotatef( (float)glfwGetTime() * 50.f * multiplier, 0.f, 0.f, 1.f);
    glBegin(GL_TRIANGLES);
    glColor3f(1.f, 0.f, 0.f);
    glVertex3f(-0.6f, -0.4f, 0.f);
    glColor3f(0.f, 1.f, 0.f);
    glVertex3f(0.6f, -0.4f, 0.f);
    glColor3f(0.f, 0.f, 1.f);
    glVertex3f(0.f, 0.6f, 0.f);
    glEnd();
}

bool available( const vector< GLuint >& queries )
{
    for( size_t i = 0; i < queries.size(); ++i )
    {
        GLuint available = 0;
        glGetQueryObjectuiv( queries[i], GL_QUERY_RESULT_AVAILABLE, &available );
        if( GL_FALSE == available )
            return false;
    }
    return true;
}

int main()
{
    glfwInit();
    GLFWwindow* window = glfwCreateWindow( 400, 400, "Simple example", NULL, NULL );
    glfwMakeContextCurrent( window );
    glewInit();

    if( !glewIsSupported( "GL_VERSION_2_1" ) )
        return -1;
    if( !glewIsSupported( "GL_EXT_framebuffer_object" ) )
        return -1;

    GLuint fbo = 0;
    glGenFramebuffersEXT( 1, &fbo );
    glBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, fbo );

    GLuint rbo0 = 0;
    glGenRenderbuffersEXT( 1, &rbo0 );
    glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbo0 );
    glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_RGBA, sz, sz );
    glFramebufferRenderbufferEXT( GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rbo0 );

    GLuint rbo1 = 0;
    glGenRenderbuffersEXT( 1, &rbo1 );
    glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbo1 );
    glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, sz, sz );
    glFramebufferRenderbufferEXT( GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo1 );

    GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
    if( status != GL_FRAMEBUFFER_COMPLETE_EXT )
        return -1;

    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );

    vector< GLuint > queries( 10 );
    glGenQueries( queries.size(), &queries[0] );

    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo );

    for( size_t i  = 0; i < queries.size(); ++i )
    {
        glBeginQuery( GL_SAMPLES_PASSED, queries[i] );
        drawScene( i + 1 );
        glEndQuery( GL_SAMPLES_PASSED );
    }

    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );

    // wait for queries to become available
    unsigned int cnt = 0;
    while( !available( queries ) )
    {
        cnt++;
    }

    // all queries available, display query results
    cout << "cnt: " << cnt << endl;
    for( size_t i = 0; i < queries.size(); ++i )
    {
        GLuint samples = 0;
        glGetQueryObjectuiv( queries[i], GL_QUERY_RESULT, &samples );
        cout << i << ": " << samples << endl;
    }
    cout << endl;

    glfwDestroyWindow( window );
    glfwTerminate();
    return 0;
}

Representative output on my system:

cnt: 1884
0: 157288
1: 157288
2: 157289
3: 157288
4: 157287
5: 157286
6: 157292
7: 157286
8: 157289
9: 157288
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • Your code works fine on my machine, and I've implemented what I can tell are the significant differences from my code (mainly including the color attachment to the FBO). For whatever reason, it appears that I am still rendering to the default framebuffer (i.e. my 1x1 window). Do you know what might be causing this? I am binding to "fbo" before I draw. – Neal Kruis Jan 30 '14 at 18:31
  • After using `glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING,&int)` it appears that it is rendering to my defined framebuffer, but for whatever reason the size is only 1x1. The framebuffer is inheriting the size of the window even though the renderbuffer storage is set to 512x512. – Neal Kruis Jan 30 '14 at 19:11
  • @NealKruis: Are you setting the viewport after you bind the FBO? – genpfault Jan 30 '14 at 19:17
  • I am setting the view matrix after I bind the FBO. Now I'm wondering if the window could possibly be setting a clipping rectangle that is affecting my renderings. – Neal Kruis Jan 30 '14 at 19:22
  • @NealKruis: Not a view matrix, the *viewport*, via [`glViewport()`](http://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml). See the "Explain what happens when the FBO has a different width/height from the window?" question in the [`EXT_framebuffer_object` spec](http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt). – genpfault Jan 30 '14 at 19:24
  • That's it. Thanks! I wasn't setting the Viewport at all before. It was probably defaulting to the window size. – Neal Kruis Jan 30 '14 at 19:27