我打算用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:
然后您需要检查为什么会收到InvalidImageFormatDescriptor
。检查参数顺序是否正确以及 tbo 中的图像描述符是否具有误导性(内部图像结构 - 请参阅 OpenCL 规范)。从规范来看:
<小时/>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the OpenGL texture internal format does not map to a supported OpenCL image format.
编辑:
所以我知道 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
的顺序错误。错误的初始化可能会导致一些未知的行为。
您是否已验证显而易见的事实:您的设备上是否可以使用 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)
The function
cl_int clEnqueueAcquireGLObjects
is used to acquire OpenCL memory objects that have been created from OpenGL objects. These objects need to be acquired before they can be used by any OpenCL commands queued to a command-queue. The OpenGL objects are acquired by the OpenCL context associated with command_queue and can therefore be used by all command-queues associated with the OpenCL context.
所以问题可能是内存对象尚未绑定(bind)到特定的命令队列。
此外,还负责发出 glFinish()
以确保 OpenGL 端的所有初始化在获取内存对象之前完成。
关于opengl - GL/CL 互操作性 : Shared Texture,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8824269/