| //+------------------------------------------------------------------+
|
| //| 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<typename TVertex>
|
| 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<typename TInput>
|
| 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<DXVertex>())
|
| {
|
| 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<typename TVertex>
|
| 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<typename TInput>
|
| 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<TInput>(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);
|
| }
|
| //+------------------------------------------------------------------+
|