コード例 #1
1
ファイル: Device.cs プロジェクト: lu4/ManOCL
        internal Device(CLDeviceID id)
        {
            this.CLDeviceID = id;

            this.PlatformID = GetDeviceInfo <CLPlatformID>(this, CLDeviceInfo.Platform);

            this.AddressBits            = GetDeviceInfo <Int32>(this, CLDeviceInfo.AddressBits);
            this.Available              = GetDeviceInfo <Boolean>(this, CLDeviceInfo.Available);
            this.CompilerAvailable      = GetDeviceInfo <Boolean>(this, CLDeviceInfo.CompilerAvailable);
            this.DriverVersion          = GetDeviceInfoString(this, CLDeviceInfo.DriverVersion);
            this.EndianLittle           = GetDeviceInfo <Boolean>(this, CLDeviceInfo.EndianLittle);
            this.ErrorCorrectionSupport = GetDeviceInfo <Boolean>(this, CLDeviceInfo.ErrorCorrectionSupport);
            this.ExecutionCapabilities  = (DeviceExecCapabilities)GetDeviceInfo <ulong>(this, CLDeviceInfo.ExecutionCapabilities);

            this.Extensions = GetDeviceInfoString(this, CLDeviceInfo.Extensions);

            this.GlobalMemCacheLineSize = GetDeviceInfo <Int32>(this, CLDeviceInfo.GlobalMemCacheLineSize);
            this.GlobalMemCacheSize     = GetDeviceInfo <Int64>(this, CLDeviceInfo.GlobalMemCacheSize);
            this.GlobalMemCacheType     = (DeviceMemCacheType)GetDeviceInfo <uint>(this, CLDeviceInfo.GlobalMemCacheType);
            this.GlobalMemSize          = GetDeviceInfo <Int64>(this, CLDeviceInfo.GlobalMemSize);
            this.Image2DMaxHeight       = GetDeviceInfo <SizeT>(this, CLDeviceInfo.Image2DMaxHeight);
            this.Image2DMaxWidth        = GetDeviceInfo <SizeT>(this, CLDeviceInfo.Image2DMaxWidth);
            this.Image3DMaxDepth        = GetDeviceInfo <SizeT>(this, CLDeviceInfo.Image3DMaxDepth);
            this.Image3DMaxHeight       = GetDeviceInfo <SizeT>(this, CLDeviceInfo.Image3DMaxHeight);
            this.Image3DMaxWidth        = GetDeviceInfo <SizeT>(this, CLDeviceInfo.Image3DMaxWidth);
            this.ImageSupport           = GetDeviceInfo <Boolean>(this, CLDeviceInfo.ImageSupport);
            this.LocalMemSize           = GetDeviceInfo <Int64>(this, CLDeviceInfo.LocalMemSize);
            this.LocalMemType           = (DeviceLocalMemType)GetDeviceInfo <uint>(this, CLDeviceInfo.LocalMemType);
            this.MaxClockFrequency      = GetDeviceInfo <Int32>(this, CLDeviceInfo.MaxClockFrequency);
            this.MaxComputeUnits        = GetDeviceInfo <Int32>(this, CLDeviceInfo.MaxComputeUnits);
            this.MaxConstantArgs        = GetDeviceInfo <Int32>(this, CLDeviceInfo.MaxConstantArgs);
            this.MaxConstantBufferSize  = GetDeviceInfo <Int64>(this, CLDeviceInfo.MaxConstantBufferSize);
            this.MaxMemAllocSize        = GetDeviceInfo <Int64>(this, CLDeviceInfo.MaxMemAllocSize);
            this.MaxParameterSize       = GetDeviceInfo <SizeT>(this, CLDeviceInfo.MaxParameterSize);
            this.MaxReadImageArgs       = GetDeviceInfo <Int32>(this, CLDeviceInfo.MaxReadImageArgs);
            this.MaxSamplers            = GetDeviceInfo <Int32>(this, CLDeviceInfo.MaxSamplers);
            this.MaxWorkGroupSize       = GetDeviceInfo <SizeT>(this, CLDeviceInfo.MaxWorkGroupSize);
            this.MaxWorkItemDimensions  = GetDeviceInfo <Int32>(this, CLDeviceInfo.MaxWorkItemDimensions);
            this.MaxWorkItemSizes       = new SizeT[this.MaxWorkItemDimensions];

            GCHandle bufferHandle = GCHandle.Alloc(this.MaxWorkItemSizes, GCHandleType.Pinned);

            try
            {
                SizeT param_value_size_ret = SizeT.Zero;

                OpenCLError.Validate(OpenCLDriver.clGetDeviceInfo(CLDeviceID, CLDeviceInfo.MaxWorkItemSizes, new SizeT(MaxWorkItemSizes.Length * IntPtr.Size), bufferHandle.AddrOfPinnedObject(), ref param_value_size_ret));
            }
            finally
            {
                bufferHandle.Free();
            }

            this.MaxWriteImageArgs    = GetDeviceInfo <Int32>(this, CLDeviceInfo.MaxWriteImageArgs);
            this.MemBaseAddrAlign     = GetDeviceInfo <Int32>(this, CLDeviceInfo.MemBaseAddrAlign);
            this.MinDataTypeAlignSize = GetDeviceInfo <Int32>(this, CLDeviceInfo.MinDataTypeAlignSize);
            this.Name = GetDeviceInfoString(this, CLDeviceInfo.Name);
            this.PreferredVectorWidthChar   = GetDeviceInfo <Int32>(this, CLDeviceInfo.PreferredVectorWidthChar);
            this.PreferredVectorWidthDouble = GetDeviceInfo <Int32>(this, CLDeviceInfo.PreferredVectorWidthDouble);
            this.PreferredVectorWidthFloat  = GetDeviceInfo <Int32>(this, CLDeviceInfo.PreferredVectorWidthFloat);
            this.PreferredVectorWidthInt    = GetDeviceInfo <Int32>(this, CLDeviceInfo.PreferredVectorWidthInt);
            this.PreferredVectorWidthLong   = GetDeviceInfo <Int32>(this, CLDeviceInfo.PreferredVectorWidthLong);
            this.PreferredVectorWidthShort  = GetDeviceInfo <Int32>(this, CLDeviceInfo.PreferredVectorWidthShort);
            this.Profile = GetDeviceInfoString(this, CLDeviceInfo.Profile);
            this.ProfilingTimerResolution = GetDeviceInfo <SizeT>(this, CLDeviceInfo.ProfilingTimerResolution);
            this.QueueProperties          = GetDeviceInfo <Int64>(this, CLDeviceInfo.QueueProperties);
            this.SingleFPConfig           = (DeviceFPConfig)GetDeviceInfo <ulong>(this, CLDeviceInfo.SingleFPConfig);
            this.CLDeviceType             = (CLDeviceType)GetDeviceInfo <ulong>(this, CLDeviceInfo.Type);
            this.Vendor   = GetDeviceInfoString(this, CLDeviceInfo.Vendor);
            this.VendorID = GetDeviceInfo <Int32>(this, CLDeviceInfo.VendorID);
            this.Version  = GetDeviceInfoString(this, CLDeviceInfo.Version);
        }
