Files
pip/libs/main/opencl/piopencl.h

345 lines
8.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \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 waitForFinish();
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