问题解决了!
从内核字符串中删除了共享的编译指示。(使用 opencl 1.2)
重新排序 GL-VBO-creating 和 CL-Context-Creating。首先从 gl-context 创建 CL-context。然后创建 GL-VBO。然后通过 cl 获取它。然后计算。然后由 cl 释放。然后通过 gl 绑定。画。完成 gl。重来。始终使用 clFinish 以确保它与 gl 同步。为了更快的速度, clflush 可能还可以,甚至可以完成我没有尝试过的隐式同步。
[来自这里的原始问题]
在 C# 中,opencl-gl-interop 的上下文构造失败,因为句柄 getter 函数给出了错误的地址和原因System.AccessViolationException
。
C#部分:
[DllImport("opengl32.dll",EntryPoint="wglGetCurrentDC")]
extern static IntPtr wglGetCurrentDC();//CAl
[DllImport("opengl32.dll", EntryPoint = "wglGetCurrentContext")]
extern static IntPtr wglGetCurrentContext();// DCAl
opencl 中的 C++ 部分(这是在 C++ opencl 的包装类中):
pl = new cl_platform_id[2];
clGetPlatformIDs( 1, pl, NULL);
cl_context_properties props[] ={ CL_GL_CONTEXT_KHR, (cl_context_properties)CAl,
CL_WGL_HDC_KHR, (cl_context_properties)DCAl,CL_CONTEXT_PLATFORM,
(cl_context_properties)&pl[0], 0};
ctx=cl::Context(CL_DEVICE_TYPE_GPU,props,NULL,NULL,NULL);//error comes from here
//ctx=cl::Context(CL_DEVICE_TYPE_GPU); this does not interop >:c
这些部分有什么问题?当我将“opengl32.dll”更改为“opengl64.dll”时,编译器/链接器找不到它。
调用wglGetCurrentDC()
和加载wglGetCurrentContext()
后glControl1
,但这些似乎给出了错误的地址。打电话wglMakeCurrent()
或glControl1.MakeCurrent()
之前那些也没有解决问题。
操作系统:64位windows7
主机:FX8150
设备:HD7870
MSVC2012(windows forms application) + OpenTK(2010_10_6) + Khronos opencl 1.2 headers
构建目标是 x64(发布)。
注意:opencl 部分在计算(sgemm)方面运行良好,opengl 部分在绘制 VBO 方面表现良好(一些平面由具有一些颜色和法线的三角形构成)但 opencl 部分(上下文)拒绝互操作。
编辑:添加#pragma OPENCL EXTENSION cl_khr_gl_sharing : enable
到内核字符串中并没有解决问题。
编辑:在构建 cl 上下文“之后”创建 GL VBO,错误消失但 opencl 内核没有更新任何内容。诡异的。另外,当我删除 cl_khr_sharing pragma 时,3D 形状开始出现伪影,这意味着 opencl 现在正在做某事,但它只是随机删除的像素和一些我没有在内核中编写的裁剪区域。更奇怪。您可以在下图中看到这一点(我正在尝试使平坦的蓝色纸张消失,但它并没有完全消失,而且我尝试改变颜色并且没有改变)
编辑: CMSoft 的 opencltemplate 看起来像我需要学习/做的,但他们的示例代码只包含 6-7 行代码!我不知道将计算内核放在哪里以及在哪里获取/设置初始数据,但是该示例效果很好(顺便说一下,给出了数百个“警告!ComputeBuffer {T}(575296656)泄漏。”)。
编辑:如果您想知道,这里是 C++ 中内核参数的构造:
//v1,v2,v3,v4 are unsigned int taken from `bindbuffer` of GL in C#
//so v1 is buf[0] and v2 is buf[1] and so goes like this
glBuf1=cl::BufferGL(ctx,CL_MEM_READ_WRITE,v1,0);
glBuf2=cl::BufferGL(ctx,CL_MEM_READ_WRITE,v2,0);
glBuf3=cl::BufferGL(ctx,CL_MEM_READ_WRITE,v3,0);
glBuf4=cl::BufferGL(ctx,CL_MEM_READ_WRITE,v4,0);
以下是如何设置到命令队列中:
v.clear();
v.push_back(glBuf1);
v.push_back(glBuf2);
v.push_back(glBuf3);
v.push_back(glBuf4);
cq.enqueueAcquireGLObjects(&v,0,0);
cq.finish();
这是我设置为内核参数的方式:
kernel.setArg(0,glBuf1);
kernel.setArg(1,glBuf2);
kernel.setArg(2,glBuf3);
kernel.setArg(3,glBuf3);
这是如何执行的:
cq.enqueueNDRangeKernel(kernel,referans,Global,Local);
cq.flush();
cq.finish();
这是如何发布的:
cq.enqueueReleaseGLObjects(&v,0,0);
cq.finish();
模拟迭代:
for (int i = 0; i < 200; i++)
{
GL.Finish(); // lets cl take over
//cl acquires buffers in glTest
clh.glTest(gci.buf[0], gci.buf[1], gci.buf[2], gci.buf[3]);// then computes
// then releases
Thread.Sleep(50);
glControl1.MakeCurrent();
glControl1.Invalidate();
gci.ciz(); //draw
}