douglas125's picture

OpenTK and Cloo - OpenCL/GL Interop

Hi, I'm trying to get OpenCL/GL interop using Cloo and OpenTK, but I keep getting a Cloo.ComputeErrorCode.CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR error.

I'm using ATI Stream SDK 2.01 so I think I *should* be able to create a Context from OpenGL but...
I get the error just as I try to create the ComputeContext Ctx.
This is the code I try to run:

            OpenTK.Graphics.IGraphicsContextInternal ctx = (OpenTK.Graphics.IGraphicsContextInternal)OpenTK.Graphics.GraphicsContext.CurrentContext;
            IntPtr raw_context_handle = ctx.Context.Handle;
            ComputeContextProperty p1 = new ComputeContextProperty(ComputeContextPropertyName.CL_GL_CONTEXT_KHR, raw_context_handle);
            ComputeContextProperty p2 = new ComputeContextProperty(ComputeContextPropertyName.Platform, ComputePlatform.Platforms[0].Handle);
            List<ComputeContextProperty> props = new List<ComputeContextProperty>() { p1, p2 };
            ComputeContextPropertyList Properties = new ComputeContextPropertyList(props);
                ComputeContext Ctx = new ComputeContext(ComputeDeviceTypes.Gpu, Properties, null, IntPtr.Zero);
                ComputeErrorCode Error;
                    Cloo.Bindings.CL10.CreateFromGLBuffer(Ctx.Handle, ComputeMemoryFlags.CopyHostPointer | ComputeMemoryFlags.ReadWrite, bufs[0], &Error);
            catch {
                int i = 0;

Any help is appreciated.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
nythrix's picture

This post looks familiar :)
As for the OpenTK part of the question I'm not really sure which OpenGL version we should use for interop. I've been trying 3.x contexts but the drivers might have had no such support back then.
I'm downloading the most recent CUDA release as we speak. I'll let you know, if I can put together a working CL/GL environment.

douglas125's picture

Thanks nythrix

I'm really looking forward to putting CL/GL together I hope it becomes possible soon.

nythrix's picture

Assuming you're running Windows you also need specify
ComputeContextProperty p3 = new ComputeContextProperty(ComputeContextPropertyName.CL_WGL_HDC_KHR, wglHandle);
but I'm not sure where we can find the WGL handle.
Does anyone know if this handle is stored somewhere near GraphicsContext? Or do we have to wglGetCurrentDC()?

nythrix's picture

Good news! I managed to create a CL GL context. Add these to your code and you should be good to go:

extern static IntPtr wglGetCurrentDC();
IntPtr glHandle = (GraphicsContext.CurrentContext as IGraphicsContextInternal).Context.Handle;
IntPtr wglHandle = wglGetCurrentDC();
ComputePlatform platform = ComputePlatform.GetByName("NVIDIA CUDA");
ComputeContextProperty p1 = new ComputeContextProperty(ComputeContextPropertyName.Platform, platform.Handle);
ComputeContextProperty p2 = new ComputeContextProperty(ComputeContextPropertyName.CL_GL_CONTEXT_KHR, glHandle);
ComputeContextProperty p3 = new ComputeContextProperty(ComputeContextPropertyName.CL_WGL_HDC_KHR, wglHandle);
ComputeContextPropertyList cpl = new ComputeContextPropertyList(new ComputeContextProperty[] { p1, p2, p3 });
ComputeContext context = new ComputeContext(ComputeDeviceTypes.Gpu, cpl, null, IntPtr.Zero);
//hint: creating a ComputeBuffer
ComputeBuffer<T> clBuffer = ComputeBuffer.CreateFromGLBuffer<T>(context, flags, glBufferId);
douglas125's picture

Hey it looks like it worked!

Wow your solution is much better, thanks!


Awesome, it works!!!

You just can't forget the Finish instructions:

            List<ComputeMemory> c = new List<ComputeMemory>() { CLGLVar };
            CQ.AcquireGLObjects(c, null);
            CQ.Execute(kernelinteropTeste, null, new long[1] { PositionData.Length }, null, null);
            CQ.ReleaseGLObjects(c, null);
LikeTK's picture

Hi all, using the examples from

It seems that the following code works on ATI cards

CLGLPositions = ComputeBuffer<float>.CreateFromGLBuffer<float>(Ctx, ComputeMemoryFlags.CopyHostPointer | ComputeMemoryFlags.ReadWrite, bufs[1]);
CLGLColors = ComputeBuffer<float>.CreateFromGLBuffer<float>(Ctx, ComputeMemoryFlags.CopyHostPointer | ComputeMemoryFlags.ReadWrite, bufs[0]);

