/// <summary>
        /// Compiles specified OpenCL program on specified device
        /// </summary>
        /// <param name="device">OpenCL device</param>
        /// <param name="programName">Program name</param>
        /// <param name="programReceiveCallback">Callback to receive program sources; or null to use default storage</param>
        /// <returns>Kernel set for program</returns>
        public OpenCLKernelSet Compile(OpenCLDevice device, string programName, Func <string, string> programReceiveCallback = null)
        {
            const string buildOptions = "-cl-fast-relaxed-math -cl-mad-enable -cl-no-signed-zeros";

            InitializeDevice(device);

            OpenCLKernelSet kernelSet;

            if (device.CachedKernels == null)
            {
                device.CachedKernels = new Dictionary <string, OpenCLKernelSet>();
            }
            else
            {
                if (device.CachedKernels.TryGetValue(programName, out kernelSet))
                {
                    return(kernelSet);
                }
            }

            string programSource;

            if (programReceiveCallback != null)
            {
                programSource = programReceiveCallback(programName);
            }
            else
            {
                programSource = LoadSourceFromResources(programName);
            }

            Program program = device.Context.CreateProgramWithSource(programSource);

            program.Build(UseRelaxedMath ? buildOptions : null);

#if ENABLE_PROFILING
            Console.WriteLine("Using kernel {0}...", programName);
            Console.WriteLine("OpenCL Build log: " + program.GetBuildLog(device.InnerDevice));
#endif

            kernelSet = new OpenCLKernelSet {
                Program     = program,
                Kernels     = new Dictionary <string, NOpenCL.Kernel>(),
                OwnerDevice = device
            };

            device.CachedKernels[programName] = kernelSet;
            return(kernelSet);
        }
        public OpenCLKernel(OpenCLKernelSet kernelSet, string kernelName)
        {
            this.kernelSet = kernelSet;

            if (!kernelSet.Kernels.TryGetValue(kernelName, out this.kernel))
            {
                this.kernel = kernelSet.Program.CreateKernel(kernelName);
            }

            this.currentArg     = 0;
            this.createdBuffers = new List <OpenCLBuffer>();

#if ENABLE_PROFILING
            if (profilingStopwatch == null)
            {
                profilingStopwatch = System.Diagnostics.Stopwatch.StartNew();
            }
            else
            {
                profilingStopwatch.Restart();
            }
#endif
        }