rol*_*oll 7 opengl performance gpu image-processing glsl
我被包含在一个项目中,该项目在CPU上进行图像处理,目前正在扩展以使用GPU,希望主要使用GPU,如果证明更快,并将CPU处理部分作为后退.我是GPU编程的新手,并且有一些问题,我在其他线程中已经讨论过这些问题,但是我们无法找到我需要的答案.
如果我们从头开始,您会推荐哪种技术用于GPU上的图像处理,以实现覆盖的最佳组合(如在客户端计算机上的支持)和速度?我们已经采用OpenGL + GLSL方式作为覆盖尽可能多的图形卡的方式,我很好奇这是否是最佳选择.例如,你对OpenCL有什么看法?
鉴于我们已经开始使用OpenGL和着色器实现GPU模块,我想知道我们是否以最有效的方式做到这一点.
我们使用Framebuffer Objects来读取和渲染纹理.在大多数情况下,正在读取的区域和正在写入的区域大小相同,但我们读取和写入的纹理可以是任意大小.换句话说,我们要求FBO读取被认为是其输入纹理的子区域,并写入被认为是其输出纹理的子区域.为此目的,输出纹理"附加"到Framebuffer对象(使用glFramebufferTexture2DEXT()),但输入纹理不是.这需要纹理"附加"和"分离",因为它们改变了它们的角色(即纹理最初可以用于写入,但在下一遍中它可以用作读取的输入).
那么,强制输入和输出是否相同,并且总是将它们连接到FBO会更有意义,在有效使用FBO和实现更好的性能方面,还是我们已经做的声音足够好?
该项目最初设计为在CPU上进行渲染,因此需要注意要求一次渲染尽可能少的像素.因此,例如,每当鼠标移动发生时,只会重新渲染光标周围的非常小的区域.或者,当渲染覆盖屏幕的整个图像时,它可能被切成条状以便一个接一个地渲染和显示. 在GPU上渲染时,这种碎片是否有意义?确定渲染请求(即输出纹理)的最佳大小的最佳方法是什么,以便充分利用GPU?
在GPU上运行代码(性能)的分析会有什么考虑?(将其与CPU上的渲染进行比较.)测量调用返回的时间(并调用glFinish()以确保在GPU上完成命令)听起来有用还是还有什么要记住的?
非常感谢你!
我想我需要添加一些细节来澄清我的问题:
2)我们实际上并没有使用相同的纹理作为渲染目标和同时读取源.只有当渲染完成时,"输出"纹理才变为"输入" - 即,当需要为另一个传递读取渲染作业的结果或作为另一个过滤器的输入时.
我关心的是附加纹理是否被区别对待,比如FBO或着色器是否可以更快地访问它们,与未连接时相比.
我最初(虽然可能不完全准确)的分析没有表现出显着的差异,所以我想我们并没有犯下那么多的表演犯罪.我会用你建议的计时功能做更多的测试 - 看起来很有用.
3)我想知道是否将图片切成小块(比如小到100 x 100像素用于鼠标移动)并请求它们逐个渲染它们会更慢或更快(或者是否无关紧要)一个GPU,它可能会使很多工作相互分离.我的直觉是,这可能是过度热情的优化,在最好的情况下,不会给我们带来太大的收益,在最坏的情况下,可能会损害性能,因此想知道是否有正式的方式来告知特定的实现.最后,我想我们会选择各种显卡的合理性.
我对你的项目没有太多的了解,但我会尝试提供一些简单的答案,也许其他人可以更详细:
只要您在没有太多同步的情况下执行图像处理中使用某些输入像素的通常修改输出像素任务,您应该可以使用通常的屏幕大小的四边形与片段着色器方法(抱歉这些奇怪的短语)。而且你可以免费获得图像过滤(如双线性插值)(我不知道 CUDA 或 OpenCL 是否支持图像过滤,尽管它们应该支持,因为无论如何都有硬件)。
无论如何,您都无法从用作渲染目标的纹理中读取内容(尽管我认为它们可能仍然被附加),所以您当前的方法应该没问题。要求它们大小相同只是为了让它们连接到 FBO 会极大地限制灵活性(我认为连接成本可以忽略不计)。
最佳大小实际上取决于实现,但限制渲染范围,因此片段着色器调用应该始终是一个好主意,只要这些限制计算不会持续太长时间(简单的边界框与glScissor您的朋友,或者只使用小于屏幕尺寸的四边形)。
还有其他可能更准确的 GPU 计时方法(GL_ARB_timer_query例如,查看扩展)。对于分析和调试,我认为您可以使用通用 GPU 分析器和调试器,例如 gDEBugger 等。虽然我对此类工具没有太多经验。
编辑:给您编辑的问题:
我真的怀疑附加纹理的读取速度比未附加纹理的读取速度快。您唯一能获得的好处是,当您想要写入时,无需重新连接它,但正如我所说,该成本应该可以忽略不计(如果有的话)。
我不会通过将其分成太小的部分来过度优化。就像我说的,在使用 GL 时,您可以使用剪刀测试和模板测试来完成此类事情。但我认为,这一切都必须经过测试才能确保性能提升。我不知道鼠标移动是什么意思,因为当您将鼠标移到窗口上时,窗口系统通常会将光标渲染为覆盖层,因此您无需再次重新绘制底层图像,因为它是我认为是由窗口系统缓冲的。