opencl Compiling your Kernel


Example

Kernels can be compiled at runtime on the target device. To do so, you need

  • the kernel source code
  • the target device on which to compile
  • a context built with the target device

A quick terminology update: A program contains a collection of kernels. You can think of a program as a complete C/C++/C# source file, while kernels are the different function members of that file.

First you'll need to create a program out of your source code.

var program = Cl.CreateProgramWithSource(_context, 1, new[] { source }, null, out err);

You can combine multiple source files into one program and compile them together, which allows you to have kernels in different files and compile them together in one go.

In the next step you'll need to compile the program on your target device.

err = Cl.BuildProgram(program, 1, new[] { _device }, string.Empty, null, IntPtr.Zero);

Now here comes a little caveat: The error code only tells you, whether the function call itself was successfull but not whether your code did actually compile. To verify that, we have to query some additional information

BuildStatus status;
status = Cl.GetProgramBuildInfo(program, _device, ProgramBuildInfo.Status, out err).CastTo<BuildStatus>();
if (status != BuildStatus.Success) {
    var log = Cl.GetProgramBuildInfo(program, _device, ProgramBuildInfo.Log, out err);
}

C/C++ people can ignore the cast at the end and just compare the returned integer with the corresponding constant.

The first call checks whether our build was actually successfull. If not we can retreive a log and see exactly where things went wrong. See the remarks for some common pitfals regarding different platforms.

Once the program is built, you need to extract your different kernels out of the compiled program. To do so you create your kernels with

_kernel = Cl.CreateKernel(_program, kernel, out err);

where 'kernel' is a string of the kernel name. When you are finished with your kernel, you need to release it with

Cl.ReleaseKernel(_kernel);