Beispiel #1
0
        private void panelOutput_MouseMove(object sender, MouseEventArgs e)
        {
            // Transform mouse position into node space
            float2 mousePosition = Client2Pos(e.Location);
            float  nodeRadius    = 0.01f * 0.5f * (m_CB_Main.m._cameraSize.x + m_CB_Main.m._cameraSize.y);              // Radius adapts to camera size
            float  sqNodeRadius  = nodeRadius * nodeRadius;

            // Identify any node under the mouse
            m_SB_NodeSims[0].Read();

            m_displayText = null;
            m_CB_Main.m._hoveredNodeIndex = ~0U;
            for (int nodeIndex = 0; nodeIndex < m_nodesCount; nodeIndex++)
            {
                float2 nodePosition = m_SB_NodeSims[0].m[nodeIndex].m_position;
                float2 delta        = nodePosition - mousePosition;
                float  sqDistance   = delta.Dot(delta);
                if (sqDistance > sqNodeRadius)
                {
                    continue;
                }

                // Found it!
                ProtoParser.Neuron selectedNeuron = m_graph[nodeIndex];
                m_displayText          = selectedNeuron.m_name != null ? selectedNeuron.m_name : selectedNeuron.Parents[0].m_name + "()";
                m_selectedNodePosition = nodePosition;

                m_CB_Main.m._hoveredNodeIndex = (uint)nodeIndex;
                break;
            }

            m_CB_Main.UpdateData();
        }
Beispiel #2
0
        ProtoParser.Neuron      ProcessQuery(string _query)
        {
            _query = _query.Trim();

            ProtoParser.Neuron single = m_graph.FindNeuron(_query);
            return(single);
        }
Beispiel #3
0
        private void textBoxSelection_TextChanged(object sender, EventArgs e)
        {
            try {
                string[] queries = textBoxSelection.Text.Split('\n', ',', ' ', ';');

                if (queries.Length > 0)
                {
                    string message = "";

                    List <ProtoParser.Neuron> selectedNodes = new List <ProtoParser.Neuron>();
                    for (int i = 0; i < queries.Length; i++)
                    {
                        string query = queries[i].Trim();
                        if (query.StartsWith("\""))
                        {
//							query = query.Remove( 0, 1 );	// Remove "
                            while (!query.EndsWith("\"") && i < queries.Length - 1)
                            {
                                query += " " + queries[++i];
                                query  = query.Trim();
                            }
//                          if ( query.Length > 0 )
//                              query = query.Remove( query.Length-1, 1 );	// Remove last "
                        }

                        try {
                            ProtoParser.Neuron N = ProcessQuery(query);
                            if (N == null)
                            {
                                continue;
                            }

                            selectedNodes.Add(N);

                            message += "OK: " + N + "\r\n";
                        } catch (Exception _e) {
                            message += "Error on \"" + query + "\": " + _e.Message + "\r\n";
                        }
                    }

                    Selection = selectedNodes.ToArray();

                    message += "Total selection: " + selectedNodes.Count + "\r\n";

                    textBoxProcessedSelection.Text = message;
                }
                else
                {
                    textBoxProcessedSelection.Text = "Empty.";
                }
            } catch (Exception _e) {
                Selection = null;
                textBoxProcessedSelection.Text = "Error during selection: " + _e.Message;
            }
        }
Beispiel #4
0
        private void textBoxSearch_TextChanged(object sender, EventArgs e)
        {
            try {
                string[] queries = textBoxSearch.Text.Split('\n');

                if (queries.Length > 0)
                {
                    string message = "";

                    List <ProtoParser.Neuron> queryNodes = new List <ProtoParser.Neuron>();
                    foreach (string query in queries)
                    {
                        try {
                            ProtoParser.Neuron N = ProcessQuery(query);
                            if (N == null)
                            {
                                continue;
                            }

                            queryNodes.Add(N);

                            message += "OK: " + N + "\r\n";
                        } catch (Exception _e) {
                            message += "Error on \"" + query + "\": " + _e.Message + "\r\n";
                        }
                    }

                    QueryNodes = queryNodes.ToArray();

                    message += "Total queries: " + queryNodes.Count + "\r\n";

                    textBoxProcessedQuery.Text = message;
                }
                else
                {
                    textBoxProcessedQuery.Text = "No query source.";
                }
            } catch (Exception _e) {
                QueryNodes = null;
                textBoxProcessedQuery.Text = "Error during search: " + _e.Message;
            }
        }
