Дополнение: производительность асинхронных внеэкранных запросов

Недавно я задал этот вопрос:

Как выполнять асинхронные внеэкранные запросы?

Что я слышал, но пока не смог подтвердить, так это то, что рендеринг в окно обходится дороже, чем рендеринг в фреймбуфер. Прежде всего, кто-нибудь может прокомментировать это? Могу ли я рисовать несколько сцен в фреймбуферах быстрее, чем в окне? Существуют ли другие варианты, например, pbuffers или PBO?

Я начал играть с фреймбуферами, но не смог заставить запрос работать. Вот некоторый псевдокод для того, что я настроил до сих пор:

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();

Пока все работает, но все запросы возвращают "0". Есть ли что-то в запросе при рисовании в буфер кадра, что отличается от запроса при рисовании в оконный буфер?

И снова мои два вопроса:

  1. Могу ли я рисовать несколько сцен в фреймбуферах быстрее, чем в окне? Существуют ли другие варианты, например, pbuffers или PBO?
  2. Есть ли что-то в запросе при рисовании в буфер кадра, что отличается от запроса при рисовании в оконный буфер?

person Neal Kruis    schedule 28.01.2014    source источник
comment
Итак, у вас есть один запрос или несколько запросов? Ваши звонки glGenQueries() и glBeginQuery() не совпадают.   -  person genpfault    schedule 28.01.2014
comment
ой. это должно быть несколько запросов. Я исправлю это. Идея состоит в том, что во время отрисовки других сцен может выполняться некоторое количество асинхронных запросов.   -  person Neal Kruis    schedule 28.01.2014


Ответы (1)


Попробуйте что-то вроде этого:

#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
cnt: 1884
0: 157288
1: 157288
2: 157289
3: 157288
4: 157287
5: 157286
6: 157292
7: 157286
8: 157289
9: 157288
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; }

Репрезентативный вывод в моей системе:

cnt: 1884
0: 157288
1: 157288
2: 157289
3: 157288
4: 157287
5: 157286
6: 157292
7: 157286
8: 157289
9: 157288
person genpfault    schedule 28.01.2014
comment
Ваш код отлично работает на моей машине, и я реализовал то, что могу сказать, это существенные отличия от моего кода (в основном, включая цветовую привязку к FBO). По какой-то причине кажется, что я все еще выполняю рендеринг в буфер кадра по умолчанию (то есть в мое окно 1x1). Вы знаете, что может быть причиной этого? Я привязываюсь к fbo перед рисованием. - person Neal Kruis; 30.01.2014
comment
После использования glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING,&int) кажется, что он рендерится в мой определенный буфер кадра, но по какой-то причине размер всего 1x1. Фреймбуфер наследует размер окна, даже если хранилище рендербуфера установлено на 512x512. - person Neal Kruis; 30.01.2014
comment
@NealKruis: Вы устанавливаете область просмотра после привязки FBO? - person genpfault; 30.01.2014
comment
Я устанавливаю матрицу представления после привязки FBO. Теперь мне интересно, может ли окно устанавливать прямоугольник обрезки, который влияет на мои рендеринги. - person Neal Kruis; 30.01.2014
comment
@NealKruis: не матрица просмотра, а окно просмотра, через glViewport(). См. Объясните, что происходит, когда FBO имеет другую ширину/высоту от окна? вопрос в EXT_framebuffer_object спецификации. - person genpfault; 30.01.2014
comment
Вот и все. Спасибо! Раньше я вообще не устанавливал Viewport. Вероятно, это был размер окна по умолчанию. - person Neal Kruis; 30.01.2014