/*! \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 . */ //! \~english OpenCL module //! \~russian Модуль OpenCL //! \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" //! \~english Main OpenCL wrapper class //! \~russian Главный класс-обёртка OpenCL class PIP_OPENCL_EXPORT PIOpenCL { public: //! \~english Kernel argument structure //! \~russian Структура аргумента ядра struct KernelArg; //! \~english Device structure //! \~russian Структура устройства struct Device; //! \~english Platform structure //! \~russian Структура платформы struct Platform; //! \~english OpenCL context class //! \~russian Класс контекста OpenCL class Context; //! \~english OpenCL buffer class //! \~russian Класс буфера OpenCL class Buffer; //! \~english OpenCL program class //! \~russian Класс программы OpenCL class Program; //! \~english OpenCL kernel class //! \~russian Класс ядра OpenCL class Kernel; //! \~english List of devices //! \~russian Список устройств typedef PIVector DeviceList; //! \~english Address space qualifiers //! \~russian Квалификаторы адресного пространства enum AddressQualifier { AddressGlobal, AddressLocal, AddressConstant, AddressPrivate, }; //! \~english Access qualifiers //! \~russian Квалификаторы доступа enum AccessQualifier { AccessReadOnly, AccessWriteOnly, AccessReadWrite, AccessNone, }; //! \~english Buffer direction //! \~russian Направление буфера enum Direction { Input = 0x01, Output = 0x02, InputOutput = Input | Output, }; //! \~english Type qualifiers //! \~russian Квалификаторы типа enum TypeQualifier { TypeConst, TypeRestrict, TypeVolatile, TypeNone, }; //! \~english Argument types //! \~russian Типы аргументов enum ArgType { Char = 1, UChar, Short, UShort, Int, UInt, Long, ULong, Float, Double, }; //! \~english Kernel argument information //! \~russian Информация об аргументе ядра struct PIP_OPENCL_EXPORT KernelArg { //! \~english Default constructor //! \~russian Конструктор по умолчанию KernelArg(); //! \~english Address qualifier //! \~russian Квалификатор адреса AddressQualifier address_qualifier; //! \~english Access qualifier //! \~russian Квалификатор доступа AccessQualifier access_qualifier; //! \~english Buffer direction //! \~russian Направление буфера Direction direction; //! \~english Type qualifier //! \~russian Квалификатор типа TypeQualifier type_qualifier; //! \~english Argument name //! \~russian Имя аргумента PIString arg_name; //! \~english Type name //! \~russian Имя типа PIString type_name; //! \~english Base type name //! \~russian Имя базового типа PIString base_type_name; //! \~english Is pointer //! \~russian Является указателем bool is_pointer; //! \~english Argument type //! \~russian Тип аргумента ArgType arg_type; //! \~english Dimensions //! \~russian Размерности int dims; private: friend class Kernel; void init(void * _k, uint index); }; //! \~english OpenCL device information //! \~russian Информация об устройстве OpenCL struct PIP_OPENCL_EXPORT Device { //! \~english Default constructor //! \~russian Конструктор по умолчанию Device() { id = platform_id = 0; max_compute_units = max_clock_frequency = 0; max_memory_size = 0; } //! \~english Check if device is valid //! \~russian Проверить устройство на корректность bool isValid() const { return id != 0; } //! \~english Get display text //! \~russian Получить текст для отображения PIString displayText() const { return name.trimmed() + " (" + device_version.trimmed() + ")"; } //! \~english Device handle //! \~russian Дескриптор устройства void * id; //! \~english Platform ID //! \~russian ID платформы void * platform_id; //! \~english Device name //! \~russian Имя устройства PIString name; //! \~english Vendor name //! \~russian Имя производителя PIString vendor; //! \~english Device version //! \~russian Версия устройства PIString device_version; //! \~english Driver version //! \~russian Версия драйвера PIString driver_version; //! \~english Maximum compute units //! \~russian Максимум вычислительных блоков int max_compute_units; //! \~english Maximum clock frequency //! \~russian Максимальная тактовая частота int max_clock_frequency; //! \~english Maximum memory size //! \~russian Максимальный размер памяти ullong max_memory_size; }; //! \~english OpenCL platform information //! \~russian Информация о платформе OpenCL struct PIP_OPENCL_EXPORT Platform { //! \~english Default constructor //! \~russian Конструктор по умолчанию Platform() { id = 0; } //! \~english Check if platform is valid //! \~russian Проверить платформу на корректность bool isValid() const { return id != 0; } //! \~english Get display text //! \~russian Получить текст для отображения PIString displayText() const { return name.trimmed() + " (" + version.trimmed() + ", " + profile.trimmed() + ")"; } //! \~english Platform handle //! \~russian Дескриптор платформы void * id; //! \~english Platform name //! \~russian Имя платформы PIString name; //! \~english Vendor name //! \~russian Имя производителя PIString vendor; //! \~english Profile //! \~russian Профиль PIString profile; //! \~english Version //! \~russian Версия PIString version; //! \~english Extensions //! \~russian Расширения PIStringList extensions; //! \~english Available devices //! \~russian Доступные устройства PIVector devices; }; //! \~english OpenCL context for managing devices and resources //! \~russian Контекст OpenCL для управления устройствами и ресурсами class PIP_OPENCL_EXPORT Context { friend class Buffer; friend class Program; friend class Kernel; public: //! \~english Destructor //! \~russian Деструктор ~Context(); //! \~english Get context handle //! \~russian Получить дескриптор контекста void * handle(); //! \~english Get command queue //! \~russian Получить очередь команд void * queue(); //! \~english Create context for device list //! \~russian Создать контекст для списка устройств //! \param dl List of devices //! \return New context or nullptr static Context * create(const DeviceList & dl); //! \~english Create context for single device //! \~russian Создать контекст для одного устройства //! \param d Device //! \return New context or nullptr static Context * create(const Device & d) { return create(DeviceList() << d); } //! \~english Create context by platform name //! \~russian Создать контекст по имени платформы //! \param part_name Platform name pattern //! \return New context or nullptr static Context * create(const PIString & part_name); //! \~english Create program from source //! \~russian Создать программу из исходного кода //! \param source OpenCL source code //! \param args Build arguments //! \param error Error message output //! \return New program or nullptr Program * createProgram(const PIString & source, const PIStringList & args = PIStringList(), PIString * error = 0); //! \~english Create buffer from vector //! \~russian Создать буфер из вектора template Buffer * createBuffer(PIOpenCL::Direction dir, PIVector & container) { T def = T(); return createBuffer(dir, &container, Buffer::cVector, PIByteArray(&def, sizeof(T)), container.size()); } //! \~english Create buffer from deque //! \~russian Создать буфер из deque template Buffer * createBuffer(PIOpenCL::Direction dir, PIDeque & container) { T def = T(); return createBuffer(dir, &container, Buffer::cDeque, PIByteArray(&def, sizeof(T)), container.size()); } //! \~english Create buffer from 2D vector //! \~russian Создать буфер из 2D вектора template Buffer * createBuffer(PIOpenCL::Direction dir, PIVector2D & container) { T def = T(); return createBuffer(dir, &container, Buffer::cVector2D, PIByteArray(&def, sizeof(T)), container.size()); } //! \~english Create buffer for elements //! \~russian Создать буфер для элементов 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) }; //! \~english OpenCL buffer for data storage //! \~russian Буфер OpenCL для хранения данных class PIP_OPENCL_EXPORT Buffer { friend class Context; friend class Kernel; public: //! \~english Destructor //! \~russian Деструктор ~Buffer(); //! \~english Get buffer handle //! \~russian Получить дескриптор буфера void * handle(); //! \~english Resize buffer //! \~russian Изменить размер буфера //! \param new_elements New number of elements //! \return true if successful bool resize(uint new_elements); //! \~english Clear buffer //! \~russian Очистить буфер void clear(); //! \~english Copy to container //! \~russian Копировать в контейнер void copyToContainer(); //! \~english Copy to memory //! \~russian Копировать в память void copyTo(void * data); //! \~english Copy to memory with offset //! \~russian Копировать в память со смещением void copyTo(void * data, int elements_count, int elements_offset = 0); //! \~english Copy to another buffer //! \~russian Копировать в другой буфер void copyTo(Buffer * buffer, int elements_count = -1, int elements_from_offset = 0, int elements_to_offset = 0); //! \~english Copy from container //! \~russian Копировать из контейнера void copyFromContainer(); //! \~english Copy from memory //! \~russian Копировать из памяти void copyFrom(void * data); //! \~english Copy from memory with offset //! \~russian Копировать из памяти со смещением void copyFrom(void * data, int elements_count, int elements_offset = 0); //! \~english Copy from another buffer //! \~russian Копировать из другого буфера void copyFrom(Buffer * buffer, int elements_count = -1, int elements_from_offset = 0, int elements_to_offset = 0); //! \~english Get elements count //! \~russian Получить количество элементов uint elementsCount() const { return elements; } private: //! \~english Container types //! \~russian Типы контейнеров 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) }; //! \~english OpenCL program containing kernels //! \~russian Программа OpenCL содержащая ядра class PIP_OPENCL_EXPORT Program { friend class Context; friend class Kernel; friend class Buffer; public: //! \~english Destructor //! \~russian Деструктор ~Program(); //! \~english Get context //! \~russian Получить контекст Context * context() const { return context_; } //! \~english Get source code //! \~russian Получить исходный код const PIString & sourceCode() const { return source_; } //! \~english Get kernel by index //! \~russian Получить ядро по индексу Kernel * kernel(int index = 0) const { return kernels_[index]; } //! \~english Get all kernels //! \~russian Получить все ядра 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) }; //! \~english OpenCL kernel for execution //! \~russian Ядро OpenCL для выполнения class PIP_OPENCL_EXPORT Kernel { friend class Program; friend class Buffer; public: //! \~english Get parent program //! \~russian Получить родительскую программу Program * program() const { return program_; } //! \~english Execute kernel //! \~russian Выполнить ядро //! \return true if successful bool execute(); //! \~english Wait for execution to finish //! \~russian Ждать завершения выполнения void waitForFinish(); //! \~english Set execution range (1D) //! \~russian Установить диапазон выполнения (1D) //! \param size Number of work items void setExecuteRange(int size) { setExecuteRanges(PIVector() << size); } //! \~english Set execution ranges (ND) //! \~russian Установить диапазоны выполнения (ND) //! \param ranges Array of sizes per dimension void setExecuteRanges(const PIVector & ranges); //! \~english Get kernel name //! \~russian Получить имя ядра const PIString & name() const { return name_; } //! \~english Get kernel arguments //! \~russian Получить аргументы ядра const PIVector & args() const { return args_; } //! \~english Set argument value by index //! \~russian Установить значение аргумента по индексу template bool setArgValue(int index, const T & value) { return setArgValueS(index, PIVariant::fromValue(value)); } //! \~english Set argument value by name //! \~russian Установить значение аргумента по имени template bool setArgValue(const PIString & arg, const T & value) { return setArgValue(argIndex(arg), value); } //! \~english Set variant argument value //! \~russian Установить значение аргумента variant bool setArgValue(const PIString & arg, const PIVariant & value) { return setArgValueS(argIndex(arg), value); } //! \~english Bind buffer to argument //! \~russian Привязать буфер к аргументу bool bindArgValue(int index, Buffer * buffer); //! \~english Bind buffer to argument by name //! \~russian Привязать буфер к аргументу по имени 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) }; //! \~english Initialize OpenCL //! \~russian Инициализировать OpenCL static void init(); //! \~english Get available platforms //! \~russian Получить доступные платформы //! \return Vector of platforms static const PIVector & platforms(); //! \~english Get all available devices //! \~russian Получить все доступные устройства //! \return Vector of devices static const PIVector devices(); //! \~english Get device by ID //! \~russian Получить устройство по ID //! \param id Device handle //! \return Device info static Device deviceByID(void * id); //! \~english Prepare program source //! \~russian Подготовить исходный код программы //! \param prog Program source //! \return Prepared source static PIString prepareProgram(const PIString & prog); private: static PIString prog_header; PIOpenCL() { ; } //! \~english Initialization helper //! \~russian Помощник инициализации class PIP_OPENCL_EXPORT Initializer { public: Initializer(); static Initializer * instance(); void init(); PIVector platforms_; bool inited_; }; }; //! \~english Output stream operator for KernelArg //! \~russian Оператор вывода в поток для KernelArg PIP_OPENCL_EXPORT PICout operator<<(PICout s, const PIOpenCL::KernelArg & v); #endif // PIOPENCL_H