Exemple #1
0
// OpenCL functions
int InitialiseCLEnvironment(cl_platform_id **platform, cl_device_id ***device_id, cl_program *program, renderStruct *render)
{
	// error flag
	cl_int err;
	char infostring[1024];
	char deviceInfo[1024];

	// need to ensure platform supports OpenGL OpenCL interop before querying devices
	// to avoid segfault when calling clGetGLContextInfoKHR
	int *platformSupportsInterop;

	//get kernel from file
	FILE* kernelFile = fopen(kernelFileName, "rb");
	fseek(kernelFile, 0, SEEK_END);
	long fileLength = ftell(kernelFile);
	rewind(kernelFile);
	char *kernelSource = malloc(fileLength*sizeof(char));
	long read = fread(kernelSource, sizeof(char), fileLength, kernelFile);
	if (fileLength != read) printf("Error reading kernel file, line %d\n", __LINE__);
	fclose(kernelFile);

	//get platform and device information
	cl_uint numPlatforms;
	err = clGetPlatformIDs(0, NULL, &numPlatforms);
	*platform = malloc(numPlatforms * sizeof(cl_platform_id));
	*device_id = malloc(numPlatforms * sizeof(cl_device_id*));
	platformSupportsInterop = malloc(numPlatforms * sizeof(*platformSupportsInterop));
	err |= clGetPlatformIDs(numPlatforms, *platform, NULL);
	CheckOpenCLError(err, __LINE__);
	cl_uint *numDevices;
	numDevices = malloc(numPlatforms * sizeof(cl_uint));

	for (cl_uint i = 0; i < numPlatforms; i++) {
		clGetPlatformInfo((*platform)[i], CL_PLATFORM_VENDOR, sizeof(infostring), infostring, NULL);
		printf("\n---OpenCL: Platform Vendor %d: %s\n", i, infostring);

		err = clGetDeviceIDs((*platform)[i], CL_DEVICE_TYPE_ALL, 0, NULL, &(numDevices[i]));
		CheckOpenCLError(err, __LINE__);
		(*device_id)[i] = malloc(numDevices[i] * sizeof(cl_device_id));
		platformSupportsInterop[i] = 0;
		err = clGetDeviceIDs((*platform)[i], CL_DEVICE_TYPE_ALL, numDevices[i], (*device_id)[i], NULL);
		CheckOpenCLError(err, __LINE__);
		for (cl_uint j = 0; j < numDevices[i]; j++) {
			char deviceName[200];
			clGetDeviceInfo((*device_id)[i][j], CL_DEVICE_NAME, sizeof(deviceName), deviceName, NULL);
			printf("---OpenCL:    Device found %d. %s\n", j, deviceName);
			clGetDeviceInfo((*device_id)[i][j], CL_DEVICE_EXTENSIONS, sizeof(deviceInfo), deviceInfo, NULL);
			if (strstr(deviceInfo, "cl_khr_gl_sharing") != NULL) {
				printf("---OpenCL:        cl_khr_gl_sharing supported!\n");
				platformSupportsInterop[i] = 1;
			}
			else {
				printf("---OpenCL:        cl_khr_gl_sharing NOT supported!\n");
				platformSupportsInterop[i] |= 0;
			}
			if (strstr(deviceInfo, "cl_khr_fp64") != NULL) {
				printf("---OpenCL:        cl_khr_fp64 supported!\n");
			}
			else {
				printf("---OpenCL:        cl_khr_fp64 NOT supported!\n");
			}
		}
	}
	printf("\n");


	////////////////////////////////
	// This part is different to how we usually do things. Need to get context and device from existing
	// OpenGL context. Loop through all platforms looking for the device:
	cl_device_id device = NULL;
	int deviceFound = 0;
	cl_uint checkPlatform = 0;

#ifdef TRYINTEROP
	while (!deviceFound) {
		if (platformSupportsInterop[checkPlatform]) {
			printf("---OpenCL: Looking for OpenGL Context device on platform %d ... ", checkPlatform);
			clGetGLContextInfoKHR_fn pclGetGLContextInfoKHR;
			PTR_FUNC_PTR pclGetGLContextInfoKHR = clGetExtensionFunctionAddressForPlatform((*platform)[checkPlatform], "clGetGLContextInfoKHR");
			cl_context_properties properties[] = {
				CL_GL_CONTEXT_KHR, (cl_context_properties) glfwGetGLXContext(render->window),
				CL_GLX_DISPLAY_KHR, (cl_context_properties) glfwGetX11Display(),
				CL_CONTEXT_PLATFORM, (cl_context_properties) (*platform)[checkPlatform],
				0};
			err = pclGetGLContextInfoKHR(properties, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, sizeof(cl_device_id), &device, NULL);
			if (err != CL_SUCCESS) {
				printf("Not Found.\n");
				checkPlatform++;
				if (checkPlatform > numPlatforms-1) {
					printf("---OpenCL: Error! Could not find OpenGL sharing device.\n");
					deviceFound = 1;
					render->glclInterop = 0;
				}
			}
			else {
				printf("Found!\n");
				deviceFound = 1;
				render->glclInterop = 1;
			}
		}
		else {
			checkPlatform++;
		}
	}

	if (render->glclInterop) {
		// Check the device we've found supports double precision
		clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, sizeof(deviceInfo), deviceInfo, NULL);
		if (strstr(deviceInfo, "cl_khr_fp64") == NULL) {
			printf("---OpenCL: Interop device doesn't support double precision! We cannot use it.\n");
		}
		else {
			cl_context_properties properties[] = {
				CL_GL_CONTEXT_KHR, (cl_context_properties) glfwGetGLXContext(render->window),
				CL_GLX_DISPLAY_KHR, (cl_context_properties) glfwGetX11Display(),
				CL_CONTEXT_PLATFORM, (cl_context_properties) (*platform)[checkPlatform],
				0};
			render->contextCL = clCreateContext(properties, 1, &device, NULL, 0, &err);
			CheckOpenCLError(err, __LINE__);
		}
	}
