323 lines
8.4 KiB
C++
323 lines
8.4 KiB
C++
/*! \file piopencl.h
|
||
* \ingroup OpenCL
|
||
* \~\brief
|
||
* \~english OpenCL classes
|
||
* \~russian Классы OpenCL
|
||
*/
|
||
/*
|
||
PIP - Platform Independent Primitives
|
||
OpenCL wrappers
|
||
Ivan Pelipenko peri4ko@yandex.ru
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
//! \defgroup OpenCL OpenCL
|
||
//! \~\brief
|
||
//! \~english OpenCL support
|
||
//! \~russian Поддержка OpenCL
|
||
//!
|
||
//! \~\details
|
||
//! \~english \section cmake_module_OpenCL Building with CMake
|
||
//! \~russian \section cmake_module_OpenCL Сборка с использованием CMake
|
||
//!
|
||
//! \~\code
|
||
//! find_package(PIP REQUIRED)
|
||
//! target_link_libraries([target] PIP::OpenCL)
|
||
//! \endcode
|
||
//!
|
||
//! \~english \par Common
|
||
//! \~russian \par Общее
|
||
//!
|
||
//! \~english
|
||
//! These files provides OpenCL classes wrap.
|
||
//!
|
||
//! \~russian
|
||
//! Эти файлы обеспечивают классовую обвязку OpenCL.
|
||
//!
|
||
//! \~\authors
|
||
//! \~english
|
||
//! Ivan Pelipenko peri4ko@yandex.ru;
|
||
//! Andrey Bychkov work.a.b@yandex.ru;
|
||
//! \~russian
|
||
//! Иван Пелипенко peri4ko@yandex.ru;
|
||
//! Андрей Бычков work.a.b@yandex.ru;
|
||
//!
|
||
|
||
#ifndef PIOPENCL_H
|
||
#define PIOPENCL_H
|
||
|
||
#include "pip_opencl_export.h"
|
||
#include "pivariant.h"
|
||
|
||
|
||
class PIP_OPENCL_EXPORT PIOpenCL {
|
||
public:
|
||
|
||
struct KernelArg;
|
||
struct Device;
|
||
struct Platform;
|
||
class Context;
|
||
class Buffer;
|
||
class Program;
|
||
class Kernel;
|
||
|
||
typedef PIVector<Device> DeviceList;
|
||
|
||
|
||
enum AddressQualifier {
|
||
AddressGlobal,
|
||
AddressLocal,
|
||
AddressConstant,
|
||
AddressPrivate,
|
||
};
|
||
|
||
enum AccessQualifier {
|
||
AccessReadOnly,
|
||
AccessWriteOnly,
|
||
AccessReadWrite,
|
||
AccessNone,
|
||
};
|
||
|
||
enum Direction {
|
||
Input = 0x01,
|
||
Output = 0x02,
|
||
InputOutput = Input | Output,
|
||
};
|
||
|
||
enum TypeQualifier {
|
||
TypeConst,
|
||
TypeRestrict,
|
||
TypeVolatile,
|
||
TypeNone,
|
||
};
|
||
|
||
enum ArgType {
|
||
Char = 1,
|
||
UChar,
|
||
Short,
|
||
UShort,
|
||
Int,
|
||
UInt,
|
||
Long,
|
||
ULong,
|
||
Float,
|
||
Double,
|
||
};
|
||
|
||
|
||
struct PIP_OPENCL_EXPORT KernelArg {
|
||
KernelArg();
|
||
AddressQualifier address_qualifier;
|
||
AccessQualifier access_qualifier;
|
||
Direction direction;
|
||
TypeQualifier type_qualifier;
|
||
PIString arg_name;
|
||
PIString type_name;
|
||
PIString base_type_name;
|
||
bool is_pointer;
|
||
ArgType arg_type;
|
||
int dims;
|
||
private:
|
||
friend class Kernel;
|
||
void init(void * _k, uint index);
|
||
};
|
||
|
||
|
||
struct PIP_OPENCL_EXPORT Device {
|
||
Device() {id = platform_id = 0; max_compute_units = max_clock_frequency = 0; max_memory_size = 0;}
|
||
bool isValid() const {return id != 0;}
|
||
PIString displayText() const {return name.trimmed() + " (" + device_version.trimmed() + ")";}
|
||
void * id;
|
||
void * platform_id;
|
||
PIString name;
|
||
PIString vendor;
|
||
PIString device_version;
|
||
PIString driver_version;
|
||
int max_compute_units;
|
||
int max_clock_frequency;
|
||
ullong max_memory_size;
|
||
};
|
||
|
||
|
||
struct PIP_OPENCL_EXPORT Platform {
|
||
Platform() {id = 0;}
|
||
bool isValid() const {return id != 0;}
|
||
PIString displayText() const {return name.trimmed() + " (" + version.trimmed() + ", " + profile.trimmed() + ")";}
|
||
void * id;
|
||
PIString name;
|
||
PIString vendor;
|
||
PIString profile;
|
||
PIString version;
|
||
PIStringList extensions;
|
||
PIVector<Device> devices;
|
||
};
|
||
|
||
|
||
class PIP_OPENCL_EXPORT Context {
|
||
friend class Buffer;
|
||
friend class Program;
|
||
friend class Kernel;
|
||
public:
|
||
~Context();
|
||
void * handle();
|
||
void * queue();
|
||
static Context * create(const DeviceList & dl);
|
||
static Context * create(const Device & d) {return create(DeviceList() << d);}
|
||
static Context * create(const PIString & part_name);
|
||
Program * createProgram(const PIString & source, const PIStringList & args = PIStringList(), PIString * error = 0);
|
||
template <typename T> Buffer * createBuffer(PIOpenCL::Direction dir, PIVector <T> & container) {
|
||
T def = T();
|
||
return createBuffer(dir, &container, Buffer::cVector , PIByteArray(&def, sizeof(T)), container.size());
|
||
}
|
||
template <typename T> Buffer * createBuffer(PIOpenCL::Direction dir, PIDeque <T> & container) {
|
||
T def = T();
|
||
return createBuffer(dir, &container, Buffer::cDeque , PIByteArray(&def, sizeof(T)), container.size());
|
||
}
|
||
template <typename T> Buffer * createBuffer(PIOpenCL::Direction dir, PIVector2D<T> & container) {
|
||
T def = T();
|
||
return createBuffer(dir, &container, Buffer::cVector2D, PIByteArray(&def, sizeof(T)), container.size());
|
||
}
|
||
template <typename T> Buffer * createBuffer(PIOpenCL::Direction dir, uint elements) {
|
||
T def = T();
|
||
Buffer * ret = createBuffer(dir, 0, Buffer::cNone, PIByteArray(&def, sizeof(T)), elements);
|
||
if (ret)
|
||
ret->clear();
|
||
return ret;
|
||
}
|
||
private:
|
||
Context();
|
||
void zero();
|
||
void deletePrograms();
|
||
void deleteBuffers();
|
||
Buffer * createBuffer(PIOpenCL::Direction dir, void * container, int type, PIByteArray def, uint elements);
|
||
PIVector<Program * > programs_;
|
||
PIVector<Buffer * > buffers_;
|
||
PRIVATE_DECLARATION(PIP_OPENCL_EXPORT)
|
||
};
|
||
|
||
|
||
class PIP_OPENCL_EXPORT Buffer {
|
||
friend class Context;
|
||
friend class Kernel;
|
||
public:
|
||
~Buffer();
|
||
void * handle();
|
||
bool resize(uint new_elements);
|
||
void clear();
|
||
void copyToContainer();
|
||
void copyTo(void * data);
|
||
void copyTo(void * data, int elements_count, int elements_offset = 0);
|
||
void copyFromContainer();
|
||
void copyFrom(void * data);
|
||
void copyFrom(void * data, int elements_count, int elements_offset = 0);
|
||
uint elementsCount() const {return elements;}
|
||
private:
|
||
enum Container {
|
||
cNone,
|
||
cVector,
|
||
cDeque,
|
||
cVector2D,
|
||
};
|
||
Buffer();
|
||
void zero();
|
||
bool init();
|
||
void * containerData();
|
||
Context * context_;
|
||
Direction dir;
|
||
Container type;
|
||
void * container;
|
||
PIByteArray def;
|
||
uint elements;
|
||
PRIVATE_DECLARATION(PIP_OPENCL_EXPORT)
|
||
};
|
||
|
||
|
||
class PIP_OPENCL_EXPORT Program {
|
||
friend class Context;
|
||
friend class Kernel;
|
||
friend class Buffer;
|
||
public:
|
||
~Program();
|
||
Context * context() const {return context_;}
|
||
const PIString & sourceCode() const {return source_;}
|
||
Kernel * kernel(int index = 0) const {return kernels_[index];}
|
||
const PIVector<Kernel * > & kernels() const {return kernels_;}
|
||
private:
|
||
Program();
|
||
void zero();
|
||
bool initKernels(PIVector<void*> kerns);
|
||
Context * context_;
|
||
PIString source_;
|
||
PIVector<Kernel * > kernels_;
|
||
PRIVATE_DECLARATION(PIP_OPENCL_EXPORT)
|
||
};
|
||
|
||
|
||
class PIP_OPENCL_EXPORT Kernel {
|
||
friend class Program;
|
||
friend class Buffer;
|
||
public:
|
||
Program * program() const {return program_;}
|
||
bool execute();
|
||
void setExecuteRange(int size) {setExecuteRanges(PIVector<int>() << size);}
|
||
void setExecuteRanges(const PIVector<int> & ranges);
|
||
const PIString & name() const {return name_;}
|
||
const PIVector<KernelArg> & args() const {return args_;}
|
||
template <typename T> bool setArgValue(int index, const T & value) {return setArgValueS(index, PIVariant::fromValue(value));}
|
||
template <typename T> bool setArgValue(const PIString & arg, const T & value) {return setArgValue(argIndex(arg), value);}
|
||
bool setArgValue(const PIString & arg, const PIVariant & value) {return setArgValueS(argIndex(arg), value);}
|
||
bool bindArgValue(int index, Buffer * buffer);
|
||
bool bindArgValue(const PIString & arg, Buffer * buffer) {return bindArgValue(argIndex(arg), buffer);}
|
||
private:
|
||
Kernel();
|
||
~Kernel();
|
||
void zero();
|
||
bool init();
|
||
bool setArgValueS(int index, const PIVariant & value);
|
||
int argIndex(const PIString & an) const;
|
||
KernelArg argByName(const PIString & an) const;
|
||
Context * context_;
|
||
Program * program_;
|
||
PIString name_;
|
||
PIVector<KernelArg> args_;
|
||
PIVector<size_t> dims;
|
||
PRIVATE_DECLARATION(PIP_OPENCL_EXPORT)
|
||
};
|
||
|
||
|
||
static void init();
|
||
static const PIVector<Platform> & platforms();
|
||
static const PIVector<Device> devices();
|
||
static Device deviceByID(void * id);
|
||
static PIString prepareProgram(const PIString & prog);
|
||
|
||
private:
|
||
static PIString prog_header;
|
||
PIOpenCL() {;}
|
||
class PIP_OPENCL_EXPORT Initializer {
|
||
public:
|
||
Initializer();
|
||
static Initializer * instance();
|
||
void init();
|
||
PIVector<Platform> platforms_;
|
||
bool inited_;
|
||
};
|
||
};
|
||
|
||
|
||
PIP_OPENCL_EXPORT PICout operator <<(PICout s, const PIOpenCL::KernelArg & v);
|
||
|
||
|
||
#endif // PIOPENCL_H
|