Beispiel #5
0
//      void	SelectNeuronsAndHierarchy( ProtoParser.Neuron[] _neurons ) {
//          if ( _neurons == null ) {
//              Selection = null;
//          }
//
//          List<ProtoParser.Neuron>	neurons = new List<ProtoParser.Neuron>( _neurons );
//          foreach ( ProtoParser.Neuron N in _neurons ) {
//              ProtoParser.Neuron parent = N;
//              while ( parent.ParentsCount > 0 ) {
//                  parent = parent.Parents[0];
//                  neurons.Add( parent );
//              }
//          }
//
//          Selection = neurons.ToArray();
//      }

        private void textBoxSearch_TextChanged(object sender, EventArgs e)
        {
            try {
                ProtoParser.Neuron[] results = m_graph.FindNeurons(textBoxSearch.Text);

                if (results == null || results.Length == 0)
                {
                    ProtoParser.Neuron single = m_graph.FindNeuron(textBoxSearch.Text);
                    if (single != null)
                    {
                        results = new ProtoParser.Neuron[] { single };
                    }
                    else
                    {
                        results = new ProtoParser.Neuron[0];
                    }
                }

                if (results.Length > 0)
                {
                    labelSearchResults.Text = results.Length > 1 ? "Multiple results:\n" : "Single result:\n";
                    foreach (ProtoParser.Neuron result in results)
                    {
                        labelSearchResults.Text += "	"+ result.FullName + "\n";
                    }
                }
                else
                {
                    labelSearchResults.Text = "No result.\n";
                }

//				SelectNeuronsAndHierarchy( results );
                Selection = results;
            } catch (Exception _e) {
                labelSearchResults.Text = "Error during search: " + _e.Message;
//				SelectNeuronsAndHierarchy( new ProtoParser.Neuron[0] );
                Selection = new ProtoParser.Neuron[0];
            }
        }
