#ifdef __APPLE__
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif
#include <iostream>
#include <fstream>
#include <sstream>
#include <iostream>
#include "Globals.h"
#include "clInitFunctions.hpp"
void openCLinit::print_cl_err(int err_code)
{
switch(err_code)
{
case 0:
fprintf(stderr, "Error code: 0 CL_SUCCESS\n");
break;
case -1:
fprintf(stderr, "Error code: -1 CL_DEVICE_NOT_FOUND\n");
break;
case -2:
fprintf(stderr, "Error code: -2 CL_DEVICE_NOT_AVAILABLE\n");
break;
case -3:
fprintf(stderr, "Error code: -3 CL_COMPILER_NOT_AVAILABLE\n");
break;
case -4:
fprintf(stderr, "Error code: -4 CL_MEM_OBJECT_ALLOCATION_FAILURE\n");
break;
case -5:
fprintf(stderr, "Error code: -5 CL_OUT_OF_RESOURCES\n");
break;
case -6:
fprintf(stderr, "Error code: -6 CL_OUT_OF_HOST_MEMORY\n");
break;
case -7:
fprintf(stderr, "Error code: -7 CL_PROFILING_INFO_NOT_AVAILABLE\n");
break;
case -8:
fprintf(stderr, "Error code: -8 CL_MEM_COPY_OVERLAP\n");
break;
case -9:
fprintf(stderr, "Error code: -9 CL_IMAGE_FORMAT_MISMATCH\n");
break;
case -10:
fprintf(stderr, "Error code: -10 CL_IMAGE_FORMAT_NOT_SUPPORTED\n");
break;
case -11:
fprintf(stderr, "Error code: -11 CL_BUILD_PROGRAM_FAILURE\n");
break;
case -12:
fprintf(stderr, "Error code: -12 CL_MAP_FAILURE\n");
break;
case -30:
fprintf(stderr, "Error code: -30 CL_INVALID_VALUE\n");
break;
case -31:
fprintf(stderr, "Error code: -31 CL_INVALID_DEVICE_TYPE\n");
break;
case -32:
fprintf(stderr, "Error code: -32 CL_INVALID_PLATFORM\n");
break;
case -33:
fprintf(stderr, "Error code: -33 CL_INVALID_DEVICE\n");
break;
case -34:
fprintf(stderr, "Error code: -34 CL_INVALID_CONTEXT\n");
break;
case -35:
fprintf(stderr, "Error code: -35 CL_INVALID_QUEUE_PROPERTIES\n");
break;
case -36:
fprintf(stderr, "Error code: -36 CL_INVALID_COMMAND_QUEUE\n");
break;
case -37:
fprintf(stderr, "Error code: -37 CL_INVALID_HOST_PTR\n");
break;
case -38:
fprintf(stderr, "Error code: -38 CL_INVALID_MEM_OBJECT\n");
break;
case -39:
fprintf(stderr, "Error code: -39 CL_INVALID_IMAGE_FORMAT_DESCRIPTOR\n");
break;
case -40:
fprintf(stderr, "Error code: -40 CL_INVALID_IMAGE_SIZE\n");
break;
case -41:
fprintf(stderr, "Error code: -41 CL_INVALID_SAMPLER\n");
break;
case -42:
fprintf(stderr, "Error code: -42 CL_INVALID_BINARY\n");
break;
case -43:
fprintf(stderr, "Error code: -43 CL_INVALID_BUILD_OPTIONS\n");
break;
case -44:
fprintf(stderr, "Error code: -44 CL_INVALID_PROGRAM\n");
break;
case -45:
fprintf(stderr, "Error code: -45 CL_INVALID_PROGRAM_EXECUTABLE\n");
break;
case -46:
fprintf(stderr, "Error code: -46 CL_INVALID_KERNEL_NAME\n");
break;
case -47:
fprintf(stderr, "Error code: -47 CL_INVALID_KERNEL_DEFINITION\n");
break;
case -48:
fprintf(stderr, "Error code: -48 CL_INVALID_KERNEL\n");
break;
case -49:
fprintf(stderr, "Error code: -49 CL_INVALID_ARG_INDEX\n");
break;
case -50:
fprintf(stderr, "Error code: -50 CL_INVALID_ARG_VALUE\n");
break;
case -51:
fprintf(stderr, "Error code: -51 CL_INVALID_ARG_SIZE\n");
break;
case -52:
fprintf(stderr, "Error code: -52 CL_INVALID_KERNEL_ARGS\n");
break;
case -53:
fprintf(stderr, "Error code: -53 CL_INVALID_WORK_DIMENSION\n");
break;
case -54:
fprintf(stderr, "Error code: -54 CL_INVALID_WORK_GROUP_SIZE\n");
break;
case -55:
fprintf(stderr, "Error code: -55 CL_INVALID_WORK_ITEM_SIZE\n");
break;
case -56:
fprintf(stderr, "Error code: -56 CL_INVALID_GLOBAL_OFFSET\n");
break;
case -57:
fprintf(stderr, "Error code: -57 CL_INVALID_EVENT_WAIT_LIST\n");
break;
case -58:
fprintf(stderr, "Error code: -58 CL_INVALID_EVENT\n");
break;
case -59:
fprintf(stderr, "Error code: -59 CL_INVALID_OPERATION\n");
break;
case -60:
fprintf(stderr, "Error code: -60 CL_INVALID_GL_OBJECT\n");
break;
case -61:
fprintf(stderr, "Error code: -61 CL_INVALID_BUFFER_SIZE\n");
break;
case -62:
fprintf(stderr, "Error code: -62 CL_INVALID_MIP_LEVEL\n");
break;
case -63:
fprintf(stderr, "Error code: -63 CL_INVALID_GLOBAL_WORK_SIZE\n");
break;
default:
fprintf(stderr, "Unknown error code: %d\n", err_code);
break;
}
}
/**
* Gibt die Geräteinformationen (Name, Hersteller) der möglichen Devices aus, die für OpenCl benutzt werden können.
*
*
**/
void openCLinit::getDeviceInfos (){
cl_platform_id platforms[100];
cl_uint platforms_n = 0;
cl_uint devices_n = 0;
char buffer[10240];
cl_uint buf_uint;
clGetPlatformIDs(100, platforms, &platforms_n);
cl_device_id devices[100];
clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_ALL, 100, devices, &devices_n);
for (int i=0; i< devices_n; i++)
{
std::cout << "DEVICE " << i << "\n";
clGetDeviceInfo(devices[i], CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL);
printf(" VENDOR_NAME = %s\n", buffer);
clGetDeviceInfo(devices[i], CL_DEVICE_NAME, sizeof(buffer), buffer, NULL);
printf(" DEVICE_NAME = %s\n", buffer);
clGetDeviceInfo(devices[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buf_uint), &buf_uint, NULL);
printf(" DEVICE_MAX_COMPUTE_UNITS = %u\n", (unsigned int)buf_uint);
clGetDeviceInfo(devices[i], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buf_uint), &buf_uint, NULL);
printf(" CL_DEVICE_MAX_CLOCK_FREQUENCY = %u\n", (unsigned int)buf_uint);
printf("\n");printf("\n");
}
}
cl_context openCLinit::CreateContext()
{
cl_int errNum;
cl_uint numPlatforms;
cl_platform_id firstPlatformId;
cl_context context = NULL;
// First, select an OpenCL platform to run on. For this example, we
// simply choose the first available platform. Normally, you would
// query for all available platforms and select the most appropriate one.
errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlatforms);
if (errNum != CL_SUCCESS || numPlatforms <= 0)
{
std::cerr << "Failed to find any OpenCL platforms." << std::endl;
return NULL;
}
// Next, create an OpenCL context on the platform. Attempt to
// create a GPU-based context, and if that fails, try to create
// a CPU-based context.
cl_context_properties contextProperties[] =
{
CL_CONTEXT_PLATFORM,
(cl_context_properties)firstPlatformId,
0
};
context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU,
NULL, NULL, &errNum);
if (errNum != CL_SUCCESS)
{
std::cout << "Could not create GPU context, trying CPU..." << std::endl;
context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_CPU,
NULL, NULL, &errNum);
if (errNum != CL_SUCCESS)
{
std::cerr << "Failed to create an OpenCL GPU or CPU context." << std::endl;
return NULL;
}
}
return context;
}
///
// Create a command queue on the first device available on the
// context
//
cl_command_queue openCLinit::CreateCommandQueue(cl_context context, cl_device_id *device)
{
cl_int errNum;
cl_device_id *devices;
cl_command_queue commandQueue = NULL;
size_t deviceBufferSize = -1;
// First get the size of the devices buffer
errNum = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceBufferSize);
if (errNum != CL_SUCCESS)
{
std::cerr << "Failed call to clGetContextInfo(...,GL_CONTEXT_DEVICES,...)";
return NULL;
}
if (deviceBufferSize <= 0)
{
std::cerr << "No devices available.";
return NULL;
}
// Allocate memory for the devices buffer
devices = new cl_device_id[deviceBufferSize / sizeof(cl_device_id)];
errNum = clGetContextInfo(context, CL_CONTEXT_DEVICES, deviceBufferSize, devices, NULL);
if (errNum != CL_SUCCESS)
{
delete [] devices;
std::cerr << "Failed to get device IDs";
return NULL;
}
// In this example, we just choose the first available device. In a
// real program, you would likely use all available devices or choose
// the highest performance device based on OpenCL device queries
commandQueue = clCreateCommandQueue(context, devices[0], 0, NULL);
if (commandQueue == NULL)
{
delete [] devices;
std::cerr << "Failed to create commandQueue for device 0";
return NULL;
}
*device = devices[0];
delete [] devices;
return commandQueue;
}
///
// Create an OpenCL program from the kernel source file
//
cl_program openCLinit::CreateProgram(cl_context context, cl_device_id device, const char* fileName)
{
cl_int errNum;
cl_program program;
std::ifstream kernelFile(fileName, std::ios::in);
if (!kernelFile.is_open())
{
std::cerr << "Failed to open file for reading: " << fileName << std::endl;
return NULL;
}
std::ostringstream oss;
oss << kernelFile.rdbuf();
std::string srcStdStr = oss.str();
const char *srcStr = srcStdStr.c_str();
program = clCreateProgramWithSource(context, 1,
(const char**)&srcStr,
NULL, NULL);
if (program == NULL)
{
std::cerr << "Failed to create CL program from source." << std::endl;
return NULL;
}
errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
if (errNum != CL_SUCCESS)
{
// Determine the reason for the error
char buildLog[16384];
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,
sizeof(buildLog), buildLog, NULL);
std::cerr << "Error in kernel: " << std::endl;
std::cerr << buildLog;
clReleaseProgram(program);
return NULL;
}
return program;
}
///
// Create memory objects used as the arguments to the kernel
// The kernel takes three arguments: result (output), a (input),
// and b (input)
//
bool openCLinit::CreateMemObjects(cl_context context, cl_mem memObjects[3],
float *a, float *b)
{
memObjects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, a, NULL);
memObjects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, b, NULL);
memObjects[2] = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(float) * ARRAY_SIZE, NULL, NULL);
if (memObjects[0] == NULL || memObjects[1] == NULL || memObjects[2] == NULL)
{
std::cerr << "Error creating memory objects." << std::endl;
return false;
}
return true;
}
bool CreateMemObjectsAnts(cl_context context, cl_mem memObjects[7],
float *world, float *antX, float *antY, float *targetX, float *targetY, float *speed, int *direction, float * resultX, float * resultY)
{
memObjects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, world, NULL);
memObjects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, antX, NULL);
memObjects[2] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, antY, NULL);
memObjects[3] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, targetX, NULL);
memObjects[4] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, targetY, NULL);
memObjects[5] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, speed, NULL);
memObjects[6] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * ARRAY_SIZE, direction, NULL);
memObjects[7] = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(float) * ARRAY_SIZE, NULL, NULL);
memObjects[8] = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(float) * ARRAY_SIZE, NULL, NULL);
if (memObjects[0] == NULL || memObjects[1] == NULL || memObjects[2] == NULL || memObjects[3] == NULL || memObjects[4] == NULL || memObjects[5] == NULL)
{
std::cerr << "Error creating memory objects." << std::endl;
return false;
}
return true;
}
///
// Cleanup any created OpenCL resources
//
void openCLinit::Cleanup(cl_context context, cl_command_queue commandQueue,
cl_program program, cl_kernel kernel, cl_mem memObjects[3])
{
for (int i = 0; i < 3; i++)
{
if (memObjects[i] != 0)
clReleaseMemObject(memObjects[i]);
}
if (commandQueue != 0)
clReleaseCommandQueue(commandQueue);
if (kernel != 0)
clReleaseKernel(kernel);
if (program != 0)
clReleaseProgram(program);
if (context != 0)
clReleaseContext(context);
}
int openCLinit::startOpenCLmain(){
std::ofstream openclLogger;
cl_context context = 0;
cl_command_queue commandQueue = 0;
cl_program program = 0;
cl_device_id device = 0;
cl_kernel kernel = 0;
cl_mem memObjects[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
cl_int errNum = 0;
openclLogger.open ("C:\\Users\\Chris\\Desktop\\uni\\8_semester\\Code\\log\\logdateiCL.txt", std::ios::out | std::ios::app);
// DEBUG
//getDeviceInfos();
// Create an OpenCL context on first available platform
context = CreateContext();
if (context == NULL)
{
print_cl_err(errNum);
return 1;
}
// Create a command-queue on the first device available
// on the created context
commandQueue = CreateCommandQueue(context, &device);
if (commandQueue == NULL)
{
print_cl_err(errNum);
Cleanup(context, commandQueue, program, kernel, memObjects);
return 1;
}
// Create OpenCL program from HelloWorld.cl kernel source
program = CreateProgram(context, device, "Ant.cl");
if (program == NULL)
{
print_cl_err(errNum);
Cleanup(context, commandQueue, program, kernel, memObjects);
return 1;
}
// Create OpenCL kernel
kernel = clCreateKernel(program, "stepSizeAnt", NULL);
if (kernel == NULL)
{
print_cl_err(errNum);
Cleanup(context, commandQueue, program, kernel, memObjects);
return 1;
}
// Create memory objects that will be used as arguments to
// kernel. First create host memory arrays that will be
// used to store the arguments to the kernel
if (!CreateMemObjectsAnts(context, memObjects, world, antX, antY, targetX, targetY, speed, direction, resultX, resultY))
{
Cleanup(context, commandQueue, program, kernel, memObjects);
return 1;
}
// Set the kernel arguments (result, a, b)
for (int i = 0; i < 9; i++){
errNum |= clSetKernelArg(kernel, i, sizeof(cl_mem), &memObjects[i]);
}
if (errNum != CL_SUCCESS)
{
print_cl_err(errNum);
Cleanup(context, commandQueue, program, kernel, memObjects);
return 1;
}
size_t globalWorkSize[1] = { ARRAY_SIZE };
size_t localWorkSize[1] = { 1 };
// Queue the kernel up for execution across the array
errNum = clEnqueueNDRangeKernel(commandQueue, kernel, 1, NULL,
globalWorkSize, localWorkSize,
0, NULL, NULL);
if (errNum != CL_SUCCESS)
{
print_cl_err(errNum);
Cleanup(context, commandQueue, program, kernel, memObjects);
return 1;
}
// Read the output buffer back to the Host
errNum = clEnqueueReadBuffer(commandQueue, memObjects[7], CL_TRUE,
0, ARRAY_SIZE * sizeof(float), resultX,
0, NULL, NULL);
errNum = clEnqueueReadBuffer(commandQueue, memObjects[8], CL_TRUE,
0, ARRAY_SIZE * sizeof(float), resultY,
0, NULL, NULL);
if (errNum != CL_SUCCESS)
{
print_cl_err(errNum);
Cleanup(context, commandQueue, program, kernel, memObjects);
return 1;
}
std::cout << std::endl;
openclLogger << "Executed program succesfully." << std::endl;
// Output the result buffer
for (int i = 0; i < ARRAY_SIZE; i++)
{
openclLogger << "ID : " << i << std::endl;
openclLogger << "AntX: " << antX[i] << " AntY: " << antY[i] << std::endl;
openclLogger << "TargetX: " << targetX[i] << " TargetY: " << targetY[i] << std::endl;
openclLogger << "NewX: " << resultX[i] << " NewY: " << resultY[i] << std::endl << std::endl;
}
Cleanup(context, commandQueue, program, kernel, memObjects);
}
Error 9 error LNK2005: "bool * targetArrived" (?targetArrived@@3PA_NA) already defined in Bachelorarbeit.obj C:\Users\Chris\Desktop\uni\8_semester\Code\OpenCL1\SDL1\clInitFunctions.obj
Error 10 error LNK2005: "float * resultX" (?resultX@@3PAMA) already defined in Bachelorarbeit.obj C:\Users\Chris\Desktop\uni\8_semester\Code\OpenCL1\SDL1\clInitFunctions.obj
Error 11 error LNK2005: "float * resultY" (?resultY@@3PAMA) already defined in Bachelorarbeit.obj C:\Users\Chris\Desktop\uni\8_semester\Code\OpenCL1\SDL1\clInitFunctions.obj
Error 12 error LNK2005: "float * world" (?world@@3PAMA) already defined in Bachelorarbeit.obj C:\Users\Chris\Desktop\uni\8_semester\Code\OpenCL1\SDL1\clInitFunctions.obj
Error 13 error LNK2005: "float * antX" (?antX@@3PAMA) already defined in Bachelorarbeit.obj C:\Users\Chris\Desktop\uni\8_semester\Code\OpenCL1\SDL1\clInitFunctions.obj