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();
            }
        }
Example #2
0
        public static void DebugExpressionGraph(VFXGraph graph, VFXExpressionContextOption option, string fileName = "expGraph.dot")
        {
            var expressionGraph = new VFXExpressionGraph();

            expressionGraph.CompileExpressions(graph, option, true);

            var mainExpressions = new Dictionary <VFXExpression, List <string> >();

            FillMainExpressions(mainExpressions, expressionGraph.GPUExpressionsToReduced, expressionGraph);
            FillMainExpressions(mainExpressions, expressionGraph.CPUExpressionsToReduced, expressionGraph);

            var expressions = expressionGraph.Expressions;

            DotGraph dotGraph = new DotGraph();

            var expressionsToDot = new Dictionary <VFXExpression, DotNode>();

            foreach (var exp in expressions)
            {
                var dotNode = new DotNode();

                string name = exp.GetType().Name;
                name += " " + exp.valueType.ToString();
                string valueStr = GetExpressionValue(exp);
                if (!string.IsNullOrEmpty(valueStr))
                {
                    name += string.Format(" ({0})", valueStr);
                }

                dotNode.attributes[DotAttribute.Shape] = DotShape.Box;

                if (mainExpressions.ContainsKey(exp))
                {
                    string allOwnersStr = string.Empty;
                    foreach (var str in mainExpressions[exp])
                    {
                        allOwnersStr += "\n" + str;
                    }

                    name += string.Format("{0}", allOwnersStr);

                    if (exp.IsAny(VFXExpression.Flags.NotCompilableOnCPU))
                    {
                        dotNode.attributes[DotAttribute.Color] = DotColor.Orange;
                    }
                    else if (exp.Is(VFXExpression.Flags.Constant))
                    {
                        dotNode.attributes[DotAttribute.Color] = DotColor.SteelBlue;
                    }
                    else
                    {
                        dotNode.attributes[DotAttribute.Color] = DotColor.Cyan;
                    }
                }
                else if (exp.IsAny(VFXExpression.Flags.NotCompilableOnCPU))
                {
                    dotNode.attributes[DotAttribute.Color] = DotColor.Yellow;
                }
                else if (exp.Is(VFXExpression.Flags.Constant))
                {
                    dotNode.attributes[DotAttribute.Color] = DotColor.SlateGray;
                }
                else if (exp.Is(VFXExpression.Flags.Foldable))
                {
                    dotNode.attributes[DotAttribute.Color] = DotColor.LightGray;
                }

                if (dotNode.attributes.ContainsKey(DotAttribute.Color))
                {
                    dotNode.attributes[DotAttribute.Style] = DotStyle.Filled;
                }

                dotNode.Label = name;

                expressionsToDot[exp] = dotNode;
                dotGraph.AddElement(dotNode);
            }

            foreach (var exp in expressionsToDot)
            {
                var parents = exp.Key.parents;
                for (int i = 0; i < parents.Length; ++i)
                {
                    var dotEdge = new DotEdge(expressionsToDot[parents[i]], exp.Value);
                    if (parents.Length > 1)
                    {
                        dotEdge.attributes[DotAttribute.HeadLabel] = i.ToString();
                    }
                    dotGraph.AddElement(dotEdge);
                }
            }

            var basePath = Application.dataPath;

            basePath = basePath.Replace("/Assets", "");
            basePath = basePath.Replace("/", "\\");

            var outputfile = basePath + "\\GraphViz\\output\\" + fileName;

            dotGraph.OutputToDotFile(outputfile);

            var proc = new Process();

            proc.StartInfo.WindowStyle     = ProcessWindowStyle.Hidden;
            proc.StartInfo.CreateNoWindow  = true;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.FileName        = "C:\\Windows\\system32\\cmd.exe";
            var path = basePath + "\\GraphViz\\Postbuild.bat";

            proc.StartInfo.Arguments = "/c" + path + " \"" + outputfile + "\"";
            proc.EnableRaisingEvents = true;
            proc.Start();
        }