-
-
Save PontiacGTX/745b4942acab0c7213dee1fede6a8e35 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS | |
#include <iostream> | |
#include "ApplicationCL.h" | |
unsigned long int sizeArr = 256; | |
std::vector<cl_uchar> vChars(sizeArr); | |
std::vector<char> fileBytes; | |
std::vector<cl_uchar*> compressedBytes; | |
std::vector<cl_ulong> indexByte; | |
float limit; | |
unsigned long filebyteCount = 0; | |
cl_ulong compressedByteCount = 0; | |
#define NELEMS(x) (sizeof(x) / sizeof((x)[0])) | |
void GetPlatformInfo(const cl_uint& numPlatforms, cl_platform_id* platforms, std::string& details) | |
{ | |
std::string attributeNames[] = { "Name", "Vendor", "Version", "Profile", "Extensions" }; | |
const cl_platform_info attributeTypes[5] = { CL_PLATFORM_NAME,CL_PLATFORM_VENDOR,CL_PLATFORM_VERSION,CL_PLATFORM_PROFILE, | |
CL_PLATFORM_EXTENSIONS }; | |
size_t infoSize; | |
int numAttributes = NELEMS(attributeTypes); | |
char* info; | |
std::string infoContent = ""; | |
for (size_t i = 0; i < numPlatforms; i++) | |
{ | |
for (size_t j = 0; j < numAttributes; j++) | |
{ | |
clGetPlatformInfo(platforms[i], attributeTypes[j], 0, NULL, &infoSize); | |
info = new char[infoSize]; | |
// get platform attribute value | |
clGetPlatformInfo(platforms[i], attributeTypes[j], infoSize, info, NULL); | |
infoContent.assign(info, info + strlen(info)); | |
details += attributeNames[j] + " " + infoContent + '\n'; | |
} | |
std::cout << details << std::endl; | |
} | |
} | |
void ReadBytes(std::vector<char>* bytes,const std::string& pathDecode,unsigned long& fileSize) | |
{ | |
std::ifstream* file = new std::ifstream(pathDecode, std::ios::binary); | |
file->unsetf(std::ios::skipws); | |
file->seekg(0, std::ios::end); | |
fileSize = file->tellg(); | |
file->seekg(0, std::ios::beg); | |
bytes->reserve(fileSize); | |
bytes->insert(bytes->begin(), std::istream_iterator<char>(*file), std::istream_iterator<char>()); | |
delete file; | |
} | |
int Program::ParseFile(std::string& content, const std::string& filename) | |
{ | |
std::ifstream* openFile = new std::ifstream(filename, std::ios::binary); | |
size_t fileSize = 0; | |
if (openFile->is_open()) | |
{ | |
openFile->seekg(0, std::fstream::end); | |
fileSize = openFile->tellg(); | |
openFile->seekg(0, std::fstream::beg); | |
} | |
content.reserve(fileSize); | |
content.insert(content.begin(), std::istreambuf_iterator<char>(*openFile), std::istreambuf_iterator<char>()); | |
delete openFile; | |
if (content.size() <= 1) | |
return 1; | |
return 0; | |
} | |
void GetMessageError(cl_int status, cl_program program, cl_device_id device) | |
{ | |
size_t length = 0; | |
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &length); | |
size_t total = length * sizeof(char); | |
char* buffer = new char[total]; | |
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, length, buffer, NULL); | |
std::string message(buffer, total); | |
if (!message.empty()) | |
std::cout << message << std::endl; | |
else | |
std::cout << "Error: " << status << std::endl; | |
delete[] buffer; | |
} | |
void CheckErrorCode(cl_int status, cl_program& program, cl_device_id& devices, const std::string& message) | |
{ | |
if (status != 0) | |
{ | |
std::cout << message << std::endl; | |
GetMessageError(status, program, devices); | |
} | |
} | |
void Program::GetPlatform(cl_platform_id& platform,cl_uint& numberPlatforms,cl_platform_id* platforms) | |
{ | |
cl_int status = clGetPlatformIDs(0, NULL, &numberPlatforms); | |
if (status == 1) | |
{ | |
std::cout << "Failed Platforms not found" << std::endl; | |
} | |
if (numberPlatforms > 0) | |
{ | |
platforms = new cl_platform_id[numberPlatforms * sizeof(cl_platform_id)]; | |
status = clGetPlatformIDs(numberPlatforms, &platforms[0], &numberPlatforms); | |
platform = platforms[0]; | |
if (platform == nullptr) | |
{ | |
std::cout << "Error Obtaining platformId" << std::endl; | |
} | |
//std::string temp = ""; | |
//GetPlatformInfo(numberPlatforms,platforms,1,temp); | |
delete[] platforms; | |
} | |
} | |
void Program::GetDeviceIDs(cl_device_id*& devices, const cl_platform_id& platform) | |
{ | |
cl_uint deviceCount = 0; | |
cl_int status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &deviceCount); | |
if (deviceCount == 0) | |
{ | |
std::cout << "No GPU device available." << std::endl; | |
std::cout << "Choose CPU as default device." << std::endl; | |
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 0, NULL, &deviceCount); | |
devices = new cl_device_id[deviceCount * sizeof(cl_device_id)]; | |
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, deviceCount, devices, NULL); | |
} | |
else | |
{ | |
devices = new cl_device_id[(deviceCount * sizeof(cl_device_id))]; | |
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, deviceCount, devices, NULL); | |
} | |
} | |
void Program::GetContext(cl_context& context, const cl_platform_id& platform, cl_device_id*& devices) | |
{ | |
cl_context_properties contextProperties[] = { CL_CONTEXT_PLATFORM,reinterpret_cast<cl_context_properties>(platform), 0 }; | |
cl_int status = 0; | |
context = clCreateContext(contextProperties, 1, devices, NULL, NULL, &status); | |
if (status != 0) | |
{ | |
std::cout << "Error creating context for device" << std::endl; | |
} | |
} | |
void Program::GetCommandQueue(cl_command_queue& commandQueue, const cl_context& context, cl_device_id*& devices) | |
{ | |
commandQueue = clCreateCommandQueue(context, devices[0], 0, NULL); | |
} | |
template<size_t size> | |
void Program::CreateProgramWithSource(const char*& filePath, std::string& SourceStr, size_t(&sourceSize)[size], cl_context& context, cl_program& program) | |
{ | |
bool parsedFile = ParseFile(SourceStr, filePath); | |
if (parsedFile == 0) | |
{ | |
std::cout << "File Parsed" << std::endl; | |
} | |
const char* Source = SourceStr.c_str(); | |
sourceSize[0] = { strlen(Source) }; | |
program = clCreateProgramWithSource(context, 1, &Source, sourceSize, NULL); | |
} | |
void Program::BuildProgram(cl_program& program, const cl_uint& deviceCount, cl_device_id*& devices,const char* oclVersion) | |
{ | |
status = clBuildProgram(program, 1, devices, oclVersion, NULL, NULL); | |
if (status != 0) | |
{ | |
std::cout << "Program couldnt be built" << std::endl; | |
GetMessageError(status, program, devices[0]); | |
} | |
} | |
int main() | |
{ | |
Program p1; | |
cl_uint numPlatf = 0; | |
p1.GetPlatform(p1.platform,numPlatf,p1.platforms); | |
p1.GetDeviceIDs(p1.devices,p1.platform); | |
p1.GetContext(p1.context,p1.platform,p1.devices); | |
p1.GetCommandQueue(p1.commandQueue,p1.context,p1.devices); | |
p1.CreateProgramWithSource(p1.filePath,p1.strSource,p1.sourceSize,p1.context,p1.program); | |
p1.BuildProgram(p1.program,1,p1.devices,"-cl-std=CL2.0"); | |
std::string s; | |
GetPlatformInfo(numPlatf, &p1.platform,s); | |
limit=256.0f; | |
vChars.resize(sizeArr); | |
cl_mem outputBuffer = clCreateBuffer(p1.context, CL_MEM_WRITE_ONLY, sizeArr/*+ 1)*/*sizeof(cl_uchar), NULL, &p1.status); | |
/*cl_mem cbuff = clCreateBuffer(p1.context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float), (void*)& c, NULL);*/ | |
//create kernel | |
cl_kernel kernelAdd = clCreateKernel(p1.program, "Add", &p1.status); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating Kernel"); | |
//create kernel argument | |
p1.status = clSetKernelArg(kernelAdd, 0, sizeof(cl_float), (void*)& limit); | |
CheckErrorCode(p1.status,p1.program,p1.devices[0], "Failed adding Argument 0"); | |
p1.status = clSetKernelArg(kernelAdd, 1, sizeof(cl_mem), (void*)& outputBuffer); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed adding Argument 1"); | |
//array of work_dim unsigned values that describe the number of global work - items in work_dim dimensions | |
//that will execute the kernel function.The total number of global work - items is computed as global_work_size[0] * … * global_work_size[work_dim – 1]. | |
/****************************************/ | |
size_t globalWorkSize[1] = { sizeArr }; | |
//enqueues a command to execute a kernel on a device | |
/****************************************/ | |
size_t localWorkSize = 64; | |
p1.status = clEnqueueNDRangeKernel(p1.commandQueue, kernelAdd, 1, NULL, globalWorkSize,&localWorkSize , 0, NULL, NULL); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueNDRangeKernel 0"); | |
//enqueue the buffer for read | |
p1.status = clEnqueueReadBuffer(p1.commandQueue, outputBuffer, CL_TRUE, 0, sizeof(cl_uchar)*sizeArr, vChars.data(), 0, NULL, NULL); //call request that the device send data to the host,(sends the output result) | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed clEnqueueReadBuffer 0"); | |
/// | |
///output[sizeInput] = '\0'; //Add the terminal character to the end of output. | |
/// | |
for (int i = 0; i < vChars.size(); i++) | |
{ | |
std::cout << vChars[i] << std::endl; | |
} | |
const char* path = "C:\\Users\\PontiacGTX\\Desktop\\opencl.txt"; | |
ReadBytes(&fileBytes, path, filebyteCount); | |
indexByte.resize(filebyteCount); | |
compressedBytes.resize(filebyteCount); | |
compressedByteCount = globalWorkSize[0] = filebyteCount; | |
/*ReadBytes(&fileBytes,path, filebyteCount); | |
fileBytes.shrink_to_fit(); | |
filebyteCount = fileBytes.size(); | |
indexByte.resize(filebyteCount); | |
compressedBytes.resize(filebyteCount); | |
globalWorkSize[0] = filebyteCount;*/ | |
cl_kernel kernelCopyBytes = clCreateKernel(p1.program, "CopyBytes", &p1.status); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating kernel 1"); | |
cl_mem fileBytesBuffer = clCreateBuffer(p1.context, CL_MEM_READ_ONLY| CL_MEM_USE_HOST_PTR, filebyteCount * sizeof(cl_uchar),fileBytes.data(),&p1.status); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating buffer 0"); | |
/*cl_mem bufferSize = clCreateBuffer(p1.context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_ulong), &filebyteCount, &p1.status); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating buffer 1");*/ | |
cl_mem compressedBytesbuffer = clCreateBuffer(p1.context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, filebyteCount * sizeof(cl_uchar),compressedBytes.data(), &p1.status); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating buffer 2"); | |
int flags = CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER| CL_DEVICE_SVM_COARSE_GRAIN_BUFFER; | |
void* bufferCompressedBytes= clSVMAlloc(p1.context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, filebyteCount * sizeof(cl_uchar),0); | |
cl_mem indexByteBuffer = clCreateBuffer(p1.context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, filebyteCount * sizeof(cl_ulong), indexByte.data(), &p1.status); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating buffer 3"); | |
p1.status = clEnqueueWriteBuffer(p1.commandQueue, fileBytesBuffer, CL_TRUE, 0, filebyteCount * sizeof(cl_uchar), fileBytes.data(), 0, NULL, NULL); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueReadBuffer 1"); | |
p1.status = clSetKernelArg(kernelCopyBytes,0,sizeof(fileBytesBuffer),(void*)&fileBytesBuffer); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Adding Argument 0"); | |
p1.status = clSetKernelArg(kernelCopyBytes, 1, sizeof(cl_ulong), (void*)& compressedByteCount); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Adding Argument 1"); | |
p1.status = clSetKernelArg(kernelCopyBytes, 2, sizeof(compressedBytesbuffer), &compressedBytesbuffer);//compressedBytesbuffer | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Adding Argument 2"); | |
p1.status = clSetKernelArg(kernelCopyBytes,3, sizeof(indexByteBuffer), (void*)& indexByteBuffer); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Adding Argument 3"); | |
p1.status = clEnqueueNDRangeKernel(p1.commandQueue, kernelCopyBytes, 1, NULL, globalWorkSize, &localWorkSize, 0, NULL, NULL); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueNDRangeKernel 1"); | |
//enqueue the buffer for read | |
p1.status = clEnqueueReadBuffer(p1.commandQueue, compressedBytesbuffer, CL_TRUE, 0, filebyteCount * sizeof(cl_uchar*),(void*) compressedBytes.data(), 0, NULL, NULL); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueReadBuffer 1"); | |
p1.status = clEnqueueReadBuffer(p1.commandQueue, indexByteBuffer, CL_TRUE, 0, filebyteCount * sizeof(cl_ulong), (void*)indexByte.data(), 0, NULL, NULL); | |
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueReadBuffer 2"); | |
if (compressedBytes[0] != (char)NULL) | |
{ | |
std::cout << "File bytes passed to compressBytes array" << std::endl; | |
} | |
compressedBytes.shrink_to_fit(); | |
auto total = compressedBytes.size(); | |
for (auto i=0;i<total;i++) | |
{ | |
std::cout << compressedBytes[i] << std::endl; | |
} | |
//Step 12: Clean the resources. | |
/******************************/ | |
//Release kernel. | |
p1.status = clReleaseKernel(kernelAdd); | |
//Release the program object. | |
p1.status = clReleaseProgram(p1.program); | |
//Release mem object. | |
/****************************/ | |
//status = clReleaseMemObject(inputBuffer); | |
p1.status = clReleaseMemObject(outputBuffer); | |
//Release Command queue. | |
p1.status = clReleaseCommandQueue(p1.commandQueue); | |
//Release Command queue. | |
p1.status = clReleaseContext(p1.context); | |
/*if (output != NULL) | |
{ | |
free(output); | |
output = NULL; | |
}*/ | |
if (p1.devices != NULL) | |
{ | |
free(p1.devices); | |
p1.devices = NULL; | |
} | |
std::cout << "Passed!\n"; | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment