有没有办法将运行在 GPU 上的着色器的结果返回到运行在 CPU 上的程序?
我想根据 GPU 上的计算成本高的算法从简单的体素数据生成多边形网格,但我需要 CPU 上的结果用于物理计算。
有没有办法将运行在 GPU 上的着色器的结果返回到运行在 CPU 上的程序?
我想根据 GPU 上的计算成本高的算法从简单的体素数据生成多边形网格,但我需要 CPU 上的结果用于物理计算。
定义“结果”?
一般来说,如果您使用 OpenGL 进行 GPGPU 风格的计算,您将需要围绕渲染系统的需求来构建着色器。渲染系统被设计成单向的:数据进入其中并生成图像。倒退,让渲染系统产生数据,通常不是渲染系统的结构。
当然,这并不意味着你不能这样做。但是您需要围绕 OpenGL 的限制来构建一切。
OpenGL 提供了许多钩子,您可以在其中写入来自某些着色器阶段的数据。其中大多数需要专门的硬件
任何能够使用片段着色器的硬件显然都允许您写入正在渲染的当前帧缓冲区。通过使用具有浮点或整数图像格式的帧缓冲区对象和纹理,您可以将几乎任何您想要的数据写入各种图像。一旦进入纹理,您可以简单地调用以获取渲染的像素数据。或者,如果 FBO 仍受约束,您可以直接获取它。无论哪种方式都有效。glGetTexImage
glReadPixels
这种方法的主要限制是:
您可以附加到帧缓冲区的图像数量;这限制了您可以写入的数据量。在 GL 3.x 之前的硬件上,FBO 通常仅限于 4 个图像加上一个深度/模板缓冲区。在 3.x 和更好的硬件中,您可以期望至少 8 个图像。
你正在渲染的事实。这意味着您需要设置顶点数据以将三角形准确定位在您希望它修改数据的位置。这不是一项微不足道的工作。获得有用的输入数据也很困难,因为您通常希望每个纹素彼此相当独立。围绕这些限制构建片段着色器是很困难的。并非不可能,但在许多情况下并非微不足道。
此 OpenGL 3.0 功能允许在一个或多个缓冲区对象中捕获来自 OpenGL 的顶点处理阶段的输出(顶点着色器和可选的几何着色器)。
这对于捕获要播放或再次渲染的顶点数据来说更加自然。在您的情况下,您需要在渲染后将其读回,可能是通过glGetBufferSubData
调用或使用glMapBufferRange
for reading。
这里的限制是您通常只能捕获 4 个输出值,其中每个值都是一个 vec4。还有一些严格的布局限制。一些 OpenGL 3.x 和 4.x 硬件提供了将数据写入多个反馈流的能力,这些反馈流都可以写入不同的缓冲区。
这个 GL 4.2 特性代表了写入的巅峰:您可以绑定图像(缓冲区纹理,如果您想写入缓冲区),然后直接写入。您需要在其中工作的内存排序限制。
它非常灵活,但也非常复杂。除了难以正确使用它之外,还有许多限制。您可以写入的图像数量相当有限,可能是 8 个左右。并且实现可能具有总写入限制,因此要写入的 8 个图像可能必须由片段着色器的输出共享。
更重要的是,图像输出只保证片段着色器(和 4.3 的计算着色器)。也就是说,允许硬件禁止您在非 FS/CS 着色器阶段使用图像加载/存储。