我打算用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附件而改变?如何修复并使其有效?
答案 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)
函数
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驱动程序。