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(); } }
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(); }