コード例 #2
0
ファイル: OpenCLError.cs プロジェクト: lu4/ManOCL
        internal static void ValidateBuild(CLProgram openclProgram, Device device, CLError error)
        {
            if (CLError.None != error)
            {
                SizeT bufferSize = SizeT.Zero;

                OpenCLError.Validate(OpenCLDriver.clGetProgramBuildInfo(openclProgram, device.CLDeviceID, CLProgramBuildInfo.Log, SizeT.Zero, IntPtr.Zero, ref bufferSize));

                byte[] buffer = new byte[(Int64)bufferSize];

                GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);

                try
                {
                    OpenCLError.Validate(OpenCLDriver.clGetProgramBuildInfo(openclProgram, device.CLDeviceID, CLProgramBuildInfo.Log, new SizeT(buffer.LongLength), bufferHandle.AddrOfPinnedObject(), ref bufferSize));

                    Int32 count = Array.IndexOf <byte>(buffer, 0);

                    throw new OpenCLBuildError(error, System.Text.Encoding.ASCII.GetString(buffer, 0, count < 0 ? buffer.Length : count).Trim());
                }
                finally
                {
                    bufferHandle.Free();
                }
            }
        }
コード例 #3
0
        internal override void SetAsKernelArgument(CLKernel kernel, int index)
        {
            var clMem = new CLMem
            {
                Value = openCLSampler.Value
            };

            OpenCLError.Validate(OpenCLDriver.clSetKernelArg(kernel, index, new SizeT(IntPtr.Size), ref clMem));
        }
