/* 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 . */ #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(); 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, 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(); bool resize(uint new_elements); void clear(); void copyToContainer(); void copyFromContainer(); 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(); 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: bool execute(); 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