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.
655 lines
22 KiB
655 lines
22 KiB
4 years ago
|
#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 "logger/Logger.h"
|
||
|
#include "lib/CL/cl2.hpp"
|
||
|
|
||
|
#define caseReturnString(x) case x: \
|
||
|
return #x
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief The OpenCLHelper class
|
||
|
* @note This class can not be broken to .h and .cpp files, because of the way opencl works,
|
||
|
* if we include it in 2 places it complains about duplicated defenition
|
||
|
* @author Mohsen Emami revised by Hessamoddin Hediyehloo(H-4nd-H)
|
||
|
* @date 2019/8/5(1398/5/14)
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
class OpenClHelper : public QObject
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
|
||
|
private:
|
||
|
inline std::vector<cl::Platform> getAllAvailablePlatform();
|
||
|
|
||
|
inline std::vector<cl::Platform> getAmdAndNvidiaPlatforms();
|
||
|
|
||
|
inline std::vector<cl::Platform> filterNoneAmdAndNoneNvidiaPlatforms(
|
||
|
std::vector<cl::Platform> platforms);
|
||
|
|
||
|
inline void ThrowIfNoPlatformAvailable(const std::vector<cl::Platform>& platforms);
|
||
|
|
||
|
inline std::vector<cl::Device> getAllAvailableDevicesForValidPlatforms(
|
||
|
const std::vector<cl::Platform>& platforms);
|
||
|
|
||
|
inline std::vector<cl::Device> getAllAvailableDevicesForGivenPlatforms(
|
||
|
const cl::Platform& platform);
|
||
|
|
||
|
inline void ThrowIfNoDeviceAvailable(const std::vector<cl::Device>& devices);
|
||
|
|
||
|
inline QString getErrorString(int error);
|
||
|
|
||
|
inline QString getKernelFullPath(QString kernelPath, QString kernelName);
|
||
|
|
||
|
inline std::string readKernelSourceCode(QString kernelPath);
|
||
|
|
||
|
inline cl::Program createProgramFromKernelCode(const cl::Context& context,
|
||
|
std::string kernelSource);
|
||
|
|
||
|
inline cl::Kernel createKernelFromProgram(const cl::Program& program, QString kernelName);
|
||
|
|
||
|
public:
|
||
|
inline cl::Context& getContext();
|
||
|
inline cl::Device getFirstDeviceByContext(const cl::Context& context);
|
||
|
inline cl::Kernel createKernel(const cl::Context& context,
|
||
|
const QString kernelPath,
|
||
|
const QString KernelName);
|
||
|
|
||
|
inline cl::Buffer* allocateClBuffer(const cl::Context& context,
|
||
|
quint64 size,
|
||
|
bool read);
|
||
|
|
||
|
inline cl::Image* allocateClImage(const cl::Context& context,
|
||
|
cl::ImageFormat clFrameFormat,
|
||
|
QList<quint64> dimensions, bool read);
|
||
|
|
||
|
inline cl::CommandQueue createCommandQueue(const cl::Context& context,
|
||
|
const cl_command_queue_properties properties);
|
||
|
template<typename ... Ts>
|
||
|
inline cl::KernelFunctor<Ts...> createKernelFunctor(const cl::Kernel& kernel);
|
||
|
|
||
|
template<typename ... Ts>
|
||
|
inline void runKernelFunctor(cl::KernelFunctor<Ts...>& kernelFunctor,
|
||
|
cl::EnqueueArgs args,
|
||
|
Ts... ts);
|
||
|
};
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Returns the name of error
|
||
|
* @param error The error to get th ename of
|
||
|
* @return The error name
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
QString OpenClHelper::getErrorString(int error)
|
||
|
{
|
||
|
switch(error)
|
||
|
{
|
||
|
caseReturnString(CL_SUCCESS);
|
||
|
caseReturnString(CL_DEVICE_NOT_FOUND);
|
||
|
caseReturnString(CL_DEVICE_NOT_AVAILABLE);
|
||
|
caseReturnString(CL_COMPILER_NOT_AVAILABLE);
|
||
|
caseReturnString(CL_MEM_OBJECT_ALLOCATION_FAILURE);
|
||
|
caseReturnString(CL_OUT_OF_RESOURCES);
|
||
|
caseReturnString(CL_OUT_OF_HOST_MEMORY);
|
||
|
caseReturnString(CL_PROFILING_INFO_NOT_AVAILABLE);
|
||
|
caseReturnString(CL_MEM_COPY_OVERLAP);
|
||
|
caseReturnString(CL_IMAGE_FORMAT_MISMATCH);
|
||
|
caseReturnString(CL_IMAGE_FORMAT_NOT_SUPPORTED);
|
||
|
caseReturnString(CL_BUILD_PROGRAM_FAILURE);
|
||
|
caseReturnString(CL_MAP_FAILURE);
|
||
|
caseReturnString(CL_MISALIGNED_SUB_BUFFER_OFFSET);
|
||
|
caseReturnString(CL_COMPILE_PROGRAM_FAILURE);
|
||
|
caseReturnString(CL_LINKER_NOT_AVAILABLE);
|
||
|
caseReturnString(CL_LINK_PROGRAM_FAILURE);
|
||
|
caseReturnString(CL_DEVICE_PARTITION_FAILED);
|
||
|
caseReturnString(CL_KERNEL_ARG_INFO_NOT_AVAILABLE);
|
||
|
caseReturnString(CL_INVALID_VALUE);
|
||
|
caseReturnString(CL_INVALID_DEVICE_TYPE);
|
||
|
caseReturnString(CL_INVALID_PLATFORM);
|
||
|
caseReturnString(CL_INVALID_DEVICE);
|
||
|
caseReturnString(CL_INVALID_CONTEXT);
|
||
|
caseReturnString(CL_INVALID_QUEUE_PROPERTIES);
|
||
|
caseReturnString(CL_INVALID_COMMAND_QUEUE);
|
||
|
caseReturnString(CL_INVALID_HOST_PTR);
|
||
|
caseReturnString(CL_INVALID_MEM_OBJECT);
|
||
|
caseReturnString(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
|
||
|
caseReturnString(CL_INVALID_IMAGE_SIZE);
|
||
|
caseReturnString(CL_INVALID_SAMPLER);
|
||
|
caseReturnString(CL_INVALID_BINARY);
|
||
|
caseReturnString(CL_INVALID_BUILD_OPTIONS);
|
||
|
caseReturnString(CL_INVALID_PROGRAM);
|
||
|
caseReturnString(CL_INVALID_PROGRAM_EXECUTABLE);
|
||
|
caseReturnString(CL_INVALID_KERNEL_NAME);
|
||
|
caseReturnString(CL_INVALID_KERNEL_DEFINITION);
|
||
|
caseReturnString(CL_INVALID_KERNEL);
|
||
|
caseReturnString(CL_INVALID_ARG_INDEX);
|
||
|
caseReturnString(CL_INVALID_ARG_VALUE);
|
||
|
caseReturnString(CL_INVALID_ARG_SIZE);
|
||
|
caseReturnString(CL_INVALID_KERNEL_ARGS);
|
||
|
caseReturnString(CL_INVALID_WORK_DIMENSION);
|
||
|
caseReturnString(CL_INVALID_WORK_GROUP_SIZE);
|
||
|
caseReturnString(CL_INVALID_WORK_ITEM_SIZE);
|
||
|
caseReturnString(CL_INVALID_GLOBAL_OFFSET);
|
||
|
caseReturnString(CL_INVALID_EVENT_WAIT_LIST);
|
||
|
caseReturnString(CL_INVALID_EVENT);
|
||
|
caseReturnString(CL_INVALID_OPERATION);
|
||
|
caseReturnString(CL_INVALID_GL_OBJECT);
|
||
|
caseReturnString(CL_INVALID_BUFFER_SIZE);
|
||
|
caseReturnString(CL_INVALID_MIP_LEVEL);
|
||
|
caseReturnString(CL_INVALID_GLOBAL_WORK_SIZE);
|
||
|
caseReturnString(CL_INVALID_PROPERTY);
|
||
|
caseReturnString(CL_INVALID_IMAGE_DESCRIPTOR);
|
||
|
caseReturnString(CL_INVALID_COMPILER_OPTIONS);
|
||
|
caseReturnString(CL_INVALID_LINKER_OPTIONS);
|
||
|
caseReturnString(CL_INVALID_DEVICE_PARTITION_COUNT);
|
||
|
|
||
|
default:
|
||
|
return "Unknown OpenCL error code";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Return the full file path for the kernel
|
||
|
* @param kernelPath Directory of kernel
|
||
|
* @param kernelName Kernel name
|
||
|
* @return Full kernel path
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
QString OpenClHelper::getKernelFullPath(QString kernelPath, QString kernelName)
|
||
|
{
|
||
|
return QDir(kernelPath).filePath(kernelName + ".cl");
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Read kernel source file from the given path
|
||
|
* @param kernelPath Kernel file path
|
||
|
* @return Kernel source code
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
std::string OpenClHelper::readKernelSourceCode(QString kernelPath)
|
||
|
{
|
||
|
QFile kernelFile(kernelPath);
|
||
|
|
||
|
if(!kernelFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLKernelError,
|
||
|
"Can not open kernel file @ " + kernelPath,
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
auto kernelSource = kernelFile.readAll().toStdString();
|
||
|
|
||
|
kernelFile.close();
|
||
|
|
||
|
return kernelSource;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Compile the rkernel code and create a ne wprogram object
|
||
|
* @param context OpenCL object
|
||
|
* @param kernelSource Kernel source code
|
||
|
* @return Created program object
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
cl::Program OpenClHelper::createProgramFromKernelCode(const cl::Context& context,
|
||
|
std::string kernelSource)
|
||
|
{
|
||
|
cl_int err = 0;
|
||
|
|
||
|
cl::Program program(context, kernelSource, true, &err);
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLKernelError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return program;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Create kernel object from openCl program object
|
||
|
* @param program OpenCL program object
|
||
|
* @param kernelName Name of the kernel
|
||
|
* @return OpenCl kernel
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
cl::Kernel OpenClHelper::createKernelFromProgram(const cl::Program& program, QString kernelName)
|
||
|
{
|
||
|
cl_int err;
|
||
|
|
||
|
cl::Kernel kernel(program, kernelName.toStdString().c_str(), &err);
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLKernelError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return kernel;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Checks to see if platform list is empty or not, throws exception if empty
|
||
|
* @param platforms List of platforms
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
void OpenClHelper::ThrowIfNoPlatformAvailable(const std::vector<cl::Platform>& platforms)
|
||
|
{
|
||
|
if(platforms.size() > 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLPlatformError,
|
||
|
"No valid platform was found",
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Checks to see if device list is empty or not, throws exception if empty
|
||
|
* @param devices List of devices
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
void OpenClHelper::ThrowIfNoDeviceAvailable(const std::vector<cl::Device>& devices)
|
||
|
{
|
||
|
if(devices.size() > 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLDeviceError,
|
||
|
"No valid device was found",
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Return all available opencl platforms
|
||
|
* @return Availaable opencl platforms
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
std::vector<cl::Platform> OpenClHelper::getAllAvailablePlatform()
|
||
|
{
|
||
|
std::vector<cl::Platform> availablePlatforms;
|
||
|
|
||
|
cl_int err = cl::Platform::get(&availablePlatforms);
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLPlatformError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return availablePlatforms;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Remove none amd and none nvidia paltforsm from a given list of platforms
|
||
|
* @param platforms List of available platforms
|
||
|
* @return Platform list containing only nvidia and amd
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
std::vector<cl::Platform> OpenClHelper::filterNoneAmdAndNoneNvidiaPlatforms(
|
||
|
std::vector<cl::Platform> platforms)
|
||
|
{
|
||
|
std::vector<cl::Platform> AmdNvidiaPlatforms;
|
||
|
for(auto it = platforms.begin(); it != platforms.end(); it++)
|
||
|
{
|
||
|
cl::string currentPlatformName = it->getInfo<CL_PLATFORM_NAME>();
|
||
|
|
||
|
Logger::log(ESeverityLevel::Debug, ELogID::CLPlatformInfo,
|
||
|
"Platform Name: " + QString::fromStdString(currentPlatformName),
|
||
|
this->metaObject()->className());
|
||
|
|
||
|
if(!(it->getInfo<CL_PLATFORM_NAME>().find("NVIDIA") == cl::string::npos) ||
|
||
|
!(it->getInfo<CL_PLATFORM_NAME>().find("AMD") == cl::string::npos))
|
||
|
{
|
||
|
AmdNvidiaPlatforms.push_back(*it);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return AmdNvidiaPlatforms;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief gets available nvidia or amd platforms on host machine
|
||
|
* @return platforms The list of available nvidia nd amd platforms
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
std::vector<cl::Platform> OpenClHelper::getAmdAndNvidiaPlatforms()
|
||
|
{
|
||
|
auto availablePlatform = getAllAvailablePlatform();
|
||
|
|
||
|
availablePlatform = filterNoneAmdAndNoneNvidiaPlatforms(availablePlatform);
|
||
|
|
||
|
ThrowIfNoPlatformAvailable(availablePlatform);
|
||
|
|
||
|
return availablePlatform;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief get the opencl devices for all provided platforms
|
||
|
* @param platforms The list of nvidia and amd platforms \sa getPlatforms
|
||
|
* @return devices List of available devices for provided platforms
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
std::vector<cl::Device> OpenClHelper::getAllAvailableDevicesForValidPlatforms(
|
||
|
const std::vector<cl::Platform>& platforms)
|
||
|
{
|
||
|
std::vector<cl::Device> availableDevices;
|
||
|
for(auto platform = platforms.begin(); platform != platforms.end(); platform++)
|
||
|
{
|
||
|
auto temp = getAllAvailableDevicesForGivenPlatforms(*platform);
|
||
|
|
||
|
for(auto device = temp.begin(); device != temp.end(); device++)
|
||
|
{
|
||
|
availableDevices.push_back(*device);
|
||
|
cl::string currentDeviceName = device->getInfo<CL_DEVICE_NAME>();
|
||
|
|
||
|
Logger::log(ESeverityLevel::Debug, ELogID::CLDeviceInfo,
|
||
|
"Device Name: " + QString::fromStdString(currentDeviceName),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return availableDevices;
|
||
|
}
|
||
|
|
||
|
std::vector<cl::Device> OpenClHelper::getAllAvailableDevicesForGivenPlatforms(
|
||
|
const cl::Platform& platform)
|
||
|
{
|
||
|
std::vector<cl::Device> availableDevices;
|
||
|
cl_int err = platform.getDevices(CL_DEVICE_TYPE_GPU, &availableDevices);
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLDeviceError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return availableDevices;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief get context of opencl
|
||
|
* @return context Actual opencl context
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
cl::Context& OpenClHelper::getContext()
|
||
|
{
|
||
|
static cl::Context* internalContext = nullptr;
|
||
|
if(internalContext)
|
||
|
{
|
||
|
return *internalContext;
|
||
|
}
|
||
|
|
||
|
auto platforms = getAmdAndNvidiaPlatforms();
|
||
|
|
||
|
auto devices = getAllAvailableDevicesForValidPlatforms(platforms);
|
||
|
|
||
|
cl_int err;
|
||
|
internalContext = new cl::Context(devices, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, &err);
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLContextError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return *internalContext;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Creates and compiles the given kernel
|
||
|
* @param context OpenCl contex \sa getContext
|
||
|
* @param kernelPath The folder directory for kernel
|
||
|
* @param kernelName The kernel file name without .cl extension
|
||
|
* @return kernel The newly created kernel instance
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
cl::Kernel OpenClHelper::createKernel(const cl::Context& context,
|
||
|
const QString kernelPath,
|
||
|
const QString kernelName)
|
||
|
{
|
||
|
auto kernelFullPath = getKernelFullPath(kernelPath, kernelName);
|
||
|
|
||
|
auto kernelSource = readKernelSourceCode(kernelFullPath);
|
||
|
|
||
|
auto program = createProgramFromKernelCode(context, kernelSource);
|
||
|
|
||
|
return createKernelFromProgram(program, kernelName);
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief allocate a cl buffer
|
||
|
* @param context OpenCL context \sa getContext
|
||
|
* @param size Number of bytes to allocate
|
||
|
* @param read Should the buffer be allocated with read access or write access
|
||
|
* @return buffer The allocated buffer pointer
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
cl::Buffer* OpenClHelper::allocateClBuffer(const cl::Context& context,
|
||
|
quint64 size, bool read = true)
|
||
|
{
|
||
|
cl_mem_flags clMemFlags = read ? CL_MEM_READ_ONLY : CL_MEM_WRITE_ONLY;
|
||
|
|
||
|
cl_int err;
|
||
|
auto buffer = new cl::Buffer(context, clMemFlags, size, Q_NULLPTR, &err);
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLBufferError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return buffer;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Allocate proper CL image based on input
|
||
|
* @param context OpenCL context \sa getContext
|
||
|
* @param clFrameFormat Frame format for image
|
||
|
* @param dimensions List containing size for each image dimension, can be 1D, 2D or 3D
|
||
|
* @return image Actual allocated image
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
cl::Image* OpenClHelper::allocateClImage(const cl::Context& context,
|
||
|
cl::ImageFormat clFrameFormat,
|
||
|
QList<quint64> dimensions,
|
||
|
bool read)
|
||
|
{
|
||
|
cl_mem_flags clMemFlags = CL_MEM_READ_WRITE;
|
||
|
|
||
|
cl::Image* image = Q_NULLPTR;
|
||
|
|
||
|
cl_int err = 0;
|
||
|
|
||
|
switch(dimensions.size())
|
||
|
{
|
||
|
case 1:
|
||
|
image = new cl::Image1D(context,
|
||
|
clMemFlags,
|
||
|
clFrameFormat,
|
||
|
dimensions[0],
|
||
|
&err);
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
image = new cl::Image2D(context,
|
||
|
clMemFlags,
|
||
|
clFrameFormat,
|
||
|
dimensions[0],
|
||
|
dimensions[1],
|
||
|
0,
|
||
|
&err);
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
image = new cl::Image3D(context,
|
||
|
clMemFlags,
|
||
|
clFrameFormat,
|
||
|
dimensions[0],
|
||
|
dimensions[1],
|
||
|
dimensions[2],
|
||
|
0,
|
||
|
0,
|
||
|
&err);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLFrameError,
|
||
|
"Invalid dimension size",
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLFrameError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return image;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Creates a functor for given kernel
|
||
|
* @param kernel The kernel to build functor for
|
||
|
* @return functor The created functor
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
template<typename ... Ts>
|
||
|
cl::KernelFunctor<Ts...> OpenClHelper::createKernelFunctor(const cl::Kernel& kernel)
|
||
|
{
|
||
|
auto kernelName = QString::fromStdString(kernel.getInfo<CL_KERNEL_FUNCTION_NAME>());
|
||
|
|
||
|
cl_int err;
|
||
|
|
||
|
cl::KernelFunctor<Ts...> functor(kernel.getInfo<CL_KERNEL_PROGRAM>(), kernelName, &err);
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLKernelFunctorError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return functor;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Create an OpenCl commandQueue
|
||
|
* @param context OpenCL context \sa getContext
|
||
|
* @param properties Properties to build queue upon them
|
||
|
* @return queue The newly created queue
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
cl::CommandQueue OpenClHelper::createCommandQueue(const cl::Context& context,
|
||
|
const cl_command_queue_properties properties)
|
||
|
{
|
||
|
cl_int err;
|
||
|
cl::CommandQueue commandQueue(context, properties, &err);
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLCommandQueueCreationError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return commandQueue;
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Returns the first device of context
|
||
|
* @param context OpenCl context \sa getContext
|
||
|
* @param device First device of context
|
||
|
* @return success or failure
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
cl::Device OpenClHelper::getFirstDeviceByContext(const cl::Context& context)
|
||
|
{
|
||
|
std::vector<cl::Device> devices;
|
||
|
auto err = context.getInfo<std::vector<cl::Device> >(CL_CONTEXT_DEVICES, &devices);
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLDeviceError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
|
||
|
return devices[0];
|
||
|
}
|
||
|
|
||
|
/*************************************************************************************************/
|
||
|
/**
|
||
|
* @brief Run the kernel functor \sa createKernelFunctor
|
||
|
* @param kernelFunctor Functor to run
|
||
|
* @param args Arg structure for functor
|
||
|
* @param ts actual arg for functor
|
||
|
* @return success or failure
|
||
|
*/
|
||
|
/*************************************************************************************************/
|
||
|
template<typename ... Ts>
|
||
|
void OpenClHelper::runKernelFunctor(cl::KernelFunctor<Ts...>& kernelFunctor,
|
||
|
cl::EnqueueArgs args,
|
||
|
Ts... ts)
|
||
|
{
|
||
|
cl_int err;
|
||
|
kernelFunctor(args, ts ..., err);
|
||
|
|
||
|
if(err != CL_SUCCESS)
|
||
|
{
|
||
|
throw LoggerException(ESeverityLevel::Alert,
|
||
|
ELogID::CLKernelRunError,
|
||
|
getErrorString(err),
|
||
|
this->metaObject()->className());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|