2013-02-25 6 views
1

У меня 5-мегапиксельная текстура, у меня возникли проблемы с обновлением. Текстура отображается на прямоугольнике, не отличающемся от видеопотока.OpenGL Texture Оценить слишком медленно?

Команды OpenGL выполняются быстро, но реальная скорость обновления текстур является суб оптимальной, возможно, всего 3 фактических кадра в секунду. При использовании меньшей текстуры (500x500) есть некоторые изменения, но не так сильно.

Машина имеет NVIDIA GTX 570

Мои первоначальные усилия были использовать glTexSubImage2D и glBufferSubData, но они выполнены несколько хуже, чем памяти отображаются схемы.

Есть ли способ заставить графическую карту обновлять текстуру? Как написано программное обеспечение для потоковой передачи видео?

Рендер Loop

void glStream::paintGL() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 
    program1.bind(); 
    program1.setUniformValue("texture", 0); 
    program1.enableAttributeArray(vertexAttr1); 
    program1.enableAttributeArray(vertexTexr1); 
    program1.setAttributeArray(vertexAttr1, vertices.constData()); 
    program1.setAttributeArray(vertexTexr1, texCoords.constData()); 
    // 
    glECheck(); 
    glBindTexture(GL_TEXTURE_2D, textures[0]); 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,pbos[0]); 
    void* memory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,GL_WRITE_ONLY); 
    device->fillBuffer((unsigned char *)memory,heightGL,widthGL); // takes 2ms (not long) 
    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); 
    glTexSubImage2D(GL_TEXTURE_2D,0,0,0,widthGL,heightGL,GL_LUMINANCE,GL_UNSIGNED_BYTE, NULL); 
    glDrawArrays(GL_TRIANGLES, 0, vertices.size()); 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0); 
    glBindTexture(GL_TEXTURE_2D,0); 
    // 
    program1.disableAttributeArray(vertexTexr1); 
    program1.disableAttributeArray(vertexAttr1); 
    program1.release(); 
    glECheck();//no errors 
} 

текстуры Резервирование

void glStream::reserveTextures() 
{ 
    assert(numGLFrames>0); 
    assert(glGenBuffers); 
    displayBuff = (GLubyte*) calloc(numGLFrames*widthGL*heightGL,sizeof(GLubyte));//GL_RGB8 
    memset(displayBuff,100,numGLFrames*widthGL*heightGL*sizeof(GLubyte)); 
    glGenBuffers(1,&pbos[0]); 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbos[0]); 
    glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, 
       numGLFrames*widthGL*heightGL*sizeof(GLubyte), 
       &displayBuff[0], GL_STREAM_DRAW); 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 
    glGenTextures(1,&textures[0]); 
    glBindTexture(GL_TEXTURE_2D,textures[0]); 
    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE, 
       widthGL,heightGL,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,NULL); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); 
    glBindTexture(GL_TEXTURE_2D,0); 
} 

Инициализация

