我使用glTexSubImage2D作为使用openGL的更新窗口。
我发现此函数需要花费大量时间才能返回,并且还需要4%的CPU。
以下是我使用的代码:
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, (*i)->getTextureID());
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (*i)->getWidth(), (*i)->getHeightView(),
GL_BGRA, GL_UNSIGNED_BYTE,(*i)->getBuffer());
有人知道更好的实施吗?性能更好的东西会占用更少的CPU吗?
现在这让我的节目变得迟钝。
答案 0 :(得分:6)
你可以做一些事情,不过你可以从中受益多少取决于具体情况。
首先,确保您的像素上传格式符合驱动程序的需要。您似乎已经使用GL_BGRA, GL_UNSIGNED_BYTE
进行了处理,这可能是驱动程序首选GL_RGBA8
图像格式的格式。
但是,如果您碰巧有权访问OpenGL 4.3或实现ARB_internalformat_query2的驱动程序,您实际上可以在运行时检测首选的上载格式。 Like this:
GLint pixelFormat, pixelType;
glGetInternalFormativ(GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_IMAGE_FORMAT, 1, &pixelFormat);
glGetInternalFormativ(GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1, &pixelType);
当然,这意味着您需要能够修改数据生成方法,以便以上述格式/类型对生成数据。
一旦您采取措施安抚驱动程序,您的下一个可能性就是使用buffer objects to store your pixel transfer data。这可能无助于整体性能,但可以减轻CPU负担。
然而,为了充分利用这一点,您需要能够通过mapping it“直接”将像素数据生成到缓冲区对象的内存中。如果你能够做到这一点,那么你可能会收回一些上传的CPU成本。否则,它可能不值得。
如果您这样做,则应使用正确的buffer object streaming techniques。
双重缓冲纹理也可能有所帮助。也就是说,当您从一个纹理对象进行渲染时,您将上传到另一个纹理对象。这将防止等待先前渲染完成的GPU停顿。这有多大帮助取决于你的渲染方式。
在不了解应用程序的具体情况的情况下,可以说的更多。
答案 1 :(得分:3)
如果您的纹理确实每帧都在改变,那么您将需要使用双缓冲区将数据传输到GPU。 (如果它没有改变每一帧,那么明显的优化就是只上传一次!)
每个帧,您将数据上传到一个缓冲区并从另一个缓冲区中提取数据,然后切换每帧使用的缓冲区。这将加速一切,因为GPU不必等待内存传输完成。
关于公益组织的教程在某种程度上超出了我的压缩能力,但是“OpenGL Pixel Buffer Objects”是一个不错的参考,我会查看“OGL Samples”存储库以了解公益组织是如何工作的
然而,如果您无法提前计算纹理框架,那么使用PBO没有任何实际优势。只需使用glTexSubImage2D
。
那就是说, 4%的CPU可能不成为问题。
答案 2 :(得分:1)
您不应该每帧更改纹理数据以更新屏幕。纹理意味着加载一次,很少(如果有的话)改变。如果你试图写入屏幕上的单个像素,我建议不要使用OpenGL,并使用更适合任务的东西,比如SDL。
编辑:好的,这不一定是真的。见下面的讨论。
答案 3 :(得分:0)
据我从this answer的注释线程中了解到,您正在CPU端渲染一个网站(或渲染的图像通过CPU),但是在其上应用了OpenGL着色器。如果是这样,则需要一个GPU端渲染器,渲染网页并在GPU端应用着色器。这样,您将不再通过CPU将每个帧上传到GPU,并且按原计划,CPU将不再需要渲染。