//+------------------------------------------------------------------+ //| DXDispatcher.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2000-2025, MetaQuotes Ltd." #property link "https://www.mql5.com" //--- #include "DXObjectBase.mqh" #include "DXData.mqh" #include "DXBuffers.mqh" #include "DXInput.mqh" #include "DXTexture.mqh" #include "DXShader.mqh" //--- default shaders #resource "Shaders/DefaultShaderVertex.hlsl" as string ExtDefaultShaderVertex; #resource "Shaders/DefaultShaderPixel.hlsl" as string ExtDefaultShaderPixel; //+------------------------------------------------------------------+ //| DX dispatcher which holds all resources | //+------------------------------------------------------------------+ class CDXDispatcher : public CDXObjectBase { protected: CDXObjectBase m_dx_resources; // DX resources list (Textures, Shaders, etc.) //--- default shaders CDXShader* m_default_vs; CDXShader* m_default_ps; public: CDXDispatcher(void); ~CDXDispatcher(void); //--- create/destroy bool Create(int context); void Destroy(void); //--- check resources void Check(void); //--- get DX Context Handle int DXContext(void) const { return(m_context); } //--- create shaders CDXShader* ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type); CDXShader* ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point); CDXShader* ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point); //--- create buffers template CDXVertexBuffer* VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY); CDXIndexBuffer* IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY); //--- create shader inputs template CDXInput* InputCreate(void); CDXTexture* TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0); CDXTexture* TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0); private: //--- add resource to list bool ResourceAdd(CDXObjectBase *resource); //--- check resources void ResourcesCheck(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CDXDispatcher::CDXDispatcher(void) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CDXDispatcher::~CDXDispatcher(void) { Destroy(); } //+------------------------------------------------------------------+ //| Create | //+------------------------------------------------------------------+ bool CDXDispatcher::Create(int context) { //--- check if context already exist if(m_context!=INVALID_HANDLE) return(false); //--- save context m_context=context; //--- return(true); } //+------------------------------------------------------------------+ //| Destroy | //+------------------------------------------------------------------+ void CDXDispatcher::Destroy(void) { //--- release default shaders if(m_default_ps) { m_default_ps.Release(); m_default_ps=NULL; } if(m_default_vs) { m_default_vs.Release(); m_default_vs=NULL; } //--- release and delete all DX resources while(m_dx_resources.Next()) { CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next(); resource.Release(); } //--- forget context m_context=INVALID_HANDLE; } //+------------------------------------------------------------------+ //| Check resources | //+------------------------------------------------------------------+ void CDXDispatcher::Check(void) { //--- CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next(); //--- release and delete all DX resources while(CheckPointer(resource)!=POINTER_INVALID) { CDXHandleShared* next=(CDXHandleShared*)resource.Next(); //--- if references count 1 or less, then only we hold the resource if(resource.References()<=1) resource.Release(); //--- resource=next; } } //+------------------------------------------------------------------+ //| Create default shader of specified type | //+------------------------------------------------------------------+ CDXShader* CDXDispatcher::ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type) { switch(shader_type) { //--- default pixel shader case DX_SHADER_PIXEL: { if(m_default_ps==NULL) m_default_ps=ShaderCreateFromSource(DX_SHADER_PIXEL,ExtDefaultShaderPixel,"PSMain"); return(m_default_ps); } //--- default vertex shader case DX_SHADER_VERTEX: { if(m_default_vs==NULL) { m_default_vs=ShaderCreateFromSource(DX_SHADER_VERTEX,ExtDefaultShaderVertex,"VSMain"); if(m_default_vs && !m_default_vs.LayoutSet()) { m_default_vs.Release(); m_default_vs=NULL; } } return(m_default_vs); } } //--- return result return(NULL); } //+------------------------------------------------------------------+ //| Create new shader of specified type from file | //+------------------------------------------------------------------+ CDXShader* CDXDispatcher::ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point) { //--- open source file int file=FileOpen(path,FILE_READ); if(file==INVALID_HANDLE) return(NULL); //--- check file size uint size=(uint)FileSize(file); FileClose(file); if(size>16*1024*1024) return(NULL); //--- prepare buffer char buffer[]; ArrayResize(buffer,size); //--- read file into buffer int read=(int)FileLoad(path,buffer); if(read<=0) return(NULL); //--- convert vuffer to string string source=CharArrayToString(buffer,0,WHOLE_ARRAY,CP_UTF8); //--- add shader by source return(ShaderCreateFromSource(shader_type,source,entry_point)); } //+------------------------------------------------------------------+ //| Create new shader of specified type from source code | //+------------------------------------------------------------------+ CDXShader* CDXDispatcher::ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point) { //--- check context if(m_context==INVALID_HANDLE) return(NULL); //--- allocate new shader CDXShader* shader=new CDXShader(); if(shader==NULL) return(NULL); //--- create shader if(!shader.Create(m_context,shader_type,source,entry_point)) { shader.Release(); return(NULL); } //--- add shader to resources list if(!ResourceAdd(shader)) { shader.Release(); return(NULL); } //--- return shader return(shader); } //+------------------------------------------------------------------+ //| Create vertex buffer | //+------------------------------------------------------------------+ template CDXVertexBuffer* CDXDispatcher::VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY) { //--- check context if(m_context==INVALID_HANDLE) return(NULL); //--- allocate new buffer CDXVertexBuffer* buffer=new CDXVertexBuffer(); if(buffer==NULL) return(NULL); //--- create buffer if(!buffer.Create(m_context,vertices,start,count)) { buffer.Release(); return(NULL); } //--- add buffer to resources list if(!ResourceAdd(buffer)) { buffer.Release(); return(NULL); } //--- return buffer return(buffer); } //+------------------------------------------------------------------+ //| Create vertex buffer | //+------------------------------------------------------------------+ CDXIndexBuffer* CDXDispatcher::IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY) { //--- check context if(m_context==INVALID_HANDLE) return(NULL); //--- allocate new buffer CDXIndexBuffer* buffer=new CDXIndexBuffer(); if(buffer==NULL) return(NULL); //--- create buffer if(!buffer.Create(m_context,indicies,start,count)) { buffer.Release(); return(NULL); } //--- add buffer to resources list if(!ResourceAdd(buffer)) { buffer.Release(); return(NULL); } //--- return input buffer return(buffer); } //+------------------------------------------------------------------+ //| Create shader input buffer | //+------------------------------------------------------------------+ template CDXInput* CDXDispatcher::InputCreate(void) { //--- check context if(m_context==INVALID_HANDLE) return(NULL); //--- allocate new input buffer CDXInput* input_buffer=new CDXInput(); if(input_buffer==NULL) return(NULL); //--- create buffer if(!input_buffer.Create(m_context)) { input_buffer.Release(); return(NULL); } //--- add buffer to resources list if(!ResourceAdd(input_buffer)) { input_buffer.Release(); return(NULL); } //--- return shader return(input_buffer); } //+------------------------------------------------------------------+ //| Create texture from bitmap file | //+------------------------------------------------------------------+ CDXTexture* CDXDispatcher::TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0) { //--- check context if(m_context==INVALID_HANDLE) return(NULL); //--- allocate new texture CDXTexture* texture=new CDXTexture(); if(texture==NULL) return(NULL); //--- create texture if(!texture.Create(m_context,path,data_x,data_y,data_width,data_height)) { texture.Release(); return(NULL); } //--- add texture to resources list if(!ResourceAdd(texture)) { texture.Release(); return(NULL); } //--- return shader return(texture); } //+------------------------------------------------------------------+ //| Create texture from raw data, only 32-bit pixel formats supported| //+------------------------------------------------------------------+ CDXTexture* CDXDispatcher::TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0) { //--- check context if(m_context==INVALID_HANDLE) return(NULL); //--- allocate new texture CDXTexture* texture=new CDXTexture(); if(texture==NULL) return(NULL); //--- create texture if(!texture.Create(m_context,format,width,height,data,data_x,data_y,data_width,data_height)) { texture.Release(); return(NULL); } //--- add texture to resources list if(!ResourceAdd(texture)) { texture.Release(); return(NULL); } //--- return shader return(texture); } //+------------------------------------------------------------------+ //| Add DX resource | //+------------------------------------------------------------------+ bool CDXDispatcher::ResourceAdd(CDXObjectBase *resource) { //--- add resource if(!CheckPointer(resource)) return(false); //--- CDXObjectBase *last=&m_dx_resources; while(CheckPointer(last.Next())!=POINTER_INVALID) { if(last==resource) return(false); //--- last=last.Next(); } //--- resource.Next(NULL); resource.Prev(last); last.Next(resource); return(true); } //+------------------------------------------------------------------+