| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //  GLBackend.h
 | 
					
						
							|  |  |  | //  MNN
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //  Created by MNN on 2019/01/31.
 | 
					
						
							|  |  |  | //  Copyright © 2018, Alibaba Group Holding Limited
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef GLBACKEND_H
 | 
					
						
							|  |  |  | #define GLBACKEND_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <list>
 | 
					
						
							|  |  |  | #include <map>
 | 
					
						
							|  |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | #include "core/Backend.hpp"
 | 
					
						
							|  |  |  | #include "backend/opengl/GLContext.hpp"
 | 
					
						
							|  |  |  | #include "backend/opengl/GLProgram.hpp"
 | 
					
						
							|  |  |  | #include "backend/opengl/GLSSBOBuffer.hpp"
 | 
					
						
							|  |  |  | #include "backend/opengl/GLTexture.hpp"
 | 
					
						
							| 
									
										
										
										
											2019-05-24 11:26:54 +08:00
										 |  |  | #include "MNN_generated.h"
 | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | #include "backend/opengl/GLUtils.hpp"
 | 
					
						
							|  |  |  | #include "core/TensorUtils.hpp"
 | 
					
						
							|  |  |  | #include "backend/opengl/GLHead.hpp"
 | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace MNN { | 
					
						
							| 
									
										
										
										
											2019-05-24 11:26:54 +08:00
										 |  |  | namespace OpenGL { | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  |     /** Each backend belong to a runtime*/ | 
					
						
							|  |  |  | class GLRuntime : public Runtime { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     GLRuntime(const Backend::Info& info) : mInfo(info) { | 
					
						
							|  |  |  |         // Do nothing
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     virtual ~GLRuntime() = default; | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      @brief create backend | 
					
						
							|  |  |  |      @return created backend | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-04-08 15:34:23 +08:00
										 |  |  |     virtual Backend* onCreate(const BackendConfig* config) const override; | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      @brief clear unuseful resource | 
					
						
							|  |  |  |      @param level clear level: 0 - 100, bigger mean clear more, smaller mean cache more | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     virtual void onGabageCollect(int level) override { | 
					
						
							|  |  |  |         // Do nothing
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     virtual CompilerType onGetCompilerType() const override; | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      @brief Measure the memory it used in MB | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     virtual float onGetMemoryInMB() override { | 
					
						
							|  |  |  |         return 0.0f; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-30 10:10:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     int onGetRuntimeStatus(RuntimeStatus statusEnum) const override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  | private: | 
					
						
							|  |  |  |     Backend::Info mInfo; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | class GLBackend : public Backend { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
											
												- dynamic computation graph (beta)
	- add supports (/express)
	- add tests
	- add benchmarks with it (/benchmark/exprModels)
- Python
	- MNN engine and tools were submitted to pip
	- available on Windows/macOS/Linux
- Engine/Converter
	- add supports for each op benchmarking
	- refactor optimizer by separating steps
- CPU
	- add supports for Conv3D, Pool3D, ELU, ReverseSequence
	- fix ArgMax, Permute, Scale, BinaryOp, Slice, SliceTf
- OpenCL
	- add half transform in CPU
	- add broadcast supports for binary
	- optimize Conv2D, Reshape, Eltwise, Gemm, etc.
- OpenGL
	- add sub, real div supports for binary
	- add supports for unary
	- optimize Conv2D, Reshape
- Vulkan
	- add max supports for eltwise
- Metal
	- fix metallib missing problem
- Train/Quantization
	- use express to refactor training codes
											
										 
											2019-09-26 21:02:07 +08:00
										 |  |  |     GLBackend(BackendConfig::PrecisionMode precision, BackendConfig::PowerMode power); | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  |     virtual ~GLBackend(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void upload(GLuint textureId, const float* inputData, int d1, int d2, int d3, bool align = false) const; | 
					
						
							|  |  |  |     void download(GLuint textureId, float* outputData, int d1, int d2, int d3, bool align = false) const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |     void copyImageToNhwcBuffer(GLuint textureId, float *outputData, int width, int height, int channel) const; | 
					
						
							|  |  |  |     void copyNhwcBufferToImage(GLuint textureId, const float *inputData, int width, int height, int channel) const; | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  |     std::shared_ptr<GLProgram> getProgram(const std::string& key, const char* content); | 
					
						
							|  |  |  |     std::shared_ptr<GLProgram> getProgram(const std::string& key, const char* content, | 
					
						
							|  |  |  |                                           const std::vector<std::string>& prefix); | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 11:32:41 +08:00
										 |  |  |     enum GPUType { ADRENO = 0, MALI = 1, OTHER = 2 }; | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 11:32:41 +08:00
										 |  |  |     inline GPUType gpuType() const { | 
					
						
							|  |  |  |         return mGpuType; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 11:32:41 +08:00
										 |  |  |     inline int glVersion() const { | 
					
						
							|  |  |  |         return mVersion; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |     void wait() const; | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |     void compute(int dim1, int dim2, int dim3, bool needWait = false) const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  |     /*For Buffer alloc and release*/ | 
					
						
							| 
									
										
										
										
											2021-11-30 10:10:53 +08:00
										 |  |  |     virtual Backend::MemObj* onAcquire(const Tensor* nativeTensor, StorageType storageType) override; | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Clear All Dynamic Buffer
 | 
					
						
							|  |  |  |     virtual bool onClearBuffer() override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void onCopyBuffer(const Tensor* srcTensor, const Tensor* dstTensor) const override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void onExecuteBegin() const override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void onExecuteEnd() const override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-18 10:31:02 +08:00
										 |  |  |     virtual ErrorCode onResizeEnd() override { return NO_ERROR; } | 
					
						
							| 
									
										
										
										
											2023-09-21 21:29:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  |     /// get execution
 | 
					
						
							|  |  |  |     virtual Execution* onCreate(const std::vector<Tensor*>& inputs, const std::vector<Tensor*>& outputs, | 
					
						
							|  |  |  |                                 const MNN::Op* op) override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-24 11:26:54 +08:00
										 |  |  |     class Creator { | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |         virtual ~Creator() = default; | 
					
						
							|  |  |  |         virtual Execution *onCreate(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &output, const MNN::Op *op, Backend *backend) const = 0; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |     static bool addCreator(OpType t, Creator *c); | 
					
						
							| 
									
										
										
										
											2019-07-25 13:36:35 +08:00
										 |  |  |     bool isCreateError() const; | 
					
						
							|  |  |  |     bool isSupportHalf() const; | 
					
						
							| 
									
										
										
										
											2021-11-30 10:10:53 +08:00
										 |  |  |     static bool getOpenGLExtensions(const std::string& extStr); | 
					
						
							| 
									
										
										
										
											2019-07-25 13:36:35 +08:00
										 |  |  |     GLenum getTextrueFormat() const; | 
					
						
							|  |  |  |     std::string getImageFormat() const; | 
					
						
							|  |  |  |     std::shared_ptr<GLProgram> getTreatedProgramWithPrefix(const char *content, | 
					
						
							|  |  |  |                                                               const std::vector<std::string> &prefix); | 
					
						
							|  |  |  |     std::shared_ptr<GLProgram> getTreatedProgram(const char *content); | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  |     struct Runtime { | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |         std::shared_ptr<GLProgram> mNchw2ImageProgram; | 
					
						
							|  |  |  |         std::shared_ptr<GLProgram> mImage2NchwProgram; | 
					
						
							|  |  |  |         std::shared_ptr<GLProgram> mNc4hw42ImageProgram; | 
					
						
							|  |  |  |         std::shared_ptr<GLProgram> mImage2Nc4hw4Program; | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |         std::shared_ptr<GLProgram> mNhwc2ImageProgram; | 
					
						
							|  |  |  |         std::shared_ptr<GLProgram> mImage2NhwcProgram; | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         std::map<std::string, std::shared_ptr<GLProgram>> mProgramCache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         std::list<std::shared_ptr<GLTexture>> mBlocks; | 
					
						
							|  |  |  |         std::list<std::pair<const Tensor*, GLuint>> mFreeTextures; | 
					
						
							|  |  |  |         mutable std::shared_ptr<GLSSBOBuffer> mTempBuffer; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-11-30 10:10:53 +08:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2019-07-25 13:36:35 +08:00
										 |  |  |     Runtime* mRuntime = nullptr; | 
					
						
							|  |  |  |     static std::unique_ptr<GLContext> mContext; | 
					
						
							| 
									
										
										
										
											2019-06-24 11:32:41 +08:00
										 |  |  |     GPUType mGpuType = OTHER; | 
					
						
							|  |  |  |     int mVersion = 0; | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |     int mLocalSize[3]; | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  |     bool mIsCreateError{false}; | 
					
						
							| 
									
										
										
										
											2019-07-25 13:36:35 +08:00
										 |  |  |     bool mIsSupportHalf{false}; | 
					
						
							|  |  |  |     GLenum mTextrueFormat{GL_RGBA32F}; | 
					
						
							|  |  |  |     std::string mImageFormat{"rgba32f"}; | 
					
						
							| 
									
										
										
										
											2019-05-24 11:26:54 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  | inline std::vector<int> tensorShapeFormat(const Tensor *input) { | 
					
						
							|  |  |  |     int iN = std::max(1, input->batch()); | 
					
						
							|  |  |  |     int iC = std::max(1, input->channel()); | 
					
						
							|  |  |  |     int iH = std::max(1, input->height()); | 
					
						
							|  |  |  |     int iW = std::max(1, input->width()); | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |     if (input->dimensions() == 3) { | 
					
						
							|  |  |  |         iN = 1; | 
					
						
							|  |  |  |         iH = input->buffer().dim[0].extent; | 
					
						
							|  |  |  |         iW = input->buffer().dim[1].extent; | 
					
						
							|  |  |  |         iC = input->buffer().dim[2].extent; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |     if (input->dimensions() == 2) { | 
					
						
							|  |  |  |         iN = input->buffer().dim[0].extent; | 
					
						
							|  |  |  |         iH = 1; | 
					
						
							|  |  |  |         iW = 1; | 
					
						
							|  |  |  |         iC = input->buffer().dim[1].extent; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (input->dimensions() == 1) { | 
					
						
							|  |  |  |         iN = 1; | 
					
						
							|  |  |  |         iH = 1; | 
					
						
							|  |  |  |         iW = 1; | 
					
						
							|  |  |  |         iC = input->buffer().dim[0].extent; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  | #ifdef LOG_VERBOSE
 | 
					
						
							|  |  |  |     MNN_PRINT("dim %d : [%d, %d, %d, %d] \n",input->dimensions(), iN, iH, iW, iC); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     std::vector<int> shape_vec{iN, iH, iW, iC}; | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |     return shape_vec; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-12-27 22:16:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-24 11:26:54 +08:00
										 |  |  | template <class T> | 
					
						
							|  |  |  | class GLCreatorRegister { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     GLCreatorRegister(OpType type) { | 
					
						
							| 
									
										
										
										
											2019-07-02 18:01:08 +08:00
										 |  |  |         GLBackend::addCreator(type, new T); | 
					
						
							| 
									
										
										
										
											2019-05-24 11:26:54 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     ~GLCreatorRegister() = default; | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2019-05-24 11:26:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | template <typename T> | 
					
						
							|  |  |  | class TypedCreator : public GLBackend::Creator { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     virtual ~TypedCreator() = default; | 
					
						
							|  |  |  |     virtual Execution *onCreate(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs, const MNN::Op *op, | 
					
						
							|  |  |  |                                 Backend *backend) const override { | 
					
						
							|  |  |  |         return new T(inputs, op, backend); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace OpenGL
 | 
					
						
							| 
									
										
										
										
											2019-04-17 10:49:11 +08:00
										 |  |  | } // namespace MNN
 | 
					
						
							|  |  |  | #endif
 |