コード例 #4
0
ファイル: Context.cs プロジェクト: lu4/ManOCL
        public static Context Share(IntPtr openclContext)
        {
            SizeT devicesSize = SizeT.Zero;

            CLContext clContext = new CLContext {
                Value = openclContext
            };

            OpenCLError.Validate(OpenCLDriver.clGetContextInfo(clContext, CLContextInfo.Devices, SizeT.Zero, IntPtr.Zero, ref devicesSize));

            CLDeviceID[] devices = new CLDeviceID[((Int64)(devicesSize)) / IntPtr.Size];

            GCHandle devicesHandle = GCHandle.Alloc(devices, GCHandleType.Pinned);

            try
            {
                OpenCLError.Validate(OpenCLDriver.clGetContextInfo(clContext, CLContextInfo.Devices, devicesSize, devicesHandle.AddrOfPinnedObject(), ref devicesSize));

                Dictionary <CLPlatformID, CLPlatformID> platformsDictionary = new Dictionary <CLPlatformID, CLPlatformID>();

                CLPlatformID[] platforms = null;

                foreach (CLDeviceID device in devices)
                {
                    SizeT platformsSize = SizeT.Zero;

                    OpenCLError.Validate(OpenCLDriver.clGetDeviceInfo(device, CLDeviceInfo.Platform, SizeT.Zero, platforms, ref platformsSize));

                    platforms = new CLPlatformID[((Int64)(platformsSize)) / IntPtr.Size];

                    OpenCLError.Validate(OpenCLDriver.clGetDeviceInfo(device, CLDeviceInfo.Platform, platformsSize, platforms, ref platformsSize));

                    foreach (CLPlatformID platform in platforms)
                    {
                        if (!platformsDictionary.ContainsKey(platform))
                        {
                            platformsDictionary.Add(platform, platform);
                        }
                    }
                }

                platforms = new CLPlatformID[platformsDictionary.Count];

                Int32 index = 0;

                foreach (var platform in platformsDictionary.Keys)
                {
                    platforms[index++] = platform;
                }

                return(new Context(clContext, new Platforms(platforms), new Devices(devices)));
            }
            finally
            {
                devicesHandle.Free();
            }
        }
コード例 #5
0
        public static CommandQueue Create(Context context, Device device, CommandQueueProperties commandQueueProperties)
        {
            CLError error = CLError.None;

            CLCommandQueue openclCommandQueue = OpenCLDriver.clCreateCommandQueue(context.CLContext, device.CLDeviceID, (ManOCL.Internal.OpenCL.CLCommandQueueProperties)commandQueueProperties, ref error);

            OpenCLError.Validate(error);

            return(new CommandQueue(openclCommandQueue, context, device, commandQueueProperties));
        }
コード例 #6
0
ファイル: DeviceImage.cs プロジェクト: lu4/ManOCL
        public Event Acquire(CommandQueue commandQueue, Events eventWaitList)
        {
            CLEvent e = new CLEvent();

            OpenCLError.Validate(OpenCLGLDriver.clEnqueueAcquireGLObjects(commandQueue.CLCommandQueue, memObjects.Length, memObjects, eventWaitList.Count, eventWaitList.OpenCLEventArray, ref e));

            Acquired = true;

            return(new Event(e));
        }
コード例 #7
0
        public static Context Create(Platforms platforms, Devices devices)
        {
            CLError error = CLError.None;

            // TODO: Add parameter pfn_notify (logging function)
            CLContext openclContext = OpenCLDriver.clCreateContext(GetContextProperties(platforms), devices.Count, devices.OpenCLDeviceArray, null, IntPtr.Zero, ref error);

            OpenCLError.Validate(error);

            return(new Context(openclContext, platforms, devices));
        }
コード例 #8
0
        public static Program Create(String[] sources, Context context, Devices devices, String buildOptions)
        {
            CLError error = CLError.None;

            CLProgram openclProgram = OpenCLDriver.clCreateProgramWithSource(context.CLContext, sources.Length, sources, GetLengths(sources), ref error);

            OpenCLError.Validate(error);

            OpenCLBuildError.ValidateBuild(openclProgram, devices[0], OpenCLDriver.clBuildProgram(openclProgram, devices.Count, devices.OpenCLDeviceArray, buildOptions, null, IntPtr.Zero));

            return(new Program(openclProgram, sources, context, devices, buildOptions));
        }
