Moisés Viñas Buceta

Start

cl::CommandQueue* commandqueue;
cl::Program* program;
cl::Kernel* kernel;
cl::Context* context;
cl::Device* device;

std::map< KeyProgramMap,cl::Device* > devices; ///< Map of devices found in the context.
std::map< KeyProgramMap,cl::CommandQueue* > queues; ///< Map of commandQueues.
std::map< KeyProgramMap,cl::Context* > contexts; ///< Map of contexts created, one by device.
std::map< KeyDevicesMap,int > devices_number;

void check_device(int platform_id, cl_device_type device_type, int device, 
					int* p_id_out, cl_device_type * d_t_out, int* d_d_out)
{
  cl::Device* d = devices[KeyProgramMap(platform_id, device_type, device)];
  if(d) {
    *p_id_out = platform_id;
    *d_t_out = device_type;
    *d_d_out = device;
    return;
  }
  
  for(int i = 0; i < MAX_PLATFORMS; i++)
  {
  	d = devices[KeyProgramMap(i, device_type, device)];
  	if(d) {
  		std::cout << "Info: Changing device to on " << PlatformName[i] <<
  				((device_type == CL_DEVICE_TYPE_GPU) ? " GPU#": " CPU#") <<
  				device << std::endl;

  		*p_id_out = i;
  		*d_t_out = device_type;
  		*d_d_out = device;
  		return;
  	}
  }
  
  d = devices[KeyProgramMap(NVIDIA, CL_DEVICE_TYPE_GPU, 0)];
  if(d) {
    if((device_type != CL_DEVICE_TYPE_GPU) && (device_type != CL_DEVICE_TYPE_CPU))
    {
    	std::cout << "The device type is not valid!" << std::endl;
    	exit(-1);
    }

    std::cout << "Info: Changing device to on NVIDIA GPU#0." << std::endl;
    *p_id_out = NVIDIA;
    *d_t_out = CL_DEVICE_TYPE_GPU;
    *d_d_out = 0;
    return;
  }

  d = devices[KeyProgramMap(AMD, CL_DEVICE_TYPE_GPU, 0)];
  if(d) {
	  std::cout << "Info: Changing device to on AMD GPU#0." << std::endl;
    *p_id_out = AMD;
    *d_t_out = CL_DEVICE_TYPE_GPU;
    *d_d_out = 0;
    return;
  }

  d = devices[KeyProgramMap(INTEL, CL_DEVICE_TYPE_CPU, 0)];
  if(d) {
	  std::cout << "Info: Changing device to on Intel CPU#0." << std::endl;
    *p_id_out = INTEL;
    *d_t_out = CL_DEVICE_TYPE_CPU;
    *d_d_out = 0;
    return;
  }

  d = devices[KeyProgramMap(INTEL, CL_DEVICE_TYPE_GPU, 0)];
  if(d) {
	std::cout << "Info: Changing device to on Intel GPU#0." << std::endl;
    *p_id_out = INTEL;
    *d_t_out = CL_DEVICE_TYPE_GPU;
    *d_d_out = 0;
    return;
  }

  d = devices[KeyProgramMap(APPLE, CL_DEVICE_TYPE_GPU, 0)];
  if(d) {
	  std::cout << "Info: Changing device to on Apple GPU#0." << std::endl;
    *p_id_out = APPLE;
    *d_t_out = CL_DEVICE_TYPE_GPU;
    *d_d_out = 0;
    return;
  }

  d = devices[KeyProgramMap(APPLE, CL_DEVICE_TYPE_CPU, 0)];
  if(d) {
    std::cout << "Info: Changing device to on Apple CPU#0." << std::endl;
    *p_id_out = APPLE;
    *d_t_out = CL_DEVICE_TYPE_CPU;
    *d_d_out = 0;
    return;
  }

  d = devices[KeyProgramMap(AMD, CL_DEVICE_TYPE_CPU, 0)];
  if (d) {
    std::cout << "Info: Changing device to on AMD CPU#0." << std::endl;
    *p_id_out = AMD;
    *d_t_out = CL_DEVICE_TYPE_CPU;
    *d_d_out = 0;
    return;
  }

  std::cout << "The device was not identified!\n" << std::endl;
  exit(-1);
}

