//+------------------------------------------------------------------+ //| Main.mqh | //| Copyright 2026, Niquel Mendoza. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Niquel Mendoza." #property link "https://www.mql5.com" #property strict #ifndef SCALERBYLEO_SRC_CL_MAIN_MQH #define SCALERBYLEO_SRC_CL_MAIN_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ //-- incluimos hashmap #include #include //-- tambien los kerneles #include "..\\Kernels\\Rsrc.mqh" #include "..\\..\\..\\CLByLeo\\SharedCtx.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| Defines | //+------------------------------------------------------------------+ #ifndef SCALERBYLEO_CL_DEVICE #define SCALERBYLEO_CL_DEVICE (CL_USE_ANY) #endif // SCALERBYLEO_CL_DEVICE //--- enum ENUM_CLCONTEXT_MANAGER_LAST_ERR { CLCONTEXT_MANAGER_LAST_ERR_NOT, CLCONTEXT_MANAGER_LAST_ERR_INVALID_HANDLE, CLCONTEXT_MANAGER_LAST_ERR_CL, }; //--- #define SCALERBYLEO_CLCTX_IS_CREATE (CCLCtxShared::s_context != INVALID_HANDLE && s_program != INVALID_HANDLE) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template class COpenCLCtxManager { private: static CHashMapFastP(int, uint, _fibbo) s_hash; static CHashMapFast(string, int) s_hash_kernel; //--- template static bool UpdateVectorDataInternal(int &handle, vector &vec, uint flags); public: COpenCLCtxManager(void) {} ~COpenCLCtxManager(void) {} //--- static string s_last_build_log; static int s_program; static ENUM_CLCONTEXT_MANAGER_LAST_ERR s_last_err; //--- static bool ProgramInit(const string& src); static bool KernelGet(const string& name, int& h); //--- static bool UpdateVectorData(int& h, vector& vec, uint flags); //--- static void Deinit(const int reason); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template int COpenCLCtxManager::s_program = INVALID_HANDLE; template string COpenCLCtxManager::s_last_build_log = ""; template ENUM_CLCONTEXT_MANAGER_LAST_ERR COpenCLCtxManager::s_last_err = CLCONTEXT_MANAGER_LAST_ERR_NOT; //--- template CHashMapFastP(int, uint, _fibbo) COpenCLCtxManager::s_hash; template CHashMapFast(string, int) COpenCLCtxManager::s_hash_kernel; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template static bool COpenCLCtxManager::ProgramInit(const string& src) { //--- if(SCALERBYLEO_CLCTX_IS_CREATE) return true; //--- ::ResetLastError(); //--- if(!CCLCtxShared::ContextInit()) { s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL; return false; } //--- if((s_program = CLProgramCreate(CCLCtxShared::s_context, src, s_last_build_log)) == INVALID_HANDLE) { s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL; // En caso hayamos fallado en su creacion igual lo liberamos (dado que si logramos iniciar) CCLCtxShared::ContextFree(); return false; } //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template static void COpenCLCtxManager::Deinit(const int reason) { //--- // Si en caso la razon de remove fue chart change o parameotrs // Los objetod golbales como tal se conservan no se liberan.. por lo que ya no se volvera a llamar a esa funcion o limpiar lo que tiene // asi que lo prevenimos. //--- if(reason == REASON_CHARTCHANGE || reason == REASON_PARAMETERS) { //FastLog(FUNCION_ACTUAL, WARNING_TEXT, "No se limpara el factory de features dado que la razon de deinit es chart-change,params"); return; } //--- if(s_program != INVALID_HANDLE) { CLProgramFree(s_program); s_program = INVALID_HANDLE; CCLCtxShared::ContextFree(); } //--- CHashMapFastIteratorP(int, uint, _fibbo) it = s_hash.BeginIteration(); while(it.IsValid()) { CLBufferFree(it.Key()); it.Next(); } s_hash.Clear(); //--- CHashMapFastIterator(string, int) it_kernels = s_hash_kernel.BeginIteration(); while(it_kernels.IsValid()) { CLKernelFree(it_kernels.Val()); it_kernels.Next(); } s_hash_kernel.Clear(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template static bool COpenCLCtxManager::KernelGet(const string &name, int& h) { //--- if(!s_hash_kernel.ReserveSlot(name)) { const uint p = s_hash_kernel.m_last_pos_tbl; h = s_hash_kernel.m_table[p].value; return true; } //--- if((h = CLKernelCreate(s_program, name)) == INVALID_HANDLE) { //--- const uint p = s_hash_kernel.m_last_pos_tbl; s_hash_kernel.m_bit_pos = int(TSN_FASTHASHMAP_INDEX_GET_BITPOS_WCORR(p)); // truqueamos s_hash_kernel.RemoveLastFindCall(); //--- s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL; return false; } //--- const uint p = s_hash_kernel.m_last_pos_tbl; s_hash_kernel.m_table[p].value = h; // ya poenmos //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // La idea siempre revismos un vec // dependie del TFlt tenemos que evitanso una copia o hacer la copia\conversion.. // Si en caso tflt es dbl entonces sin copias.. template static bool COpenCLCtxManager::UpdateVectorData(int &h, vector &vec, uint flags) { //--- // 1. si es float enveonces el vector (De datos) hay que converitlo a float (dado qeu es dbl) // 2. si en cambio la clase es dbl (Es pro que el usuario precisa tener soporte para dbl) lo mandamos tal cual //--- if(sizeof(TFlt) == sizeof(float)) { vectorf f; f.Assign(vec); return UpdateVectorDataInternal(h, f, flags); } else return UpdateVectorDataInternal(h, vec, flags); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template template static bool COpenCLCtxManager::UpdateVectorDataInternal(int &handle, vector &vec, uint flags) { //--- const uint vec_size = uint(vec.Size()); const uint vec_bytes = uint(vec_size * sizeof(TValue)); //--- // en caso haya cambiado de tamaño entonces tambine cremos ::ResetLastError(); if(handle == INVALID_HANDLE) { if((handle = CLBufferCreate(CCLCtxShared::s_context, vec_bytes, flags)) == INVALID_HANDLE) { s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL; return false; } s_hash.Add(handle, vec_bytes); } else { uint bytes; if(!s_hash.TryGet(handle, bytes)) { s_last_err = CLCONTEXT_MANAGER_LAST_ERR_INVALID_HANDLE; return false; } if(bytes != vec_bytes) { //--- CLBufferFree(handle); //--- if((handle = CLBufferCreate(CCLCtxShared::s_context, vec_bytes, flags)) == INVALID_HANDLE) { s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL; return false; } //--- actulizamos el tamaño const uint p = s_hash.m_last_pos_tbl; s_hash.m_table[p].value = vec_bytes; } // iguales no actulizamos } //--- actulizamos if(!CLBufferWrite(handle, 0, vec)) { s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL; return false; } //--- return true; } //+------------------------------------------------------------------+ //| Macros de ayuda | //+------------------------------------------------------------------+ #define OPENCLMANAGER_MAKE_VECTOR(h, vec, flags) if(!COpenCLCtxManager::UpdateVectorData(h, vec, flags)) { m_last_err=SCALERBYLEO_ERR_IN_CTX_MANAGER_CL; return false; } //--- end namepsace } //+------------------------------------------------------------------+ #endif // SCALERBYLEO_SRC_CL_MAIN_MQH