コード例 #9
0
ファイル: Device.cs プロジェクト: lu4/ManOCL
        private static Byte[] GetDeviceInfoBuffer(Device device, CLDeviceInfo deviceInfo)
        {
            SizeT bufferSize = SizeT.Zero;

            OpenCLError.Validate(OpenCLDriver.clGetDeviceInfo(device.CLDeviceID, deviceInfo, SizeT.Zero, IntPtr.Zero, ref bufferSize));

            Byte[] buffer = new Byte[(Int64)bufferSize];

            OpenCLError.Validate(OpenCLDriver.clGetDeviceInfo(device.CLDeviceID, deviceInfo, bufferSize, buffer, ref bufferSize));

            return(buffer);
        }
コード例 #10
0
        public static Platforms Create()
        {
            Int32 platformsCount = 0;

            OpenCLError.Validate(OpenCLDriver.clGetPlatformIDs(0, null, ref platformsCount));

            CLPlatformID[] platforms = new CLPlatformID[platformsCount];

            OpenCLError.Validate(OpenCLDriver.clGetPlatformIDs(platformsCount, platforms, ref platformsCount));

            return(new Platforms(platforms));
        }
コード例 #11
0
ファイル: ValueArgument.cs プロジェクト: lu4/ManOCL
        internal override void SetAsKernelArgument(CLKernel kernel, int index)
        {
            GCHandle handle = GCHandle.Alloc(Value, GCHandleType.Pinned);

            try
            {
                OpenCLError.Validate(OpenCLDriver.clSetKernelArg(kernel, index, new SizeT(Marshal.SizeOf(typeof(T))), handle.AddrOfPinnedObject()));
            }
            finally
            {
                handle.Free();
            }
        }
コード例 #12
0
        public static DeviceSampler Create(Boolean normalizedCoords, AddressingMode addressingMode, FilterMode filterMode, Context context)
        {
            CLError error = new CLError();

            CLSampler sampler = OpenCLDriver.clCreateSampler(context.CLContext, normalizedCoords ? CLBool.True : CLBool.False, (CLAddressingMode)addressingMode, (CLFilterMode)filterMode, ref error);

            OpenCLError.Validate(error);

            return(new DeviceSampler()
            {
                openCLSampler = sampler
            });
        }
コード例 #13
0
        public static Devices Create(CLDeviceType deviceType, Platform platform)
        {
            Int32 deviceCount = 0;

            CLPlatformID pfm = platform == null ? new CLPlatformID() : platform.CLPlatformID;

            OpenCLError.Validate(OpenCLDriver.clGetDeviceIDs(pfm, (ManOCL.Internal.OpenCL.CLDeviceType)deviceType, 0, null, ref deviceCount));

            CLDeviceID[] deviceIds = new CLDeviceID[deviceCount];

            OpenCLError.Validate(OpenCLDriver.clGetDeviceIDs(pfm, (ManOCL.Internal.OpenCL.CLDeviceType)deviceType, deviceCount, deviceIds, ref deviceCount));

            return(new Devices(deviceIds));
        }
コード例 #14
0
        public static void CreateAsync <T>(CreateCallback <T> createCallback, T userData, String[] sources, Devices devices, Context context, String buildOptions)
        {
            CLError error = CLError.None;

            CLProgram openclProgram = OpenCLDriver.clCreateProgramWithSource(context.CLContext, sources.Length, sources, GetLengths(sources), ref error);

            OpenCLError.Validate(error);

            Program program = new Program(openclProgram, sources, context, devices, buildOptions);

            program.AsyncHelperObject = new AsyncHelper <T>(program, createCallback, userData);

            OpenCLError.Validate(OpenCLDriver.clBuildProgram(openclProgram, devices.Count, devices.OpenCLDeviceArray, buildOptions, program.AsyncCallback, IntPtr.Zero));
        }
コード例 #15
0
ファイル: DeviceImage.cs プロジェクト: lu4/ManOCL
        public static DeviceImage CreateFromTexture2D(UInt32 texture, Int32 mipLevel, DeviceBufferAccess access, Context context)
        {
            CLError error = CLError.None;

            CLMem mem = ManOCL.Internal.OpenCL.OpenGL.OpenCLGLDriver.clCreateFromGLTexture2D(context.CLContext, GetMemFlags(access), 3553 /* GL_TEXTURE_2D */, mipLevel, texture, ref error);

            OpenCLError.Validate(error);

            DeviceImage result = new DeviceImage(new Mem {
                Value = mem.Value
            });

            return(result);
        }