void platform_init()
{
	cl_int err;

	std::vector< cl::Platform > platforms;
	err = cl::Platform::get(&platforms);
	if(err != CL_SUCCESS) {
		std::cout << "Error: "<< err << 
			", in platform_init: Platform::get() failed" << std::endl;
		exit(0);
	}

	std::vector< cl::Device > CPU_devices_aux;
	std::vector< cl::Device > GPU_devices_aux;

	cl::STRING_CLASS platform_name;
	cl::STRING_CLASS device_vendor;
	int platform_id = 0, match_cpus = 0, match_gpus = 0, 
		cleared_cpus = 0, cleared_gpus = 0;

	for(int i = 0; i < platforms.size(); i++)
	{
		CPU_devices_aux.clear();
		GPU_devices_aux.clear();
		cl_context_properties cps[3] = {
				CL_CONTEXT_PLATFORM,
				(cl_context_properties)(platforms[i])(),
				0
		};

		platforms[i].getInfo(CL_PLATFORM_NAME, &platform_name);
		platform_id = string_to_platform_id(platform_name);

		err = platforms[i].getDevices(CL_DEVICE_TYPE_CPU, &CPU_devices_aux);
		err |= platforms[i].getDevices(CL_DEVICE_TYPE_GPU, &GPU_devices_aux);

		if(err != CL_SUCCESS)
		{
			std::cout << "Error: " << err << 
				", in platform_init: Platform::getDevices() No device available" << std::endl;
		}

		if(match_gpus > 0)
			for(int j = 0; j < GPU_devices_aux.size(); j++) {
				GPU_devices_aux[j].getInfo< cl::STRING_CLASS >(CL_DEVICE_VENDOR, &device_vendor);

				if(!match_platform_device(platform_name, device_vendor))
				{
					GPU_devices_aux.erase(GPU_devices_aux.begin()+j);
					j=j-1;
				}
				else
				{
					if(cleared_gpus) continue;
					for(int m = 0; m < MAX_PLATFORMS; m++)
					{
						if(devices_number[KeyDevicesMap(m,CL_DEVICE_TYPE_GPU)]==0) continue;

						KeyProgramMap kp(m,CL_DEVICE_TYPE_GPU,0);
						cl::Device* d = devices[kp];
						std::string dev_vendor_aux;
						d->getInfo< cl::STRING_CLASS >(CL_DEVICE_VENDOR, &dev_vendor_aux);
						bool match = match_platform_device(PlatformName[m], dev_vendor_aux);
						if(!match)
						{
							for(int  k = 0; k < devices_number[KeyDevicesMap(m,CL_DEVICE_TYPE_GPU)]; k++)
							{
								KeyProgramMap kp(m,CL_DEVICE_TYPE_GPU,k);
								cl::Device* d = devices[kp];
								cl::Context* c = contexts[kp];
								cl::CommandQueue* q = queues[kp];
								delete c;
								contexts.erase(kp);
								delete d;
								devices.erase(kp);
								delete q;
								queues.erase(kp);
							}
							cleared_gpus = 1;
							devices_number[KeyDevicesMap(m,CL_DEVICE_TYPE_GPU)] = 0;
						}
					}
				}
			}

		if(match_cpus > 0)
			for(int j = 0; j < CPU_devices_aux.size(); j++) {
				CPU_devices_aux[j].getInfo< cl::STRING_CLASS >(CL_DEVICE_VENDOR, &device_vendor);
				if(!match_platform_device(platform_name, device_vendor))
				{
					CPU_devices_aux.erase(CPU_devices_aux.begin()+j);
					j=j-1;
				}
				else
				{
					if(cleared_cpus) continue;
					for(int m = 0; m < MAX_PLATFORMS; m++)
					{
						if(devices_number[KeyDevicesMap(m,CL_DEVICE_TYPE_CPU)]==0) continue;

						KeyProgramMap kp(m,CL_DEVICE_TYPE_CPU,0);
						cl::Device* d = devices[kp];
						std::string dev_vendor_aux;
						d->getInfo< cl::STRING_CLASS >(CL_DEVICE_VENDOR, &dev_vendor_aux);
						bool match = match_platform_device(PlatformName[m], dev_vendor_aux);
						if(!match)
						{
							for(int  k = 0; k < devices_number[KeyDevicesMap(m,CL_DEVICE_TYPE_CPU)]; k++)
							{
								KeyProgramMap kp(m,CL_DEVICE_TYPE_CPU,k);
								cl::Device* d = devices[kp];
								cl::Context* c = contexts[kp];
								cl::CommandQueue* q = queues[kp];
								delete c;
								contexts.erase(kp);
								delete d;
								devices.erase(kp);
								delete q;
								queues.erase(kp);
							}
							cleared_cpus = 1;
							devices_number[KeyDevicesMap(m,CL_DEVICE_TYPE_CPU)] = 0;
						}
					}
				}
			}

		for(int j = 0; j < GPU_devices_aux.size(); j++) {
			std::vector< cl::Device > device(1,GPU_devices_aux[j]);
			contexts[KeyProgramMap(platform_id,CL_DEVICE_TYPE_GPU,j)] =
					new cl::Context(device, cps, NULL, NULL, &err);
			if (err != CL_SUCCESS) {
				std::cout << "Context() failed for GPU and CPU" << std::endl;
			}
		}

		for(int j = 0; j < CPU_devices_aux.size(); j++) {
			std::vector< cl::Device > device(1,CPU_devices_aux[j]);
			contexts[KeyProgramMap(platform_id,CL_DEVICE_TYPE_CPU,j)] =
					new cl::Context(device, cps, NULL, NULL, &err);
			if (err != CL_SUCCESS) {
				std::cout << "Context::Context() failed for GPU and CPU \n" << std::endl;
			}
		}

		for(int j = 0; j < GPU_devices_aux.size(); j++)
		{
			KeyProgramMap kp(platform_id,CL_DEVICE_TYPE_GPU,j);
			devices[kp] = new cl::Device((GPU_devices_aux[j]));
			queues[kp] = new cl::CommandQueue(*(contexts[kp]), *(devices[kp]), 0, &err);
		}

		for(int j = 0; j < CPU_devices_aux.size(); j++)
		{
			KeyProgramMap kp(platform_id,CL_DEVICE_TYPE_CPU,j);
			devices[kp] = new cl::Device((CPU_devices_aux[j]));
 			queues[kp] = new cl::CommandQueue(*(contexts[kp]), *(devices[kp]), 0, &err);
		}

		devices_number[KeyDevicesMap(platform_id,CL_DEVICE_TYPE_GPU)] = GPU_devices_aux.size();
		devices_number[KeyDevicesMap(platform_id,CL_DEVICE_TYPE_CPU)] = CPU_devices_aux.size();
		if(GPU_devices_aux.size()>0) match_gpus = 1;
		if(CPU_devices_aux.size()>0) match_cpus = 1;

	}

	if (err != CL_SUCCESS) {
		std::cout << "CommandQueue::CommandQueue() failed" << std::endl;
	}
}

