the Fiddler's picture

C# OpenCL bindings ready for testing

Update: current efforts are focused on Cloo (object-oriented CL wrapper), which can be found here. It provides a much cleaner OpenCL API compared to raw bindings (which are also available in case you need them).

The generator now supports generating C# OpenCL wrappers from the C headers. The OpenCL wrappers reside under the OpenTK.Compute.CL10 namespace of SVN trunk. An OpenCL sample has also been added to Examples.exe: if you have access to an OpenCL implementation, please run the VectorAdd sample and report your results here.

AMD has released a public beta of its OpenCL implementation that you can download from AMD's developer website (free registration needed). This implementation runs on all SSE3-capable CPUs and is available for Window and Linux platforms.

There is a lot of fine-tuning left to do for OpenTK's OpenCL wrappers and the sooner you test the bindings, the sooner they will become ready for release.


Comments

Comment viewing options

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

Hi,

I also have an InvalidKernelName... but with the NVidia driver !!

It is not with the vectorAdd sample but with my own kernel code :-P

randre's picture

Hi,

here is some sample code to dump informations about OpenCL Platform and Devices:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using OpenTK.Compute.CL10;
 
namespace OpenTK_CLInfo
{
	class Program
	{
		[STAThread]
		public static void Main(string[] args)
		{
			IntPtr[] lIDs;
			if (ErrorCode.Success == GetPlatformIDs(out lIDs))
			{
				for (int i = 0; i < lIDs.Length; i++)
				{
					IntPtr lPlatform = lIDs[i];
					Debug.WriteLine("Platform: " + string.Format("{0:X}", lPlatform.ToInt32()));
					string s;
					if (ErrorCode.Success == GetPlatformInfo(lPlatform, PlatformInfo.PlatformName, out s) && s != null)
					{
						Debug.WriteLine("PlatformName: " + s);
					}
					if (ErrorCode.Success == GetPlatformInfo(lPlatform, PlatformInfo.PlatformVendor, out s) && s != null)
					{
						Debug.WriteLine("PlatformVendor: " + s);
					}
					if (ErrorCode.Success == GetPlatformInfo(lPlatform, PlatformInfo.PlatformVersion, out s) && s != null)
					{
						Debug.WriteLine("PlatformVersion: " + s);
					}
					if (ErrorCode.Success == GetPlatformInfo(lPlatform, PlatformInfo.PlatformProfile, out s) && s != null)
					{
						Debug.WriteLine("PlatformProfile: " + s);
					}
					if (ErrorCode.Success == GetPlatformInfo(lPlatform, PlatformInfo.PlatformExtensions, out s) && s != null)
					{
						Debug.WriteLine("PlatformExtensions: " + s);
					}
 
					IntPtr[] lDeviceIDs;
					if (ErrorCode.Success == GetPlatformDeviceIDs(lPlatform, out lDeviceIDs))
					{
						Debug.WriteLine("Number of devices: " + lDeviceIDs.Length);
						for (int j = 0; j < lDeviceIDs.Length; j++)
						{
							IntPtr lDevice = lDeviceIDs[j];
							int lTemp;
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceName, out s) && s != null)
							{
								Debug.WriteLine("DeviceName: " + s);
							}
							DeviceTypeFlags lDeviceType;
							if (ErrorCode.Success == GetDeviceType(lDevice, out lDeviceType) && s != null)
							{
								Debug.WriteLine("DeviceType: " + lDeviceType);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DevicePlatform, out lTemp))
							{
								Debug.WriteLine("DevicePlatform: " + string.Format("{0:X}", lTemp));
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceVendor, out s) && s != null)
							{
								Debug.WriteLine("DeviceVendor: " + s);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DriverVersion, out s) && s != null)
							{
								Debug.WriteLine("DriverVersion: " + s);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceProfile, out s) && s != null)
							{
								Debug.WriteLine("DeviceProfile: " + s);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceVersion, out s) && s != null)
							{
								Debug.WriteLine("DeviceVersion: " + s);
							}
							if (ErrorCode.Success == GetDeviceInfo<int>(lDevice, DeviceInfo.DeviceVendorId, out lTemp) && s != null)
							{
								Debug.WriteLine("DeviceVendorId: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceExtensions, out s) && s != null)
							{
								Debug.WriteLine("DeviceExtensions: " + s);
							}
							if (ErrorCode.Success == GetDeviceInfo<int>(lDevice, DeviceInfo.DeviceMaxComputeUnits, out lTemp))
							{
								Debug.WriteLine("DeviceMaxComputeUnits: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo<int>(lDevice, DeviceInfo.DeviceMaxWorkGroupSize, out lTemp))
							{
								Debug.WriteLine("DeviceMaxWorkGroupSize: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxWorkItemDimensions, out lTemp))
							{
								Debug.WriteLine("DeviceMaxWorkItemDimensions: " + lTemp);
							}
							uint[] lDimensions;
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxWorkItemSizes, out lDimensions) && lDimensions != null)
							{
								Debug.WriteLine("DeviceMaxWorkItemSizes: " + string.Join(", ", lDimensions.Select(d => d.ToString()).ToArray()));
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DevicePreferredVectorWidthChar, out lTemp))
							{
								Debug.WriteLine("DevicePreferredVectorWidthChar: " + lTemp);
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DevicePreferredVectorWidthShort, out lTemp))
							{
								Debug.WriteLine("DevicePreferredVectorWidthShort: " + lTemp);
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DevicePreferredVectorWidthInt, out lTemp))
							{
								Debug.WriteLine("DevicePreferredVectorWidthInt: " + lTemp);
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DevicePreferredVectorWidthLong, out lTemp))
							{
								Debug.WriteLine("DevicePreferredVectorWidthLong: " + lTemp);
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DevicePreferredVectorWidthFloat, out lTemp))
							{
								Debug.WriteLine("DevicePreferredVectorWidthFloat: " + lTemp);
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DevicePreferredVectorWidthDouble, out lTemp))
							{
								Debug.WriteLine("DevicePreferredVectorWidthDouble: " + lTemp);
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxClockFrequency, out lTemp))
							{
								Debug.WriteLine("DeviceMaxClockFrequency: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceAddressBits, out lTemp))
							{
								Debug.WriteLine("DeviceAddressBits: " + lTemp);
							}
							long lLongTemp;
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxMemAllocSize, out lLongTemp))
							{
								Debug.WriteLine("DeviceMaxMemAllocSize: " + lLongTemp);
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceImageSupport, out lTemp))
							{
								Debug.WriteLine("DeviceImageSupport: " + (lTemp == 0 ? "no" : "yes"));
 
								if (lTemp > 0)
								{
									if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxReadImageArgs, out lTemp))
									{
										Debug.WriteLine("DeviceMaxReadImageArgs: " + lTemp);
									}
									if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxWriteImageArgs, out lTemp))
									{
										Debug.WriteLine("DeviceMaxWriteImageArgs: " + lTemp);
									}
									if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceImage2dMaxWidth, out lTemp))
									{
										Debug.WriteLine("DeviceImage2dMaxWidth: " + lTemp);
									}
									if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceImage2dMaxHeight, out lTemp))
									{
										Debug.WriteLine("DeviceImage2dMaxHeight: " + lTemp);
									}
									if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceImage3dMaxWidth, out lTemp))
									{
										Debug.WriteLine("DeviceImage3dMaxWidth: " + lTemp);
									}
									if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceImage3dMaxHeight, out lTemp))
									{
										Debug.WriteLine("DeviceImage3dMaxHeight: " + lTemp);
									}
									if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceImage3dMaxDepth, out lTemp))
									{
										Debug.WriteLine("DeviceImage3dMaxDepth: " + lTemp);
									}
									if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxSamplers, out lTemp))
									{
										Debug.WriteLine("DeviceMaxSamplers: " + lTemp);
									}
								}
							}
 
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxParameterSize, out lTemp))
							{
								Debug.WriteLine("DeviceMaxParameterSize: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMemBaseAddrAlign, out lTemp))
							{
								Debug.WriteLine("DeviceMemBaseAddrAlign: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMemBaseAddrAlign, out lTemp))
							{
								Debug.WriteLine("DeviceMemBaseAddrAlign: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMinDataTypeAlignSize, out lTemp))
							{
								Debug.WriteLine("DeviceMinDataTypeAlignSize: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceSingleFpConfig, out lTemp))
							{
								DeviceFpConfigFlags lFpConfigFlags = (DeviceFpConfigFlags)lTemp;
								Debug.WriteLine("SinglePrecisionCapality: " + string.Format("{0:X}", lFpConfigFlags));
								Debug.WriteLine("\tDenorm: " + ((lFpConfigFlags & DeviceFpConfigFlags.FpDenorm) == DeviceFpConfigFlags.FpDenorm ? "yes" : "no"));
								Debug.WriteLine("\tFma: " + ((lFpConfigFlags & DeviceFpConfigFlags.FpFma) == DeviceFpConfigFlags.FpFma ? "yes" : "no"));
								Debug.WriteLine("\tInfNaN: " + ((lFpConfigFlags & DeviceFpConfigFlags.FpInfNan) == DeviceFpConfigFlags.FpInfNan ? "yes" : "no"));
								Debug.WriteLine("\tRoundToInf: " + ((lFpConfigFlags & DeviceFpConfigFlags.FpRoundToInf) == DeviceFpConfigFlags.FpRoundToInf ? "yes" : "no"));
								Debug.WriteLine("\tRoundToNearest: " + ((lFpConfigFlags & DeviceFpConfigFlags.FpRoundToNearest) == DeviceFpConfigFlags.FpRoundToNearest ? "yes" : "no"));
								Debug.WriteLine("\tRoundToZero: " + ((lFpConfigFlags & DeviceFpConfigFlags.FpRoundToZero) == DeviceFpConfigFlags.FpRoundToZero ? "yes" : "no"));
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceGlobalMemCacheType, out lTemp))
							{
								DeviceMemCacheType lGlobalMemCacheType = (DeviceMemCacheType)lTemp;
								Debug.WriteLine("DeviceGlobalMemCacheType: " + lGlobalMemCacheType);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceGlobalMemCachelineSize, out lTemp))
							{
								Debug.WriteLine("DeviceGlobalMemCachelineSize: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceGlobalMemCacheSize, out lTemp))
							{
								Debug.WriteLine("DeviceGlobalMemCacheSize: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceGlobalMemSize, out lTemp))
							{
								Debug.WriteLine("DeviceGlobalMemSize: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxConstantBufferSize, out lTemp))
							{
								Debug.WriteLine("DeviceMaxConstantBufferSize: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceMaxConstantArgs, out lTemp))
							{
								Debug.WriteLine("DeviceMaxConstantArgs: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceLocalMemType, out lTemp))
							{
								DeviceLocalMemType lLocalMemType = (DeviceLocalMemType)lTemp;
								Debug.WriteLine("DeviceLocalMemType: " + lLocalMemType);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceLocalMemSize, out lTemp))
							{
								Debug.WriteLine("DeviceLocalMemSize: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceErrorCorrectionSupport, out lTemp))
							{
								Debug.WriteLine("DeviceErrorCorrectionSupport: " + (lTemp == 0 ? "no" : "yes"));
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceProfilingTimerResolution, out lTemp))
							{
								Debug.WriteLine("DeviceProfilingTimerResolution: " + lTemp);
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceEndianLittle, out lTemp))
							{
								Debug.WriteLine("DeviceEndianLittle: " + (lTemp == 0 ? "no" : "yes"));
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceAvailable, out lTemp))
							{
								Debug.WriteLine("DeviceAvailable: " + (lTemp == 0 ? "no" : "yes"));
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceCompilerAvailable, out lTemp))
							{
								Debug.WriteLine("DeviceCompilerAvailable: " + (lTemp == 0 ? "no" : "yes"));
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceExecutionCapabilities, out lTemp))
							{
								DeviceExecCapabilitiesFlags lDeviceExecCapabilitiesFlags = (DeviceExecCapabilitiesFlags)lTemp;
								Debug.WriteLine("DeviceExecutionCapabilities: " + string.Format("{0:X}", lDeviceExecCapabilitiesFlags));
								Debug.WriteLine("\tExecKernel: " + ((lDeviceExecCapabilitiesFlags & DeviceExecCapabilitiesFlags.ExecKernel) == DeviceExecCapabilitiesFlags.ExecKernel ? "yes" : "no"));
								Debug.WriteLine("\tExecNativeKernel: " + ((lDeviceExecCapabilitiesFlags & DeviceExecCapabilitiesFlags.ExecNativeKernel) == DeviceExecCapabilitiesFlags.ExecNativeKernel ? "yes" : "no"));
							}
							if (ErrorCode.Success == GetDeviceInfo(lDevice, DeviceInfo.DeviceQueueProperties, out lTemp))
							{
								CommandQueueFlags lCommandQueueFlags = (CommandQueueFlags)lTemp;
								Debug.WriteLine("DeviceQueueProperties: " + string.Format("{0:X}", lCommandQueueFlags));
								Debug.WriteLine("\tQueueOutOfOrderExecModeEnable: " + ((lCommandQueueFlags & CommandQueueFlags.QueueOutOfOrderExecModeEnable) == CommandQueueFlags.QueueOutOfOrderExecModeEnable ? "yes" : "no"));
								Debug.WriteLine("\tQueueProfilingEnable: " + ((lCommandQueueFlags & CommandQueueFlags.QueueProfilingEnable) == CommandQueueFlags.QueueProfilingEnable ? "yes" : "no"));
							}
						}
					}
				}
			}
		}
 
		private static ErrorCode GetPlatformIDs(out IntPtr[] pIDs)
		{
			pIDs = null;
			IntPtr[] lIDs = null;
			int[] lNumPlatforms = new int[1];
			ErrorCode lResult = (ErrorCode)CL.GetPlatformIDs(0, lIDs, lNumPlatforms);
			if (lResult == (int)OpenTK.Compute.CL10.All.Success)
			{
				if (lNumPlatforms[0] > 0)
				{
					lIDs = new IntPtr[lNumPlatforms[0]];
					lResult = (ErrorCode)CL.GetPlatformIDs(lIDs.Length, lIDs, null);
					if (lResult == (int)OpenTK.Compute.CL10.All.Success)
					{
						pIDs = lIDs;
						return lResult;
					}
				}
			}
			return lResult;
		}
 
		private static unsafe ErrorCode GetPlatformInfo(IntPtr lPlatform, PlatformInfo pPlatformInfo, out string s)
		{
			s = null;
			ErrorCode lResult;
			IntPtr lRequired;
			PlatformInfo lPlatformInfo = pPlatformInfo;
			lResult = (ErrorCode)CL.GetPlatformInfo(lPlatform, lPlatformInfo, IntPtr.Zero, IntPtr.Zero, out lRequired);
			if (lResult == (int)OpenTK.Compute.CL10.All.Success)
			{
				int lSize = lRequired.ToInt32();
				byte[] lBytes = new byte[lSize];
				IntPtr lReturn;
				fixed (byte* pBytes = &lBytes[0])
				{
					lResult = (ErrorCode)CL.GetPlatformInfo(lPlatform, lPlatformInfo, new IntPtr(lSize), new IntPtr(pBytes), out lReturn);
					if (lResult == (int)OpenTK.Compute.CL10.All.Success)
					{
						int lLength = Array.IndexOf(lBytes, (byte)0);
						s = Encoding.ASCII.GetString(lBytes, 0, lLength);
					}
				}
			}
			return lResult;
		}
 
		private static ErrorCode GetPlatformDeviceIDs(IntPtr pPlatform, out IntPtr[] pIDs)
		{
			DeviceTypeFlags lDeviceType = DeviceTypeFlags.DeviceTypeAll;
			return GetPlatformDeviceIDs(pPlatform, lDeviceType, out pIDs);
		}
 
		private static ErrorCode GetPlatformDeviceIDs(IntPtr pPlatform, DeviceTypeFlags pDeviceType, out IntPtr[] pIDs)
		{
			pIDs = null;
			IntPtr[] lIDs = new IntPtr[0];
			int[] lNumDevices = new int[1];
			ErrorCode lResult = (ErrorCode)CL.GetDeviceIDs(pPlatform, pDeviceType, 0, null, lNumDevices);
			if (lResult == (int)OpenTK.Compute.CL10.All.Success)
			{
				if (lNumDevices[0] > 0)
				{
					lIDs = new IntPtr[lNumDevices[0]];
					lResult = (ErrorCode)CL.GetDeviceIDs(pPlatform, pDeviceType, lIDs.Length, lIDs, null);
					if (lResult == (int)OpenTK.Compute.CL10.All.Success)
					{
						pIDs = lIDs;
						return lResult;
					}
				}
			}
			return lResult;
		}
 
		private static unsafe ErrorCode GetDeviceType(IntPtr pDevice, out DeviceTypeFlags pDeviceType)
		{
			pDeviceType = DeviceTypeFlags.DeviceTypeAll;
			ErrorCode lResult;
			IntPtr lRequired;
			DeviceInfo lDeviceInfo = DeviceInfo.DeviceType;
			lResult = (ErrorCode)CL.GetDeviceInfo(pDevice, lDeviceInfo, IntPtr.Zero, IntPtr.Zero, out lRequired);
			if (lResult == (int)OpenTK.Compute.CL10.All.Success)
			{
				int lSize = lRequired.ToInt32();
				byte[] lBytes = new byte[lSize];
				IntPtr lReturn;
				fixed (byte* pBytes = &lBytes[0])
				{
					lResult = (ErrorCode)CL.GetDeviceInfo(pDevice, lDeviceInfo, new IntPtr(lSize), new IntPtr(pBytes), out lReturn);
					if (lResult == (int)OpenTK.Compute.CL10.All.Success)
					{
						pDeviceType = (DeviceTypeFlags)lBytes[0];
					}
				}
			}
			return lResult;
		}
 
		private static unsafe ErrorCode GetDeviceInfo(IntPtr pDevice, DeviceInfo pDeviceInfo, out string s)
		{
			s = null;
			ErrorCode lResult;
			IntPtr lRequired;
			DeviceInfo lDeviceInfo = pDeviceInfo;
			lResult = (ErrorCode)CL.GetDeviceInfo(pDevice, lDeviceInfo, IntPtr.Zero, IntPtr.Zero, out lRequired);
			if (lResult == (int)OpenTK.Compute.CL10.All.Success)
			{
				int lSize = lRequired.ToInt32();
				byte[] lBytes = new byte[lSize];
				IntPtr lReturn;
				fixed (byte* pBytes = &lBytes[0])
				{
					lResult = (ErrorCode)CL.GetDeviceInfo(pDevice, lDeviceInfo, new IntPtr(lSize), new IntPtr(pBytes), out lReturn);
					if (lResult == (int)OpenTK.Compute.CL10.All.Success)
					{
						int lLength = Array.IndexOf(lBytes, (byte)0);
						s = Encoding.ASCII.GetString(lBytes, 0, lLength == -1 ? lBytes.Length : lLength);
					}
				}
			}
			return lResult;
		}
 
		private static unsafe ErrorCode GetDeviceInfo(IntPtr pDevice, DeviceInfo pDeviceInfo, out uint[] pArray)
		{
			pArray = null;
			ErrorCode lResult;
			IntPtr lRequired;
			DeviceInfo lDeviceInfo = pDeviceInfo;
			lResult = (ErrorCode)CL.GetDeviceInfo(pDevice, lDeviceInfo, IntPtr.Zero, IntPtr.Zero, out lRequired);
			if (lResult == (int)OpenTK.Compute.CL10.All.Success)
			{
				int lSize = lRequired.ToInt32();
				int lSize2 = lSize / sizeof(uint);
				uint[] lInts = new uint[lSize2];
				IntPtr lReturn;
				fixed (uint* pValues = &lInts[0])
				{
					lResult = (ErrorCode)CL.GetDeviceInfo(pDevice, lDeviceInfo, new IntPtr(lSize), new IntPtr(pValues), out lReturn);
					if (lResult == (int)OpenTK.Compute.CL10.All.Success)
					{
						pArray = lInts;
					}
				}
			}
			return lResult;
		}
 
		private static ErrorCode GetDeviceInfo<T>(IntPtr pDevice, DeviceInfo pDeviceInfo, out T s) where T : struct
		{
			s = default(T);
			ErrorCode lResult;
			IntPtr lRequired;
			DeviceInfo lDeviceInfo = pDeviceInfo;
			lResult = (ErrorCode)CL.GetDeviceInfo(pDevice, lDeviceInfo, IntPtr.Zero, IntPtr.Zero, out lRequired);
			if (lResult == (int)OpenTK.Compute.CL10.All.Success)
			{
				int lSize = lRequired.ToInt32();
				int lSize2 = lSize / Marshal.SizeOf(typeof(T));
				T[] lValues = new T[Math.Max(1, lSize2)];
				IntPtr lReturn;
				GCHandle lHandle = GCHandle.Alloc(lValues, GCHandleType.Pinned);
				lResult = (ErrorCode)CL.GetDeviceInfo(pDevice, lDeviceInfo, new IntPtr(lSize), lHandle.AddrOfPinnedObject(), out lReturn);
				if (lResult == (int)OpenTK.Compute.CL10.All.Success)
				{
					s = (T)Marshal.PtrToStructure(lHandle.AddrOfPinnedObject(), typeof(T));
					lHandle.Free();
					return lResult;
				}
			}
			return lResult;
		}
	}
}

Don't forget to compile with "unsafe".