#endif

	// if render->glclInterop is 0, either we are not trying to use it, we couldn't find an interop
	// device, or we found an interop device but it doesn't support double precision.
	// In these cases, have the user choose a platform and device manually.
	if (!(render->glclInterop)) {
		printf("Choose a platform and device.\n");
		checkPlatform = numPlatforms;
		while (checkPlatform >= numPlatforms) {
			printf("Platform: ");
			scanf("%u", &checkPlatform);
			if (checkPlatform >= numPlatforms) {
				printf("Invalid Platform choice.\n");
			}
		}

		cl_uint chooseDevice = numDevices[checkPlatform];
		while (chooseDevice >= numDevices[checkPlatform]) {
			printf("Device: ");
			scanf("%u", &chooseDevice);
			if (chooseDevice >= numDevices[checkPlatform]) {
				printf("Invalid Device choice.\n");
			} else {
				// Check the device we've chosen supports double precision
				clGetDeviceInfo((*device_id)[checkPlatform][chooseDevice], CL_DEVICE_EXTENSIONS, sizeof(deviceInfo), deviceInfo, NULL);
				if (strstr(deviceInfo, "cl_khr_fp64") == NULL) {
					printf("---OpenCL: Interop device doesn't support double precision! We cannot use it.\n");
					chooseDevice = numDevices[checkPlatform];
				}
			}
		}

		// Create non-interop context
		render->contextCL = clCreateContext(NULL, 1, &((*device_id)[checkPlatform][chooseDevice]), NULL, NULL, &err);
		device = (*device_id)[checkPlatform][chooseDevice];
	}
	////////////////////////////////

	// device is now fixed. Query its max global memory allocation size and store it, used in
	// HighResolutionRender routine, to determine into how many tiles we need to split the
	// computation.
	clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(render->deviceMaxAlloc), &(render->deviceMaxAlloc), NULL);
	printf("---OpenCL: Selected device has CL_DEVICE_MAX_MEM_ALLOC_SIZE: %lfMB\n",
	       render->deviceMaxAlloc/1024.0/1024.0);

	// create a command queue
	render->queue = clCreateCommandQueue(render->contextCL, device, 0, &err);
	CheckOpenCLError(err, __LINE__);


	//create the program with the source above
