在 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 纹理附件的主要内容,如果未能解决你的问题,请参考以下文章