我正在开发一个应用程序,其中我将相机姿势传递给GPU,GPU将生成包含有关对象可见顶点(法线深度...)的不同信息的纹理。 基于这些信息,我想选择一些顶点,并通过生成的纹理将这些顶点的所有信息检索到CPU中。
我已经阅读了一些文章,最好的方法似乎是使用Trasform反馈。 但是,许多人似乎不喜欢the last comment here或this blog并选择使用计算着色器。
答案 0 :(得分:0)
Transform feedback机制不是您的解决方案。这对于在GPU上捕获数据的当前状态并在GPU上的下一个绘图调用进行更新非常有用,而无需为了数据更新而执行GPU到CPU并回乒乓球。 Particles rendering是转换收费的流行用例之一。 您尚未说出目标平台是什么,因此很难理解您的硬件限制/功能,但是这里有几种下载主机(CPU)更新而又不拖延渲染管线的方法:
使用PBO ping-pong。如果可以将数据写入纹理,则可以download as well as upload from/to GPU asynchronously使用像素缓冲区对象。如果您阅读链接中的文档,还可以看到可以使用共享上下文通过线程传输进行进一步的处理。这些技术大大缩短了传输时间。
如果使用缓冲区,并且可以使用持久性映射功能(OpenGL 4.4),则可以尝试两次甚至三次缓冲,如上所述,这种缓冲类似于“ PBO ping-pong”,但是使用了缓冲区。 Here对该概念进行了详细说明,但是一般的想法是持久地映射一个使用中大小的缓冲区3倍,并且每个帧都从主机上3个部分之一读取,而写入到3个部分中的另一个设备。 probably通过DMA对GPU可见固定的内存块,尽管通常持久性映射缓冲区的速度不比常规映射缓冲区快,但它们的确会显着减少驱动程序开销(每次帧更新)。
繁重的规范,例如在单独的线程中使用CUDA或OpenCL。我不知道如何使用OpenCL完成此操作,但是使用CUDA时,您可以在单独的线程中设置CUDA上下文,将GL resource(如缓冲区或纹理)映射到CUDA拥有的资源,然后使用Producer-Consumer范式从主机读取数据CUDA映射的GL缓冲区,同时保持在OpenGL线程中渲染。当然,当映射到CUDA上下文时,您将必须在线程之间作为OpenGL shouldn't access缓冲区进行同步,因为这种访问的结果是不确定的。
我个人会选择选项2 +使用共享上下文和线程来持久地映射指针以读取数据。它在同步方面具有复杂性,但是如果操作正确,则可以提供非常快速的解决方案。