You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1185 lines
31 KiB

#ifndef OPENCLHELPER_H
#define OPENCLHELPER_H
#define CL_HPP_MINIMUM_OPENCL_VERSION 120
#define CL_HPP_TARGET_OPENCL_VERSION 120
#include <QObject>
#include <QFile>
#include <QDebug>
#include "CL/cl2.hpp"
#include "ESeverityLevel.h"
#include "ELogId.h"
using namespace cl;
class OpenCLHelper : public QObject
{
Q_OBJECT
private:
inline void handleError(ESeverityLevel::eSeverityLevel severityLevel,
ELogID::eLogId logID,
QString logText,
bool emitThrow = true) const;
inline std::vector<Platform> getPlatforms();
inline std::vector<Device> getDevices(std::vector<Platform> platforms);
inline QString getDeviceName(const Device& device);
public:
inline Context getContext();
inline Kernel createKernel(const Context context,
const QString kernelPath,
const QString KernelName);
inline Buffer* array2CLBuffer(const Context &context,
quint64 size,
bool read);
inline Image* frame2CLFrame(const Context& context,
ImageFormat clFrameFormat,
QVector<quint64> dimensions, bool read);
inline CommandQueue createCommandQueue(const Context& context,
const Device& device,
const cl_command_queue_properties properties);
template<typename... Ts>
inline KernelFunctor<Ts...> createKernelFunctor(const Kernel& kernel);
inline QVector<Device> getDevicesByContext(const Context& context);
inline size_t* getMaxGlobalWorkSize(const Kernel& kernel, const Device& device);
template<typename... Ts>
inline void runKernelFunctor(KernelFunctor<Ts...>& kernelFunctor,
EnqueueArgs args,
Ts... ts);
signals:
void sgl_sendLog (ESeverityLevel::eSeverityLevel severityLevel,
ELogID::eLogId logID,
QString logText) const;
};
void OpenCLHelper::handleError(ESeverityLevel::eSeverityLevel severityLevel,
ELogID::eLogId logID,
QString logText,
bool emitThrow) const
{
qDebug() << logText;
}
std::vector<Platform> OpenCLHelper::getPlatforms()
{
std::vector<Platform> platforms;
try {
if (Platform::get(&platforms) == CL_INVALID_VALUE)
{
handleError(ESeverityLevel::Alert,
ELogID::CLPlatformError,
"(CL_INVALID_VALUE)Error getting CL Platforms");
}
} catch (...) {
throw;
}
/// Removes platforms which are not nvidia or amd based
try {
std::vector<Platform> temp(platforms);
platforms.clear();
for (auto it = temp.begin(); it != temp.end(); it++)
{
string currentPlatformName = it->getInfo<CL_PLATFORM_NAME>();
handleError(ESeverityLevel::Debug,
ELogID::CLPlatformInfo,
"Platform Name: " + QString::fromStdString(currentPlatformName),
false);
if (!(it->getInfo<CL_PLATFORM_NAME>().find("NVIDIA") == string::npos) ||
!(it->getInfo<CL_PLATFORM_NAME>().find("AMD") == string::npos))
{
platforms.push_back(*it);
}
}
} catch (...) {
throw;
}
try {
if (platforms.size() == 0)
{
handleError(ESeverityLevel::Alert,
ELogID::CLPlatformError,
"No valid NVIDIA or AMD platform available.");
}
} catch (...) {
throw;
}
return platforms;
}
std::vector<Device> OpenCLHelper::getDevices(std::vector<Platform> platforms)
{
vector<Device> devices;
try {
if (platforms.size() == 0)
{
handleError(ESeverityLevel::Alert,
ELogID::CLPlatformError,
"No valid platforms.");
}
} catch (...) {
throw;
}
for (auto platform = platforms.begin(); platform != platforms.end(); platform++)
{
vector<Device> tempDevices;
try {
switch(cl_int err = platform->getDevices(CL_DEVICE_TYPE_GPU, &devices))
{
case CL_INVALID_DEVICE_TYPE:
{
QString messageText = QString::fromStdString(
"(CL_INVALID_DEVICE_TYPE) Invalid CL device type (" +
std::to_string(CL_DEVICE_TYPE_GPU) +
") while getting devices of platform " +
platform->getInfo<CL_PLATFORM_NAME>());
handleError(ESeverityLevel::Alert,
ELogID::CLPlatformError,
messageText,
false);
break;
}
case CL_INVALID_ARG_VALUE:
{
QString messageText = QString::fromStdString(
"(CL_INVALID_ARG_VALUE) Null device while getting devices of platform " +
platform->getInfo<CL_PLATFORM_NAME>());
handleError(ESeverityLevel::Alert,
ELogID::CLPlatformError,
messageText,
false);
break;
}
case CL_SUCCESS:
{
devices.insert(devices.begin(), tempDevices.begin(), tempDevices.end());
QString logText = "Devices registered successfuly: \"";
for (auto deviceIt = devices.begin(); deviceIt != devices.end(); deviceIt++)
{
logText = logText + QString::fromStdString(deviceIt->getInfo<CL_DEVICE_NAME>() + ",");
}
logText = logText + "\"";
handleError(ESeverityLevel::Debug,
ELogID::CLPlatformInfo,
logText,
false);
break;
}
default:
{
QString messageText = "Unknown error occured while getting devices of platform " +
QString::fromStdString(platform->getInfo<CL_PLATFORM_NAME>()) +
". CL error: " +
QString::number(err);
break;
}
} // end of switch
} catch (...) {
throw;
}
}
return devices;
}
Context OpenCLHelper::getContext()
{
static Context* context = nullptr;
if (context)
{
return *context;
}
vector<Platform> allPlatforms;
try
{
allPlatforms = getPlatforms();
}
catch(...)
{
throw;
}
vector<Device> allDevices;
try
{
allDevices = getDevices(allPlatforms);
}
catch(...)
{
throw;
}
if (allDevices.size() == 0)
{
try
{
handleError(ESeverityLevel::Alert,
ELogID::CLPlatformError,
"No processing devices found.");
}
catch(...)
{
throw;
}
}
cl_int err;
context = new Context(allDevices, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, &err);
try {
switch (err)
{
case CL_INVALID_PROPERTY:
{
handleError(ESeverityLevel::Critical,
ELogID::CLContextError,
"Error occured while creating CL context: CL_INVALID_PROPERTY");
break;
}
case CL_INVALID_DEVICE_TYPE:
{
handleError(ESeverityLevel::Critical,
ELogID::CLContextError,
"Error occured while creating CL context: CL_INVALID_DEVICE_TYPE");
break;
}
case CL_DEVICE_NOT_AVAILABLE:
{
handleError(ESeverityLevel::Critical,
ELogID::CLContextError,
"Error occured while creating CL context: CL_DEVICE_NOT_AVAILABLE");
break;
}
case CL_DEVICE_NOT_FOUND:
{
handleError(ESeverityLevel::Critical,
ELogID::CLContextError,
"Error occured while creating CL context: CL_DEVICE_NOT_FOUND");
break;
}
case CL_OUT_OF_HOST_MEMORY:
{
handleError(ESeverityLevel::Critical,
ELogID::CLContextError,
"Error occured while creating CL context: CL_OUT_OF_HOST_MEMORY");
break;
}
case CL_SUCCESS:
{
handleError(ESeverityLevel::Debug,
ELogID::CLContextInfo,
"CL Context created successfully.",
false);
break;
}
default:
{
QString logText = "Unknown error while creating CL context. CL error: " + QString::number(err);
handleError(ESeverityLevel::Critical,
ELogID::CLContextError,
logText);
}
} // end of switch
} catch (...) {
throw;
}
return *context;
}
Kernel OpenCLHelper::createKernel(const Context context,
const QString kernelPath,
const QString kernelName)
{
QString kernelFullPath = kernelPath + "/" + kernelName + ".cl";
QFile kernelFile(kernelFullPath);
try {
if (!kernelFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
handleError(ESeverityLevel::Critical,
ELogID::FileOpenError,
"Could not open kernel file: " + kernelFullPath);
}
} catch (...) {
}
QString kernelSource = kernelFile.readAll();
cl_int buildError;
Program program(context, kernelSource.toStdString(), true, &buildError);
try {
switch (buildError)
{
case CL_INVALID_CONTEXT:
{
QString logText = " (CL_INVALID_CONTEXT) Error building kernel \"" +
kernelFullPath +
"\". Context is not valid.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelBuildError,
logText);
break;
}
case CL_INVALID_VALUE:
{
QString logText = "(CL_INVALID_VALUE) Error building kernel \"" +
kernelFullPath +
"\". Source contains zero entries or any entry contains a tuple with NULL.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelBuildError,
logText);
break;
}
case CL_OUT_OF_RESOURCES:
{
QString logText = "(CL_OUT_OF_RESOURCES) Error building kernel \"" +
kernelFullPath +
"\". Failure to allocate resources on the device.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelBuildError,
logText);
break;
}
case CL_OUT_OF_HOST_MEMORY:
{
QString logText = "(CL_OUT_OF_HOST_MEMORY) Error building kernel \"" +
kernelFullPath +
"\". Failure to allocate resources on the host.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelBuildError,
logText);
break;
}
case CL_SUCCESS:
{
handleError(ESeverityLevel::Informational,
ELogID::CLKernelBuilt,
"Kernel \"" + kernelFullPath + "\" built successfully.",
false);
break;
}
default:
{
QString logText = "Unknown error occured whild building kernel \"" +
kernelFullPath +
"\". Error: " +
QString::number(buildError);
handleError(ESeverityLevel::Critical,
ELogID::CLKernelBuildError,
logText);
}
} // end of switch
} catch (...) {
}
// It is considered that there is only one kernel in the program and it's name is known.
cl_int kernelError;
Kernel kernel(program, kernelName.toStdString().c_str(), &kernelError);
try {
switch (kernelError)
{
case CL_INVALID_PROGRAM:
{
QString logText = "(CL_INVALID_PROGRAM) Kernel creation error (" +
kernelName +
"): Invalid program object.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelCreationError,
logText);
break;
}
case CL_INVALID_PROGRAM_EXECUTABLE:
{
QString logText = "(CL_INVALID_PROGRAM_EXECUTABLE) Kernel creation error (" +
kernelName +
"): There is no valid built executable.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelCreationError,
logText);
break;
}
case CL_INVALID_KERNEL_NAME:
{
QString logText = "(CL_INVALID_KERNEL_NAME) Kernel creation error (" +
kernelName +
"): Name is not found int the program.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelCreationError,
logText);
break;
}
case CL_INVALID_KERNEL_DEFINITION:
{
QString logText = "(CL_INVALID_KERNEL_DEFINITION) Kernel creation error (" +
kernelName +
"): Invalid kernel definition.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelCreationError,
logText);
break;
}
case CL_INVALID_VALUE:
{
QString logText = "(CL_INVALID_VALUE) Kernel creation error (" +
kernelName +
"): Name is NULL";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelCreationError,
logText);
break;
}
case CL_OUT_OF_RESOURCES:
{
QString logText = "(CL_OUT_OF_RESOURCES) Kernel creation error (" +
kernelName +
"): Failure to allocate resources on the device.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelCreationError,
logText);
break;
}
case CL_OUT_OF_HOST_MEMORY:
{
QString logText = "(CL_OUT_OF_HOST_MEMORY) Kernel creation error (" +
kernelName +
"): Failure to allocate resources on the host.";
handleError(ESeverityLevel::Critical,
ELogID::CLKernelCreationError,
logText);
break;
}
case CL_SUCCESS:
{
handleError(ESeverityLevel::Debug,
ELogID::CLKernelCreated,
"Kernel created successfully for kernel: " + kernelName,
false);
break;
}
default:
{
QString logText = "Kernel creation error (" +
kernelName +
"): Unknown error: " + QString::number(kernelError);
handleError(ESeverityLevel::Critical,
ELogID::CLKernelCreationError,
logText);
}
} //end of switch
} catch (...) {
}
return kernel;
}
Buffer* OpenCLHelper::array2CLBuffer(const Context &context,
quint64 size,
bool read = true)
{
Buffer* buffer = Q_NULLPTR;
cl_mem_flags clMemFlags = read ? CL_MEM_READ_ONLY : CL_MEM_WRITE_ONLY;
cl_int error;
buffer = new Buffer(context, clMemFlags, size, NULL, &error);
if(error != 0)
qDebug() << error;
return buffer;
}
Image* OpenCLHelper::frame2CLFrame(const Context &context,
ImageFormat clFrameFormat,
QVector<quint64> dimensions,
bool read = true)
{
Image* image = Q_NULLPTR;
cl_mem_flags clMemFlags = CL_MEM_READ_WRITE;
cl_int* error = Q_NULLPTR;
switch (dimensions.size())
{
case 1:
image = new Image1D(context,
clMemFlags,
clFrameFormat,
dimensions[0],
error);
break;
case 2:
image = new Image2D(context,
clMemFlags,
clFrameFormat,
dimensions[0],
dimensions[1],
0,
error);
break;
case 3:
image = new Image3D(context,
clMemFlags,
clFrameFormat,
dimensions[0],
dimensions[1],
dimensions[2],
0,
0,
error);
break;
default:
try {
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
"Number of dimenstions is not supported: " + QString::number(dimensions.size()));
} catch (...) {
throw;
}
}
try {
if (error)
{
QString logText;
switch (*error)
{
case CL_INVALID_CONTEXT:
logText = QString("(CL_INVALID_CONTEXT) The context is not valid ") +
"while creating CLImage.";
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_INVALID_VALUE:
logText = QString("(CL_INVALID_VALUE) Invalid memory flags ") +
"while creating CLImage: " + QString::number(clMemFlags);
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
logText = QString("(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR) Invalid CL frame format ") +
"while creating CLImage: image_channel_order: " +
QString::number(clFrameFormat.image_channel_order) +
" image_channel_data_type: " +
QString::number(clFrameFormat.image_channel_data_type);
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_INVALID_IMAGE_SIZE:
logText = QString("(CL_INVALID_IMAGE_SIZE) Invalid CL frame size ") +
"while creating CLImage: ";
foreach (quint64 dimension, dimensions)
{
logText += QString::number(dimension) + ",";
}
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_INVALID_HOST_PTR:
logText = QString("(CL_INVALID_HOST_PTR) Invalid host pointer ") +
"while creating CLImage.";
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_IMAGE_FORMAT_NOT_SUPPORTED :
logText = QString("(CL_IMAGE_FORMAT_NOT_SUPPORTED) CL Frame format not supported ") +
"while creating CLImage: image_channel_order: " +
QString::number(clFrameFormat.image_channel_order) +
" image_channel_data_type: " +
QString::number(clFrameFormat.image_channel_data_type);
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_MEM_OBJECT_ALLOCATION_FAILURE:
logText = QString("(CL_MEM_OBJECT_ALLOCATION_FAILURE) Failed to allocate memory ") +
"while creating CLImage.";
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_INVALID_OPERATION:
logText = QString("(CL_INVALID_OPERATION) No device in context to support CL frame ") +
"while creating CLImage.";
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_OUT_OF_RESOURCES:
logText = QString("(CL_OUT_OF_RESOURCES ) Failed to allocate resources on the device") +
"while creating CLImage.";
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
case CL_OUT_OF_HOST_MEMORY:
logText = QString("(CL_OUT_OF_RESOURCES ) Failed to allocate resources on the host") +
"while creating CLImage.";
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
default:
logText = QString("An unknown error occured ") +
"while creating CLImage.";
handleError(ESeverityLevel::Error,
ELogID::CLFrameError,
logText);
break;
} // end of switch
}
else
{
handleError(ESeverityLevel::Debug,
ELogID::CLFrameInfo,
"Frame successfully converted to CL Frame.",
false);
}
} catch (...) {
throw;
}
return image;
}
template<typename... Ts>
KernelFunctor<Ts...> OpenCLHelper::createKernelFunctor(const Kernel& kernel)
{
QString kernelName = QString::fromStdString(kernel.getInfo<CL_KERNEL_FUNCTION_NAME>());
cl_int error;
KernelFunctor<Ts...> kernelFunctor(kernel.getInfo<CL_KERNEL_PROGRAM>(), kernelName, &error);
try {
switch (error)
{
case CL_INVALID_PROGRAM:
{
QString logText = "(CL_INVALID_PROGRAM) KernelFunctor creation error (" +
kernelName +
"): Invalid program object.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelFunctorError,
logText);
break;
}
case CL_INVALID_PROGRAM_EXECUTABLE:
{
QString logText = "(CL_INVALID_PROGRAM_EXECUTABLE) KernelFunctor creation error (" +
kernelName +
"): There is no valid built executable.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelFunctorError,
logText);
break;
}
case CL_INVALID_KERNEL_NAME:
{
QString logText = "(CL_INVALID_KERNEL_NAME) KernelFunctor creation error (" +
kernelName +
"): Name is not found int the program.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelFunctorError,
logText);
break;
}
case CL_INVALID_KERNEL_DEFINITION:
{
QString logText = "(CL_INVALID_KERNEL_DEFINITION) KernelFunctor creation error (" +
kernelName +
"): Invalid kernel definition.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelFunctorError,
logText);
break;
}
case CL_INVALID_VALUE:
{
QString logText = "(CL_INVALID_VALUE) KernelFunctor creation error (" +
kernelName +
"): Name is NULL";
handleError(ESeverityLevel::Error,
ELogID::CLKernelFunctorError,
logText);
break;
}
case CL_OUT_OF_RESOURCES:
{
QString logText = "(CL_OUT_OF_RESOURCES) KernelFunctor creation error (" +
kernelName +
"): Failure to allocate resources on the device.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelFunctorError,
logText);
break;
}
case CL_OUT_OF_HOST_MEMORY:
{
QString logText = "(CL_OUT_OF_HOST_MEMORY) KernelFunctor creation error (" +
kernelName +
"): Failure to allocate resources on the host.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelFunctorError,
logText);
break;
}
case CL_SUCCESS:
{
handleError(ESeverityLevel::Debug,
ELogID::CLKernelFunctorCreated,
"KernelFunctor created successfully for kernel: " + kernelName,
false);
break;
}
default:
{
QString logText = "KernelFunctor creation error (" +
kernelName +
"): Unknown error: " + QString::number(error);
handleError(ESeverityLevel::Error,
ELogID::CLKernelFunctorError,
logText);
break;
}
} // end of switch
} catch (...) {
throw;
}
return (kernelFunctor);
}
CommandQueue OpenCLHelper::createCommandQueue(const Context& context,
const Device& device,
const cl_command_queue_properties properties = 0)
{
cl_int error;
CommandQueue commandQ(context, properties, &error);
try {
switch (error)
{
case CL_INVALID_CONTEXT:
{
QString logText = QString("(CL_INVALID_CONTEXT) An error occured while creating Queue. ") +
"Invalid context on device: " +
QString::fromStdString(device.getInfo<CL_DEVICE_NAME>());
handleError(ESeverityLevel::Error,
ELogID::CLCommandQueueCreationError,
logText);
break;
}
case CL_INVALID_DEVICE:
{
QString logText = QString("(CL_INVALID_DEVICE) An error occured while creating Queue on device. ") +
"Invalid device or not associated with the provided context: " +
QString::fromStdString(device.getInfo<CL_DEVICE_NAME>());
handleError(ESeverityLevel::Error,
ELogID::CLCommandQueueCreationError,
logText);
break;
}
case CL_INVALID_VALUE:
{
QString logText = QString("(CL_INVALID_VALUE) An error occured while creating Queue on device. ") +
"Invalid properties: " + QString::number(properties);
handleError(ESeverityLevel::Error,
ELogID::CLCommandQueueCreationError,
logText);
break;
}
case CL_INVALID_QUEUE_PROPERTIES:
{
QString logText = QString("(CL_INVALID_QUEUE_PROPERTIES) An error occured while creating Queue on device. ") +
"Properties \"" + QString::number(properties) + "\" " +
"not supperted by device: " + QString::fromStdString(device.getInfo<CL_DEVICE_NAME>());
handleError(ESeverityLevel::Error,
ELogID::CLCommandQueueCreationError,
logText);
break;
}
case CL_OUT_OF_RESOURCES:
{
QString logText = QString("(CL_OUT_OF_RESOURCES) An error occured while creating Queue on device. ") +
"Failed to allocate resources on device: " + QString::fromStdString(device.getInfo<CL_DEVICE_NAME>());
handleError(ESeverityLevel::Error,
ELogID::CLCommandQueueCreationError,
logText);
break;
}
case CL_OUT_OF_HOST_MEMORY:
{
QString logText = QString("(CL_OUT_OF_HOST_MEMORY) An error occured while creating Queue on device. ") +
"Failed to allocate resources on the host.";
handleError(ESeverityLevel::Error,
ELogID::CLCommandQueueCreationError,
logText);
break;
}
case CL_SUCCESS:
{
handleError(ESeverityLevel::Debug,
ELogID::CLCommandQueueCreated,
"CL Command Queue created successfully for device: " +
QString::fromStdString(device.getInfo<CL_DEVICE_NAME>()),
false);
break;
}
default:
{
handleError(ESeverityLevel::Error,
ELogID::CLCommandQueueCreationError,
"Unknown error occured while creating command queue on device " +
QString::fromStdString(device.getInfo<CL_DEVICE_NAME>()) +
" : " + QString::number(error));
break;
}
} // end of switch
} catch(...) {
throw;
}
return commandQ;
}
size_t* OpenCLHelper::getMaxGlobalWorkSize(const Kernel& kernel, const Device& device)
{
size_t* maxGlobalWorkSize = new size_t[3];
QString deviceName;
try
{
deviceName = getDeviceName(device);
}
catch (...)
{
handleError(ESeverityLevel::Warning,
ELogID::CLKernelError,
"An error occured while querying name of a CL device.",
false);
deviceName = "UNKNOWN_DEVICE";
}
auto error = kernel.getWorkGroupInfo<decltype (maxGlobalWorkSize)>(device, CL_KERNEL_GLOBAL_WORK_SIZE, &maxGlobalWorkSize);
try {
switch (error)
{
case CL_INVALID_DEVICE:
{
QString logText =
"(CL_INVALID_DEVICE) An error occured while querying maximum global work size from device: " +
deviceName + ". The device is invalid.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelError,
logText);
break;
}
case CL_INVALID_VALUE:
{
QString logText =
"(CL_INVALID_VALUE) An error occured while querying maximum global work size from device: " +
deviceName + ". Invlid passed parameters.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelError,
logText);
break;
}
case CL_INVALID_KERNEL:
{
QString logText =
"(CL_INVALID_KERNEL) An error occured while querying maximum global work size from device: " +
deviceName + ". Invalid kernel object.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelError,
logText);
break;
}
case CL_OUT_OF_RESOURCES:
{
QString logText =
"(CL_OUT_OF_RESOURCES) An error occured while querying maximum global work size from device: " +
deviceName + ". Failed to allocate resources on the device.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelError,
logText);
break;
}
case CL_OUT_OF_HOST_MEMORY:
{
QString logText =
"(CL_OUT_OF_HOST_MEMORY) An error occured while querying maximum global work size from device: " +
deviceName + ". Failed to allocate resources on the host.";
handleError(ESeverityLevel::Error,
ELogID::CLKernelError,
logText);
break;
}
case CL_SUCCESS:
{
handleError(ESeverityLevel::Debug,
ELogID::CLKernelInfo,
"Successfully queried the maximum global work size from device: " + deviceName,
false);
break;
}
default:
{
handleError(ESeverityLevel::Error,
ELogID::CLKernelError,
"Unknown error occured while querying the maximum global work size from device: " +
deviceName);
break;
}
} // end of switch
} catch (...) {
throw;
}
return (maxGlobalWorkSize);
}
QString OpenCLHelper::getDeviceName(const Device& device)
{
cl_int error;
auto deviceName = device.getInfo<CL_DEVICE_NAME>(&error);
try {
switch (error)
{
case CL_INVALID_DEVICE:
{
handleError(ESeverityLevel::Error,
ELogID::CLDeviceError,
"(CL_INVALID_DEVICE) An error occured while querying name of a CL device.");
break;
}
case CL_INVALID_VALUE:
{
handleError(ESeverityLevel::Error,
ELogID::CLDeviceError,
"(CL_INVALID_VALUE) An error occured related to passed parameters while querying name of a CL device.");
break;
}
case CL_OUT_OF_RESOURCES:
{
handleError(ESeverityLevel::Error,
ELogID::CLDeviceError,
QString("(CL_OUT_OF_RESOURCES) An error occured while querying name of a CL device. ") +
"Failed to allocate resources on the device.");
break;
}
case CL_OUT_OF_HOST_MEMORY:
{
handleError(ESeverityLevel::Error,
ELogID::CLDeviceError,
QString("(CL_OUT_OF_HOST_MEMORY) An error occured while querying name of a CL device. ") +
"Failed to allocate resources on the host.");
break;
}
case CL_SUCCESS:
{
handleError(ESeverityLevel::Debug,
ELogID::CLDeviceInfo,
"Successfully queried the name of a device: " + QString::fromStdString(deviceName),
false);
break;
}
default:
{
handleError(ESeverityLevel::Error,
ELogID::CLDeviceError,
"An unknown error occured while quering name of a CL device. error: " + QString::number(error));
break;
}
} // end of switch
} catch (...) {
throw;
}
return QString::fromStdString(deviceName);
}
QVector<Device> OpenCLHelper::getDevicesByContext(const Context &context)
{
std::vector<Device> devices;
auto error = context.getInfo<std::vector<Device>>(CL_CONTEXT_DEVICES, &devices);
try {
switch (error)
{
case CL_INVALID_CONTEXT:
{
handleError(ESeverityLevel::Error,
ELogID::CLContextError,
"(CL_INVALID_CONTEXT) An error occured while getting devices from a context.");
break;
}
case CL_INVALID_VALUE:
{
handleError(ESeverityLevel::Error,
ELogID::CLContextError,
QString("(CL_INVALID_VALUE) An error occured while getting devices from a context.") +
"Something went wrong with the parsed parameter value.");
break;
}
case CL_OUT_OF_RESOURCES:
{
handleError(ESeverityLevel::Error,
ELogID::CLContextError,
"(CL_OUT_OF_RESOURCES) An error occured while getting devices from a context.");
break;
}
case CL_OUT_OF_HOST_MEMORY:
{
handleError(ESeverityLevel::Error,
ELogID::CLContextError,
"(CL_OUT_OF_HOST_MEMORY) An error occured while getting devices from a context.");
break;
}
case CL_SUCCESS:
{
handleError(ESeverityLevel::Debug,
ELogID::CLContextInfo,
"Devices successfully queried from context.",
false);
break;
}
default:
{
handleError(ESeverityLevel::Error,
ELogID::CLContextError,
"Unknown error occured while quering devices from context. error: " + QString::number(error));
break;
}
} // end of switch
} catch (...)
{
throw;
}
// qDebug() << "End of kernel functor";
return (QVector<Device>::fromStdVector(devices));
}
template<typename... Ts>
void OpenCLHelper::runKernelFunctor (KernelFunctor<Ts...>& kernelFunctor,
EnqueueArgs args,
Ts... ts)
{
cl_int error;
kernelFunctor(args, ts..., error);
if(error != 0)
qDebug() << "Error : "<< error;
try {
switch(error)
{
case CL_INVALID_PROGRAM_EXECUTABLE:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_PROGRAM_EXECUTABLE) There is no successfully built program executable.");
break;
case CL_INVALID_KERNEL:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_KERNEL) Invalid kernel object.");
break;
case CL_INVALID_CONTEXT:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_CONTEXT) Invalid context associated with the command queue and kernel.");
break;
case CL_INVALID_KERNEL_ARGS:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_KERNEL_ARGS) Kernel arguments has not been specified.");
break;
case CL_INVALID_GLOBAL_WORK_SIZE:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_GLOBAL_WORK_SIZE) Invalid global work size specified.");
break;
case CL_INVALID_GLOBAL_OFFSET:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_GLOBAL_OFFSET) Invalid offset size specified.");
break;
case CL_INVALID_WORK_GROUP_SIZE:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_WORK_GROUP_SIZE) Work group size mismatch.");
break;
case CL_INVALID_WORK_ITEM_SIZE:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_WORK_ITEM_SIZE) Work item size mismatch.");
break;
case CL_MISALIGNED_SUB_BUFFER_OFFSET:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_MISALIGNED_SUB_BUFFER_OFFSET) Subbuffer offset mismatch.");
break;
case CL_INVALID_IMAGE_SIZE:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_IMAGE_SIZE) Image dimension not supported by the device.");
break;
case CL_OUT_OF_RESOURCES:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_OUT_OF_RESOURCES) Insufficient resources needed to execute the kernel.");
break;
case CL_MEM_OBJECT_ALLOCATION_FAILURE:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_MEM_OBJECT_ALLOCATION_FAILURE) Failure to allocate memory.");
break;
case CL_INVALID_EVENT_WAIT_LIST:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_INVALID_EVENT_WAIT_LIST) Invalid event objects in events wait list.");
break;
case CL_OUT_OF_HOST_MEMORY:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunError,
"(CL_OUT_OF_HOST_MEMORY) Failure to allocate resources on the host.");
break;
case CL_SUCCESS:
{
handleError(ESeverityLevel::Debug,
ELogID::CLKernelRunInfo,
"Successfully ran the kernel.",
false);
break;
}
default:
handleError(ESeverityLevel::Error,
ELogID::CLKernelRunInfo,
"There was an unknown error while running the kernel.");
break;
} // end of switch
} catch (...)
{
throw;
}
}
#endif