优化GPU到CPU数据传输

时间:2017-07-03 21:54:25

标签: performance opengl graphics

我有点超出我的深度(最好的方式让我想到),但我正在寻找可以减少我的应用程序的GPU到CPU数据传输的优化。

我有一个应用程序对GPU中的顶点数据执行一些修改。有时,CPU必须读回修改后的顶点数据的一部分,然后计算一些参数,然后通过制服传递回GPU着色器,形成一个循环。

将所有顶点数据传回CPU,然后在CPU(数百万点)上筛选它需要很长时间,所以我有一个" hack"尽管不是最佳的,但可以将工作量减少到可用的水平。

我的所作所为:

  1. CPU:读取图片
  2. CPU:每个像素生成1个顶点,Z基于颜色信息/过滤器等
  3. CPU:将所有顶点数据传输到GPU
  4. GPU:根据从CPU设置的一些统一参数,实时转换用于实时更新GL_POINT顶点坐标的反馈。
  5. 当我只想阅读矩形"部分"时,我使用glMapBufferRange映射构成所需矩形的整行(坏图警报):

    enter image description here

    这应该代表GPU中的图像/顶点集。我的" hack"涉及必须读取所有蓝色和红色顶点。这是因为我只能指定1个连续范围的数据来回读。

    有没有人知道一种聪明的方法来有效地获得红色,没有蓝色? (无需发出一系列glMapBufferRange调用)

    编辑 -

    用例是我将图像渲染为3D世界作为GLPoints,在Z中着色和偏移量基于颜色信息(根据距离确定大小等)。然后,用户可以使用鼠标光标刷修改顶点Z数据。一些画笔应用程序代码背后的逻辑需要知道鼠标下面区域的Z(画笔圆圈),例如。最小/最大/平均等,以便CPU可以通过设置一系列馈入着色器的制服来控制着色器对数据的修改。因此,例如用户可以说,我希望光标下的所有点都设置为平均值。这可能完全可以在GPU中完成,但我的想法是,一旦我获得了CPU-GPU" loop" (根据我可以合理地进行优化),然后我可以扩展min / max / avg的东西来在CPU上做有趣的事情,这些事情很可能(可能)完全在GPU上完成。

    干杯! Laythe

2 个答案:

答案 0 :(得分:1)

要从GPU获取任何数据到CPU,您需要在任何情况下映射GPU内存,这意味着OpenGL应用程序必须使用mmap之类的内容。我已经检查了x86和ARM的实现,看起来它是页面对齐的,所以你不能在任何给定的时间映射少于1个连续的GPU内存页面,所以即使你可以请求映射只是红色区域,您很可能也会获得蓝色区域(取决于您的页面和像素数据大小)。

解决方案1 ​​ 只需使用glReadPixels,因为这允许您选择帧缓冲区的窗口。我假设像英特尔这样的GPU供应商会优化驱动程序,因此它会映射尽可能少的页面,但这不能保证,在某些情况下,您可能需要映射2个页面仅2个像素。

解决方案2 创建计算着色器或使用几个glCopyBufferSubData调用将您感兴趣的区域复制到GPU内存中的连续缓冲区中。如果你知道你想要的高度和宽度,你就可以解开并在CPU端获得一个2D缓冲区。

上述哪种解决方案更好地取决于您的硬件和驱动程序实施。如果GPU-> CPU是瓶颈而GPU-> GPU速度很快,那么第二种解决方案可能会运行良好,但您必须进行试验。

解决方案3 正如评论中所建议的,在GPU上做一切。这在很大程度上取决于工作是否能够很好地并行化,但如果内存复制对你来说太慢,那么你就没有太多其他选择了。

答案 1 :(得分:-1)

我想你是在问,因为你不能在着色器上做所有工作,对吧?

如果渲染到帧缓冲对象,然后将其绑定为GL_READ_FRAMEBUFFER,则可以通过glReadPixels读取它的块。