private static VFXExpressionValueContainerDesc <T> CreateValueDesc <T>(VFXExpression exp, int expIndex)
        {
            var desc = new VFXExpressionValueContainerDesc <T>();

            desc.value = exp.Get <T>();
            return(desc);
        }
        public void Compile(VFXCompilationMode compilationMode)
        {
            // Prevent doing anything ( and especially showing progesses ) in an empty graph.
            if (m_Graph.children.Count() < 1)
            {
                // Cleaning
                if (m_Graph.visualEffectResource != null)
                {
                    m_Graph.visualEffectResource.ClearRuntimeData();
                }

                m_ExpressionGraph  = new VFXExpressionGraph();
                m_ExpressionValues = new VFXExpressionValueContainerDesc[] {};
                return;
            }

            Profiler.BeginSample("VFXEditor.CompileAsset");
            try
            {
                float  nbSteps          = 12.0f;
                string assetPath        = AssetDatabase.GetAssetPath(visualEffectResource);
                string progressBarTitle = "Compiling " + assetPath;

                EditorUtility.DisplayProgressBar(progressBarTitle, "Collecting dependencies", 0 / nbSteps);
                var models = new HashSet <ScriptableObject>();
                m_Graph.CollectDependencies(models);

                var contexts = models.OfType <VFXContext>().ToArray();

                foreach (var c in contexts) // Unflag all contexts
                {
                    c.MarkAsCompiled(false);
                }

                var compilableContexts = models.OfType <VFXContext>().Where(c => c.CanBeCompiled());
                var compilableData     = models.OfType <VFXData>().Where(d => d.CanBeCompiled());

                IEnumerable <VFXContext> implicitContexts = Enumerable.Empty <VFXContext>();
                foreach (var d in compilableData) // Flag compiled contexts
                {
                    implicitContexts = implicitContexts.Concat(d.InitImplicitContexts());
                }
                compilableContexts = compilableContexts.Concat(implicitContexts.ToArray());

                foreach (var c in compilableContexts) // Flag compiled contexts
                {
                    c.MarkAsCompiled(true);
                }

                EditorUtility.DisplayProgressBar(progressBarTitle, "Collecting attributes", 1 / nbSteps);
                foreach (var data in compilableData)
                {
                    data.CollectAttributes();
                }

                EditorUtility.DisplayProgressBar(progressBarTitle, "Computing layers", 2 / nbSteps);
                foreach (var data in compilableData)
                {
                    data.ComputeLayer();
                }

                EditorUtility.DisplayProgressBar(progressBarTitle, "Compiling expression Graph", 3 / nbSteps);
                m_ExpressionGraph = new VFXExpressionGraph();
                var exposedExpressionContext = ScriptableObject.CreateInstance <VFXImplicitContextOfExposedExpression>();
                exposedExpressionContext.FillExpression(m_Graph); //Force all exposed expression to be visible, only for registering in CompileExpressions

                var expressionContextOptions = compilationMode == VFXCompilationMode.Runtime ? VFXExpressionContextOption.ConstantFolding : VFXExpressionContextOption.Reduction;
                m_ExpressionGraph.CompileExpressions(compilableContexts.Concat(new VFXContext[] { exposedExpressionContext }), expressionContextOptions);

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating bytecode", 4 / nbSteps);
                var expressionDescs = new List <VFXExpressionDesc>();
                var valueDescs      = new List <VFXExpressionValueContainerDesc>();
                FillExpressionDescs(expressionDescs, valueDescs, m_ExpressionGraph);

                Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData = new Dictionary <VFXContext, VFXContextCompiledData>();
                foreach (var context in compilableContexts)
                {
                    contextToCompiledData.Add(context, new VFXContextCompiledData());
                }

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating mappings", 5 / nbSteps);
                foreach (var context in compilableContexts)
                {
                    var cpuMapper   = m_ExpressionGraph.BuildCPUMapper(context);
                    var contextData = contextToCompiledData[context];
                    contextData.cpuMapper          = cpuMapper;
                    contextData.parameters         = context.additionalMappings.ToArray();
                    contextToCompiledData[context] = contextData;
                }

                var exposedParameterDescs = new List <VFXMapping>();
                FillExposedDescs(exposedParameterDescs, m_ExpressionGraph, models.OfType <VFXParameter>());
                var globalEventAttributeDescs = new List <VFXLayoutElementDesc>()
                {
                    new VFXLayoutElementDesc()
                    {
                        name = "spawnCount", type = VFXValueType.Float
                    }
                };
                FillEventAttributeDescs(globalEventAttributeDescs, m_ExpressionGraph, compilableContexts);

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating Attribute layouts", 6 / nbSteps);
                foreach (var data in compilableData)
                {
                    data.GenerateAttributeLayout();
                }

                var generatedCodeData = new List <GeneratedCodeData>();

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating shaders", 7 / nbSteps);
                GenerateShaders(generatedCodeData, m_ExpressionGraph, compilableContexts, contextToCompiledData, compilationMode);

                EditorUtility.DisplayProgressBar(progressBarTitle, "Saving shaders", 8 / nbSteps);
                SaveShaderFiles(m_Graph.visualEffectResource, generatedCodeData, contextToCompiledData);

                var bufferDescs    = new List <VFXGPUBufferDesc>();
                var cpuBufferDescs = new List <VFXCPUBufferDesc>();
                var systemDescs    = new List <VFXEditorSystemDesc>();

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating systems", 9 / nbSteps);
                cpuBufferDescs.Add(new VFXCPUBufferDesc()
                {
                    capacity    = 1u,
                    layout      = globalEventAttributeDescs.ToArray(),
                    stride      = globalEventAttributeDescs.First().offset.structure,
                    initialData = ComputeArrayOfStructureInitialData(globalEventAttributeDescs)
                });
                var contextSpawnToSpawnInfo = new Dictionary <VFXContext, SpawnInfo>();
                FillSpawner(contextSpawnToSpawnInfo, cpuBufferDescs, systemDescs, compilableContexts, m_ExpressionGraph, globalEventAttributeDescs, contextToCompiledData);

                var eventDescs = new List <VFXEventDesc>();
                FillEvent(eventDescs, contextSpawnToSpawnInfo, compilableContexts);

                var attributeBufferDictionnary = new Dictionary <VFXData, int>();
                var eventGpuBufferDictionnary  = new Dictionary <VFXData, int>();
                FillDependentBuffer(compilableData, bufferDescs, attributeBufferDictionnary, eventGpuBufferDictionnary);

                var contextSpawnToBufferIndex = contextSpawnToSpawnInfo.Select(o => new { o.Key, o.Value.bufferIndex }).ToDictionary(o => o.Key, o => o.bufferIndex);
                foreach (var data in compilableData)
                {
                    data.FillDescs(bufferDescs,
                                   systemDescs,
                                   m_ExpressionGraph,
                                   contextToCompiledData,
                                   contextSpawnToBufferIndex,
                                   attributeBufferDictionnary,
                                   eventGpuBufferDictionnary);
                }

                // Update renderer settings
                VFXRendererSettings rendererSettings = GetRendererSettings(m_Graph.visualEffectResource.rendererSettings, compilableContexts.OfType <IVFXSubRenderer>());
                m_Graph.visualEffectResource.rendererSettings = rendererSettings;

                EditorUtility.DisplayProgressBar(progressBarTitle, "Setting up systems", 10 / nbSteps);
                var expressionSheet = new VFXExpressionSheet();
                expressionSheet.expressions = expressionDescs.ToArray();
                expressionSheet.values      = valueDescs.OrderBy(o => o.expressionIndex).ToArray();
                expressionSheet.exposed     = exposedParameterDescs.OrderBy(o => o.name).ToArray();

                m_Graph.visualEffectResource.SetRuntimeData(expressionSheet, systemDescs.ToArray(), eventDescs.ToArray(), bufferDescs.ToArray(), cpuBufferDescs.ToArray());
                m_ExpressionValues = expressionSheet.values;

                EditorUtility.DisplayProgressBar(progressBarTitle, "Importing VFX", 11 / nbSteps);
                Profiler.BeginSample("VFXEditor.CompileAsset:ImportAsset");
                AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); //This should compile the shaders on the C++ size
                Profiler.EndSample();
            }
            catch (Exception e)
            {
                Debug.LogError(string.Format("Exception while compiling expression graph: {0}: {1}", e, e.StackTrace));

                // Cleaning
                if (m_Graph.visualEffectResource != null)
                {
                    m_Graph.visualEffectResource.ClearRuntimeData();
                }

                m_ExpressionGraph  = new VFXExpressionGraph();
                m_ExpressionValues = new VFXExpressionValueContainerDesc[] {};
            }
            finally
            {
                Profiler.EndSample();
                EditorUtility.ClearProgressBar();
            }
        }
 private void SetValueDesc <T>(VFXExpressionValueContainerDesc desc, VFXExpression exp)
 {
     ((VFXExpressionValueContainerDesc <T>)desc).value = exp.Get <T>();
 }