【问题标题】:GL/CL interoperability: Shared Texture [closed]GL/CL 互操作性:共享纹理 [关闭]
【发布时间】:2012-02-08 02:29:40
【问题描述】:

我打算使用 OpenCL 进行图形计算,例如光线投射、光线行进等。我想使用 OpenGL 来显示这个计算的结果(像素图像)。我使用附加到帧缓冲区的纹理缓冲区。 OpenCL 将结果写入纹理,然后我使用 glBlitFrameBuffer 函数将纹理数据复制到应用程序窗口帧缓冲区。 我在执行过程中遇到了一个 CL/GL 间问题。我写了一个简单的例子来展示它。这个例子展示了帧缓冲区对象和纹理对象的初始化,它们的结合,从 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 附件而改变?如何修复它并使其正常工作?

【问题讨论】:

  • 我最终可以确认这种行为,只要有一个 Image2DGL 对象绑定到纹理,纹理就会被阻止并且无法写入或从另一个上下文写入。这也在英伟达设备上。问题来了,为什么有明确的acquirerelease 如果无论如何都被阻止了。

标签: opengl opencl gpgpu gpu


【解决方案1】:

编辑 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 互操作的纹理/图像初始化:您是否获得了内存对象?

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 端的所有初始化。

【讨论】:

  • Itun' 的例子非常简单——你可以看到那里甚至没有使用 CL——只有 GL。因此,既不需要clEnqueueAcquireGLObjects 也不需要glFinish。问题的本质是CL.CreateFromGLTexture2D 调用,之后“渲染循环” sn-p 停止工作(同样“渲染循环”示例仅使用 GL)。例如,在我的系统(Radeon HD 5870)上,我得到System.Exception: CL Error has occured: InvalidImageFormatDescriptor。在 Itun 系统上,令人惊讶的是(NVidia GeForce ),我们也不例外 - GL 只是停止正常工作。
  • 看起来CL.CreateFromGLTexture2D 会造成一些干扰。无论如何,许多组合(如使用glFinish)已经过测试。解决方案尚未到来。如果有人可以在他们自己的平台上测试类似的代码并提供一些反馈,那就太好了。
  • 正如我所提到的,我假设并未显示有关 OpenCL 部分的所有代码(因此没有尝试测试代码)。 OP 表示他想使用 OpenCL 进行光线投射等计算,因此我检查了 CL/GL 互操作链初始化中可能存在的遗漏。
  • 你好像知道他的问题,那CL/GL互操作是什么意思?
  • 感觉是我们想要使用 CL/GL 互操作以便: (1) 使用 CL 进行计算,并让 CL 将结果写入纹理缓冲区; (2) 使用 GL 将“BlitFramebuffer”生成的纹理直接发送到帧缓冲区。但是,当我们使用 CL.CreateFromGLTexture2D 激活纹理互操作时 - 我们无法在 GL 和 CL 中对该纹理执行任何操作。
【解决方案2】:

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

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

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

【讨论】:

  • 仅作记录:你有什么 nVidia 芯片?
  • 另外,很高兴知道您必须更改哪些内容才能使用您的 AMD 卡摆脱错误的图像描述符...
猜你喜欢
  • 2012-02-19
  • 2018-09-04
  • 2013-10-12
  • 2012-05-20
  • 2016-08-18
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
  • 2014-06-21
相关资源
最近更新 更多