Beispiel #6
0
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try {
                m_device.Init(panelOutput.Handle, false, true);
            } catch (Exception _e) {
                m_device = null;
                MessageBox.Show("Failed to initialize DX device!\n\n" + _e.Message, "Heat Wave Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try {
                //////////////////////////////////////////////////////////////////////////
                // Load the graph we need to simulate
                m_graph = new ProtoParser.Graph();

//				FileInfo	file = new FileInfo( "../../../AI/Projects/Semantic Memory/Tests/Birds Database/Tools/ProtoParser/Concepts.graph" );
                FileInfo file = new FileInfo("../../../AI/Projects/Semantic Memory/Tests/Birds Database/Tools/ProtoParser/TestGraph.graph");
                if (!file.Exists)
                {
                    file = new FileInfo("./Graphs/TestGraph.graph");
                }

                using (FileStream S = file.OpenRead())
                    using (BinaryReader R = new BinaryReader(S))
                        m_graph.Read(R);

                ProtoParser.Neuron[] neurons = m_graph.Neurons;
                m_nodesCount = (uint)neurons.Length;

/*
 * m_nodesCount = 2;
 * neurons = new ProtoParser.Neuron[2];
 * neurons[0] = new ProtoParser.Neuron();
 * neurons[1] = new ProtoParser.Neuron();
 * neurons[0].LinkChild( neurons[1] );
 * //*/


                //////////////////////////////////////////////////////////////////////////
                m_CB_Main       = new ConstantBuffer <CB_Main>(m_device, 0);
                m_CB_Simulation = new ConstantBuffer <CB_Simulation>(m_device, 1);
                m_CB_Text       = new ConstantBuffer <CB_Text>(m_device, 2);

                m_shader_ComputeForces = new ComputeShader(m_device, new FileInfo("./Shaders/SimulateGraph.hlsl"), "CS");
                m_shader_Simulate      = new ComputeShader(m_device, new FileInfo("./Shaders/SimulateGraph.hlsl"), "CS2");
        #if RENDER_GRAPH_PROPER
                m_shader_RenderGraphNode = new Shader(m_device, new FileInfo("./Shaders/RenderGraph2.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS");
                m_shader_RenderGraphLink = new Shader(m_device, new FileInfo("./Shaders/RenderGraph2.hlsl"), VERTEX_FORMAT.Pt4, "VS2", null, "PS2");
        #else
                m_shader_RenderGraph = new Shader(m_device, new FileInfo("./Shaders/RenderGraph.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS");
        #endif

                m_shader_RenderText = new Shader(m_device, new FileInfo("./Shaders/RenderText.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS");

                // Build node info
                m_SB_Nodes = new StructuredBuffer <SB_NodeInfo>(m_device, m_nodesCount, true);

                m_neuron2ID = new Dictionary <ProtoParser.Neuron, uint>(neurons.Length);

                float maxMass = 0.0f;
                for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++)
                {
                    ProtoParser.Neuron N = neurons[neuronIndex];
                    m_neuron2ID[N] = (uint)neuronIndex;

                    uint linksCount = (uint)(N.ParentsCount + N.ChildrenCount + N.FeaturesCount);
                    //				m_SB_Nodes.m[neuronIndex].m_mass = (1 + 10.0f * linksCount) / (0.1f + N.Distance2Root);			// Works with S=1e4 D=-1e3
                    //				m_SB_Nodes.m[neuronIndex].m_mass = (1 + 1.0f * linksCount) / (0.01f + 0.0f * N.Distance2Root);	// Works with S=1e4 D=-1e3
                    //				m_SB_Nodes.m[neuronIndex].m_mass = (1 + 0.1f * linksCount) / (0.1f + N.Distance2Root);			// Works with S=10 D=-10
                    m_SB_Nodes.m[neuronIndex].m_mass       = 100.0f * (1 + 1.0f * linksCount);                  // Works with S=1e4 D=-1e3
                    m_SB_Nodes.m[neuronIndex].m_linkOffset = m_totalLinksCount;
                    m_SB_Nodes.m[neuronIndex].m_linksCount = linksCount;
                    m_SB_Nodes.m[neuronIndex].m_flags      = 0U;

                    maxMass = Mathf.Max(maxMass, m_SB_Nodes.m[neuronIndex].m_mass);

                    m_totalLinksCount += linksCount;
                }

                m_SB_Nodes.m[0].m_mass = 1e4f;

                m_SB_Nodes.Write();

                // Build node links
                m_SB_Links        = new StructuredBuffer <uint>(m_device, m_totalLinksCount, true);
                m_SB_LinkSources  = new StructuredBuffer <uint>(m_device, m_totalLinksCount, true);
                m_totalLinksCount = 0;
                for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++)
                {
                    ProtoParser.Neuron N = neurons[neuronIndex];
                    foreach (ProtoParser.Neuron O in N.Parents)
                    {
                        m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex;
                        m_SB_Links.m[m_totalLinksCount++]     = m_neuron2ID[O];
                    }
                    foreach (ProtoParser.Neuron O in N.Children)
                    {
                        m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex;
                        m_SB_Links.m[m_totalLinksCount++]     = m_neuron2ID[O];
                    }
                    foreach (ProtoParser.Neuron O in N.Features)
                    {
                        m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex;
                        m_SB_Links.m[m_totalLinksCount++]     = m_neuron2ID[O];
                    }
                }
                m_SB_Links.Write();
                m_SB_LinkSources.Write();

                // Setup initial CB
                m_CB_Main.m._nodesCount   = m_nodesCount;
                m_CB_Main.m._resX         = (uint)panelOutput.Width;
                m_CB_Main.m._resY         = (uint)panelOutput.Height;
                m_CB_Main.m._maxMass      = maxMass;
                m_CB_Main.m._cameraCenter = float2.Zero;
                m_CB_Main.m._cameraSize.Set(10.0f, 10.0f);
                m_CB_Main.m._hoveredNodeIndex = ~0U;
                m_CB_Main.UpdateData();

                // Initialize sim buffers
                m_SB_Forces      = new StructuredBuffer <float2>(m_device, m_nodesCount * m_nodesCount, false);
                m_SB_NodeSims[0] = new StructuredBuffer <SB_NodeSim>(m_device, m_nodesCount, true);
                m_SB_NodeSims[1] = new StructuredBuffer <SB_NodeSim>(m_device, m_nodesCount, true);

                buttonReset_Click(null, EventArgs.Empty);

                //			m_shader_HeatDiffusion = new Shader( m_device, new FileInfo( "./Shaders/HeatDiffusion.hlsl" ), VERTEX_FORMAT.Pt4, "VS", null, "PS", null );

                //          m_tex_Search = new Texture2D( m_device, (uint) GRAPH_SIZE, (uint) GRAPH_SIZE, 1, 1, ImageUtility.PIXEL_FORMAT.RGBA8, ImageUtility.COMPONENT_FORMAT.UNORM, false, false, null );
                //          m_tex_Search_Staging = new Texture2D( m_device, (uint) GRAPH_SIZE, (uint) GRAPH_SIZE, 1, 1, ImageUtility.PIXEL_FORMAT.RGBA8, ImageUtility.COMPONENT_FORMAT.UNORM, true, false, null );

                // Load false colors
                //			using ( ImageUtility.ImageFile sourceImage = new ImageUtility.ImageFile( new FileInfo( "../../Images/Gradients/Viridis.png" ), ImageUtility.ImageFile.FILE_FORMAT.PNG ) ) {
                using (ImageUtility.ImageFile sourceImage = new ImageUtility.ImageFile(new FileInfo("../../Images/Gradients/Magma.png"), ImageUtility.ImageFile.FILE_FORMAT.PNG)) {
                    ImageUtility.ImageFile convertedImage = new ImageUtility.ImageFile();
                    convertedImage.ConvertFrom(sourceImage, ImageUtility.PIXEL_FORMAT.BGRA8);
                    using (ImageUtility.ImagesMatrix image = new ImageUtility.ImagesMatrix(convertedImage, ImageUtility.ImagesMatrix.IMAGE_TYPE.sRGB))
                        m_tex_FalseColors = new Texture2D(m_device, image, ImageUtility.COMPONENT_FORMAT.UNORM_sRGB);
                }

                // Prepare font atlas
                m_SB_Text = new StructuredBuffer <SB_Letter>(m_device, 1024U, true);
                BuildFont();

                Application.Idle += Application_Idle;
            } catch (Exception _e) {
                m_device = null;
                MessageBox.Show("Failed to initialize shaders!\n\n" + _e.Message, "Heat Wave Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }
Beispiel #7
0
        private void panelOutput_MouseMove(object sender, MouseEventArgs e)
        {
            // Transform mouse position into node space
            float2 mousePosition = Client2Pos(e.Location);
            float  nodeRadius    = 0.01f * 0.5f * (m_CB_Main.m._cameraSize.x + m_CB_Main.m._cameraSize.y);              // Radius adapts to camera size
            float  sqNodeRadius  = nodeRadius * nodeRadius;

            // Identify any node under the mouse
            m_SB_Nodes.Read();

            m_displayText = null;
            m_CB_Main.m._hoveredNodeIndex = ~0U;
            for (int nodeIndex = 0; nodeIndex < m_nodesCount; nodeIndex++)
            {
                float2 nodePosition = m_SB_Nodes.m[nodeIndex].m_position;
                float2 delta        = nodePosition - mousePosition;
                float  sqDistance   = delta.Dot(delta);
                if (sqDistance > sqNodeRadius)
                {
                    continue;
                }

                // Found it!
                ProtoParser.Neuron selectedNeuron = m_graph[nodeIndex];
                if (selectedNeuron.m_name != null)
                {
                    m_displayText = selectedNeuron.m_name;
                }
                else
                {
                    m_displayText = "*" + selectedNeuron.Parents[0].m_name;
                }

                if (selectedNeuron.m_value is ProtoParser.NeuronValue)
                {
                    // Show value
                    m_displayText += "( ";
                    m_displayText += (selectedNeuron.m_value as ProtoParser.NeuronValue).m_valueMean != null ? (selectedNeuron.m_value as ProtoParser.NeuronValue).m_valueMean : "<null>";
                    m_displayText += " )";
                }

                // Show value
                if (radioButtonShowTemperature.Checked)
                {
                    m_SB_HeatSource.Read();
                    float heat = m_SB_HeatSource.m[m_nodesCount * integerTrackbarControlShowQuerySourceIndex.Value + m_neuron2ID[selectedNeuron]];
                    m_displayText += " = " + heat.ToString("G4");
                }
                else if (radioButtonShowBarycentrics.Checked)
                {
                    GetBarycentricsBuffer();
                    float heat = m_SB_HeatBarycentrics.m[m_nodesCount * integerTrackbarControlShowQuerySourceIndex.Value + m_neuron2ID[selectedNeuron]];
                    m_displayText += " = " + heat.ToString("G4");
                }
                else if (radioButtonShowResultsBarycentric.Checked)
                {
                    GetBarycentricsBuffer();
                    float heat = ComputeResult(m_neuron2ID[selectedNeuron]);
                    m_displayText += " = " + heat.ToString("G4");
                }
                else if (radioButtonShowResultsSum.Checked)
                {
                    float heatSum = GetSumBuffer().m[m_neuron2ID[selectedNeuron]];
                    m_displayText += " = " + heatSum.ToString("G4");
                }

                m_selectedNodePosition = nodePosition;

                m_CB_Main.m._hoveredNodeIndex = (uint)nodeIndex;
                break;
            }

            m_CB_Main.UpdateData();
        }
Beispiel #8
0
        private void buttonGrabResults_Click(object sender, EventArgs e)
        {
            int sourcesCount = m_queryNodes.Length;

            if (sourcesCount == 0)
            {
                textBoxSearchResults.Text = "No results.";
                return;
            }

            // Compute barycentrics needed for results
            if (radioButtonShowResultsBarycentric.Checked)
            {
                GetBarycentricsBuffer().Read();

                // Compute node scores
                float bias             = floatTrackbarControlBarycentricBias.Value;
                int   biasSourceTarget = integerTrackbarControlShowQuerySourceIndex.Value;

                float isoBarycentricCenter0 = (1.0f - bias) / (sourcesCount - bias);                    // The ideal center is a vector with all components equal to this value
                float isoBarycentricCenter1 = Mathf.Lerp(isoBarycentricCenter0, 1.0f, bias);

                m_resultScores      = new float[m_nodesCount];
                m_resultNodeIndices = new int[m_nodesCount];
                for (int nodeIndex = 0; nodeIndex < m_nodesCount; nodeIndex++)
                {
                    float sqDistance = 0.0f;
                    for (int sourceIndex = 0; sourceIndex < sourcesCount; sourceIndex++)
                    {
                        float barycentric = m_SB_HeatBarycentrics.m[m_nodesCount * sourceIndex + nodeIndex];
                        float delta       = barycentric - (sourceIndex == biasSourceTarget ? isoBarycentricCenter1 : isoBarycentricCenter0);
                        sqDistance += delta * delta;
                    }

                    m_resultScores[nodeIndex]      = Mathf.Sqrt(sqDistance);
                    m_resultNodeIndices[nodeIndex] = nodeIndex;
                }
            }
            else
            {
                GetSumBuffer().Read();

                // Compute node scores
                m_resultScores      = new float[m_nodesCount];
                m_resultNodeIndices = new int[m_nodesCount];
                for (int nodeIndex = 0; nodeIndex < m_nodesCount; nodeIndex++)
                {
                    m_resultScores[nodeIndex]      = 1.0f - m_SB_HeatSum.m[nodeIndex];                  // Lowest scores are better!
                    m_resultNodeIndices[nodeIndex] = nodeIndex;
                }
            }

//Il faut aussi isoler les résultats du type qu'on veut !

            // Dump results
            string results = "";

            if (Selection.Length > 0)
            {
                // Show selected nodes first
                results += "Results for selection:\r\n";
                foreach (ProtoParser.Neuron selectedNode in Selection)
                {
                    float score = m_resultScores[m_neuron2ID[selectedNode]];
                    results += selectedNode + (selectedNode.m_value is ProtoParser.NeuronValue ? "( " + ((selectedNode.m_value as ProtoParser.NeuronValue).m_valueMean != null ? (selectedNode.m_value as ProtoParser.NeuronValue).m_valueMean : "<null>") + " )" : "") + " - " + score.ToString("G4") + "\r\n";
                }

                results += "\r\n";
            }

            // Sort scores & dump the N first
            Array.Sort(m_resultScores, m_resultNodeIndices);

            for (int i = 0; i < integerTrackbarControlSignificantResultsCount.Value; i++)
            {
                float score          = m_resultScores[i];
                ProtoParser.Neuron N = m_graph.Neurons[m_resultNodeIndices[i]];
                results += N + (N.m_value is ProtoParser.NeuronValue ? "( " + ((N.m_value as ProtoParser.NeuronValue).m_valueMean != null ? (N.m_value as ProtoParser.NeuronValue).m_valueMean : "<null>") + " )" : "") + " - " + score.ToString("G4") + "\r\n";
            }
            textBoxSearchResults.Text = results;
        }
Beispiel #9
0
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try {
                m_device.Init(panelOutput.Handle, false, true);
            }
            catch (Exception _e) {
                m_device = null;
                MessageBox.Show("Failed to initialize DX device!\n\n" + _e.Message, "Heat Wave Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //////////////////////////////////////////////////////////////////////////
            m_CB_Main = new ConstantBuffer <CB_Main>(m_device, 0);
            m_CB_Text = new ConstantBuffer <CB_Text>(m_device, 2);

            m_compute_HeatDiffusion    = new ComputeShader(m_device, new FileInfo("./Shaders/HeatDiffusion.hlsl"), "CS");
            m_compute_SplatHeatSources = new ComputeShader(m_device, new FileInfo("./Shaders/HeatDiffusion.hlsl"), "CS2");

            m_shader_RenderGraphNode = new Shader(m_device, new FileInfo("./Shaders/RenderGraph.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS");
            m_shader_RenderGraphLink = new Shader(m_device, new FileInfo("./Shaders/RenderGraph.hlsl"), VERTEX_FORMAT.Pt4, "VS2", null, "PS2");
            m_shader_RenderText      = new Shader(m_device, new FileInfo("./Shaders/RenderText.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS");


            //////////////////////////////////////////////////////////////////////////
            // Load the graph we need to run
            m_graph = new ProtoParser.Graph();

            // Load graph
            using (FileStream S = new FileInfo("./Graphs/Birds.graph").OpenRead())
                using (BinaryReader R = new BinaryReader(S))
                    m_graph.Read(R);

            // Load graph node positions (simulated and saved by the TestGraphViz project)
            float2[] graphNodePositions = null;
            using (FileStream S = new FileInfo("./Graphs/Birds.graphpos").OpenRead())
                using (BinaryReader R = new BinaryReader(S)) {
                    float2 BBoxMin = new float2(R.ReadSingle(), R.ReadSingle());
                    float2 BBoxMax = new float2(R.ReadSingle(), R.ReadSingle());

                    m_CB_Main.m._cameraCenter = 0.5f * (BBoxMin + BBoxMax);
                    m_CB_Main.m._cameraSize   = BBoxMax - BBoxMin;

                    int nodesCount = R.ReadInt32();
                    if (nodesCount != m_graph.NeuronsCount)
                    {
                        throw new Exception("Graph nodes count mismatch!");
                    }

                    graphNodePositions = new float2[nodesCount];
                    for (int i = 0; i < nodesCount; i++)
                    {
                        graphNodePositions[i].Set(R.ReadSingle(), R.ReadSingle());
                    }
                }

            ProtoParser.Neuron[] neurons = m_graph.Neurons;
            m_nodesCount = (uint)neurons.Length;

            // Build node info
            m_SB_Nodes = new StructuredBuffer <SB_NodeInfo>(m_device, m_nodesCount, true);

            m_neuron2ID = new Dictionary <ProtoParser.Neuron, uint>(neurons.Length);

            for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++)
            {
                ProtoParser.Neuron N = neurons[neuronIndex];
                m_neuron2ID[N] = (uint)neuronIndex;

                uint linksCount = (uint)(N.ParentsCount + N.ChildrenCount + N.FeaturesCount);
                m_SB_Nodes.m[neuronIndex].m_position   = graphNodePositions[neuronIndex];
                m_SB_Nodes.m[neuronIndex].m_linkOffset = m_totalLinksCount;
                m_SB_Nodes.m[neuronIndex].m_linksCount = linksCount;
                m_SB_Nodes.m[neuronIndex].m_flags      = 0U;

                m_totalLinksCount += linksCount;
            }

            m_SB_Nodes.Write();

            // Build node links
            m_SB_LinkTargets  = new StructuredBuffer <uint>(m_device, m_totalLinksCount, true);
            m_SB_LinkSources  = new StructuredBuffer <uint>(m_device, m_totalLinksCount, true);
            m_totalLinksCount = 0;
            for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++)
            {
                ProtoParser.Neuron N = neurons[neuronIndex];
                foreach (ProtoParser.Neuron O in N.Parents)
                {
                    m_SB_LinkSources.m[m_totalLinksCount]   = (uint)neuronIndex;
                    m_SB_LinkTargets.m[m_totalLinksCount++] = m_neuron2ID[O];
                }
                foreach (ProtoParser.Neuron O in N.Children)
                {
                    m_SB_LinkSources.m[m_totalLinksCount]   = (uint)neuronIndex;
                    m_SB_LinkTargets.m[m_totalLinksCount++] = m_neuron2ID[O];
                }
                foreach (ProtoParser.Neuron O in N.Features)
                {
                    m_SB_LinkSources.m[m_totalLinksCount]   = (uint)neuronIndex;
                    m_SB_LinkTargets.m[m_totalLinksCount++] = m_neuron2ID[O];
                }
            }
            m_SB_LinkTargets.Write();
            m_SB_LinkSources.Write();


            // Build heat buffers
            uint elementsCount = m_nodesCount * MAX_QUERY_SOURCES;

            m_SB_SourceIndices = new StructuredBuffer <uint>(m_device, MAX_QUERY_SOURCES, true);
            m_SB_HeatSource    = new StructuredBuffer <float>(m_device, elementsCount, true);
            m_SB_HeatTarget    = new StructuredBuffer <float>(m_device, elementsCount, true);

            m_SB_HeatBarycentrics = new StructuredBuffer <float>(m_device, elementsCount, true);
            m_SB_HeatSum          = new StructuredBuffer <float>(m_device, m_nodesCount, true);

            // Setup initial CB
            m_CB_Main.m._nodesCount           = m_nodesCount;
            m_CB_Main.m._sourcesCount         = 0;
            m_CB_Main.m._resX                 = (uint)panelOutput.Width;
            m_CB_Main.m._resY                 = (uint)panelOutput.Height;
            m_CB_Main.m._diffusionCoefficient = 1.0f;
            m_CB_Main.m._hoveredNodeIndex     = ~0U;
            m_CB_Main.m._renderFlags          = 0U;
            m_CB_Main.UpdateData();

            // Load false colors
            m_tex_FalseColors0 = LoadFalseColors(new FileInfo("../../Images/Gradients/Magma.png"));
            m_tex_FalseColors1 = LoadFalseColors(new FileInfo("../../Images/Gradients/Viridis.png"));

            // Prepare font atlas
            m_SB_Text = new StructuredBuffer <SB_Letter>(m_device, 1024U, true);
            BuildFont();

            Application.Idle += Application_Idle;
        }