blob: ac895311508a574e0a04609860013979cec9943c [file] [log] [blame]
//TODO: copyrights
#include "device.h"
#include "buffer.h"
#include "kernel.h"
#include "program.h"
#include "worker.h"
#include "builtins.h"
#include "propertylist.h"
#include "commandqueue.h"
#include "events.h"
#include "memobject.h"
#include "Thread.hpp"
#include "CPUID.hpp"
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace Devices;
CPUDevice::CPUDevice()
: DeviceInterface(), p_num_events(0), p_stop(false), initialized(false)
{
}
void CPUDevice::init()
{
// Initialize the locking machinery
p_events_cond = new sw::Event();
//TODO CHANGE pcore value to real
p_cpu_mhz = 3200;
// Create worker threads
for(unsigned int i = 0; i < sw::CPUID::coreCount(); ++i)
{
p_workers[i] = new sw::Thread(worker, this);
}
initialized = true;
}
CPUDevice::~CPUDevice()
{
if(!initialized)
return;
p_events_cond->signal();
p_stop = true;
delete p_events_cond;
for(int thread = 0; thread < sw::CPUID::coreCount(); thread++)
{
if(p_workers[thread])
{
p_workers[thread]->join();
delete p_workers[thread];
p_workers[thread] = 0;
}
}
}
DeviceBuffer *CPUDevice::createDeviceBuffer(MemObject *buffer, cl_int *rs)
{
return (DeviceBuffer *)new CPUBuffer(this, buffer, rs);
}
DeviceProgram *CPUDevice::createDeviceProgram(Program *program)
{
return (DeviceProgram *)new CPUProgram(this, program);
}
DeviceKernel *CPUDevice::createDeviceKernel(Kernel *kernel,
llvm::Function *function)
{
return (DeviceKernel *)new CPUKernel(this, kernel, function);
}
cl_int CPUDevice::initEventDeviceData(Event *event)
{
switch(event->type())
{
case Event::MapBuffer:
{
MapBufferEvent *e = (MapBufferEvent *)event;
CPUBuffer *buf = (CPUBuffer *)e->buffer()->deviceBuffer(this);
unsigned char *data = (unsigned char *)buf->data();
data += e->offset();
e->setPtr((void *)data);
break;
}
case Event::MapImage:
{
MapImageEvent *e = (MapImageEvent *)event;
Image2D *image = (Image2D *)e->buffer();
CPUBuffer *buf = (CPUBuffer *)image->deviceBuffer(this);
unsigned char *data = (unsigned char *)buf->data();
data = imageData(data,
e->origin(0),
e->origin(1),
e->origin(2),
image->row_pitch(),
image->slice_pitch(),
image->pixel_size());
e->setPtr((void *)data);
e->setRowPitch(image->row_pitch());
e->setSlicePitch(image->slice_pitch());
break;
}
case Event::UnmapMemObject:
// Nothing do to
break;
case Event::NDRangeKernel:
case Event::TaskKernel:
{
//TODO
// Instantiate the JIT for the CPU program
KernelEvent *e = (KernelEvent *)event;
//Program *p = (Program *)e->kernel()->parent();
//CPUProgram *prog = (CPUProgram *)p->deviceDependentProgram(this);
/*if(!prog->initJIT())
return CL_INVALID_PROGRAM_EXECUTABLE;*/
// Set device-specific data
CPUKernelEvent *cpu_e = new CPUKernelEvent(this, e);
e->setDeviceData((void *)cpu_e);
break;
}
default:
break;
}
return CL_SUCCESS;
}
void CPUDevice::freeEventDeviceData(Event *event)
{
switch(event->type())
{
case Event::NDRangeKernel:
case Event::TaskKernel:
{
CPUKernelEvent *cpu_e = (CPUKernelEvent *)event->deviceData();
if(cpu_e)
delete cpu_e;
}
default:
break;
}
}
void CPUDevice::pushEvent(Event *event)
{
eventListResource.lock();
p_events.push_back(event);
p_num_events++;
p_events_cond->signal();
eventListResource.unlock();
}
Event *CPUDevice::getEvent(bool &stop)
{
// Return the first event in the list, if any. Remove it if it is a
// single-shot event.
while(p_num_events == 0 && !p_stop)
p_events_cond->wait();
eventListResource.lock();
if(p_stop)
{
eventListResource.unlock();
stop = true;
return 0;
}
Event *event = p_events.front();
// If the run of this event will finish it, remove it from the list
bool last_slot = true;
if(event->type() == Event::NDRangeKernel ||
event->type() == Event::TaskKernel)
{
CPUKernelEvent *ke = (CPUKernelEvent *)event->deviceData();
last_slot = ke->reserve();
}
if(last_slot)
{
p_num_events--;
p_events.pop_front();
}
eventListResource.unlock();
return event;
}
float CPUDevice::cpuMhz() const
{
return p_cpu_mhz;
}
// From inner parentheses to outher ones :
//
// sizeof * 8 => 8
// -1 => 7
// 1 << $ => 10000000
// -1 => 01111111
// *2 => 11111110
// +1 => 11111111
//
// A simple way to do this is (1 << (sizeof(type) * 8)) - 1, but it overflows
// the type (for int8, 1 << $ = 100000000 = 256 > 255)
#define TYPE_MAX(type) ((((type)1 << ((sizeof(type) * 8) - 1)) - 1) * 2 + 1)
cl_int CPUDevice::info(cl_device_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret) const
{
void *value = 0;
size_t value_length = 0;
union {
cl_device_type cl_device_type_var;
cl_uint cl_uint_var;
size_t size_t_var;
cl_ulong cl_ulong_var;
cl_bool cl_bool_var;
cl_device_fp_config cl_device_fp_config_var;
cl_device_mem_cache_type cl_device_mem_cache_type_var;
cl_device_local_mem_type cl_device_local_mem_type_var;
cl_device_exec_capabilities cl_device_exec_capabilities_var;
cl_command_queue_properties cl_command_queue_properties_var;
cl_platform_id cl_platform_id_var;
size_t work_dims[MAX_WORK_DIMS];
};
switch(param_name)
{
case CL_DEVICE_TYPE:
SIMPLE_ASSIGN(cl_device_type, CL_DEVICE_TYPE_CPU);
break;
case CL_DEVICE_VENDOR_ID:
SIMPLE_ASSIGN(cl_uint, 0);
break;
case CL_DEVICE_MAX_COMPUTE_UNITS:
SIMPLE_ASSIGN(cl_uint, sw::CPUID::coreCount());
break;
case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:
SIMPLE_ASSIGN(cl_uint, MAX_WORK_DIMS);
break;
case CL_DEVICE_MAX_WORK_GROUP_SIZE:
SIMPLE_ASSIGN(size_t, TYPE_MAX(size_t));
break;
case CL_DEVICE_MAX_WORK_ITEM_SIZES:
for(int i = 0; i<MAX_WORK_DIMS; ++i)
{
work_dims[i] = TYPE_MAX(size_t);
}
value_length = MAX_WORK_DIMS * sizeof(size_t);
value = &work_dims;
break;
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:
SIMPLE_ASSIGN(cl_uint, 16);
break;
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:
SIMPLE_ASSIGN(cl_uint, 8);
break;
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:
SIMPLE_ASSIGN(cl_uint, 4);
break;
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:
SIMPLE_ASSIGN(cl_uint, 2);
break;
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:
SIMPLE_ASSIGN(cl_uint, 4);
break;
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:
SIMPLE_ASSIGN(cl_uint, 2);
break;
case CL_DEVICE_MAX_CLOCK_FREQUENCY:
SIMPLE_ASSIGN(cl_uint, cpuMhz() * 1000000);
break;
case CL_DEVICE_ADDRESS_BITS:
SIMPLE_ASSIGN(cl_uint, 32);
break;
case CL_DEVICE_MAX_READ_IMAGE_ARGS:
SIMPLE_ASSIGN(cl_uint, 65536);
break;
case CL_DEVICE_MAX_WRITE_IMAGE_ARGS:
SIMPLE_ASSIGN(cl_uint, 65536);
break;
case CL_DEVICE_MAX_MEM_ALLOC_SIZE:
SIMPLE_ASSIGN(cl_ulong, 128 * 1024 * 1024);
break;
case CL_DEVICE_IMAGE2D_MAX_WIDTH:
SIMPLE_ASSIGN(size_t, 65536);
break;
case CL_DEVICE_IMAGE2D_MAX_HEIGHT:
SIMPLE_ASSIGN(size_t, 65536);
break;
case CL_DEVICE_IMAGE3D_MAX_WIDTH:
SIMPLE_ASSIGN(size_t, 65536);
break;
case CL_DEVICE_IMAGE3D_MAX_HEIGHT:
SIMPLE_ASSIGN(size_t, 65536);
break;
case CL_DEVICE_IMAGE3D_MAX_DEPTH:
SIMPLE_ASSIGN(size_t, 65536);
break;
case CL_DEVICE_IMAGE_SUPPORT:
SIMPLE_ASSIGN(cl_bool, CL_TRUE);
break;
case CL_DEVICE_MAX_PARAMETER_SIZE:
SIMPLE_ASSIGN(size_t, 65536);
break;
case CL_DEVICE_MAX_SAMPLERS:
SIMPLE_ASSIGN(cl_uint, 16);
break;
case CL_DEVICE_MEM_BASE_ADDR_ALIGN:
SIMPLE_ASSIGN(cl_uint, 0);
break;
case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:
SIMPLE_ASSIGN(cl_uint, 16);
break;
case CL_DEVICE_SINGLE_FP_CONFIG:
// TODO: Check what an x86 SSE engine can support.
SIMPLE_ASSIGN(cl_device_fp_config,
CL_FP_DENORM |
CL_FP_INF_NAN |
CL_FP_ROUND_TO_NEAREST);
break;
case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:
SIMPLE_ASSIGN(cl_device_mem_cache_type,
CL_READ_WRITE_CACHE);
break;
case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:
// TODO: Get this information from the processor
SIMPLE_ASSIGN(cl_uint, 16);
break;
case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:
// TODO: Get this information from the processor
SIMPLE_ASSIGN(cl_ulong, 512 * 1024 * 1024);
break;
case CL_DEVICE_GLOBAL_MEM_SIZE:
// TODO: 1 Gio seems to be enough for software acceleration
SIMPLE_ASSIGN(cl_ulong, 1 * 1024 * 1024 * 1024);
break;
case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:
SIMPLE_ASSIGN(cl_ulong, 1 * 1024 * 1024 * 1024);
break;
case CL_DEVICE_MAX_CONSTANT_ARGS:
SIMPLE_ASSIGN(cl_uint, 65536);
break;
case CL_DEVICE_LOCAL_MEM_TYPE:
SIMPLE_ASSIGN(cl_device_local_mem_type, CL_GLOBAL);
break;
case CL_DEVICE_LOCAL_MEM_SIZE:
SIMPLE_ASSIGN(cl_ulong, 1 * 1024 * 1024 * 1024);
break;
case CL_DEVICE_ERROR_CORRECTION_SUPPORT:
SIMPLE_ASSIGN(cl_bool, CL_FALSE);
break;
case CL_DEVICE_PROFILING_TIMER_RESOLUTION:
// TODO
SIMPLE_ASSIGN(size_t, 1000); // 1000 nanoseconds = 1 ms
break;
case CL_DEVICE_ENDIAN_LITTLE:
SIMPLE_ASSIGN(cl_bool, CL_TRUE);
break;
case CL_DEVICE_AVAILABLE:
SIMPLE_ASSIGN(cl_bool, CL_TRUE);
break;
case CL_DEVICE_COMPILER_AVAILABLE:
SIMPLE_ASSIGN(cl_bool, CL_TRUE);
break;
case CL_DEVICE_EXECUTION_CAPABILITIES:
SIMPLE_ASSIGN(cl_device_exec_capabilities, CL_EXEC_KERNEL |
CL_EXEC_NATIVE_KERNEL);
break;
case CL_DEVICE_QUEUE_PROPERTIES:
SIMPLE_ASSIGN(cl_command_queue_properties,
CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
CL_QUEUE_PROFILING_ENABLE);
break;
case CL_DEVICE_NAME:
STRING_ASSIGN("CPU");
break;
case CL_DEVICE_VENDOR:
STRING_ASSIGN("Mesa");
break;
case CL_DRIVER_VERSION:
STRING_ASSIGN("" "0.1.0");
break;
case CL_DEVICE_PROFILE:
STRING_ASSIGN("FULL_PROFILE");
break;
case CL_DEVICE_VERSION:
STRING_ASSIGN("OpenCL 1.1 Mesa " "0.1.0");
break;
case CL_DEVICE_EXTENSIONS:
STRING_ASSIGN("cl_khr_global_int32_base_atomics"
" cl_khr_global_int32_extended_atomics"
" cl_khr_local_int32_base_atomics"
" cl_khr_local_int32_extended_atomics"
" cl_khr_byte_addressable_store"
" cl_khr_fp64"
" cl_khr_int64_base_atomics"
" cl_khr_int64_extended_atomics")
break;
case CL_DEVICE_PLATFORM:
SIMPLE_ASSIGN(cl_platform_id, 0);
break;
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:
SIMPLE_ASSIGN(cl_uint, 0);
break;
case CL_DEVICE_HOST_UNIFIED_MEMORY:
SIMPLE_ASSIGN(cl_bool, CL_TRUE);
break;
case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:
SIMPLE_ASSIGN(cl_uint, 16);
break;
case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT:
SIMPLE_ASSIGN(cl_uint, 8);
break;
case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:
SIMPLE_ASSIGN(cl_uint, 4);
break;
case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:
SIMPLE_ASSIGN(cl_uint, 2);
break;
case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT:
SIMPLE_ASSIGN(cl_uint, 4);
break;
case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE:
SIMPLE_ASSIGN(cl_uint, 2);
break;
case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:
SIMPLE_ASSIGN(cl_uint, 0);
break;
case CL_DEVICE_OPENCL_C_VERSION:
STRING_ASSIGN("OpenCL C 1.1 LLVM " "3.7.0svn");
break;
default:
return CL_INVALID_VALUE;
}
if(param_value && param_value_size < value_length)
return CL_INVALID_VALUE;
if(param_value_size_ret)
*param_value_size_ret = value_length;
if(param_value)
std::memcpy(param_value, value, value_length);
return CL_SUCCESS;
}
//GPUDevice::GPUDevice()
// : DeviceInterface(), p_cores(0), p_num_events(0), p_workers(0), p_stop(false),
// p_initialized(false)
//{
//
//}
//
//void GPUDevice::init()
//{
// if(p_initialized)
// return;
//
// // Initialize the locking machinery
// pthread_cond_init(&p_events_cond, 0);
// pthread_mutex_init(&p_events_mutex, 0);
//
// //TODO
// // Get info about the system
// /*p_cores = sysconf(_SC_NPROCESSORS_ONLN);
// p_cpu_mhz = 0.0f;
//
// std::filebuf fb;
// fb.open("/proc/cpuinfo", std::ios::in);
// std::istream is(&fb);
//
// while(!is.eof())
// {
// std::string key, value;
//
// std::getline(is, key, ':');
// is.ignore(1);
// std::getline(is, value);
//
// if(key.compare(0, 7, "cpu MHz") == 0)
// {
// std::istringstream ss(value);
// ss >> p_cpu_mhz;
// break;
// }
// }*/
//
// //TODO CHANGE pcore value to real
// p_cores = 1;
// p_cpu_mhz = 3200;
// // Create worker threads
// p_workers = (pthread_t *)std::malloc(numCPUs() * sizeof(pthread_t));
//
// for(unsigned int i = 0; i<numCPUs(); ++i)
// {
// pthread_create(&p_workers[i], 0, &worker, this);
// }
//
// p_initialized = true;
//}
//
//GPUDevice::~GPUDevice()
//{
// if(!p_initialized)
// return;
//
// // Terminate the workers and wait for them
// pthread_mutex_lock(&p_events_mutex);
//
// p_stop = true;
//
// pthread_cond_broadcast(&p_events_cond);
// pthread_mutex_unlock(&p_events_mutex);
//
// for(unsigned int i = 0; i<numCPUs(); ++i)
// {
// pthread_join(p_workers[i], 0);
// }
//
// // Free allocated memory
// std::free((void *)p_workers);
// pthread_mutex_destroy(&p_events_mutex);
// pthread_cond_destroy(&p_events_cond);
//}
//
//DeviceBuffer *GPUDevice::createDeviceBuffer(MemObject *buffer, cl_int *rs)
//{
// return (DeviceBuffer *)new CPUBuffer((CPUDevice *)this, buffer, rs);
//}
//
//DeviceProgram *GPUDevice::createDeviceProgram(Program *program)
//{
// return (DeviceProgram *)new CPUProgram((CPUDevice *)this, program);
//}
//
//DeviceKernel *GPUDevice::createDeviceKernel(Kernel *kernel,
// llvm::Function *function)
//{
// return (DeviceKernel *)new CPUKernel((CPUDevice *)this, kernel, function);
//}
//
//cl_int GPUDevice::initEventDeviceData(Event *event)
//{
// switch(event->type())
// {
// case Event::MapBuffer:
// {
// MapBufferEvent *e = (MapBufferEvent *)event;
// CPUBuffer *buf = (CPUBuffer *)e->buffer()->deviceBuffer(this);
// unsigned char *data = (unsigned char *)buf->data();
//
// data += e->offset();
//
// e->setPtr((void *)data);
// break;
// }
// case Event::MapImage:
// {
// MapImageEvent *e = (MapImageEvent *)event;
// Image2D *image = (Image2D *)e->buffer();
// CPUBuffer *buf = (CPUBuffer *)image->deviceBuffer(this);
// unsigned char *data = (unsigned char *)buf->data();
//
// data = imageData(data,
// e->origin(0),
// e->origin(1),
// e->origin(2),
// image->row_pitch(),
// image->slice_pitch(),
// image->pixel_size());
//
// e->setPtr((void *)data);
// e->setRowPitch(image->row_pitch());
// e->setSlicePitch(image->slice_pitch());
// break;
// }
// case Event::UnmapMemObject:
// // Nothing do to
// break;
//
// case Event::NDRangeKernel:
// case Event::TaskKernel:
// {
// // Instantiate the JIT for the CPU program
// KernelEvent *e = (KernelEvent *)event;
// //Program *p = (Program *)e->kernel()->parent();
// //CPUProgram *prog = (CPUProgram *)p->deviceDependentProgram(this);
//
// /*if(!prog->initJIT())
// return CL_INVALID_PROGRAM_EXECUTABLE;*/
//
// // Set device-specific data
// CPUKernelEvent *cpu_e = new CPUKernelEvent((CPUDevice *)this, e);
// e->setDeviceData((void *)cpu_e);
//
// break;
// }
// default:
// break;
// }
//
// return CL_SUCCESS;
//}
//
//void GPUDevice::freeEventDeviceData(Event *event)
//{
// switch(event->type())
// {
// case Event::NDRangeKernel:
// case Event::TaskKernel:
// {
// CPUKernelEvent *cpu_e = (CPUKernelEvent *)event->deviceData();
//
// if(cpu_e)
// delete cpu_e;
// }
// default:
// break;
// }
//}
//
//void GPUDevice::pushEvent(Event *event)
//{
// // Add an event in the list
// pthread_mutex_lock(&p_events_mutex);
//
// p_events.push_back(event);
// p_num_events++; // Way faster than STL list::size() !
//
// pthread_cond_broadcast(&p_events_cond);
// pthread_mutex_unlock(&p_events_mutex);
//}
//
//Event *GPUDevice::getEvent(bool &stop)
//{
// // Return the first event in the list, if any. Remove it if it is a
// // single-shot event.
// pthread_mutex_lock(&p_events_mutex);
//
// while(p_num_events == 0 && !p_stop)
// pthread_cond_wait(&p_events_cond, &p_events_mutex);
//
// if(p_stop)
// {
// pthread_mutex_unlock(&p_events_mutex);
// stop = true;
// return 0;
// }
//
// Event *event = p_events.front();
//
// // If the run of this event will finish it, remove it from the list
// bool last_slot = true;
//
// if(event->type() == Event::NDRangeKernel ||
// event->type() == Event::TaskKernel)
// {
// CPUKernelEvent *ke = (CPUKernelEvent *)event->deviceData();
// last_slot = ke->reserve();
// }
//
// if(last_slot)
// {
// p_num_events--;
// p_events.pop_front();
// }
//
// pthread_mutex_unlock(&p_events_mutex);
//
// return event;
//}
//
//unsigned int GPUDevice::numCPUs() const
//{
// return p_cores;
//}
//
//float GPUDevice::cpuMhz() const
//{
// return p_cpu_mhz;
//}
//
//// From inner parentheses to outher ones :
////
//// sizeof * 8 => 8
//// -1 => 7
//// 1 << $ => 10000000
//// -1 => 01111111
//// *2 => 11111110
//// +1 => 11111111
////
//// A simple way to do this is (1 << (sizeof(type) * 8)) - 1, but it overflows
//// the type (for int8, 1 << $ = 100000000 = 256 > 255)
//#define TYPE_MAX(type) ((((type)1 << ((sizeof(type) * 8) - 1)) - 1) * 2 + 1)
//
//cl_int GPUDevice::info(cl_device_info param_name,
// size_t param_value_size,
// void *param_value,
// size_t *param_value_size_ret) const
//{
// void *value = 0;
// size_t value_length = 0;
//
// union {
// cl_device_type cl_device_type_var;
// cl_uint cl_uint_var;
// size_t size_t_var;
// cl_ulong cl_ulong_var;
// cl_bool cl_bool_var;
// cl_device_fp_config cl_device_fp_config_var;
// cl_device_mem_cache_type cl_device_mem_cache_type_var;
// cl_device_local_mem_type cl_device_local_mem_type_var;
// cl_device_exec_capabilities cl_device_exec_capabilities_var;
// cl_command_queue_properties cl_command_queue_properties_var;
// cl_platform_id cl_platform_id_var;
// size_t work_dims[MAX_WORK_DIMS];
// };
//
// switch(param_name)
// {
// case CL_DEVICE_TYPE:
// SIMPLE_ASSIGN(cl_device_type, CL_DEVICE_TYPE_CPU);
// break;
//
// case CL_DEVICE_VENDOR_ID:
// SIMPLE_ASSIGN(cl_uint, 0);
// break;
//
// case CL_DEVICE_MAX_COMPUTE_UNITS:
// SIMPLE_ASSIGN(cl_uint, numCPUs());
// break;
//
// case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:
// SIMPLE_ASSIGN(cl_uint, MAX_WORK_DIMS);
// break;
//
// case CL_DEVICE_MAX_WORK_GROUP_SIZE:
// SIMPLE_ASSIGN(size_t, TYPE_MAX(size_t));
// break;
//
// case CL_DEVICE_MAX_WORK_ITEM_SIZES:
// for(int i = 0; i<MAX_WORK_DIMS; ++i)
// {
// work_dims[i] = TYPE_MAX(size_t);
// }
// value_length = MAX_WORK_DIMS * sizeof(size_t);
// value = &work_dims;
// break;
//
// case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:
// SIMPLE_ASSIGN(cl_uint, 16);
// break;
//
// case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:
// SIMPLE_ASSIGN(cl_uint, 8);
// break;
//
// case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:
// SIMPLE_ASSIGN(cl_uint, 4);
// break;
//
// case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:
// SIMPLE_ASSIGN(cl_uint, 2);
// break;
//
// case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:
// SIMPLE_ASSIGN(cl_uint, 4);
// break;
//
// case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:
// SIMPLE_ASSIGN(cl_uint, 2);
// break;
//
// case CL_DEVICE_MAX_CLOCK_FREQUENCY:
// SIMPLE_ASSIGN(cl_uint, cpuMhz() * 1000000);
// break;
//
// case CL_DEVICE_ADDRESS_BITS:
// SIMPLE_ASSIGN(cl_uint, 32);
// break;
//
// case CL_DEVICE_MAX_READ_IMAGE_ARGS:
// SIMPLE_ASSIGN(cl_uint, 65536);
// break;
//
// case CL_DEVICE_MAX_WRITE_IMAGE_ARGS:
// SIMPLE_ASSIGN(cl_uint, 65536);
// break;
//
// case CL_DEVICE_MAX_MEM_ALLOC_SIZE:
// SIMPLE_ASSIGN(cl_ulong, 128 * 1024 * 1024);
// break;
//
// case CL_DEVICE_IMAGE2D_MAX_WIDTH:
// SIMPLE_ASSIGN(size_t, 65536);
// break;
//
// case CL_DEVICE_IMAGE2D_MAX_HEIGHT:
// SIMPLE_ASSIGN(size_t, 65536);
// break;
//
// case CL_DEVICE_IMAGE3D_MAX_WIDTH:
// SIMPLE_ASSIGN(size_t, 65536);
// break;
//
// case CL_DEVICE_IMAGE3D_MAX_HEIGHT:
// SIMPLE_ASSIGN(size_t, 65536);
// break;
//
// case CL_DEVICE_IMAGE3D_MAX_DEPTH:
// SIMPLE_ASSIGN(size_t, 65536);
// break;
//
// case CL_DEVICE_IMAGE_SUPPORT:
// SIMPLE_ASSIGN(cl_bool, CL_TRUE);
// break;
//
// case CL_DEVICE_MAX_PARAMETER_SIZE:
// SIMPLE_ASSIGN(size_t, 65536);
// break;
//
// case CL_DEVICE_MAX_SAMPLERS:
// SIMPLE_ASSIGN(cl_uint, 16);
// break;
//
// case CL_DEVICE_MEM_BASE_ADDR_ALIGN:
// SIMPLE_ASSIGN(cl_uint, 0);
// break;
//
// case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:
// SIMPLE_ASSIGN(cl_uint, 16);
// break;
//
// case CL_DEVICE_SINGLE_FP_CONFIG:
// // TODO: Check what an x86 SSE engine can support.
// SIMPLE_ASSIGN(cl_device_fp_config,
// CL_FP_DENORM |
// CL_FP_INF_NAN |
// CL_FP_ROUND_TO_NEAREST);
// break;
//
// case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:
// SIMPLE_ASSIGN(cl_device_mem_cache_type,
// CL_READ_WRITE_CACHE);
// break;
//
// case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:
// // TODO: Get this information from the processor
// SIMPLE_ASSIGN(cl_uint, 16);
// break;
//
// case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:
// // TODO: Get this information from the processor
// SIMPLE_ASSIGN(cl_ulong, 512 * 1024 * 1024);
// break;
//
// case CL_DEVICE_GLOBAL_MEM_SIZE:
// // TODO: 1 Gio seems to be enough for software acceleration
// SIMPLE_ASSIGN(cl_ulong, 1 * 1024 * 1024 * 1024);
// break;
//
// case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:
// SIMPLE_ASSIGN(cl_ulong, 1 * 1024 * 1024 * 1024);
// break;
//
// case CL_DEVICE_MAX_CONSTANT_ARGS:
// SIMPLE_ASSIGN(cl_uint, 65536);
// break;
//
// case CL_DEVICE_LOCAL_MEM_TYPE:
// SIMPLE_ASSIGN(cl_device_local_mem_type, CL_GLOBAL);
// break;
//
// case CL_DEVICE_LOCAL_MEM_SIZE:
// SIMPLE_ASSIGN(cl_ulong, 1 * 1024 * 1024 * 1024);
// break;
//
// case CL_DEVICE_ERROR_CORRECTION_SUPPORT:
// SIMPLE_ASSIGN(cl_bool, CL_FALSE);
// break;
//
// case CL_DEVICE_PROFILING_TIMER_RESOLUTION:
// // TODO
// SIMPLE_ASSIGN(size_t, 1000); // 1000 nanoseconds = 1 ms
// break;
//
// case CL_DEVICE_ENDIAN_LITTLE:
// SIMPLE_ASSIGN(cl_bool, CL_TRUE);
// break;
//
// case CL_DEVICE_AVAILABLE:
// SIMPLE_ASSIGN(cl_bool, CL_TRUE);
// break;
//
// case CL_DEVICE_COMPILER_AVAILABLE:
// SIMPLE_ASSIGN(cl_bool, CL_TRUE);
// break;
//
// case CL_DEVICE_EXECUTION_CAPABILITIES:
// SIMPLE_ASSIGN(cl_device_exec_capabilities, CL_EXEC_KERNEL |
// CL_EXEC_NATIVE_KERNEL);
// break;
//
// case CL_DEVICE_QUEUE_PROPERTIES:
// SIMPLE_ASSIGN(cl_command_queue_properties,
// CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
// CL_QUEUE_PROFILING_ENABLE);
// break;
//
// case CL_DEVICE_NAME:
// STRING_ASSIGN("CPU");
// break;
//
// case CL_DEVICE_VENDOR:
// STRING_ASSIGN("Mesa");
// break;
//
// case CL_DRIVER_VERSION:
// STRING_ASSIGN("" "0.1.0");
// break;
//
// case CL_DEVICE_PROFILE:
// STRING_ASSIGN("FULL_PROFILE");
// break;
//
// case CL_DEVICE_VERSION:
// STRING_ASSIGN("OpenCL 1.1 Mesa " "0.1.0");
// break;
//
// case CL_DEVICE_EXTENSIONS:
// STRING_ASSIGN("cl_khr_global_int32_base_atomics"
// " cl_khr_global_int32_extended_atomics"
// " cl_khr_local_int32_base_atomics"
// " cl_khr_local_int32_extended_atomics"
// " cl_khr_byte_addressable_store"
//
// " cl_khr_fp64"
// " cl_khr_int64_base_atomics"
// " cl_khr_int64_extended_atomics")
//
// break;
//
// case CL_DEVICE_PLATFORM:
// SIMPLE_ASSIGN(cl_platform_id, 0);
// break;
//
// case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:
// SIMPLE_ASSIGN(cl_uint, 0);
// break;
//
// case CL_DEVICE_HOST_UNIFIED_MEMORY:
// SIMPLE_ASSIGN(cl_bool, CL_TRUE);
// break;
//
// case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:
// SIMPLE_ASSIGN(cl_uint, 16);
// break;
//
// case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT:
// SIMPLE_ASSIGN(cl_uint, 8);
// break;
//
// case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:
// SIMPLE_ASSIGN(cl_uint, 4);
// break;
//
// case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:
// SIMPLE_ASSIGN(cl_uint, 2);
// break;
//
// case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT:
// SIMPLE_ASSIGN(cl_uint, 4);
// break;
//
// case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE:
// SIMPLE_ASSIGN(cl_uint, 2);
// break;
//
// case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:
// SIMPLE_ASSIGN(cl_uint, 0);
// break;
//
// case CL_DEVICE_OPENCL_C_VERSION:
// STRING_ASSIGN("OpenCL C 1.1 LLVM " "3.7.0svn");
// break;
//
// default:
// return CL_INVALID_VALUE;
// }
//
// if(param_value && param_value_size < value_length)
// return CL_INVALID_VALUE;
//
// if(param_value_size_ret)
// *param_value_size_ret = value_length;
//
// if(param_value)
// std::memcpy(param_value, value, value_length);
//
// return CL_SUCCESS;
//}