在 CUDA 中修改 OpenGL FBO 纹理附件

Posted

技术标签:

【中文标题】在 CUDA 中修改 OpenGL FBO 纹理附件【英文标题】:Modifying OpenGL FBO texture attachment in CUDA 【发布时间】:2013-02-09 19:09:32 【问题描述】:

我有以下场景:

我有带有纹理作为颜色附件的自定义 FBO。我将我的东西渲染到那个 FBO。下一步我需要与 CUDA 共享该纹理,然后在其上运行一些后处理内核。之后应该将纹理绑定回全屏四边形并渲染到默认帧缓冲区。 我已经阅读了several OpenGL / CUDA interop tutorials 并且执行此操作的一些步骤对我来说并不完全清楚。

首先,我看到他们通常做的是从 GL 纹理 X 读取数据,在 CUDA 中处理它,然后使用 PBO 填充纹理 Y 和结果数据。

我注意到的另一件事(如果我错了,请纠正我)是这些演示中的 OpenGL 默认使用 PBO 绑定,这意味着第一遍渲染结果存储在其中吗?我真的不确定,因为所有这些演示都使用固定的 OpenGL,并且在渲染初始几何传递时,我看不到 PBO 绑定的地方。

回到我的例子: 我的最后一个问题是——我可以在不使用 PBO 的情况下直接在 CUDA 中对 OpenGL 纹理进行操作,以便我可以在 CUDA 内核中对其进行修改吗? 如果不是,那么这是否意味着我必须在将 FBO 纹理传递到 CUDA 阶段之前将其打包到 PBO 中?

更新:

从帧缓冲区填充 PBO 通常使用 glReadPixels() 完成,这意味着它被下载到 CPU。这是我想要阻止的事情。 - 那是错误的假设。因此,基于我可以用纹理中的像素填充 PBO 的事实,下面的方法是什么? : 用纹理中的数据填充 PBO。

将其映射到 CUDA 缓冲区资源。

使用内核对数据进行更改。

从修改后的 PBO 更新目标纹理。

在 OpenGL 中使用更新后的纹理。

【问题讨论】:

【参考方案1】:

这是在 CUDA 中处理“OpenGL 纹理”然后立即在 OpenGL 中使用它而无需额外开销的示例:

https://github.com/nvpro-samples/gl_cuda_interop_pingpong_st

【讨论】:

^ 非常复杂的例子,你有没有尝试过构建它?项目文件?计时?【参考方案2】:

通常使用 glReadPixels() 从帧缓冲区填充 PBO,这意味着它被下载到 CPU。这是我想要阻止的。

错了!

glReadPixels 到 PBO 完全在 GPU 上执行,不会往返于系统内存。

更新:

CUDA 图形互操作有几个限制。例如,当图形资源绑定在图形上下文中时,您不能将图形资源映射到 CUDA 内存;具体来说,您可以映射它,但是对它的任何访问都会产生未定义的结果。因此,通常的策略使用代理对象。

因此,如果所讨论的 OpenGL 资源无论出于何种原因都不能解除绑定,那么使用 PBO 作为从 OpenGL 到 CUDA 的中介是一种有价值的方法。但是,对于 FBO,这并不重要,因为绑定到 FBO 的任何内容都不能用作数据源,只要它被绑定即可。由于该限制,通常存在多个目标对象(渲染缓冲区或纹理)实例,以多缓冲区方式使用循环。

因此,要么复制它,要么在将其映射到 CUDA 之前取消绑定。对于多个缓冲区,后者是首选方法。

使用 CUDA 纹理时,您应该始终在读取时写入不同的纹理(在纹理的情况下,您必须将它们绑定到 CUDA 表面)。

【讨论】:

你的意思是我必须先将纹理从 FBO 中分离出来,然后才能将其映射到 CUDA 资源? @MichaelIV:要么解绑 FBO,要么解绑 FBO 本身;理想情况下你两者都做。 CUDA 文档有点不清楚“正在使用的图形资源”是什么意思。最好不要冒险,进入一个确定的状态。 看看我最近的帖子:***.com/questions/15188522/… 您可以同时将 GPU 资源绑定到 CUDA 和 OpenGL。您不必解绑任何东西,请参考此示例:github.com/nvpro-samples/gl_cuda_interop_pingpong_st ^ 可笑的复杂示例,如果您曾经设法构建它并找到 chrono,请告诉我 ;)

以上是关于在 CUDA 中修改 OpenGL FBO 纹理附件的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL:渲染到 FBO 时是不是支持纹理组合器功能?

openGL FBO 复制到纹理导致黑色/深色图像

使用 FBO 和着色器 OpenGL 渲染到纹理

OpenGL FBO 多个纹理

将绑定到 FBO 的纹理复制到另一个 OpenGL 上下文

在 Android 上使用 FBO 进行慢速 OpenGL ES 渲染到纹理乒乓球