//	printf("Creating CL Program...\n");
	*program = clCreateProgramWithSource(render->contextCL, 1, (const char**)&kernelSource, NULL, &err);
	if (err != CL_SUCCESS) {
		printf("Error in clCreateProgramWithSource: %d, line %d.\n", err, __LINE__);
		return EXIT_FAILURE;
	}

	//build program executable
	err = clBuildProgram(*program, 0, NULL, "-I. -I src/", NULL, NULL);
	if (err != CL_SUCCESS) {
		printf("Error in clBuildProgram: %d, line %d.\n", err, __LINE__);
		char buffer[5000];
		clGetProgramBuildInfo(*program, device, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, NULL);
		printf("%s\n", buffer);
		return EXIT_FAILURE;
	}

	// dump ptx
	size_t binSize;
	clGetProgramInfo(*program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binSize, NULL);
	unsigned char *bin = malloc(binSize);
	clGetProgramInfo(*program, CL_PROGRAM_BINARIES, sizeof(unsigned char *), &bin, NULL);
	FILE *fp = fopen("openclPTX.ptx", "wb");
	fwrite(bin, sizeof(char), binSize, fp);
	fclose(fp);
	free(bin);

	free(numDevices);
	free(kernelSource);
	printf("\n");
	return EXIT_SUCCESS;
}
Exemple #2
0
void init_cl(const char ** sources, int count) {
    int err = CL_SUCCESS;

    // get the platform id for this system
    cl_platform_id platform;
    err = clGetPlatformIDs(1, &platform, NULL);
    cl_check_err(err, "clGetPlatformIDs(...)");

    // connect to the compute device
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device_id, NULL);
    cl_check_err(err, "clGetDeviceIDs(...)");

    // set the platform specific context properties for OpenGL + OpenCL sharing
#ifdef __APPLE__
    cl_context_properties ctx_prop[] = {
        CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
        (cl_context_properties)CGLGetShareGroup(CGLGetCurrentContext()),
        0};

#elif defined __linux__
    cl_context_properties ctx_prop[] = {
        CL_GL_CONTEXT_KHR, (cl_context_properties)glfwGetGLXContext(window),
        CL_GLX_DISPLAY_KHR, (cl_context_properties)glfwGetX11Display(),
        CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
        0};
#elif defined __MINGW32__
    cl_context_properties ctx_prop[] = {
        CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
        CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
        CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
        0};
