GL / CL互操作性:共享纹理

时间:2012-01-11 18:00:10

标签: opengl opencl gpu gpgpu gpu-programming

我打算用OpenCL进行图形计算,例如光线投射,光线行进等。我想用OpenGL来显示这个计算的结果(像素图像)。我使用附加到帧缓冲区的纹理缓冲区。 OpenCL将结果写入纹理,然后我使用glBlitFrameBuffer函数将纹理数据复制到应用程序窗口帧缓冲区。 我在实施过程中遇到了CL / GL inter问题。我写了一个简单的例子来展示它。此示例显示了帧缓冲对象和纹理对象初始化,它们的结合,从GL纹理缓冲区创建OpenCL缓冲区。最后显示了主渲染循环。它包括纹理写入,每帧中有新数据,帧缓冲附件和复制此帧缓冲。

纹理初始化:

for (int i = 0; i < data.Length; i +=4) {
    data [i] = 255;
}
GL.BindTexture (TextureTarget.Texture2D, tboID [0]);
GL.TexImage2D<byte>(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, w, h, 0,
                    PixelFormat.Rgba, PixelType.UnsignedByte, data);
GL.BindTexture (TextureTarget.Texture2D, 0)

TBO + FBO初始化:

 GL.BindFramebuffer (FramebufferTarget.FramebufferExt, fboID [0]);
 GL.FramebufferTexture2D (FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0,
                          TextureTarget.Texture2D, tboID [0], 0);
 GL.BindFramebuffer (FramebufferTarget.FramebufferExt, 0);

CL / GL初始化:

bufferID = CL.CreateFromGLTexture2D (context, memInfo, textureTarget, mipLevel, glBufferObject, out errorCode);

渲染循环:

 for (int i = 0; i < data.Length; i += 4) {
     data [i] = tt;
 }
 tt++;
 GL.BindTexture (TextureTarget.Texture2D, tboID [0]);
 GL.TexImage2D<byte> (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, w, h, 0,
                      PixelFormat.Rgba, PixelType.UnsignedByte, data);

 GL.BindTexture (TextureTarget.Texture2D, 0);
 GL.BindFramebuffer (FramebufferTarget.FramebufferExt, fboID [0]);
 GL.FramebufferTexture2D (FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0,
                          TextureTarget.Texture2D, tboID [0], 0);
 GL.BindFramebuffer (FramebufferTarget.FramebufferExt, 0);GL.BindFramebuffer (FramebufferTarget.ReadFramebuffer, fboID [0]);

 GL.ReadBuffer (ReadBufferMode.ColorAttachment0);
 GL.DrawBuffer (DrawBufferMode.Back);

 GL.BlitFramebuffer (0, 0, w, h, 0, 0, w, h, ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Nearest);

 GL.BindFramebuffer (FramebufferTarget.ReadFramebuffer, 0);

乍一看这段代码看起来很奇怪,但它完全显示了我的问题。 CL在这里根本不起作用。在此应用程序中,将创建OpenCL上下文并发生OpenCL缓冲区初始化。 这项工作应该很简单。屏幕颜色从黑色变为红色。它不会以这种方式工作。颜色不会从初始红色(纹理初始化)改变。 但是当我评论CL / GL初始化(从GL纹理创建CL缓冲区)时,它正常工作。 为什么会这样?为什么GL缓冲区的行为会根据CL附件而改变?如何修复并使其有效?

2 个答案:

答案 0 :(得分:3)

编辑2:

然后你需要检查你获得InvalidImageFormatDescriptor的原因。检查参数顺序是否正常以及tbo中的图像描述符是否具有误导性(内部图像结构 - 请参阅OpenCL规范)。来自规范:

  

如果OpenGL纹理内部格式未映射到支持的OpenCL图像格式,则为CL_INVALID_IMAGE_FORMAT_DESCRIPTOR。


编辑:

所以我理解OpenTK中的OpenCL功能是由一个名为Cloo的单独项目提供的。对于ComputeImage2D他们的文档说明:

CreateFromGLTexture2D (ComputeContext context, ComputeMemoryFlags flags, int textureTarget, int mipLevel, int textureId)

与你的相比:

CreateFromGLTexture2D (context, MemFlags.MemReadWrite, TextureTarget.Texture2D, ((uint[])tboID.Clone()) [0], 0);

看着你的mip级别和tbo的顺序错误。错误的初始化可能会导致一些未知的行为。

<小时/> 很难说出你提供的代码可能会出现什么问题。我现在正在看Interop,只是进入它。我要尝试的第一件事是在它周围放置一个try / catch块,并试图找出任何可能error code的线索。

您是否验证了明显的问题:您的设备上是否有cl_khr_gl_sharing扩展程序?

另一个猜测是,因为您只在示例代码中提供了实际OpenCl / OpenGL Interop的纹理/图像初始化:您是否获得了内存对象?

cl_int clEnqueueAcquireGLObjects (cl_command_queue command_queue,
  cl_uint num_objects.
  const cl_mem *mem_objects,
  cl_uint num_events_in_wait_list,
  const cl_event *event_wait_list,
  cl_event *event)

OpenCL 1.1 specifiction州:

  

函数cl_int clEnqueueAcquireGLObjects用于获取从OpenGL对象创建的OpenCL内存对象。这些   在排队到的任何OpenCL命令可以使用之前,需要获取这些对象   命令队列。 OpenGL对象由与之关联的OpenCL上下文获取   command_queue因此可以被与OpenCL关联的所有命令队列使用   上下文。

因此问题可能是内存对象尚未绑定到特定的命令队列。

另外,负责发出glFinish()以确保在获取内存对象之前完成OpenGL端的所有初始化。

答案 1 :(得分:1)

最后,我们能够在我的系统上运行Itun'代码(Windows 7 / AMD Radeon HD 5870)。回想一下,Itun'代码在激活此纹理上的GL / CL Interop后,通过GL逐渐将纹理中的颜色从黑色变为红色

结果至少是奇怪的。在我的系统上它按预期工作。但是,在Itun的系统(Windows 7 / NVidia GeForce)上,相同的代码根本不起作用,并且不提供任何异常或错误代码。另外,我想提一下CL在两个系统上都能正确使用这个纹理。因此,在这种情况下,GL出了问题。

我们不知道发生了什么 - 它可能是Itun'过时的GPU硬件或有缺陷的NVidia驱动程序。