コード例 #16
0
        internal Event ExecuteInternal(SizeT[] globalWorkSize, SizeT[] localWorkSize, Events eventWaitList, SizeT[] globalWorkOffset)
        {
            if (localWorkSize == null || globalWorkSize.Length == localWorkSize.Length)
            {
                CLEvent e = new CLEvent();

                OpenCLError.Validate(OpenCLDriver.clEnqueueNDRangeKernel(CommandQueue.CLCommandQueue, CLKernel, globalWorkSize.Length, globalWorkOffset, globalWorkSize, localWorkSize, eventWaitList.Count, eventWaitList.OpenCLEventArray, ref e));

                return(new Event(e));
            }
            else
            {
                throw new ArgumentException(Resources.LocalWorkSize_and_GlobalWorkSize_dimensions_do_not_agree);
            }
        }
コード例 #17
0
ファイル: Profiler.cs プロジェクト: lu4/ManOCL
        private static Int64 GetInfo(Event e, CLProfilingInfo info)
        {
            Byte[] bytes = new Byte[8];

            SizeT paramValueSizeRet = SizeT.Zero;

            GCHandle bytesHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);

            {
                OpenCLError.Validate(OpenCLDriver.clGetEventProfilingInfo(e.CLEvent, info, new SizeT(bytes.LongLength), bytesHandle.AddrOfPinnedObject(), ref paramValueSizeRet));
            }
            bytesHandle.Free();

            return(BitConverter.ToInt64(bytes, 0));
        }
コード例 #18
0
        private static Event WriteBytesInternal(CLMem openCLMem, CommandQueue commandQueue, Array array, Int64 bytesToCopy, Int64 arrayOffset, Int64 arraySize, Int64 bufferOffset, Int64 bufferSize, Events eventWaitList, WriteOperation writeDelegate)
        {
            if (bufferSize < bufferOffset + bytesToCopy)
            {
                throw new ArgumentException(Resources.Buffer_out_of_bounds);
            }
            if (arraySize < arrayOffset + bytesToCopy)
            {
                throw new ArgumentException(Resources.Array_out_of_bounds);
            }

            GCHandle valueHandle = GCHandle.Alloc(array, GCHandleType.Pinned);

            try
            {
                CLEvent e = new CLEvent();

                unsafe
                {
                    IntPtr valuePtr = new IntPtr((Byte *)(valueHandle.AddrOfPinnedObject().ToPointer()) + arrayOffset);

                    OpenCLError.Validate
                    (
                        writeDelegate
                        (
                            commandQueue.CLCommandQueue,
                            openCLMem,
                            CLBool.True,
                            new SizeT(bufferOffset),
                            new SizeT(bytesToCopy),
                            valuePtr,
                            eventWaitList == null ? 0 : eventWaitList.Count,
                            eventWaitList == null ? null : eventWaitList.OpenCLEventArray,
                            ref e
                        )
                    );
                }

                return(new Event(e));
            }
            finally
            {
                valueHandle.Free();
            }
        }
コード例 #19
0
ファイル: Context.cs プロジェクト: lu4/ManOCL
        public static IntPtr ShareForMac(IntPtr cglShareGroup)
        {
            CLError error = CLError.None;

            IntPtr[] properties =
            {
                new IntPtr(0x10000000), // CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE
                cglShareGroup,
                new IntPtr(0)
            };


            // TODO: Add parameter pfn_notify (logging function)
            CLContext openclContext = OpenCLDriver.clCreateContext(properties, 0, null, null, IntPtr.Zero, ref error);

            OpenCLError.Validate(error);

            return(openclContext.Value);
        }
コード例 #20
0
        internal static Kernels CreateInternal(CommandQueue commandQueue, Program program, Int32 kernelsCount, Int32 kernelInfoBufferSize)
        {
            Validate(commandQueue, program);

            Int32 numKernelsRet = 0;

            CLKernel[] openclKernels = new CLKernel[kernelsCount];

            OpenCLError.Validate(OpenCLDriver.clCreateKernelsInProgram(program.CLProgram, openclKernels.Length, openclKernels, ref numKernelsRet));

            Kernel[] result = new Kernel[numKernelsRet];

            for (int i = 0; i < numKernelsRet; i++)
            {
                result[i] = new Kernel(openclKernels[i], program, commandQueue, kernelInfoBufferSize);
            }

            return(new Kernels(result));
        }
