Qt OpenGL纹理速度太慢?
我有一个500万像素的纹理,我更新有困难。纹理显示在与视频流不同的矩形上 OpenGL命令执行速度很快,但实际纹理更新速率次优,可能每秒仅3帧。使用较小的纹理(500x500)时会有一些变化,但变化不大 该机器具有NVIDIA gtx 570 我最初的努力是使用Qt OpenGL纹理速度太慢?,qt,opengl,pixel,texture-mapping,pixel-manipulation,Qt,Opengl,Pixel,Texture Mapping,Pixel Manipulation,我有一个500万像素的纹理,我更新有困难。纹理显示在与视频流不同的矩形上 OpenGL命令执行速度很快,但实际纹理更新速率次优,可能每秒仅3帧。使用较小的纹理(500x500)时会有一些变化,但变化不大 该机器具有NVIDIA gtx 570 我最初的努力是使用glTexSubImage2D和glBufferSubData,但它们的性能比内存映射方案稍差 有没有办法强制图形卡更新纹理?视频流软件是如何编写的 渲染循环 void glStream::paintGL() { glClear(
glTexSubImage2D
和glBufferSubData
,但它们的性能比内存映射方案稍差
有没有办法强制图形卡更新纹理?视频流软件是如何编写的
渲染循环
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();
}
初始化
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();
}
void glStream::initializeGL()
{
GLenum err=glewInit();
如果(GLEW_OK!=错误)
{
常量字符*emessage=(常量字符*)glewGetErrorString(错误);
信息(0,“OpenGL 3.x上下文示例”,
信息);
出口(20);
}
glDisable(GLU深度测试);
QGLShader*vshader1=新的QGLShader(QGLShader::Vertex,this);
常量字符*vsrc1=
“属性vec2 coord2d;\n”
“属性mediump vec4 texCoord;\n”
“可变介质矢量4 texc;\n”
“void main()\n”
“{\n”
“gl_Position=vec4(coord2d,0.0,1.0);\n”
“texc=texCoord;\n”
“}\n”;
vshader1->编译源代码(vsrc1);
QGLShader*fshader1=新的QGLShader(QGLShader::Fragment,this);
常量字符*fsrc1=
“二维纹理的均匀采样;\n”
“可变介质矢量4 texc;\n”
“作废主(作废)\n”
“{\n”
gl_FragColor=texture2D(纹理,texc.st);\n
“}\n”;
fshader1->编译资源代码(fsrc1);
program1.addShader(vshader1);
program1.addShader(fshader1);
程序1.link();
vertexAttr1=程序1.属性位置(“coord2d”);
vertexTexr1=program1.attributeLocation(“texCoord”);
//创建顶点缓冲区。
顶点。清除();
浮点数u=1;
#定义AVEC-u,u
#定义BVEC-u,-u
#定义CVEC u,u
#定义DVEC u,-u
顶点在调用glBufferData时,PBO比纹理大得多:
numGLFrames*widthGL*heightGL*sizeof(GLubyte)
您正在为多个纹理(帧)分配足够大的PBO,但只能读取/写入一帧的数据
如果将PBO设置为与纹理相同的大小,并使用glTexImage2D而不是glTexSubImage2D,速度是否会更快?在调用glBufferData时,PBO比纹理大得多:
numGLFrames*widthGL*heightGL*sizeof(GLubyte)
您正在为多个纹理(帧)分配足够大的PBO,但只能读取/写入一帧的数据
如果将PBO设置为与纹理相同的大小,并使用glTexImage2D而不是glTexSubImage2D,速度会快得多吗?我自己不是这方面的专家,但既然您提到您有一个Nvidia卡,并且希望图形卡能够直接更新OpenGL缓冲区,那么您考虑过使用Cuda吗?有很多问题需要解决Nvidia开发者页面上的r个例子项目正好说明了这一点。你选择的词语<代码>真实纹理更新率代码>让我想知道这句话到底是什么意思?你测量了吗?是什么代码导致你的重绘发生?它们发生的频率有多高?在下面的评论中,你说了大约20fps的话:你在说我吗ngpaintGL()
每秒被调用大约20次,但每秒仅调用3次您会在屏幕上看到更新的纹理?如果是:您确定fillBuffer()
每次调用时都会出现一个“新”纹理?@axxel是的,这正是我的意思,我相信fill buffer会出现一个新纹理,因为在代码的其他部分,我将这个纹理写入文件,它确实不同。当你的文件IO比OpenGL纹理快时,这是一个悲伤的日子。这听起来很奇怪。我不这么认为你可以试试glDrawArrays(GL_三角形,0,顶点.size()/(++i%2)+1))之类的东西吗
并检查您的quad是否有一半以20fps的速度闪烁?我认为axxel是对的,似乎每次调用device->fillBuffer时都没有创建“新”纹理。我自己也不是这方面的专家,但既然您提到您有一个Nvidia卡,并且希望图形卡能够直接更新您的OpenGL缓冲区,那么:您有吗考虑过使用Cuda吗?Nvidia的开发者页面上有相当多的示例项目正好说明了这一点。你选择的词语真实纹理更新率
让我想知道这句话到底意味着什么?你测量了吗?是什么代码导致你的重绘发生?它们发生的频率有多高?在评论中下面你说了一些关于20fps的事情:你是说paintGL()
每秒被调用20次,但每秒只有3次,你会在屏幕上看到更新的纹理吗?如果是:你确定fillBuffer()
每次调用时都会出现一个“新”纹理?@axxel是的,这正是我的意思,我相信fill buffer会出现一个新纹理,因为在代码的其他部分,我将这个纹理写入文件,它确实不同。当你的文件IO比OpenGL纹理快时,这是一个悲伤的日子。这听起来很奇怪。我不这么认为你可以试试glDrawArrays(GL_三角形,0,顶点.size()/(++i%2)+1))之类的东西吗;
并检查您的四元网格是否有一半以20fps的速度闪烁?我认为axxel是对的,似乎每次调用device->fillBuffer时都不会创建“新”纹理。感谢您的建议,虽然它不是很实时,但速度会快一点。有什么想法吗?您的内存中是否已经准备好绘制所有帧,或者您是否正在使用capturi