but it does not work on my Nvidia 9 series card using the latest Cuda 3.01 driver and cloo.dll (0.72)and the OpenTK (1.0rc1). (FYI: this card passes the c++ sdk examples on openGL-OpenCL interop).

after some trial and error, the following works.

 CLGLPositions = ComputeBuffer<float>.CreateFromGLBuffer<float>(Ctx, ComputeMemoryFlags.ReadWrite, bufs[1]);
 CLGLColors = ComputeBuffer<float>.CreateFromGLBuffer<float>(Ctx,  ComputeMemoryFlags.ReadWrite, bufs[0]);

Anyone else has similar experience?

nythrix's picture

Hi, you cannot use CopyHostPointer in this case because that is a flag related to memory allocation. Here you're not allocating memory but sharing it between OpenGL and OpenCL. NVidia's implementation/behaviour is correct ( see flags argument).

douglas125's picture

This is correct. Maybe AMD OpenCL drivers just ignore the CopyHostPointer whereas NVidia's (correctly) don't. Thanks for pointing it. Tutorial is now fixed too.

Boogiwoogie's picture

hi there! i want to run the tutorial source of the cmsoft site, too (same link as LikeTK has given).
it gives me an nullpointerexception:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
  at OpenTK.Graphics.OpenGL.GL.MatrixMode (MatrixMode mode) [0x00000] in <filename unknown>:0 
  at CLGLInterop.Form1.SetupViewport () [0x00018] in /home/chrischi/Desktop/CLGLInterop/CLGLInterop/Form1.cs:203 
  at CLGLInterop.Form1.Form1_Resize (System.Object sender, System.EventArgs e) [0x00000] in /home/chrischi/Desktop/CLGLInterop/CLGLInterop/Form1.cs:308 
  at System.Windows.Forms.Control.OnResizeInternal (System.EventArgs e) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.OnResize (System.EventArgs e) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Form.OnResize (System.EventArgs e) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.OnSizeChanged (System.EventArgs e) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.UpdateBounds (Int32 x, Int32 y, Int32 width, Int32 height, Int32 clientWidth, Int32 clientHeight) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.UpdateBounds (Int32 x, Int32 y, Int32 width, Int32 height) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.SetBoundsCoreInternal (Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.SetBoundsCore (Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Form.SetBoundsCore (Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.SetBoundsInternal (Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.SetBounds (Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.ScaleControl (SizeF factor, BoundsSpecified specified) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ScrollableControl.ScaleControl (SizeF factor, BoundsSpecified specified) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Form.ScaleControl (SizeF factor, BoundsSpecified specified) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.Scale (SizeF factor) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ContainerControl.PerformAutoScale (Boolean called_by_scale) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ContainerControl.PerformAutoScale () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ContainerControl.PerformDelayedAutoScale () [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Windows.Forms.ContainerControl:PerformDelayedAutoScale ()
  at System.Windows.Forms.Control.ResumeLayout (Boolean performLayout) [0x00000] in <filename unknown>:0 
  at CLGLInterop.Form1.InitializeComponent () [0x001a8] in /home/chrischi/Desktop/CLGLInterop/CLGLInterop/Form1.Designer.cs:68 
  at CLGLInterop.Form1..ctor () [0x0002b] in /home/chrischi/Desktop/CLGLInterop/CLGLInterop/Form1.cs:23 
  at (wrapper remoting-invoke-with-check) CLGLInterop.Form1:.ctor ()
  at CLGLInterop.Program.Main () [0x0000b] in /home/chrischi/Desktop/CLGLInterop/CLGLInterop/Program.cs:18

my notebook runs ubuntu 10.04 64bit, mono 2.63, stream sdk 2.2.
i dont have a opencl capable graphic card installed (old ati 2600 in this notebook).
i want to run it as cpu device.
what i tried: svn co'ed opentk and recompiled, replaced the opentk.dll and glcontrol.dll by the fresh compiled ones.
what i want to know is, is the error message related to opencl or is it a opengl-only error?
and is it actually possible to do opengl/cl interop runnig in cpu mode? in that case the cpu would
manipulate the vbo data directly, right?
thx for any advice,

nythrix's picture

This doesn't look like an OpenCL error. On the other hand, I'm not that good in recognizing OpenGL errors so it could be anything else. There's more experienced people around here that can tell why would GL.MatrixMode fail with the null reference thingy.

As for the second part of your question the answer would be no. CL/GL interop is restricted to GPUs. Otherwise the ComputeContext creation will fail with an InvalidOperationComputeException.