void glStream::initializeGL() 
{ 
    GLenum err = glewInit(); 
    if (GLEW_OK != err) 
    { 
     const char * emssage = (const char*)glewGetErrorString(err); 
     QMessageBox::information(0, "OpenGL 3.x Context Example", 
           emssage); 
     exit(20); 
    } 
    glDisable(GL_DEPTH_TEST); 
    QGLShader *vshader1 = new QGLShader(QGLShader::Vertex, this); 
    const char *vsrc1 = 
     "attribute vec2 coord2d; \n" 
     "attribute mediump vec4 texCoord;\n" 
     "varying mediump vec4 texc;\n" 
     "void main()     \n" 
     "{       \n" 
     " gl_Position = vec4(coord2d, 0.0, 1.0); \n" 
     " texc = texCoord;\n" 
     "}       \n"; 
    vshader1->compileSourceCode(vsrc1); 
    QGLShader *fshader1 = new QGLShader(QGLShader::Fragment, this); 
    const char *fsrc1 = 
     "uniform sampler2D texture;\n" 
     "varying mediump vec4 texc;\n" 
     "void main(void)\n" 
     "{\n" 
     " gl_FragColor = texture2D(texture, texc.st);\n" 
     "}\n"; 
    fshader1->compileSourceCode(fsrc1); 
    program1.addShader(vshader1); 
    program1.addShader(fshader1); 
    program1.link(); 
    vertexAttr1 = program1.attributeLocation("coord2d"); 
    vertexTexr1 = program1.attributeLocation("texCoord"); 
    // Create the vertex buffer. 
    vertices.clear(); 
    float u=1; 
#define AVEC -u,u 
#define BVEC -u,-u 
#define CVEC u,u 
#define DVEC u,-u 
    vertices << QVector2D(AVEC);vertices << QVector2D(BVEC); 
    vertices << QVector2D(CVEC);vertices << QVector2D(BVEC); 
    vertices << QVector2D(DVEC);vertices << QVector2D(CVEC); 
    // Create the texture vertex buffer 
#define TAVEC 0,1 
#define TBVEC 0,0 
#define TCVEC 1,1 
#define TDVEC 1,0 
    texCoords << QVector2D(TAVEC);texCoords << QVector2D(TBVEC); 
    texCoords << QVector2D(TCVEC);texCoords << QVector2D(TBVEC); 
    texCoords << QVector2D(TDVEC);texCoords << QVector2D(TCVEC); 
    glECheck(); 
    reserveTextures(); 
} 

Редактировать 1

Я уверен, что заполняющий буфер содержит новую текстуру, потому что в какой-то другой части кода я пишу эту текстуру в файл, и это действительно другое. Это печальный день, когда мой файл IO быстрее, чем текстура OpenGL.

Edit 2 Я попробовал FRAPS, и я проверил, что делают цикл происходит при ~ 18 FPS, но видимые обновления медленнее (возможно, 3 FPS). Что может объяснить такое несоответствие?

+0

Я не эксперт в этом сам, но так как вы упомянули о том, что у вас есть карта Nvidia и хотите, чтобы графическая карта говорила, чтобы напрямую обновить ваш буфер OpenGL: подумали ли вы об использовании Cuda? На странице разработчиков Nvidia существует довольно много примеров проектов, которые иллюстрируют именно это. – Yellow

+1

Ваш выбор слов «реальная скорость обновления текстур» заставляет меня задаться вопросом, что именно означает это утверждение? Горячий, ты это измерил? Какой код вызывает ваши репликации? Как часто они происходят? В комментарии ниже вы сказали что-то о 20fps: вы говорите, что 'paintGL()' вызывается примерно 20 раз в секунду, но только 3 раза в секунду вы видите обновленную текстуру на экране? Если да: вы уверены, что 'fillBuffer()' придумывает «новую» текстуру каждый раз, когда вы ее вызываете? – axxel

+0

@axxel Да, это именно то, что я имею в виду, я уверен, что буфер заполнения появляется с новой текстурой, потому что в какой-то другой части кода я пишу эту текстуру в файл, и это действительно так. Это печальный день, когда ваш файл IO быстрее, чем текстура OpenGL. – Mikhail

ответ

1

ЕГО гораздо больше, чем текстура, в вызове glBufferData:

numGLFrames*widthGL*heightGL*sizeof(GLubyte) 

Вы выделение ЕГО достаточно большой для нескольких текстур (кадров), но только когда-либо чтение/записи стоит один фрейма данных.

Если вы сделаете PBO того же размера, что и текстура, и используйте glTexImage2D вместо glTexSubImage2D, это намного быстрее?

+0

Спасибо за предложение, оно идет немного быстрее, хотя его не совсем в реальном времени. Есть идеи? – Mikhail

+0

У вас есть все кадры в памяти, готовые к рисованию, или вы снимаете их с камеры? Если вы регистрируете, сколько раз в секунду вызывается вызов device-> fillBuffer? Измеряете ли вы фактические снимки fps? – shouston

+0

команда вызывается при ~ 20 кадров в секунду, а команда 'device-> fillBuffer' занимает менее 2 мс. Я измеряю фактическую визуализацию FPS, которая отличается от времени, которое требуется для цикла рендеринга. – Mikhail