/OpenCLDotNet

A C# wrapper around OpenCL

Primary LanguageC#MIT LicenseMIT

OpenCLDotNet

OpenCL Dot Net is a C# wrapper around OpenCL. The wrapper hopefully simplifies the process of setting up the OpenCL context and running programs on the GPU.

Programs

A OpenCL program can come from text file in binary or text format or it can come from a string written in the source code itself.

Below we have a simple example of a program that writes the contents of one image into another.

var program_text =
@"__kernel void read_write_test(__read_only image2d_t srcImg,
				__write_only image2d_t dstImg,
				sampler_t sampler,
				int width, int height)
			{
				
			        int2 imageCoord = (int2)(get_global_id(0), get_global_id(1));
				if (imageCoord.x < width && imageCoord.y < height)
				{
					float4 outColor = read_imagef(srcImg, sampler,imageCoord);
					write_imagef(dstImg, imageCoord, outColor);
				}
			}
			";

The first step is to take the program text and create a program object.

var program = new CLProgram(program_text);

Next we create a array and fill it with some arbritry values.

var data = new float[SIZE];
for (int i = 0; i < data.Length; i++)
	data[i] = i;	

You will see the programs kernel has 5 arguments. Two images, a sampler and two integers. We will create the two images parameter structs first using a default float image settings. We will provide the read image with the data array that will be copied into the image on creation.

var read_image_param = CLImageParameters2D.FloatImage(WIDTH, HEIGHT, CHANNELS);
read_image_param.Source = data;

var write_image_param = CLImageParameters2D.FloatImage(WIDTH, HEIGHT, CHANNELS);

Next we create rest of the kernel parameters.

var kernel_params = new CLKernelParameter()
{
	//The kernel name must be provided so the program 
	//knows which kernel to apply the arguments to.
	Name = "read_write_test",
	
	//The kernels dimension. In this case its 2D but 1D or 3D are also options
	Dimension = 2,
	
	//The work group local and global sizes. 
	GlobalSize = new CLPoint3t(WIDTH, HEIGHT, 1),
	LocalSize = new CLPoint3t(16, 16, 1),

	//Next we have the kernels aruments. We create the two images from the parameter structs, 
	//a default index based sampler and the images width and height.
	Args = new()
	{
		new CLKernelArgParameter(0, program.CreateReadImage2D(read_image_param)),
		new CLKernelArgParameter(1, program.CreateWriteImage2D(write_image_param)),
		new CLKernelArgParameter(2, program.CreateSamplerIndex()),
		new CLKernelArgParameter(3, WIDTH),
		new CLKernelArgParameter(4, HEIGHT)
	}
};

We can now run the program.

program.Run(kernel_params);

If a issue occured when the program was ran a error code is provided.

Console.WriteLine(program.Error);

The image that the data was copied into can be fetched by providing the kernel name and its argument index.

var image = program.GetImage("read_write_test", 1);

The images contents can be read back to the CPU and then we print the first 100 values.

var result = new float[SIZE];
image.Read(program.Command, result);

for (int i = 0; i < 100; i++)
	Console.WriteLine(result[i]);