| //+------------------------------------------------------------------+
|
| //| DXShader.mqh |
|
| //| Copyright 2000-2025, MetaQuotes Ltd. |
|
| //| https://www.mql5.com |
|
| //+------------------------------------------------------------------+
|
| #include "DXHandle.mqh"
|
| #include "DXInput.mqh"
|
| #include "DXTexture.mqh"
|
| //+------------------------------------------------------------------+
|
| //| Maximum inputs count for shaders |
|
| //| D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT in DX11 |
|
| //+------------------------------------------------------------------+
|
| #define DX_SHADER_INPUTS_MAX 14
|
| //+------------------------------------------------------------------+
|
| //| Class CDXShader |
|
| //+------------------------------------------------------------------+
|
| class CDXShader : public CDXHandleShared
|
| {
|
| protected:
|
| //--- shader type
|
| ENUM_DX_SHADER_TYPE m_type;
|
| //--- input data
|
| CDXInput* m_inputs[];
|
| CDXTexture* m_textures[];
|
|
|
| public:
|
| //+------------------------------------------------------------------+
|
| //| Destructor |
|
| //+------------------------------------------------------------------+
|
| virtual ~CDXShader(void)
|
| {
|
| Shutdown();
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Create a new shader from source code |
|
| //+------------------------------------------------------------------+
|
| bool Create(int context,ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point)
|
| {
|
| //--- shutdown shader
|
| Shutdown();
|
| //--- save new context
|
| m_context=context;
|
| //--- check context
|
| if(m_context==INVALID_HANDLE)
|
| return(false);
|
| //--- save shader type;
|
| m_type=shader_type;
|
| //--- compile shader
|
| string error="";
|
| m_handle=DXShaderCreate(m_context,m_type,source,entry_point,error);
|
| if(m_handle==INVALID_HANDLE)
|
| return(false);
|
| //--- success
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Set vertex shader vertices layout |
|
| //+------------------------------------------------------------------+
|
| template<typename TVertex>
|
| bool LayoutSet(void)
|
| {
|
| //--- check shader handle
|
| if(m_handle==INVALID_HANDLE)
|
| return(false);
|
| //--- layout is available only for vertex shaders
|
| if(m_type!=DX_SHADER_VERTEX)
|
| return(false);
|
| //--- set layout
|
| return(DXShaderSetLayout(m_handle,TVertex::s_layout));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Set input buffer at specified index |
|
| //+------------------------------------------------------------------+
|
| bool InputSet(int index,CDXInput* dx_input)
|
| {
|
| //---
|
| if(index>=DX_SHADER_INPUTS_MAX || CheckPointer(dx_input)==POINTER_INVALID || dx_input.Handle()==INVALID_HANDLE)
|
| return(false);
|
| //--- check if input is the same
|
| int count=ArraySize(m_inputs);
|
| if(index<count && CheckPointer(m_inputs[index])!=POINTER_INVALID && m_inputs[index].Handle()==dx_input.Handle())
|
| return(true);
|
| //--- allocate array for new inputs
|
| if(index>=count)
|
| ArrayResize(m_inputs,index+1);
|
| for(int i=count; i<=index; i++)
|
| m_inputs[i]=NULL;
|
| //--- release previous input buffer
|
| if(m_inputs[index])
|
| m_inputs[index].Release();
|
| //--- set new input buffer
|
| m_inputs[index]=dx_input;
|
| dx_input.AddRef();
|
| //--- successed
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Set texture at specified index |
|
| //+------------------------------------------------------------------+
|
| bool TextureSet(int index,CDXTexture* texture)
|
| {
|
| //---
|
| if(m_type!=DX_SHADER_PIXEL || index>=DX_SHADER_INPUTS_MAX || CheckPointer(texture)==POINTER_INVALID || texture.Handle()==INVALID_HANDLE)
|
| return(false);
|
| //--- check if texture is the same
|
| int count=ArraySize(m_textures);
|
| if(index<count && CheckPointer(m_textures[index])!=POINTER_INVALID && m_textures[index].Handle()==texture.Handle())
|
| return(true);
|
| //--- allocate array for new inputs
|
| if(index>=count)
|
| ArrayResize(m_textures,index+1);
|
| for(int i=count; i<=index; i++)
|
| m_textures[i]=NULL;
|
| //--- release previous input buffer
|
| if(m_textures[index])
|
| m_textures[index].Release();
|
| //--- set new input buffer
|
| m_textures[index]=texture;
|
| texture.AddRef();
|
| //--- successed
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Set texture at specified index |
|
| //+------------------------------------------------------------------+
|
| void TexturesClear()
|
| {
|
| //--- release textures
|
| for(int i=0; i<ArraySize(m_textures); i++)
|
| if(m_textures[i])
|
| m_textures[i].Release();
|
| ArrayFree(m_textures);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Put shader into render queue |
|
| //+------------------------------------------------------------------+
|
| virtual bool Render(void)
|
| {
|
| //--- check handles
|
| if(m_context==INVALID_HANDLE || m_handle==INVALID_HANDLE)
|
| return(false);
|
| //--- update shader inputs
|
| if(!UpdateInputs())
|
| return(false);
|
| //--- set shader
|
| return(DXShaderSet(m_context,m_handle));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Shutdown |
|
| //+------------------------------------------------------------------+
|
| virtual void Shutdown(void)
|
| {
|
| //--- relase handle
|
| if(m_handle!=INVALID_HANDLE)
|
| DXRelease(m_handle);
|
| m_handle=INVALID_HANDLE;
|
| //--- release input buffers
|
| for(int i=0; i<ArraySize(m_inputs); i++)
|
| if(m_inputs[i])
|
| m_inputs[i].Release();
|
| //--- release textures
|
| for(int i=0; i<ArraySize(m_textures); i++)
|
| if(m_textures[i])
|
| m_textures[i].Release();
|
| ArrayFree(m_textures);
|
| }
|
|
|
| private:
|
| //+------------------------------------------------------------------+
|
| //| Shutdown |
|
| //+------------------------------------------------------------------+
|
| bool UpdateInputs(void)
|
| {
|
| int handles[];
|
| //--- set inputs handles
|
| int count=ArraySize(m_inputs);
|
| if(count>0)
|
| {
|
| ArrayResize(handles,count);
|
| //--- copy inputs handles
|
| for(int i=0; i<count; i++)
|
| if(m_inputs[i])
|
| handles[i]=m_inputs[i].Handle();
|
| else
|
| handles[i]=INVALID_HANDLE;
|
| }
|
| else
|
| ArrayFree(handles);
|
| //--- set input handles
|
| if(!DXShaderInputsSet(m_handle,handles))
|
| return(false);
|
| //--- set textures handles
|
| if(m_type==DX_SHADER_PIXEL)
|
| {
|
| count=ArraySize(m_textures);
|
| if(count>0)
|
| {
|
| ArrayResize(handles,count);
|
| //--- copy inputs handles
|
| for(int i=0; i<count; i++)
|
| if(m_textures[i])
|
| handles[i]=m_textures[i].Handle();
|
| else
|
| handles[i]=INVALID_HANDLE;
|
| }
|
| else
|
| ArrayFree(handles);
|
| ResetLastError();
|
| //--- set taxtures handles
|
| if(!DXShaderTexturesSet(m_handle,handles))
|
| return(false);
|
| }
|
| //--- succes
|
| return(true);
|
| }
|
| };
|
| //+------------------------------------------------------------------+
|