private void ready()
        {
            ErrorCode error;

            context = Cl.CreateContext(null, 1, new[] { device }, null, IntPtr.Zero, out error);

            string source = System.IO.File.ReadAllText("kernels.cl");

            program = Cl.CreateProgramWithSource(context, 1, new[] { source }, null, out error);

            error = Cl.BuildProgram(program, 1, new[] { device }, string.Empty, null, IntPtr.Zero);
            InfoBuffer buildStatus = Cl.GetProgramBuildInfo(program, device, ProgramBuildInfo.Status, out error);

            if (buildStatus.CastTo <BuildStatus>() != BuildStatus.Success)
            {
                throw new Exception($"OpenCL could not build the kernel successfully: {buildStatus.CastTo<BuildStatus>()}");
            }
            allGood(error);

            Kernel[] kernels = Cl.CreateKernelsInProgram(program, out error);
            kernel = kernels[0];
            allGood(error);

            queue = Cl.CreateCommandQueue(context, device, CommandQueueProperties.None, out error);
            allGood(error);

            dataOut = Cl.CreateBuffer(context, MemFlags.WriteOnly, (IntPtr)(globalSize * sizeof(int)), out error);
            allGood(error);

            var intSizePtr = new IntPtr(Marshal.SizeOf(typeof(int)));

            error |= Cl.SetKernelArg(kernel, 2, new IntPtr(Marshal.SizeOf(typeof(IntPtr))), dataOut);
            error |= Cl.SetKernelArg(kernel, 3, intSizePtr, new IntPtr(worldSeed));
            error |= Cl.SetKernelArg(kernel, 4, intSizePtr, new IntPtr(globalSize));
            allGood(error);
        }
        private void init(string oclProgramSourcePath)
        {
            string kernelSource = File.ReadAllText(oclProgramSourcePath);

            string[] kernelNames = new string[] { "accumulate", "quickBlurImgH", "quickBlurImgV", "upsizeImg", "halfSizeImgH", "halfSizeImgV", "getLumaImg", "mapToGreyscaleBmp", "getContrastImg", "capHolesImg", "maxReduceImgH", "maxReduceImgV", "mapToFauxColorsBmp", "quickSpikesFilterImg", "convolveImg" };

            bool gpu = true;

            //err = clGetDeviceIDs(NULL, gpu ? CL_DEVICE_TYPE_GPU : CL_DEVICE_TYPE_CPU, 1, &device_id, NULL);
            // NVidia driver doesn't seem to support a NULL first param (properties)
            // http://stackoverflow.com/questions/19140989/how-to-remove-cl-invalid-platform-error-in-opencl-code

            // now get all the platform IDs
            Platform[] platforms = Cl.GetPlatformIDs(out err);
            assert(err, "Error: Failed to get platform ids!");

            InfoBuffer deviceInfo = Cl.GetPlatformInfo(platforms[0], PlatformInfo.Name, out err);

            assert(err, "error retrieving platform name");
            Console.WriteLine("Platform name: {0}\n", deviceInfo.ToString());


            //                                 Arbitrary, should be configurable
            Device[] devices = Cl.GetDeviceIDs(platforms[0], gpu ? DeviceType.Gpu : DeviceType.Cpu, out err);
            assert(err, "Error: Failed to create a device group!");

            _device = devices[0]; // Arbitrary, should be configurable

            deviceInfo = Cl.GetDeviceInfo(_device, DeviceInfo.Name, out err);
            assert(err, "error retrieving device name");
            Debug.WriteLine("Device name: {0}", deviceInfo.ToString());

            deviceInfo = Cl.GetDeviceInfo(_device, DeviceInfo.ImageSupport, out err);
            assert(err, "error retrieving device image capability");
            Debug.WriteLine("Device supports img: {0}", (deviceInfo.CastTo <Bool>() == Bool.True));

            // Create a compute context
            //
            _context = Cl.CreateContext(null, 1, new[] { _device }, ContextNotify, IntPtr.Zero, out err);
            assert(err, "Error: Failed to create a compute context!");

            // Create the compute program from the source buffer
            //
            _program = Cl.CreateProgramWithSource(_context, 1, new[] { kernelSource }, new[] { (IntPtr)kernelSource.Length }, out err);
            assert(err, "Error: Failed to create compute program!");

            // Build the program executable
            //
            err = Cl.BuildProgram(_program, 1, new[] { _device }, string.Empty, null, IntPtr.Zero);
            assert(err, "Error: Failed to build program executable!");
            InfoBuffer buffer = Cl.GetProgramBuildInfo(_program, _device, ProgramBuildInfo.Log, out err);

            Debug.WriteLine("build success: {0}", buffer.CastTo <BuildStatus>() == BuildStatus.Success);

            foreach (string kernelName in kernelNames)
            {
                // Create the compute kernel in the program we wish to run
                //
                OpenCL.Net.Kernel kernel = Cl.CreateKernel(_program, kernelName, out err);
                assert(err, "Error: Failed to create compute kernel!");
                _kernels.Add(kernelName, kernel);
            }

            // Create a command queue
            //
            _commandsQueue = Cl.CreateCommandQueue(_context, _device, CommandQueueProperties.None, out err);
            assert(err, "Error: Failed to create a command commands!");
        }
        public void TestSlimeFinder()
        {
            const int squareLength = 1024;
            int       globalSize   = squareLength * squareLength;
            var       candidates   = new int[globalSize];

            ErrorCode error;
            Device    device = (from d in
                                Cl.GetDeviceIDs(
                                    (from platform in Cl.GetPlatformIDs(out error)
                                     where Cl.GetPlatformInfo(platform, PlatformInfo.Name, out error).ToString() == "AMD Accelerated Parallel Processing" // Use "NVIDIA CUDA" if you don't have amd
                                     select platform).First(), DeviceType.Gpu, out error)
                                select d).First();

            Context context = Cl.CreateContext(null, 1, new[] { device }, null, IntPtr.Zero, out error);

            string source = System.IO.File.ReadAllText("kernels.cl");

            using Program program = Cl.CreateProgramWithSource(context, 1, new[] { source }, null, out error);

            error = Cl.BuildProgram(program, 1, new[] { device }, string.Empty, null, IntPtr.Zero);
            InfoBuffer buildStatus = Cl.GetProgramBuildInfo(program, device, ProgramBuildInfo.Status, out error);

            Assert.AreEqual(buildStatus.CastTo <BuildStatus>(), BuildStatus.Success);
            Assert.AreEqual(error, ErrorCode.Success);

            Kernel[] kernels = Cl.CreateKernelsInProgram(program, out error);
            Kernel   kernel  = kernels[0];

            Assert.AreEqual(error, ErrorCode.Success);

            CommandQueue queue = Cl.CreateCommandQueue(context, device, CommandQueueProperties.None, out error);

            Assert.AreEqual(error, ErrorCode.Success);

            IMem dataOut = Cl.CreateBuffer(context, MemFlags.WriteOnly, (IntPtr)(globalSize * sizeof(int)), out error);

            Assert.AreEqual(error, ErrorCode.Success);

            var intSizePtr = new IntPtr(Marshal.SizeOf(typeof(int)));

            error  = Cl.SetKernelArg(kernel, 0, intSizePtr, new IntPtr(0));
            error |= Cl.SetKernelArg(kernel, 1, intSizePtr, new IntPtr(0));
            error |= Cl.SetKernelArg(kernel, 2, new IntPtr(Marshal.SizeOf(typeof(IntPtr))), dataOut);
            error |= Cl.SetKernelArg(kernel, 3, intSizePtr, new IntPtr(420));
            error |= Cl.SetKernelArg(kernel, 4, intSizePtr, new IntPtr(globalSize));
            Assert.AreEqual(error, ErrorCode.Success);

            int local_size  = 256;
            int global_size = (int)Math.Ceiling(globalSize / (float)local_size) * local_size;
            var stopW       = new Stopwatch();

            stopW.Start();
            error = Cl.EnqueueNDRangeKernel(queue, kernel, 1, null, new IntPtr[] { new IntPtr(global_size) }, new IntPtr[] { new IntPtr(local_size) }, 0, null, out Event clevent);
            Assert.AreEqual(error, ErrorCode.Success);

            Cl.Finish(queue);
            stopW.Stop();


            Cl.EnqueueReadBuffer(queue, dataOut, Bool.True, IntPtr.Zero, (IntPtr)(globalSize * sizeof(int)), candidates, 0, null, out clevent);
            candidates.ForEach(c =>
            {
                if (c > 50)
                {
                    Console.Write($"{c},");
                }
            });

            Console.WriteLine($"\n{stopW.ElapsedMilliseconds} ms");


            error  = Cl.SetKernelArg(kernel, 0, intSizePtr, new IntPtr(16383));
            error |= Cl.SetKernelArg(kernel, 1, intSizePtr, new IntPtr(16383));

            stopW.Start();
            error = Cl.EnqueueNDRangeKernel(queue, kernel, 1, null, new IntPtr[] { new IntPtr(global_size) }, new IntPtr[] { new IntPtr(local_size) }, 0, null, out clevent);
            Assert.AreEqual(error, ErrorCode.Success);

            Cl.Finish(queue);
            stopW.Stop();


            Cl.EnqueueReadBuffer(queue, dataOut, Bool.True, IntPtr.Zero, (IntPtr)(globalSize * sizeof(int)), candidates, 0, null, out clevent);
            candidates.ForEach(c =>
            {
                if (c > 50)
                {
                    Console.Write($"{c},");
                }
            });

            Console.WriteLine($"\n{stopW.ElapsedMilliseconds} ms");

            Cl.ReleaseKernel(kernel);
            Cl.ReleaseMemObject(dataOut);
            Cl.ReleaseCommandQueue(queue);
            Cl.ReleaseProgram(program);
            Cl.ReleaseContext(context);
        }