コード例 #21
0
        private static String GetPlatformInfo(Platform platform, CLPlatformInfo platformInfo)
        {
            if (platform.CLPlatformID.Value == IntPtr.Zero)
            {
                return("None");
            }
            else
            {
                SizeT buffer_size = SizeT.Zero;

                OpenCLError.Validate(OpenCLDriver.clGetPlatformInfo(platform.CLPlatformID, platformInfo, SizeT.Zero, null, ref buffer_size));

                Byte[] buffer = new Byte[(Int64)buffer_size];

                OpenCLError.Validate(OpenCLDriver.clGetPlatformInfo(platform.CLPlatformID, platformInfo, buffer_size, buffer, ref buffer_size));

                Int32 count = Array.IndexOf <byte>(buffer, 0);

                return(System.Text.Encoding.ASCII.GetString(buffer, 0, count < 0 ? buffer.Length : count));
            }
        }
コード例 #22
0
        private static Byte[] GetKernelInfoBuffer(CLKernel openclKernel, CLKernelInfo kernelInfo, Int32 kernelInfoBufferSize)
        {
            SizeT bufferSize = SizeT.Zero;

            Byte[] buffer = new Byte[kernelInfoBufferSize];

            GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);

            IntPtr bufferPtr = bufferHandle.AddrOfPinnedObject();

            try
            {
                OpenCLError.Validate(OpenCLDriver.clGetKernelInfo(openclKernel, kernelInfo, new SizeT(buffer.Length), bufferPtr, ref bufferSize));
            }
            finally
            {
                bufferHandle.Free();
            }

            Array.Resize(ref buffer, (int)bufferSize);

            return(buffer);
        }
コード例 #23
0
 public void Finish()
 {
     OpenCLError.Validate(OpenCLDriver.clFinish(CLCommandQueue));
 }
コード例 #24
0
ファイル: DeviceImage.cs プロジェクト: lu4/ManOCL
 internal override void SetAsKernelArgument(CLKernel kernel, Int32 index)
 {
     OpenCLError.Validate(OpenCLDriver.clSetKernelArg(kernel, index, new SizeT(IntPtr.Size), memObjects));
 }
コード例 #25
0
 internal override void SetAsKernelArgument(CLKernel kernel, int index)
 {
     OpenCLError.Validate(OpenCLDriver.clSetKernelArg(kernel, index, new SizeT(IntPtr.Size), ref openCLMem));
 }
コード例 #26
0
        public static Context ShareWithCGL(IntPtr cglShareGroup)
        {
            IntPtr[] properties =
            {
                new IntPtr(0x10000000),                 // CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE
                cglShareGroup,
                new IntPtr(0)
            };

            CLError error = CLError.None;

            // TODO: Add parameter pfn_notify (logging function)
            CLContext openclContext = OpenCLDriver.clCreateContext(properties, 0, null, null, IntPtr.Zero, ref error);

            OpenCLError.Validate(error);

            SizeT devicesSize = SizeT.Zero;

            OpenCLError.Validate(OpenCLDriver.clGetContextInfo(openclContext, CLContextInfo.Devices, SizeT.Zero, IntPtr.Zero, ref devicesSize));

            CLDeviceID[] devices = new CLDeviceID[((Int64)(devicesSize)) / IntPtr.Size];

            GCHandle devicesHandle = GCHandle.Alloc(devices, GCHandleType.Pinned);

            try
            {
                OpenCLError.Validate(OpenCLDriver.clGetContextInfo(openclContext, CLContextInfo.Devices, devicesSize, devicesHandle.AddrOfPinnedObject(), ref devicesSize));

                Dictionary <CLPlatformID, CLPlatformID> platformsDictionary = new Dictionary <CLPlatformID, CLPlatformID>();

                CLPlatformID[] platforms = null;

                foreach (CLDeviceID device in devices)
                {
                    SizeT platformsSize = SizeT.Zero;

                    OpenCLError.Validate(OpenCLDriver.clGetDeviceInfo(device, CLDeviceInfo.Platform, SizeT.Zero, platforms, ref platformsSize));

                    platforms = new CLPlatformID[((Int64)(platformsSize)) / IntPtr.Size];

                    OpenCLError.Validate(OpenCLDriver.clGetDeviceInfo(device, CLDeviceInfo.Platform, platformsSize, platforms, ref platformsSize));

                    foreach (CLPlatformID platform in platforms)
                    {
                        if (!platformsDictionary.ContainsKey(platform))
                        {
                            platformsDictionary.Add(platform, platform);
                        }
                    }
                }

                platforms = new CLPlatformID[platformsDictionary.Count];

                Int32 index = 0;

                foreach (var platform in platformsDictionary.Keys)
                {
                    platforms[index++] = platform;
                }

                return(new Context(openclContext, new Platforms(platforms), new Devices(devices)));
            }
            finally
            {
                devicesHandle.Free();
            }
        }