2013-02-25 275 views
1

我有一个500万像素的纹理,我有麻烦更新。纹理显示在与视频流不相似的矩形上。OpenGL纹理速度太慢?

OpenGL命令可以快速执行,但真正的纹理更新速率是次优的,可能只有每秒3个实际帧。有一些变化,但使用较小纹理(500x500)时变化不大。

该机具有NVIDIA GTX 570

我最初的努力是使用glTexSubImage2DglBufferSubData,但这些表现好于存储器映射方案略差。

有没有办法强制显卡更新纹理?如何编写视频流媒体软件?

呈现循环

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纹理。

编辑2 我尝试了FRAPS和我核实,呈现循环是在18〜FPS去,但可见的更新速度较慢(可能是3 FPS)。什么可以解释这种差异?

+0

我不是这方面的专家,但是既然你提到了一个事实,那就是你有一张Nvidia卡,并且希望显卡交谈来直接更新你的OpenGL缓冲区:你有没有想过使用Cuda? Nvidia的开发者页面上有很多示例项目可以说明这一点。 – Yellow 2013-02-25 16:13:06

+1

您选择的单词“真实纹理更新率”让我想知道这句话究竟意味着什么?你觉得热了吗?什么代码导致您的重绘发生?他们多久发生一次?在下面的评论中你说了20fps的一些东西:你是说'paintGL()'每秒调用20次,但每秒只能调用3次,你会在屏幕上看到更新的纹理?如果是的话:你确定'fillBuffer()'每次打电话时都会出现'new'纹理? – axxel 2013-02-25 20:32:08

+0

@axxel是的,这正是我的意思,我相信填充缓冲区会出现一个新的纹理,因为在代码的其他部分我写这个纹理到一个文件,它确实是不同的。当你的File IO快于OpenGL纹理时,这是一个悲伤的日子。 – Mikhail 2013-02-25 20:35:52

回答

1

的PBO比质地大得多,在调用glBufferData:

numGLFrames*widthGL*heightGL*sizeof(GLubyte) 

你足够分配PBO大,多重纹理(帧),但永远只能读/写一个框架的价值数据的。

如果您将PBO与纹理大小相同并且使用glTexImage2D代替glTexSubImage2D,速度会更快吗?

+0

感谢这个建议,它虽然不是很实时,但速度稍快。有任何想法吗? – Mikhail 2013-02-25 19:15:00

+0

你有没有准备好绘制内存中的所有帧,或者你是否从相机捕捉它们?如果捕获,device-> fillBuffer每秒调用多少次? 你正在测量实际渲染的fps? – shouston 2013-02-25 19:52:49

+0

该命令以〜20 fps调用,'device-> fillBuffer'命令花费的时间少于2ms。我正在测量实际呈现的FPS,与呈现循环运行所花费的时间不同。 – Mikhail 2013-02-25 20:09:47