| //+------------------------------------------------------------------+
|
| //| Seascape.mq5 |
|
| //| Copyright 2000-2025, MetaQuotes Ltd. |
|
| //| https://www.mql5.com |
|
| //+------------------------------------------------------------------+
|
| #property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
| #property link "https://www.mql5.com"
|
| #property version "1.00"
|
|
|
| #resource "seascape.cl" as string ExtCL
|
|
|
| uint ExtSizeX=640; // Width
|
| uint ExtSizeY=360; // Height
|
| //+------------------------------------------------------------------+
|
| //| Initialize OpenCL engine |
|
| //+------------------------------------------------------------------+
|
| bool ModelInitialize(int &cl_ctx,int &cl_prg,int &cl_krn,int &cl_mem)
|
| {
|
| //--- initializing OpenCL objects
|
| if((cl_ctx=CLContextCreate())==INVALID_HANDLE)
|
| {
|
| Print("OpenCL not found");
|
| return(false);
|
| }
|
| //--- compile the program
|
| string build_log;
|
| if((cl_prg=CLProgramCreate(cl_ctx,ExtCL,build_log))==INVALID_HANDLE)
|
| {
|
| //--- free
|
| CLContextFree(cl_ctx);
|
| cl_ctx=INVALID_HANDLE;
|
| //---
|
| Print("OpenCL program create failed: ",build_log);
|
| return(false);
|
| }
|
| //--- kernel
|
| if((cl_krn=CLKernelCreate(cl_prg,"Seascape"))==INVALID_HANDLE)
|
| {
|
| //--- free
|
| CLProgramFree(cl_prg);
|
| cl_prg=INVALID_HANDLE;
|
|
|
| CLContextFree(cl_ctx);
|
| cl_ctx=INVALID_HANDLE;
|
| //---
|
| Print("OpenCL kernel create failed");
|
| return(false);
|
| }
|
| //--- create buffer
|
| ExtSizeX=(uint)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
|
| ExtSizeY=(uint)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
|
|
|
| if((cl_mem=CLBufferCreate(cl_ctx,ExtSizeX*ExtSizeY*sizeof(uint),CL_MEM_READ_WRITE))==INVALID_HANDLE)
|
| {
|
| //--- free objects
|
| CLKernelFree(cl_krn);
|
| cl_krn=INVALID_HANDLE;
|
|
|
| CLProgramFree(cl_prg);
|
| cl_prg=INVALID_HANDLE;
|
|
|
| CLContextFree(cl_ctx);
|
| cl_ctx=INVALID_HANDLE;
|
| //---
|
| Print("OpenCL buffer create failed");
|
| return(false);
|
| }
|
|
|
| CLSetKernelArgMem(cl_krn,1,cl_mem);
|
| //---
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check and resize the window |
|
| //+------------------------------------------------------------------+
|
| bool ModelResize(const int cl_ctx,const int cl_krn,int &cl_mem)
|
| {
|
| uint width =(uint)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
|
| uint height=(uint)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
|
| //--- correction
|
| width=(width + 7) & ~7; // align to 8
|
| if(width<8)
|
| width=8;
|
|
|
| if(height<8)
|
| height=8;
|
| //--- the same size?
|
| if(ExtSizeX!=width || ExtSizeY!=height)
|
| {
|
| ExtSizeX=width;
|
| ExtSizeY=height;
|
| //--- create buffer
|
| if(cl_mem!=INVALID_HANDLE)
|
| CLBufferFree(cl_mem);
|
|
|
| if((cl_mem=CLBufferCreate(cl_ctx,ExtSizeX*ExtSizeY*sizeof(uint),CL_MEM_READ_WRITE))!=INVALID_HANDLE)
|
| {
|
| CLSetKernelArgMem(cl_krn,1,cl_mem);
|
| return(true);
|
| }
|
| }
|
| //--- no changes
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Shutdown OpenCL engine |
|
| //+------------------------------------------------------------------+
|
| void ModelShutdown(int cl_ctx,int cl_prg,int cl_krn,int cl_mem)
|
| {
|
| //--- remove OpenCL objects
|
| if(cl_mem!=INVALID_HANDLE)
|
| {
|
| CLBufferFree(cl_mem);
|
| cl_mem=INVALID_HANDLE;
|
| }
|
|
|
| if(cl_krn!=INVALID_HANDLE)
|
| {
|
| CLKernelFree(cl_krn);
|
| cl_krn=INVALID_HANDLE;
|
| }
|
|
|
| if(cl_prg!=INVALID_HANDLE)
|
| {
|
| CLProgramFree(cl_prg);
|
| cl_prg=INVALID_HANDLE;
|
| }
|
|
|
| if(cl_ctx!=INVALID_HANDLE)
|
| {
|
| CLContextFree(cl_ctx);
|
| cl_ctx=INVALID_HANDLE;
|
| }
|
| //---
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Script program start function |
|
| //+------------------------------------------------------------------+
|
| void OnStart()
|
| {
|
| int cl_ctx=INVALID_HANDLE,cl_prg=INVALID_HANDLE;
|
| int cl_krn=INVALID_HANDLE,cl_mem=INVALID_HANDLE;
|
| //--- prepare the chart
|
| ChartSetInteger(0,CHART_SHOW,false);
|
| ChartRedraw();
|
| //--- initializing OpenCL objects
|
| if(ModelInitialize(cl_ctx,cl_prg,cl_krn,cl_mem))
|
| {
|
| uint buf[];
|
| uint work[2];
|
| uint offset[2]={0,0};
|
| string objname="OpenCL_"+IntegerToString(ChartID());
|
| string resname="::Seascape_"+IntegerToString(ChartID());
|
| //--- create object and empty picture
|
| ObjectCreate(0,objname,OBJ_BITMAP_LABEL,0,0,0);
|
| ObjectSetInteger(0,objname,OBJPROP_XDISTANCE,0);
|
| ObjectSetInteger(0,objname,OBJPROP_YDISTANCE,0);
|
|
|
| ArrayResize(buf,ExtSizeX*ExtSizeY);
|
| ResourceCreate(resname,buf,ExtSizeX,ExtSizeY,0,0,ExtSizeX,COLOR_FORMAT_XRGB_NOALPHA);
|
| ObjectSetString(0,objname,OBJPROP_BMPFILE,resname);
|
| //--- render
|
| work[0]=ExtSizeX;
|
| work[1]=ExtSizeY;
|
|
|
| for(float time=0;!IsStopped();time+=0.04f)
|
| {
|
| //--- check the resolution
|
| if(ModelResize(cl_ctx,cl_krn,cl_mem))
|
| {
|
| work[0]=ExtSizeX;
|
| work[1]=ExtSizeY;
|
| ArrayResize(buf,ExtSizeX*ExtSizeY);
|
| }
|
| //--- rendering the frame
|
| CLSetKernelArg(cl_krn,0,time);
|
| CLExecute(cl_krn,2,offset,work);
|
| //--- take the frame data, save in memory and draw it
|
| CLBufferRead(cl_mem,buf);
|
| ResourceCreate(resname,buf,ExtSizeX,ExtSizeY,0,0,ExtSizeX,COLOR_FORMAT_XRGB_NOALPHA);
|
|
|
| ChartRedraw();
|
| Sleep(0);
|
| }
|
| //--- remove OpenCL objects
|
| ModelShutdown(cl_ctx,cl_prg,cl_krn,cl_mem);
|
| //--- remove object
|
| ObjectDelete(0,objname);
|
| }
|
| //---
|
| ChartSetInteger(0,CHART_SHOW,true);
|
| }
|
| //+------------------------------------------------------------------+
|