{
  "Name": "Measure",
  "_id": "86580803-34fe-40a8-8dbf-9197dedb889c",
  "Namespace": "lib.basic",
  "Description": "Measures the evaluation of its connected subtree and reports it to the time log system.",
  "Inputs": [
    {
      "Name": "Input",
      "MetaInstanceID": "c9a66106-bce5-40a8-84f0-429a6cec1909",
      "DefaultValue": {
        "Type": "Generic",
        "Value": "Framefield.Core.Generic"
      },
      "MetaID": "9f831cf2-a1ec-41f4-ba80-cced9736af6b",
      "IsMultiInput": "False",
      "Relevance": "Required",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.R",
      "MetaInstanceID": "868fb6ad-ddd9-4d31-b28d-2f8c597af146",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.G",
      "MetaInstanceID": "ef61d929-7a61-435c-aa18-3927f8cbd903",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.B",
      "MetaInstanceID": "60b7da67-677b-4b1a-a694-a526ba9df3f9",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.A",
      "MetaInstanceID": "60e1f370-8e87-4859-af38-0e3bc11d5155",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    }
  ],
  "Outputs": [
    {
      "Name": "Input",
      "MetaInstanceID": "171d3f14-75d8-4570-91fa-27ea4486b016",
      "MetaID": "9f831cf2-a1ec-41f4-ba80-cced9736af6b"
    },
    {
      "Name": "Time",
      "MetaInstanceID": "edeb04c2-ca42-4e73-841b-9bc98c2e0025",
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506"
    },
    {
      "Name": "RenderedPrimitives",
      "MetaInstanceID": "02dbcd49-61f5-49ea-90d5-02e41698aec9",
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506"
    },
    {
      "Name": "PrimitivesSentToRasterizer",
      "MetaInstanceID": "d1e25c9c-bfba-41ad-9b67-524616d1a673",
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506"
    }
  ],
  "OperatorParts": [
    {
      "MetaInstanceID": "1fd514d5-2071-4c45-9f70-0f00841f5231",
      "MetaID": "f4b28c70-5dfa-426a-ade9-624ab3ac9cd3",
      "Name": "MeasureFunc",
      "Version": "8d674104-0bbb-461c-8c9d-07ce7ded41ef",
      "Type": "Generic",
      "IsMultiInput": "True",
      "Script": [
        "//>>> _using",
        "using System;",
        "using System.Collections.Generic;",
        "using System.Linq;",
        "using System.Text;",
        "using SharpDX;",
        "using SharpDX.Direct3D11;",
        "using SharpDX.Windows;",
        "//<<< _using",
        "using Framefield.Core.Profiling;",
        "",
        "namespace Framefield.Core.IDf4b28c70_5dfa_426a_ade9_624ab3ac9cd3",
        "{",
        "    public class Class_Measure : OperatorPart.Function",
        "    {",
        "        //>>> _inputids",
        "        private enum InputId",
        "        {",
        "            Input = 0,",
        "            ColorR = 1,",
        "            ColorG = 2,",
        "            ColorB = 3,",
        "            ColorA = 4",
        "        }",
        "        //<<< _inputids",
        "        ",
        "        //>>> _outputids",
        "        private enum OutputId",
        "        {",
        "            Input = 0,",
        "            Time = 1,",
        "            RenderedPrimitives = 2,",
        "            PrimitivesSentToRasterizer = 3",
        "        }",
        "        //<<< _outputids",
        "",
        "        public Class_Measure()",
        "        {",
        "            _measureElements = new MeasureElement[_maxQueryFrames];",
        "            for (int i = 0; i < _maxQueryFrames; ++i)",
        "            {",
        "                _measureElements[i] = new MeasureElement",
        "                                      {",
        "                                          FrameID = 0,",
        "                                          QueryTimeStampDisjoint = new GPUQuery(D3DDevice.Device, new QueryDescription() { Type = QueryType.TimestampDisjoint }),",
        "                                          QueryTimeStampFrameBegin = new GPUQuery(D3DDevice.Device, new QueryDescription() { Type = QueryType.Timestamp }),",
        "                                          QueryTimeStampStart = new GPUQuery(D3DDevice.Device, new QueryDescription() { Type = QueryType.Timestamp }),",
        "                                          QueryTimeStampEnd = new GPUQuery(D3DDevice.Device, new QueryDescription() { Type = QueryType.Timestamp }),",
        "                                          QueryPipelineStats = new GPUQuery(D3DDevice.Device, new QueryDescription() { Type = QueryType.PipelineStatistics })",
        "                                      };",
        "            }",
        "            _currentQueryFrame = 0;",
        "            _allQueriesValid = false;",
        "",
        "            D3DDevice.BeginFrameEvent += HandleBeginFrame;",
        "            D3DDevice.EndFrameEvent += HandleEndFrame;",
        "        }",
        "",
        "        public override void Dispose()",
        "        {",
        "            D3DDevice.BeginFrameEvent -= HandleBeginFrame;",
        "            D3DDevice.EndFrameEvent -= HandleEndFrame;",
        "",
        "            var context = D3DDevice.Device.ImmediateContext;",
        "            for (int i = 0; i < _maxQueryFrames; ++i)",
        "            {",
        "                _measureElements[i].Dispose();",
        "            }",
        "        }",
        "",
        "        void HandleBeginFrame()",
        "        {",
        "            if (!TimeLogger.Enabled)",
        "                return;",
        "",
        "            var measureElement = _measureElements[_currentQueryFrame];",
        "            measureElement.FrameID = TimeLogger.FrameID;",
        "            measureElement.QueryTimeStampDisjoint.Begin(D3DDevice.Device.ImmediateContext);",
        "            measureElement.QueryTimeStampFrameBegin.End(D3DDevice.Device.ImmediateContext);",
        "        }",
        "",
        "        void HandleEndFrame()",
        "        {",
        "            if (!TimeLogger.Enabled)",
        "                return;",
        "",
        "            var context = D3DDevice.Device.ImmediateContext;",
        "            _measureElements[_currentQueryFrame].QueryTimeStampDisjoint.End(context);",
        "",
        "            int oldestQueryFrame = (_currentQueryFrame + 1) % _maxQueryFrames;",
        "            ++_currentQueryFrame;",
        "            if (_currentQueryFrame == _maxQueryFrames)",
        "                _allQueriesValid = true;",
        "",
        "            _currentQueryFrame %= _maxQueryFrames;",
        "",
        "            if (_allQueriesValid)",
        "            {",
        "                var measureElementToFetch = _measureElements[oldestQueryFrame];",
        "                QueryDataTimestampDisjoint disjointData;",
        "                long timeStampframeBegin;",
        "                long timeStampStart;",
        "                long timeStampEnd;",
        "                QueryDataPipelineStatistics pipelineStatsData;",
        "                bool dataFetched = true;",
        "                dataFetched &= measureElementToFetch.QueryTimeStampDisjoint.GetData(context, AsynchronousFlags.None, out disjointData);",
        "                dataFetched &= measureElementToFetch.QueryTimeStampFrameBegin.GetData(context, AsynchronousFlags.None, out timeStampframeBegin);",
        "                dataFetched &= measureElementToFetch.QueryTimeStampStart.GetData(context, AsynchronousFlags.None, out timeStampStart);",
        "                dataFetched &= measureElementToFetch.QueryTimeStampEnd.GetData(context, AsynchronousFlags.None, out timeStampEnd);",
        "                dataFetched &= measureElementToFetch.QueryPipelineStats.GetData(context, AsynchronousFlags.None, out pipelineStatsData);",
        "",
        "                if (dataFetched && !disjointData.Disjoint)",
        "                {",
        "                    var entry = new DataEntry()",
        "                                    {",
        "                                        ID = GetHashCode().ToString(),",
        "                                        Name = OperatorPart.Parent.Name,",
        "                                        Color = System.Drawing.Color.FromArgb((int) (_color.Alpha*255.0), (int) (_color.Red*255.0), (int) (_color.Green*255.0), (int) (_color.Blue*255.0)),",
        "                                        Duration = (double)(timeStampEnd - timeStampStart)/disjointData.Frequency,",
        "                                        FrameTimeOffset = (double)(timeStampStart - timeStampframeBegin)/disjointData.Frequency",
        "                                    };",
        "                    TimeLogger.Add(measureElementToFetch.FrameID, entry);",
        "",
        "                    _lastTime = (float)entry.Duration;",
        "                    _lastRenderedPrimitives = pipelineStatsData.CPrimitiveCount;",
        "                    _lastPrimitivesSentToRasterizer = pipelineStatsData.CInvocationCount;",
        "                }",
        "            }",
        "        }",
        "",
        "        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)",
        "        {",
        "            //>>> _params",
        "            var Input = inputs[(int)InputId.Input];",
        "            var ColorR = inputs[(int)InputId.ColorR].Eval(context).Value;",
        "            var ColorG = inputs[(int)InputId.ColorG].Eval(context).Value;",
        "            var ColorB = inputs[(int)InputId.ColorB].Eval(context).Value;",
        "            var ColorA = inputs[(int)InputId.ColorA].Eval(context).Value;",
        "            var Color = new Color4(ColorR, ColorG, ColorB, ColorA);",
        "            //<<< _params",
        "",
        "            _color = Color;",
        "",
        "            if (TimeLogger.Enabled)",
        "            {",
        "                switch (outputIdx)",
        "                {",
        "                    case (int)OutputId.Input:",
        "                        var measureElement = _measureElements[_currentQueryFrame];",
        "                        measureElement.QueryTimeStampStart.End(context.D3DDevice.ImmediateContext);",
        "                        measureElement.QueryPipelineStats.Begin(context.D3DDevice.ImmediateContext);",
        "                        Input.Eval(context);",
        "                        measureElement.QueryTimeStampEnd.End(context.D3DDevice.ImmediateContext);",
        "                        measureElement.QueryPipelineStats.End(context.D3DDevice.ImmediateContext);",
        "",
        "                        OperatorPart.EmitChangedEventForOutput((int)OutputId.Time);",
        "                        OperatorPart.EmitChangedEventForOutput((int)OutputId.RenderedPrimitives);",
        "                        OperatorPart.EmitChangedEventForOutput((int)OutputId.PrimitivesSentToRasterizer);",
        "                        break;",
        "                    case (int)OutputId.Time: context.Value = _lastTime; break;",
        "                    case (int)OutputId.RenderedPrimitives: context.Value = _lastRenderedPrimitives; break;",
        "                    case (int)OutputId.PrimitivesSentToRasterizer: context.Value = _lastPrimitivesSentToRasterizer; break;",
        "                }",
        "            }",
        "            else",
        "            {",
        "                switch (outputIdx)",
        "                {",
        "                    case (int)OutputId.Input: Input.Eval(context); break;",
        "                    case (int)OutputId.Time: context.Value = 0.0f; break;",
        "                    case (int)OutputId.RenderedPrimitives: context.Value = 0.0f; break;",
        "                    case (int)OutputId.PrimitivesSentToRasterizer: context.Value = 0.0f; break;",
        "                }",
        "            }",
        "            return context;",
        "        }",
        "",
        "        public class MeasureElement : IDisposable",
        "        {",
        "            public Int64 FrameID { get; set; }",
        "            public GPUQuery QueryTimeStampFrameBegin { get; set; }",
        "            public GPUQuery QueryTimeStampDisjoint { get; set; }",
        "            public GPUQuery QueryTimeStampStart { get; set; }",
        "            public GPUQuery QueryTimeStampEnd { get; set; }",
        "            public GPUQuery QueryPipelineStats { get; set; }",
        "",
        "            public void Dispose()",
        "            {",
        "                FrameID = 0;",
        "                QueryTimeStampFrameBegin.Dispose();",
        "                QueryTimeStampDisjoint.Dispose();",
        "                QueryTimeStampStart.Dispose();",
        "                QueryTimeStampEnd.Dispose();",
        "                QueryPipelineStats.Dispose();",
        "            }",
        "        }",
        "",
        "        Color4 _color;",
        "        int _currentQueryFrame;",
        "        int _maxQueryFrames = 5;",
        "        bool _allQueriesValid = false;",
        "        MeasureElement[] _measureElements;",
        "",
        "        float _lastTime;",
        "        float _lastRenderedPrimitives;",
        "        float _lastPrimitivesSentToRasterizer;",
        "    }",
        "}",
        ""
      ],
      "AdditionalAssemblies": []
    }
  ],
  "Operators": [],
  "Connections": [
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "171d3f14-75d8-4570-91fa-27ea4486b016"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "c9a66106-bce5-40a8-84f0-429a6cec1909",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "868fb6ad-ddd9-4d31-b28d-2f8c597af146",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "ef61d929-7a61-435c-aa18-3927f8cbd903",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "60b7da67-677b-4b1a-a694-a526ba9df3f9",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "60e1f370-8e87-4859-af38-0e3bc11d5155",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "edeb04c2-ca42-4e73-841b-9bc98c2e0025"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "02dbcd49-61f5-49ea-90d5-02e41698aec9"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "1fd514d5-2071-4c45-9f70-0f00841f5231",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "d1e25c9c-bfba-41ad-9b67-524616d1a673"
    }
  ]
}