#endif

    // create the working context
    context = clCreateContext(ctx_prop, 1, &device_id, NULL, NULL, &err);
    cl_check_err(err, "clCreateContext(...)");

    // next up is the command queue
    command_queue = clCreateCommandQueue(context, device_id, 0, &err);
    cl_check_err(err, "clCreateCommandQueue(...)");

    // create a single source buffer for the program from the input files
    size_t length = 0;
    for (int i = 0; i < count; i++) {
        length += file_length(sources[i]);
    }

    char * buffer = (char *)malloc(length);
    buffer[0] = '\0';
    for (int i = 0; i < count; i++) {
        char * tmp = read_file(sources[i]);
        strcat(buffer, tmp);
        free(tmp);
    }

    // create the compute program from 'kernels.cl'
    program = clCreateProgramWithSource(context, 1, (const char **)&buffer, NULL, &err);
    cl_check_err(err, "clCreateProgramWithSource(...)");
    free(buffer); // program already read, we don't need the buffer anymore

    // compile the program for our device
    err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
    cl_check_err(err, "clBuildProgram(...)");

    // create the computer kernel in the program we wish to run
    kernel = clCreateKernel(program, "ray_tracer", &err);
    cl_check_err(err, "clCreateKernel(...)");
}
int main(int argc, char** argv){
  cl_int err;


  // START OPENGL INIT

  Magick::InitializeMagick(argv[0]);
  // start GL context and O/S window using the GLFW helper library
  if (!glfwInit ()) {
    fprintf (stderr, "ERROR: could not start GLFW3\n");
    return 1;
  }
  // Demand OpenGL 4.1
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);

  #ifdef __APPLE__
  // Use Core profile to obtain a context for the latest OpenGL spec.
  // Otherwise we're stuck at 2.1
  std::cout<<"Apple FTW\n";
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  #endif




  window = glfwCreateWindow (WIDTH, HEIGHT, "Hello Triangle", NULL, NULL);
  if (!window) {
    fprintf (stderr, "ERROR: could not open window with GLFW3\n");
    glfwTerminate();
    return 1;
  }
  glfwSetWindowSize( window, WIDTH/2 , HEIGHT/2);

  //glfwWindowHint(GLFW_SAMPLES, 4);
  //glEnable( GL_MULTISAMPLE );

  glfwMakeContextCurrent (window);
  checkGLErr( "glfwMakeContextCurrent" );
  // start GLEW extension handler
  glewExperimental = GL_TRUE;
  glewInit();
  glGetError();
  //checkGLErr( "GLEW init" );



  // END OPENGL INIT..

  // START OPENCL..
  std::vector<cl::Platform> platformList;
  cl::Platform::get(&platformList);

  checkErr(platformList.size()!=0 ? CL_SUCCESS : -1, "cl::Platform::get");

  std::cerr << "Platform number is: " << platformList.size() << std::endl;
  std::string platformVendor;

  platformList[0].getInfo((cl_platform_info)CL_PLATFORM_VENDOR, &platformVendor);
  std::cerr << "Platform is by: " << platformVendor << "\n";

  #ifdef __APPLE__
  CGLContextObj kCGLContext = CGLGetCurrentContext();
  CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
  cl_context_properties cprops[6] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(platformList[0])(),CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE , (cl_context_properties) kCGLShareGroup, 0, 0};
  cl::Context context( CL_DEVICE_TYPE_CPU, cprops, NULL, NULL, &err);
  #endif

  #ifdef __linux__
    cl_platform_id platform;
    err = clGetPlatformIDs(1, &platform, NULL);
    cl_context_properties props[] =
    {
    	CL_GL_CONTEXT_KHR, (cl_context_properties)glfwGetGLXContext( window ),
    	CL_GLX_DISPLAY_KHR, (cl_context_properties)glfwGetX11Display(),
    	CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
    	0
    };
    cl::Context context( CL_DEVICE_TYPE_CPU, props, NULL, NULL, &err);
  //cl::Context context = clCreateContextFromType(props, CL_DEVICE_TYPE_CPU, NULL, NULL, &err);
  #endif


  checkErr(err, "Context::Context()");

  std::cout<<"Created context."<< std::endl;

  // Create shared texture.
  pCLTarget = new RenderTarget( WIDTH, HEIGHT, GL_RGBA , GL_RGBA, GL_FLOAT, 0, false );
  checkGLErr( "RenderTarget::RenderTarget" );
  pAccumulator = new RenderTarget( WIDTH, HEIGHT, GL_RGBA, GL_RGBA, GL_FLOAT, 0, false );
  checkGLErr( "RenderTarget::RenderTarget" );

  const int inSizeS = 3;
  const int inSizeP = 0;
  const int inSizeT = 12;
  const int inSurf = 5;

  /*
  float* outH = new float[inSize];
  cl::Buffer outCL( context, CL_MEM_WRITE_ONLY, inSize * sizeof( float ) );
  */
  Sphere* spheres = new Sphere[inSizeS];
  std::cout<<"Sphere: "<< spheres[0].radius << "\n";
  spheres[1].uSurf = 0;
  spheres[1].center = glm::vec4( 0.0f, -2.0f, 0.0f, 0.0f );
  spheres[1].radius = 1.0f;
  /*spheres[1].uSurf = 0;
  spheres[1].center = glm::vec4( +1.0f, 0.0f, +1.0f, 0.0f);
  spheres[1].radius = 1.0f;*/

  spheres[0].uSurf = 2;
  spheres[0].center = glm::vec4( 0.0f, +1.50f, 0.0f, 0.0f);
  spheres[0].radius = 0.2f;

  /*spheres[2].uSurf = 0;
  spheres[2].center = glm::vec4( +0.0f, 0.0f, -0.0f, 0.0f);
  spheres[2].radius = 1.0f;*/

  spheres[2].uSurf = 0;
  spheres[2].center = glm::vec4( -2.0f, -2.0f, -2.0f, 0.0f);
  spheres[2].radius = 1.0f;

  /*spheres[4].uSurf = 0;
  spheres[4].center = glm::vec4( -1.0f, -0.0f, +1.0f, 0.0f);
  spheres[4].radius = 1.0f;*/
  Plane* planes = new Plane[inSizeP];
  int planeSize = 3.0f;
  //std::cout<<"Sphere: "<< planes[0].radius << "\n";
  /*planes[0].normal = glm::vec4( 0.0f, 1.0f, 0.0f, 0.0f );
  planes[0].point = glm::vec4( 0.0f, -planeSize, 0.0f, 0.0f );
  planes[0].uSurf = 1;
  
  planes[1].normal = glm::vec4( 0.0f, -1.0f, 0.0f, 0.0f );
  planes[1].point = glm::vec4( 0.0f, planeSize, 0.0f, 0.0f );
  planes[1].uSurf = 1;
  
  planes[2].normal = glm::vec4( 1.0f, 0.0f, 0.0f, 0.0f );
  planes[2].point = glm::vec4( -planeSize, 0.0f, 0.0f, 0.0f );
  planes[2].uSurf = 1;
  
  planes[3].normal = glm::vec4( -1.0f, 0.0f, 0.0f, 0.0f );
  planes[3].point = glm::vec4( planeSize, 0.0f, 0.0f, 0.0f );
  planes[3].uSurf = 1;
  
  planes[4].normal = glm::vec4( 0.0f, 0.0f, +1.0f, +0.0f );
  planes[4].point = glm::vec4( 0.0f, 0.0f, -planeSize, 0.0f );
  planes[4].uSurf = 1;
  
  planes[5].normal = glm::vec4( 0.0f, 0.0f, -1.0f, 0.0f );
  planes[5].point = glm::vec4( 0.0f, 0.0f, +planeSize, 0.0f );
  planes[5].uSurf = 1;*/
  
  

  Triangle* triangles = new Triangle[inSizeT];
  //std::cout<<"Sphere: "<< spheres[0].radius << "\n";
  float boxSize = 3.0f;
  triangles[0].uSurf = 1;
  triangles[0].p0 = glm::vec4( -boxSize, -boxSize, -boxSize, 0.0f);
  triangles[0].p1 = glm::vec4( -boxSize, boxSize, -boxSize, 0.0f);
  triangles[0].p2 = glm::vec4( -boxSize, -boxSize, boxSize, 0.0f);
  
  triangles[1].uSurf = 1;
  triangles[1].p0 = glm::vec4( -boxSize, boxSize, boxSize, 0.0f);
  triangles[1].p2 = glm::vec4( -boxSize, boxSize, -boxSize, 0.0f);
  triangles[1].p1 = glm::vec4( -boxSize, -boxSize, boxSize, 0.0f);
  
  triangles[2].uSurf = 1;
  triangles[2].p0 = glm::vec4( boxSize, -boxSize, -boxSize, 0.0f);
  triangles[2].p2 = glm::vec4( boxSize, boxSize, -boxSize, 0.0f);
  triangles[2].p1 = glm::vec4( boxSize, -boxSize, boxSize, 0.0f);
  
  triangles[3].uSurf = 1;
  triangles[3].p0 = glm::vec4( boxSize, boxSize, boxSize, 0.0f);
  triangles[3].p1 = glm::vec4( boxSize, boxSize, -boxSize, 0.0f);
  triangles[3].p2 = glm::vec4( boxSize, -boxSize, boxSize, 0.0f);
  

  triangles[4].uSurf = 1;
  triangles[4].p0 = glm::vec4( -boxSize, -boxSize, -boxSize, 0.0f);
  triangles[4].p2 = glm::vec4( boxSize, -boxSize, -boxSize, 0.0f);
  triangles[4].p1 = glm::vec4( -boxSize, -boxSize, boxSize, 0.0f);
  
  triangles[5].uSurf = 1;
  triangles[5].p0 = glm::vec4( boxSize, -boxSize, boxSize, 0.0f);
  triangles[5].p1 = glm::vec4( boxSize, -boxSize, -boxSize, 0.0f);
  triangles[5].p2 = glm::vec4( -boxSize, -boxSize, boxSize, 0.0f);
  
  triangles[6].uSurf = 1;
  triangles[6].p0 = glm::vec4( -boxSize, boxSize, -boxSize, 0.0f);
  triangles[6].p1 = glm::vec4( boxSize, boxSize, -boxSize, 0.0f);
  triangles[6].p2 = glm::vec4( -boxSize, boxSize, boxSize, 0.0f);
  
  triangles[7].uSurf = 1;
  triangles[7].p0 = glm::vec4( boxSize, boxSize, boxSize, 0.0f);
  triangles[7].p2 = glm::vec4( boxSize, boxSize, -boxSize, 0.0f);
  triangles[7].p1 = glm::vec4( -boxSize, boxSize, boxSize, 0.0f);
  
  triangles[8].uSurf = 3;
  triangles[8].p0 = glm::vec4( -boxSize, -boxSize, -boxSize, 0.0f);
  triangles[8].p1 = glm::vec4( boxSize, -boxSize, -boxSize, 0.0f);
  triangles[8].p2 = glm::vec4( -boxSize, boxSize, -boxSize, 0.0f);
  
  triangles[9].uSurf = 3;
  triangles[9].p0 = glm::vec4( boxSize, boxSize, -boxSize, 0.0f);
  triangles[9].p2 = glm::vec4( boxSize, -boxSize, -boxSize, 0.0f);
  triangles[9].p1 = glm::vec4( -boxSize, boxSize, -boxSize, 0.0f);
  
  triangles[10].uSurf = 4;
  triangles[10].p0 = glm::vec4( -boxSize, -boxSize, boxSize, 0.0f);
  triangles[10].p2 = glm::vec4( boxSize, -boxSize, boxSize, 0.0f);
  triangles[10].p1 = glm::vec4( -boxSize, boxSize, boxSize, 0.0f);
  
  triangles[11].uSurf = 4;
  triangles[11].p0 = glm::vec4( boxSize, boxSize, boxSize, 0.0f);
  triangles[11].p1 = glm::vec4( boxSize, -boxSize, boxSize, 0.0f);
  triangles[11].p2 = glm::vec4( -boxSize, boxSize, boxSize, 0.0f);
  
  /*triangles[12].uSurf = 1;
  triangles[12].p0 = glm::vec4( -boxSize/4.0f, boxSize, -boxSize/4.0f, 0.0f);
  triangles[12].p1 = glm::vec4( boxSize/4.0f, boxSize, -boxSize/4.0f, 0.0f);
  triangles[12].p2 = glm::vec4( -boxSize/4.0f, boxSize, boxSize/4.0f, 0.0f);
  
  triangles[13].uSurf = 1;
  triangles[13].p0 = glm::vec4( boxSize/4.0f, boxSize, boxSize/4.0f, 0.0f);
  triangles[13].p2 = glm::vec4( boxSize/4.0f, boxSize, -boxSize/4.0f, 0.0f);
  triangles[13].p1 = glm::vec4( -boxSize/4.0f, boxSize, boxSize/4.0f, 0.0f);*/
  
  
  

  GeometryDescriptor* geometry = new GeometryDescriptor( inSizeS, inSizeP, inSizeT );

  Surface* pSurf = new Surface[inSurf];
  pSurf[0].vColor = glm::vec4( 1.0f, 1.0f, 0.0f, 1.0f );
  
  pSurf[1].vColor = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f );
  
  pSurf[2].vColor = glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f );
  float lPower = 5.0f;
  pSurf[2].vEmissive = glm::vec4( lPower, lPower, lPower, lPower );
  
  pSurf[3].vColor = glm::vec4( 1.0f, 0.0f, 0.0f, 1.0f );
  
  pSurf[4].vColor = glm::vec4( 0.0f, 1.0f, 0.0f, 1.0f );

  cl::Buffer clSpheres( context, CL_MEM_READ_ONLY, inSizeS * sizeof( Sphere ));
  checkErr(err, "Buffer::Buffer()");

  cl::Buffer clPlanes( context, CL_MEM_READ_ONLY, inSizeP * sizeof( Plane ) );
  checkErr(err, "Buffer::Buffer()");

  cl::Buffer clTriangles( context, CL_MEM_READ_ONLY, inSizeT * sizeof( Triangle ) );
  checkErr(err, "Buffer::Buffer()");

  cl::Buffer clCamera( context, CL_MEM_READ_ONLY, 1 * sizeof( CLCamera ) );
  checkErr(err, "Buffer::Buffer()");

  cl::Buffer clGeom( context, CL_MEM_READ_ONLY, 1 * sizeof( GeometryDescriptor ) );
  checkErr(err, "Buffer::Buffer()");

  cl::Buffer clImgDesc( context, CL_MEM_READ_ONLY, 1 * sizeof( ImageDescriptor ) );
  checkErr(err, "Buffer::Buffer()");

  cl::Buffer clSeed( context, CL_MEM_READ_WRITE, WIDTH * HEIGHT * 4 * sizeof( uint ) );
  checkErr(err, "Buffer::Buffer()");

  cl::Buffer clSurf( context, CL_MEM_READ_WRITE, inSurf * sizeof( Surface ) );
  checkErr(err, "Buffer::Buffer()");

  cl::ImageGL imgGL( context, CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, pCLTarget->getColorTexture()->glGetInternalTexture(), &err );
  checkErr(err, "ImageGL::ImageGL()");

  cl::ImageGL accGL( context, CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, pAccumulator->getColorTexture()->glGetInternalTexture(), &err );
  checkErr(err, "ImageGL::ImageGL()");

  std::cout<<"Created buffers."<< std::endl;

  srand( time( NULL ) );
  uint *pSeeds = new uint[WIDTH * HEIGHT * 4];
  for( int i = 0; i < WIDTH * HEIGHT * 4; i++ ){
    pSeeds[i] = rand();
  }

  std::vector<cl::Device> devices;
  devices = context.getInfo<CL_CONTEXT_DEVICES>();
  checkErr(devices.size() > 0 ? CL_SUCCESS : -1, "devices.size() > 0");

  std::cout<<"Num available devices: "<< devices.size()<< std::endl;

  std::ifstream file("src/kernel/kernel0.cl");
  checkErr(file.is_open() ? CL_SUCCESS:-1, "src/kernel/kernel0.cl");
  std::string prog( std::istreambuf_iterator<char>(file), (std::istreambuf_iterator<char>()));

  cl::Program::Sources source(1, std::make_pair(prog.c_str(), prog.length()+1));

  std::cout<<"Source obtained."<< std::endl;
  
  cl::Program program(context, source);
  err = program.build(devices,"-cl-opt-disable");
  std::cout<<"Source obtained."<< std::endl;

  std::string buildLog;
  program.getBuildInfo( devices[0], CL_PROGRAM_BUILD_LOG, &buildLog );
  std::cout<<"Build log:" << buildLog<< std::endl;
  checkErr(err, "Program::build()");
  std::cout<<"Built program"<< std::endl;

  cl::Kernel kernel(program, "bi_directional_path_trace", &err);
  checkErr(err, "Kernel::Kernel()");

  err = kernel.setArg(0, clCamera);
  checkErr(err, "Kernel::setArg()");
  err = kernel.setArg(1, imgGL);
  checkErr(err, "Kernel::setArg()");
  err = kernel.setArg(2, accGL);
  checkErr(err, "Kernel::setArg()");

  err = kernel.setArg(3, clSpheres);
  checkErr(err, "Kernel::setArg()");
  err = kernel.setArg(4, clPlanes);
  checkErr(err, "Kernel::setArg()");
  err = kernel.setArg(5, clTriangles);
  checkErr(err, "Kernel::setArg()");
  err = kernel.setArg(6, clGeom);
  checkErr(err, "Kernel::setArg()");
  err = kernel.setArg(7, clImgDesc);
  checkErr(err, "Kernel::setArg()");
  err = kernel.setArg(8, clSeed);
  checkErr(err, "Kernel::setArg()");
  err = kernel.setArg(9, clSurf);
  checkErr(err, "Kernel::setArg()");

  std::cout<<"Built Kernel"<< std::endl;

  pCamera = new ModelCamera( window );
  pCamera->setSpeedX( 0.03f );
  pCamera->setSpeedY( 0.03f );

  pCamera->setRadius( 8.0f );
  pCamera->setOrientation( glm::vec3( 0.0f, -1.0f, 0.0f ) );
  pCamera->reset( glm::vec3( 1.0f, 0.1f, -0.1f ) );


  cl::CommandQueue queue(context, devices[0], 0, &err);
  checkErr(err, "CommandQueue::CommandQueue()");
  CLCamera* cam = pCamera->getCLCamera();

  std::cout<<cam->vPos.x<<","<<cam->vPos.y<<","<<cam->vPos.z<<std::endl;

  std::cout<<cam->vLookAt.x<<","<<cam->vLookAt.y<<","<<cam->vLookAt.z<<std::endl;

  std::cout<<cam->vUp.x<<","<<cam->vUp.y<<","<<cam->vUp.z<<std::endl;

  std::cout<< sizeof( Plane )<< std::endl;
  queue.enqueueWriteBuffer( clCamera, CL_TRUE, 0, 1 * sizeof(CLCamera), (const void*)cam );
  queue.enqueueWriteBuffer( clSpheres, CL_TRUE, 0, inSizeS * sizeof(Sphere), (const void*)spheres);
  queue.enqueueWriteBuffer( clPlanes, CL_TRUE, 0, inSizeP * sizeof(Plane), (const void*)planes);
  queue.enqueueWriteBuffer( clTriangles, CL_TRUE, 0, inSizeT * sizeof(Triangle), (const void*)triangles);
  queue.enqueueWriteBuffer( clGeom, CL_TRUE, 0, 1 * sizeof(GeometryDescriptor), (const void*)geometry);
  queue.enqueueWriteBuffer( clSeed, CL_TRUE, 0, WIDTH * HEIGHT * 4 * sizeof(uint), (const void*)pSeeds);
  queue.enqueueWriteBuffer( clSurf, CL_TRUE, 0, inSurf * sizeof(Surface), (const void*)pSurf);

  vSharedUnits = new std::vector<cl::Memory>();
  vSharedUnits->push_back( imgGL );
  vSharedUnits->push_back( accGL );

  //Initialise counter.
  imgDesc.numSamples = 0;
  imgDesc.sampleRate = SAMPLES;
  cLast = clock();
  while( !glfwWindowShouldClose( window ) ){
    //usleep( 1000000 );
    mainLoop( queue, context, kernel, clImgDesc, clCamera );
  }

  /* Previous Program. Remove these if you think they are not required.
  float *fout = new float[inSize];
  err = queue.enqueueReadBuffer( clSpheres, CL_TRUE, 0, inSize * sizeof(Sphere), fout);
  */
  checkErr(err, "ComamndQueue::enqueueReadBuffer()");

  std::cout<<"Kernel finished executing."<< std::endl;

  delete vSharedUnits;
  return EXIT_SUCCESS;
}