OpenCL/OpenGL 纹理互操作问题/windows
Problems with OpenCL/OpenGL Texture interop / windows
为了提高渲染质量,我正在编写 OpenCL 1.1 中的多功能可分离降频器。
基本图像(仅覆盖最终图像的一小部分)被渲染到一个非常大的帧缓冲区中。然后它的颜色附加纹理被下采样并通过 OpenCL 放置到另一个纹理中。最后渲染一个屏幕对齐的四边形以显示结果。
想法到此为止。我们有什么:
- 2 个缩减器内核实例(它存储带有交换坐标的结果(即作为 (y,x) )
- inputTexture(rtt-framebuffer 的颜色附件)
- tempTexture,尺寸:inputHeight x outputWidth,使用CL_MEM_READ_WRITE
创建
- 输出纹理
运行 kernel_instance_1( <otherParams>, inputTexture, tempTexture )
产生了预期的结果,但仅在第一帧出现 - 不知何故动画中发生的变化没有显示出来根本。由于我没有收到任何错误(见下文),我假设内核运行每一帧,但源纹理内容保持不变(事实并非如此,我还有该纹理的实时输出)。
Question:
每次帧缓冲区的内容发生变化时我都必须调用 clCreateFromGLTexture2D() 吗?
编辑 我刚刚意识到:inputTexture 仍然附加到帧缓冲区对象的 GL_COLOR_ATTACHMENT0
- 这可能是个问题吗? 编辑结束
运行 kernel_instance_2( <otherParams>, tempTexture, outputTexture )
不会产生可见的结果,即使在两个内核调用之间有一个障碍排队。 IE。 outputTexture 保持为空。
Question:
我是否需要在两次内核调用之间释放并重新获取纹理对象 tempTexture
,以便 OpenCL 看到更改?
为了查看进行了哪些 OpenCL 调用,生成了以下输出:
clCreateKernel( separable_X )
clRetainMemObject( separable_X::convolution )
clCreateKernel( separable_Y )
clRetainMemObject( separable_Y::convolution )
clCreateFromGLTexture2D( separable_X::dst + separable_y::src, texID=24, usage=temporary (source and target) )
clCreateFromGLTexture2D( separable_Y::dst, texID=18, usage=target )
clCreateFromGLTexture2D( separable_X::src, texID=22, usage=source )
clRetainMemObject( separable_X::dst )
clRetainMemObject( separable_Y::src )
clRetainMemObject( separable_Y::dst )
clRetainMemObject( clearEmpty::dst )
clEnqueueAcquireGLObjects( count=3 )
clEnqueueBarrier()
clSetKernelArg( separable_X::convert )
clSetKernelArg( separable_X::offset )
clSetKernelArg( separable_X::convolution )
clSetKernelArg( separable_X::dst )
clSetKernelArg( separable_X::src )
clEnqueueNDRangeKernel( separable_X, (1440, 1080, 0), waiting4 0 events )
clSetKernelArg( separable_Y::convert )
clSetKernelArg( separable_Y::offset )
clEnqueueBarrier()
clSetKernelArg( separable_Y::convolution )
clSetKernelArg( separable_Y::dst )
clSetKernelArg( separable_Y::src )
clEnqueueNDRangeKernel( separable_Y, (540, 1440, 0), waiting4 0 events )
clEnqueueBarrier()
clEnqueueReleaseGLObjects( count=3 )
如果任何调用产生了错误,它就会在该输出中。
我经常遇到的另一种情况是 clEnqueueReleaseGLObjects()
returns 错误代码 -9999,有人将其归档为 "NVidia: Illegal read or write to a buffer".
Question:
会不会是write_imagef()
有分量超过1.0f,存储格式为RGBA8时,不钳制颜色值?所以这实际上意味着必须写 write_imagef( texture, (int2)coord, clamp( color, 0.f, 1.f ) );
...
提前致谢 - 这让我在将近一个星期以来一直在敲我的头......
编辑
可能值得一提的更多信息:
如何区分这两个实例?
程序源代码中有 2 个具有不同名称(separable_X
和 separable_Y
)的不同 __kernel
函数,它们都具有调用 separable()
函数的相同主体。
如何在 GL 和 CL 之间同步?
- 负责获取 GL 对象的函数在调用 clEnqueueAcquireGLObjects()
之前发出 glFinish()
- 我等待 clEnqueueReleaseGLObjects()
使用 cl_events 完成(将来可能会改变)
您在 clEnqueueAcquireGLObjects 之前使用 glFinish,这是正确的,但是您应该还在 clEnqueueReleaseGLObjects 之后调用 clFinish。仔细阅读 OpenCL 1.1 规范的第 9.8.6.2 节。
另外,对于您的其他问题:
Do I have to call clCreateFromGLTexture2D() every time the contents of the framebuffer changed?
不,您只需执行一次即可从 OpenGL 纹理创建 OpenCL 图像。那应该在使用它的循环之前发生。
Do I need to release and re-acquire the texture object tempTexture in between both kernel calls, so OpenCL sees the changes?
没有。一旦获得 OpenCL,您就可以根据需要在那里使用它。
could it be that write_imagef() does not clamp the color value if any component exceeds 1.0f and the storage format is RGBA8?
不,它工作得很好。我们一直在用它。
为了提高渲染质量,我正在编写 OpenCL 1.1 中的多功能可分离降频器。
基本图像(仅覆盖最终图像的一小部分)被渲染到一个非常大的帧缓冲区中。然后它的颜色附加纹理被下采样并通过 OpenCL 放置到另一个纹理中。最后渲染一个屏幕对齐的四边形以显示结果。
想法到此为止。我们有什么:
- 2 个缩减器内核实例(它存储带有交换坐标的结果(即作为 (y,x) )
- inputTexture(rtt-framebuffer 的颜色附件)
- tempTexture,尺寸:inputHeight x outputWidth,使用CL_MEM_READ_WRITE 创建
- 输出纹理
运行 kernel_instance_1( <otherParams>, inputTexture, tempTexture )
产生了预期的结果,但仅在第一帧出现 - 不知何故动画中发生的变化没有显示出来根本。由于我没有收到任何错误(见下文),我假设内核运行每一帧,但源纹理内容保持不变(事实并非如此,我还有该纹理的实时输出)。
Question:
每次帧缓冲区的内容发生变化时我都必须调用 clCreateFromGLTexture2D() 吗?
编辑 我刚刚意识到:inputTexture 仍然附加到帧缓冲区对象的 GL_COLOR_ATTACHMENT0
- 这可能是个问题吗? 编辑结束
运行 kernel_instance_2( <otherParams>, tempTexture, outputTexture )
不会产生可见的结果,即使在两个内核调用之间有一个障碍排队。 IE。 outputTexture 保持为空。
Question:
我是否需要在两次内核调用之间释放并重新获取纹理对象 tempTexture
,以便 OpenCL 看到更改?
为了查看进行了哪些 OpenCL 调用,生成了以下输出:
clCreateKernel( separable_X )
clRetainMemObject( separable_X::convolution )
clCreateKernel( separable_Y )
clRetainMemObject( separable_Y::convolution )
clCreateFromGLTexture2D( separable_X::dst + separable_y::src, texID=24, usage=temporary (source and target) )
clCreateFromGLTexture2D( separable_Y::dst, texID=18, usage=target )
clCreateFromGLTexture2D( separable_X::src, texID=22, usage=source )
clRetainMemObject( separable_X::dst )
clRetainMemObject( separable_Y::src )
clRetainMemObject( separable_Y::dst )
clRetainMemObject( clearEmpty::dst )
clEnqueueAcquireGLObjects( count=3 )
clEnqueueBarrier()
clSetKernelArg( separable_X::convert )
clSetKernelArg( separable_X::offset )
clSetKernelArg( separable_X::convolution )
clSetKernelArg( separable_X::dst )
clSetKernelArg( separable_X::src )
clEnqueueNDRangeKernel( separable_X, (1440, 1080, 0), waiting4 0 events )
clSetKernelArg( separable_Y::convert )
clSetKernelArg( separable_Y::offset )
clEnqueueBarrier()
clSetKernelArg( separable_Y::convolution )
clSetKernelArg( separable_Y::dst )
clSetKernelArg( separable_Y::src )
clEnqueueNDRangeKernel( separable_Y, (540, 1440, 0), waiting4 0 events )
clEnqueueBarrier()
clEnqueueReleaseGLObjects( count=3 )
如果任何调用产生了错误,它就会在该输出中。
我经常遇到的另一种情况是 clEnqueueReleaseGLObjects()
returns 错误代码 -9999,有人将其归档为 "NVidia: Illegal read or write to a buffer".
Question:
会不会是write_imagef()
有分量超过1.0f,存储格式为RGBA8时,不钳制颜色值?所以这实际上意味着必须写 write_imagef( texture, (int2)coord, clamp( color, 0.f, 1.f ) );
...
提前致谢 - 这让我在将近一个星期以来一直在敲我的头......
编辑 可能值得一提的更多信息:
如何区分这两个实例?
程序源代码中有 2 个具有不同名称(separable_X
和 separable_Y
)的不同 __kernel
函数,它们都具有调用 separable()
函数的相同主体。
如何在 GL 和 CL 之间同步?
- 负责获取 GL 对象的函数在调用 clEnqueueAcquireGLObjects()
之前发出 glFinish()
- 我等待 clEnqueueReleaseGLObjects()
使用 cl_events 完成(将来可能会改变)
您在 clEnqueueAcquireGLObjects 之前使用 glFinish,这是正确的,但是您应该还在 clEnqueueReleaseGLObjects 之后调用 clFinish。仔细阅读 OpenCL 1.1 规范的第 9.8.6.2 节。
另外,对于您的其他问题:
Do I have to call clCreateFromGLTexture2D() every time the contents of the framebuffer changed?
不,您只需执行一次即可从 OpenGL 纹理创建 OpenCL 图像。那应该在使用它的循环之前发生。
Do I need to release and re-acquire the texture object tempTexture in between both kernel calls, so OpenCL sees the changes?
没有。一旦获得 OpenCL,您就可以根据需要在那里使用它。
could it be that write_imagef() does not clamp the color value if any component exceeds 1.0f and the storage format is RGBA8?
不,它工作得很好。我们一直在用它。