Where/how to add kernel source code--*.cl--to a VS2010 proj.

Where/how is the best place/way to add OpenCL kernel source code to a C++ Win32 console project in Visual Studio 2010? I want to edit the kernel source code in VS2010 and then when I compile (Debug or Release) have it accessed automatically without me having to copy and paste the current kernel into the respective executable’s directory. Thanks!

BTW, I originally posted this under Microsoft‘s Visual Studio forum and had it modded off-topic and (re)moved:
“Moved by DanielMoth Microsoft Employee 1 hour 38 minutes ago We do not support OpenCL questions in the Microsoft forums. (From:Parallel Computing in C++ and Native Code)“

I know Microsoft has their own competing technology, but I feel that was a bit extreme to not even allow other non-Microsoft employee forum members to view and respond to my post in the original posting area. Anyways, hoping for much warmer reception here. Thanks again!

Wow, that’s pretty rude. If that’s how they treat paying customers, perhaps you should consider more carefully where you spend your money.

Sorry I can’t help, I don’t use their stuff for such reasons already.

Hi sean.settle

Welcome to the Khronos Group OpenCL forums!

I’m glad I’m not the only one that was shocked by their response. I find the Khronos forums to be way more kind and helpful :).

Normally I just use gcc and a Makefile to compile my OpenCL projects, but unfortunately some run-time analysis tools I wanted to use were only available under Windows and Visual Studio :(.

Do you happen to be familiar with creating OpenCL projects using Eclipse or Netbeans? I know how to create normal C/C++ projects using both of those IDEs, including linking with libraries, but I don’t know what’s the recommended way to add kernel source code to projects. Any tips? Thanks again!

I am not entirely sure of what you mean. Basically, you want the CL source to be built-in on the host’s binary?
You can set a makefile rule to generate a header file with your CL source and set it onto a standard char* which you can use on clCreateProgramWithSource.

I am not entirely sure on how to implement that in Windows though, but its likely that you will have similar methods; surely VS will allow you to have custom dependencies on your binary build.

On the rule to build your c/c++ file, add a dependency on another header file. Define a rule to build the header file with a shell command that will echo the cl source file into a header file for you to include.

clsourceheaderh: source.cl
cat “char* clSource = " > clsourceheader.h
cat source.cl >> clsourceheader.h”
cat “;” > clsourceheader.h

You can also have the cl source directly on your C source file.

char* source = "kernel void mykernel()
"
"{
"
"}
";

Regarding your question with netbeans/ecliple, they can be configured to use regular Makefiles, which is how I use it (Netbeans) :slight_smile:

EDIT: A quick Google revealed this: http://msdn.microsoft.com/en-us/library … hy(v=vs.80.aspx which describes your problem; you have a custom dependency on a source file.

I don’t want to include the kernel source inside the binary, but load the kernel source from a file when executing the binary. The problem is that when I add the kernel source to the project using [Project] -> [Add Item], and then compile, the generated binary is located in a separate directory (e.g., …\x64\Debug) than the source codes. So when I then code to run the binary, it can’t find the source code unless I manually copy it to the binary’s directory. Then if I switch to Release instead of Debug I’ve got to do it again, and every time I change the kernel source. There should be some way to automatically include the kernel source in the compiled binary directory.

I’m not sure that the link you included covers this case because I’m not trying to build the kernel into the binary, just edit it within the same project and have it placed together with the compiled binary.

Cheers!

I use netbeans, but I use JOCL and Java, and just include the sources in the jar file.

For development purposes I would suggest hard-coding the path to the CL source to point to your development tree and just load them directly from there.

For deployment either check a path to where the code should be, use an env var, and/or write a script to generate the distribution which has everything where it needs to be.

In VS2010 you can set a Pre-Build Event that will copy the files for you. That way the .cl files that your program loads kernels from will always be up to date. I will attach a screen shot if I can figure out how…

Hello sean.settle,

in my opinion there is only one way to get those projects nearly compatible with any C++ compiler (regarding some quality aspects included).

One way is to embed the code via char, but you dont get any code highlighting and have to escape some chars and so one. It’s the most annoying way and not nice, I think!

Another way to embed your opencl code in the binary is to use resources. Just declare your files as resource and you will get an ID for them to get the resource at runtime anywhere, but it’s ugly code, and I don’t know, how G++ solves it!?

And now the one and only way with respect to testing issues:

There are three types of code:

  • special host code
  • special device code
  • C99 code

The special host code cannot be run by the device, and the other way round. The only code you can test is the host code (since running in your development environment) and the C99 called from the host. The device code cannot be tested that easy (e.g. asserts). So you have to reduce the device code to write more C99 code. Think of only implementing helper methods your host can test, before the device invokes it. It’s not the same machine code but the same source code and same behavior!

So create your yourname.h.cl and yourname.cpp.cl file. Via preprocessor macros you can separate your source between host code, device code, and C99 pure code, included by the host and by the device. Just set the build options when compiling the opencl code.

See my current project fcocl (means “fast convolution open cl”):


// yourname.h.cl

#include "yourname.h.cl"

/* differ between host and opencl code */
#	ifndef fcocl_IS_HOST
#		error IS_HOST has to be defined to decide whether to gather host or opencl code!
#	else /* ifndef fcocl_IS_HOST */
#		if fcocl_IS_HOST == 0
#			define _fcocl_OPENCLCODE
#		elif fcocl_IS_HOST == 1 /* if fcocl_IS_HOST == 0 */
#			define _fcocl_HOSTCODE
#		else /* if _fcocl_IS_HOST == 1 */
#			error fcocl_IS_HOST has a wrong value!
#		endif /* if fcocl_IS_HOST != 0 && fcocl_IS_HOST != 1 */
#	endif /* ifdef fcocl_IS_HOST */

// ...

	/* type definition to use unique file,
		host and device */
#	ifdef _fcocl_HOSTCODE
/* #		define __CL_ENABLE_EXCEPTIONS */
#		define __NO_STD_VECTOR

#		ifdef __CL_ENABLE_EXCEPTIONS
#			pragma warning(push)
#			pragma warning(disable:4290)
#		endif

#		include <CL/cl.hpp>

#		ifdef __CL_ENABLE_EXCEPTIONS
#			pragma warning(pop)
#		endif

		typedef cl_uchar		fcocl_uchar;
		typedef cl_char			fcocl_char;
		typedef cl_ushort		fcocl_ushort;
		typedef cl_short		fcocl_short;
		typedef cl_uint			fcocl_uint;
		typedef cl_int			fcocl_int;
		typedef cl_ulong		fcocl_ulong;
		typedef cl_long			fcocl_long;
		typedef cl_half			fcocl_half;
		typedef cl_float		fcocl_float;

#	else /* ifdef _fcocl_HOSTCODE */
		typedef unsigned char	fcocl_uchar;
		typedef char			fcocl_char;
		typedef unsigned short	fcocl_ushort;
		typedef short			fcocl_short;
		typedef unsigned int	fcocl_uint;
		typedef int				fcocl_int;
		typedef unsigned long	fcocl_ulong;
		typedef long			fcocl_long;
		typedef half			fcocl_half;
		typedef float			fcocl_float;
#	endif /* ifndef _fcocl_HOSTCODE */


	/* C99 code */
	struct some_c99_structs
	{
	// ...	
	};

#ifdef _fcocl_OPENCLCODE

__kernel void fcocl_tfunc(

		/* size is kernel_size */
		__global	const fcocl_sample	*g_h_real,
		__global	const fcocl_sample	*g_h_imag,
					fcocl_uint	kernel_size,

		/* size is fcocl_FFT_SIZE */
		__global	fcocl_sample	*g_uninit_H_real,
		__global	fcocl_sample	*g_uninit_H_imag

		)
	{
// ...
}

#endif



// initopencl.cpp
cl::Program program(
	context,
	"#include \"yourname.cpp.cl\"",
	false
	);
// ...

std::stringstream buildOptions;
buildOptions << " -D fcocl_IS_HOST=0 "; // preprocessor define
buildOptions << " -I \"X:\\Development\\C++\\YourProject\""; // has to be dynamic e.g. ".\\" for current directory

So the only code to compile ist the “#include yourname.cpp.cl” and the include directory can be given via build options. In VS C++ you can set the running-in directory, but it is actually not in the Debug or Release, but the parent folder where the source is! So you can set it to “.\” as the current running-in folder, any absolute path or getting the location of the .exe file via WinAPI.

The only disadvantage is, e.g. providing a .exe file on your website you have to provide the two files (binary and opencl code). If you use archives the user must not run the binary out of the archiving program, since the binary is extracted to any temporary folder.