/*! \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 . */ //! \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 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 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 Buffer * createBuffer(PIOpenCL::Direction dir, PIVector & container) { T def = T(); return createBuffer(dir, &container, Buffer::cVector, PIByteArray(&def, sizeof(T)), container.size()); } template Buffer * createBuffer(PIOpenCL::Direction dir, PIDeque & container) { T def = T(); return createBuffer(dir, &container, Buffer::cDeque, PIByteArray(&def, sizeof(T)), container.size()); } template Buffer * createBuffer(PIOpenCL::Direction dir, PIVector2D & container) { T def = T(); return createBuffer(dir, &container, Buffer::cVector2D, PIByteArray(&def, sizeof(T)), container.size()); } template 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 programs_; PIVector 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 copyTo(Buffer * buffer, int elements_count = -1, int elements_from_offset = 0, int elements_to_offset = 0); void copyFromContainer(); void copyFrom(void * data); void copyFrom(void * data, int elements_count, int elements_offset = 0); void copyFrom(Buffer * buffer, int elements_count = -1, int elements_from_offset = 0, int elements_to_offset = 0); uint elementsCount() const { return elements; } private: enum Container { cNone, cVector, cDeque, cVector2D, }; Buffer(); void zero(); bool init(); void * containerData(); static void copy(Buffer * buffer_from, Buffer * buffer_to, int elements_count, int elements_from_offset, int elements_to_offset); 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 & kernels() const { return kernels_; } private: Program(); void zero(); bool initKernels(PIVector kerns); Context * context_; PIString source_; PIVector 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() << size); } void setExecuteRanges(const PIVector & ranges); const PIString & name() const { return name_; } const PIVector & args() const { return args_; } template bool setArgValue(int index, const T & value) { return setArgValueS(index, PIVariant::fromValue(value)); } template 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 args_; PIVector dims; PRIVATE_DECLARATION(PIP_OPENCL_EXPORT) }; static void init(); static const PIVector & platforms(); static const PIVector 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 platforms_; bool inited_; }; }; PIP_OPENCL_EXPORT PICout operator<<(PICout s, const PIOpenCL::KernelArg & v); #endif // PIOPENCL_H