void build_program(const char* kernel_name)
{
	cl_int err;
	cl::Program::Sources *sources;

	std::ifstream sourceFile;

	sourceFile.open("kernel.cl");
	if( sourceFile.is_open() == false ) {
		std::cout << "Error: "<< err << ", in build_program: The CL source code could not be load" << std::endl;
		return;
	}

	std::string *sourceCode = new std::string(std::istreambuf_iterator< char >(sourceFile),
			(std::istreambuf_iterator< char >()));
	sources = new cl::Program::Sources(1, std::make_pair(sourceCode->c_str(), sourceCode->length()+1));

	program = new cl::Program(*(context), *sources, &err);

	if (err != CL_SUCCESS) {
		std::cout << "Error: " << err << ", in build_program: Program::Program() failed" << std::endl;
		return;
	}

	std::vector< cl::Device > devices_aux;
	devices_aux.push_back(*(device));

	err = program->build(devices_aux);

	if (err != CL_SUCCESS) {
		if(err == CL_BUILD_PROGRAM_FAILURE) {
			cl::STRING_CLASS str = program->getBuildInfo< CL_PROGRAM_BUILD_LOG >(*(device));
			std::cout << " \n\t\t\tBUILD LOG\n";
			std::cout << " ************************************************\n";
			std::cout << str.c_str() << std::endl;
			std::cout << " ************************************************\n";
			std::cout << "Error: " << err << ", in build_program: Program::build() failed" << std::endl;
		}
		if(err != CL_INVALID_BINARY)
		{
			std::cout << "Error: " << err << ", in build_program: Program::build() failed" << std::endl;
		}
	}

	kernel = new cl::Kernel(*(program), kernel_name, &err);

	if (err != CL_SUCCESS) {
		std::cout << "Error: " << err << ", in build_program: Kernel::kernel() failed" << std::endl;
		return;
	}

}