예제 #1
0
        internal static void BuildFragInputsGeneration(VFXContext context, VFXContextCompiledData contextData, bool useFragInputs, out string buildFragInputsGeneration)
        {
            var expressionToName = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            var fragInputsGeneration = new VFXShaderWriter();

            foreach (string fragmentParameter in context.fragmentParameters)
            {
                var filteredNamedExpression = mainParameters.FirstOrDefault(o => fragmentParameter == o.name);
                if (filteredNamedExpression.exp == null)
                {
                    throw new InvalidOperationException("FragInputs generation failed to find expected parameter: " + fragmentParameter);
                }

                var isInterpolant = !(expressionToName.ContainsKey(filteredNamedExpression.exp) && expressionToName[filteredNamedExpression.exp] == filteredNamedExpression.name);

                var surfaceSetter = useFragInputs ? "output.vfx" : "output";
                fragInputsGeneration.WriteAssignement(filteredNamedExpression.exp.valueType, $"{surfaceSetter}.{filteredNamedExpression.name}", $"{(isInterpolant ? "input." : string.Empty)}{filteredNamedExpression.name}");
                fragInputsGeneration.WriteLine();
            }

            buildFragInputsGeneration = fragInputsGeneration.ToString();
        }
예제 #2
0
        internal static void BuildVertexPropertiesAssign(VFXContext context, VFXContextCompiledData contextData, out string buildVertexPropertiesGeneration)
        {
            var expressionToName = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            var vertexInputsGeneration = new VFXShaderWriter();

            foreach (string vertexParameter in context.vertexParameters)
            {
                var filteredNamedExpression = mainParameters.FirstOrDefault(o => vertexParameter == o.name);
                if (filteredNamedExpression.exp == null)
                {
                    throw new InvalidOperationException(string.Format("Cannot find vertex property : {0}", vertexParameter));
                }

                // If the parameter is in the global scope, read from the cbuffer directly (no suffix).
                if (!(expressionToName.ContainsKey(filteredNamedExpression.exp) && expressionToName[filteredNamedExpression.exp] == filteredNamedExpression.name))
                {
                    vertexInputsGeneration.WriteAssignement(filteredNamedExpression.exp.valueType, $"properties.{filteredNamedExpression.name}", $"{filteredNamedExpression.name}__");
                }
                else
                {
                    vertexInputsGeneration.WriteAssignement(filteredNamedExpression.exp.valueType, $"properties.{filteredNamedExpression.name}", $"{filteredNamedExpression.name}");
                }

                vertexInputsGeneration.WriteLine();
            }

            buildVertexPropertiesGeneration = vertexInputsGeneration.ToString();
        }
예제 #3
0
        internal static void BuildVertexProperties(VFXContext context, VFXContextCompiledData contextData, out string vertexProperties)
        {
            var expressionToName = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            var additionalVertexProperties = new VFXShaderWriter();

            foreach (string vertexParameter in context.vertexParameters)
            {
                var filteredNamedExpression = mainParameters.FirstOrDefault(o => vertexParameter == o.name &&
                                                                            !(expressionToName.ContainsKey(o.exp) && expressionToName[o.exp] == o.name));      // if parameter already in the global scope, there's nothing to do

                if (filteredNamedExpression.exp != null)
                {
                    additionalVertexProperties.WriteVariable(filteredNamedExpression.exp.valueType, filteredNamedExpression.name + "__", "0");
                    var expressionToNameLocal = new Dictionary <VFXExpression, string>(expressionToName);
                    additionalVertexProperties.EnterScope();
                    {
                        if (!expressionToNameLocal.ContainsKey(filteredNamedExpression.exp))
                        {
                            additionalVertexProperties.WriteVariable(filteredNamedExpression.exp, expressionToNameLocal);
                            additionalVertexProperties.WriteLine();
                        }
                        additionalVertexProperties.WriteAssignement(filteredNamedExpression.exp.valueType, filteredNamedExpression.name + "__", expressionToNameLocal[filteredNamedExpression.exp]);
                        additionalVertexProperties.WriteLine();
                    }
                    additionalVertexProperties.ExitScope();
                }
            }

            vertexProperties = additionalVertexProperties.ToString();
        }
예제 #4
0
        private static void InnerUnlink(VFXContext from, VFXContext to, int fromIndex = 0, int toIndex = 0, bool notify = true)
        {
            if (from.GetData() == to.GetData() && from.GetData() != null)
            {
                to.SetDefaultData(false);
            }

            int count = from.m_OutputFlowSlot[fromIndex].link.RemoveAll(o => o.context == to && o.slotIndex == toIndex);

            count += to.m_InputFlowSlot[toIndex].link.RemoveAll(o => o.context == from && o.slotIndex == fromIndex);

            if (count > 0 && notify)
            {
                from.Invalidate(InvalidationCause.kConnectionChanged);
                to.Invalidate(InvalidationCause.kConnectionChanged);
            }
        }
예제 #5
0
        private static void InnerUnlink(VFXContext from, VFXContext to, int fromIndex = 0, int toIndex = 0, bool notify = true)
        {
            if (from.GetData() == to.GetData() && from.GetData() != null)
            {
                to.SetDefaultData(false);
            }

            from.m_OutputFlowSlot[fromIndex].link.RemoveAll(o => o.context == to && o.slotIndex == toIndex);
            to.m_InputFlowSlot[toIndex].link.RemoveAll(o => o.context == from && o.slotIndex == fromIndex);

            // TODO Might need a specific event ?
            if (notify)
            {
                from.Invalidate(InvalidationCause.kStructureChanged);
                to.Invalidate(InvalidationCause.kStructureChanged);
            }
        }
예제 #6
0
        protected static void InnerLink(VFXContext from, VFXContext to, int fromIndex, int toIndex, bool notify = true)
        {
            if (!CanLink(from, to, fromIndex, toIndex))
            {
                throw new ArgumentException(string.Format("Cannot link contexts {0} and {1}", from, to));
            }

            // Handle constraints on connections
            foreach (var link in from.m_OutputFlowSlot[fromIndex].link.ToArray())
            {
                if (!link.context.CanLinkFromMany() ||
                    !CanMixingFrom(from.contextType, link.context.contextType, to.contextType))
                {
                    if (link.context.inputFlowCount > toIndex) //Special case from SubGraph, not sure how this test could be false
                    {
                        InnerUnlink(from, link.context, fromIndex, toIndex, notify);
                    }
                }
            }

            foreach (var link in to.m_InputFlowSlot[toIndex].link.ToArray())
            {
                if (!link.context.CanLinkToMany() ||
                    !CanMixingTo(link.context.contextType, to.contextType, from.contextType))
                {
                    InnerUnlink(link.context, to, fromIndex, toIndex, notify);
                }
            }

            if ((from.ownedType & to.ownedType) == to.ownedType)
            {
                to.InnerSetData(from.GetData(), false);
            }

            from.m_OutputFlowSlot[fromIndex].link.Add(new VFXContextLink()
            {
                context = to, slotIndex = toIndex
            });
            to.m_InputFlowSlot[toIndex].link.Add(new VFXContextLink()
            {
                context = from, slotIndex = fromIndex
            });

            if (notify)
            {
                from.Invalidate(InvalidationCause.kConnectionChanged);
                to.Invalidate(InvalidationCause.kConnectionChanged);
            }
        }
        static private VFXShaderWriter GenerateComputeSourceIndex(VFXContext context)
        {
            var r = new VFXShaderWriter();
            var spawnCountAttribute = new VFXAttribute("spawnCount", VFXValueType.Float);

            if (!context.GetData().dependenciesIn.Any())
            {
                var spawnLinkCount = context.GetData().sourceCount;
                r.WriteLine("int sourceIndex = 0;");

                if (spawnLinkCount <= 1)
                {
                    r.WriteLine("/*//Loop with 1 iteration generate a wrong IL Assembly (and actually, useless code)");
                }

                r.WriteLine("uint currentSumSpawnCount = 0u;");
                r.WriteLineFormat("for (sourceIndex=0; sourceIndex<{0}; sourceIndex++)", spawnLinkCount);
                r.EnterScope();
                r.WriteLineFormat("currentSumSpawnCount += uint({0});", context.GetData().GetLoadAttributeCode(spawnCountAttribute, VFXAttributeLocation.Source));
                r.WriteLine("if (id < currentSumSpawnCount)");
                r.EnterScope();
                r.WriteLine("break;");
                r.ExitScope();
                r.ExitScope();

                if (spawnLinkCount <= 1)
                {
                    r.WriteLine("*/");
                }
            }
            else
            {
                /* context invalid or GPU event */
            }
            return(r);
        }
예제 #8
0
        public string GetContextShaderName(VFXContext context)
        {
            string prefix = shaderNamePrefix;

            if (context.GetData() != null)
            {
                string dataName = context.GetData().fileName;
                if (!string.IsNullOrEmpty(dataName))
                {
                    prefix += "/" + dataName;
                }
            }

            if (context.letter != '\0')
            {
                if (string.IsNullOrEmpty(context.label))
                {
                    return(string.Format("{2}/({0}) {1}", context.letter, libraryName, prefix));
                }
                else
                {
                    return(string.Format("{2}/({0}) {1}", context.letter, context.label, prefix));
                }
            }
            else
            {
                if (string.IsNullOrEmpty(context.label))
                {
                    return(string.Format("{1}/{0}", libraryName, prefix));
                }
                else
                {
                    return(string.Format("{1}/{0}", context.label, prefix));
                }
            }
        }
예제 #9
0
        private static void InnerLink(VFXContext from, VFXContext to, int fromIndex, int toIndex, bool notify = true)
        {
            if (!CanLink(from, to, fromIndex, toIndex))
            {
                throw new ArgumentException(string.Format("Cannot link contexts {0} and {1}", from, to));
            }

            // Handle constraints on connections
            foreach (var link in from.m_OutputFlowSlot[fromIndex].link.ToArray())
            {
                if (!link.context.CanLinkFromMany() || (IsExclusiveLink(link.context.contextType, to.contextType) && from.contextType == link.context.contextType))
                {
                    if (link.context.inputFlowCount > toIndex)
                    {
                        InnerUnlink(from, link.context, fromIndex, toIndex, notify);
                    }
                }
            }

            foreach (var link in to.m_InputFlowSlot[toIndex].link.ToArray())
            {
                if (!link.context.CanLinkToMany() || IsExclusiveLink(link.context.contextType, from.contextType))
                {
                    InnerUnlink(link.context, to, fromIndex, toIndex, notify);
                }
            }

            if ((from.ownedType & to.ownedType) == to.ownedType)
            {
                to.InnerSetData(from.GetData(), false);
            }

            from.m_OutputFlowSlot[fromIndex].link.Add(new VFXContextLink()
            {
                context = to, slotIndex = toIndex
            });
            to.m_InputFlowSlot[toIndex].link.Add(new VFXContextLink()
            {
                context = from, slotIndex = fromIndex
            });

            if (notify)
            {
                // TODO Might need a specific event ?
                from.Invalidate(InvalidationCause.kStructureChanged);
                to.Invalidate(InvalidationCause.kStructureChanged);
            }
        }
예제 #10
0
        internal static void BuildPixelPropertiesAssign(VFXContext context, VFXContextCompiledData contextData, out string buildFragInputsGeneration)
        {
            var expressionToName = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));
            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            var fragInputsGeneration = new VFXShaderWriter();

            foreach (string fragmentParameter in context.fragmentParameters)
            {
                var filteredNamedExpression = mainParameters.FirstOrDefault(o => fragmentParameter == o.name);
                fragInputsGeneration.WriteAssignement(filteredNamedExpression.exp.valueType, $"properties.{filteredNamedExpression.name}", $"fragInputs.vfx.{filteredNamedExpression.name}");
                fragInputsGeneration.WriteLine();
            }

            buildFragInputsGeneration = fragInputsGeneration.ToString();
        }
예제 #11
0
        internal static void BuildContextBlocks(VFXContext context, VFXContextCompiledData contextData,
            out string blockFunctionContent,
            out string blockCallFunctionContent)
        {
            var linkedEventOut = context.allLinkedOutputSlot.Where(s => ((VFXModel)s.owner).GetFirstOfType<VFXContext>().CanBeCompiled()).ToList();

            //< Block processor
            var blockFunction = new VFXShaderWriter();
            var blockCallFunction = new VFXShaderWriter();
            var blockDeclared = new HashSet<string>();
            var expressionToName = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));
            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            int cpt = 0;
            foreach (var current in context.activeFlattenedChildrenWithImplicit)
            {
                BuildBlock(contextData, linkedEventOut, blockFunction, blockCallFunction, blockDeclared, expressionToName, current, ref cpt);
            }

            blockFunctionContent = blockFunction.builder.ToString();
            blockCallFunctionContent = blockCallFunction.builder.ToString();
        }
예제 #12
0
        static private VFXShaderWriter GenerateLoadAttribute(string matching, VFXContext context)
        {
            var r = new VFXShaderWriter();

            var regex = new Regex(matching);
            var attributesFromContext = context.GetData().GetAttributes().Where(o => regex.IsMatch(o.attrib.name)).ToArray();
            var attributesSource      = attributesFromContext.Where(a => context.GetData().IsSourceAttributeUsed(a.attrib, context)).ToArray();
            var attributesCurrent     = attributesFromContext.Where(a => context.GetData().IsCurrentAttributeUsed(a.attrib, context) || (context.contextType == VFXContextType.Init && context.GetData().IsAttributeStored(a.attrib))).ToArray();

            //< Current Attribute
            foreach (var attribute in attributesCurrent.Select(o => o.attrib))
            {
                var name = attribute.GetNameInCode(VFXAttributeLocation.Current);
                if (attribute.name != VFXAttribute.EventCount.name)
                {
                    if (context.contextType != VFXContextType.Init && context.GetData().IsAttributeStored(attribute))
                    {
                        r.WriteAssignement(attribute.type, name, context.GetData().GetLoadAttributeCode(attribute, VFXAttributeLocation.Current));
                    }
                    else
                    {
                        r.WriteAssignement(attribute.type, name, attribute.value.GetCodeString(null));
                    }
                }
                else
                {
                    var linkedOutCount = context.allLinkedOutputSlot.Count();
                    r.WriteAssignement(attribute.type, name, attribute.value.GetCodeString(null));
                    for (uint i = 0; i < linkedOutCount; ++i)
                    {
                        r.WriteLine();
                        r.WriteFormat("uint {0}_{1} = 0u;", VFXAttribute.EventCount.name, VFXCodeGeneratorHelper.GeneratePrefix(i));
                    }
                }
                r.WriteLine();
            }

            //< Source Attribute (default temporary behavior, source is always the initial current value except for init context)
            foreach (var attribute in attributesSource.Select(o => o.attrib))
            {
                var name = attribute.GetNameInCode(VFXAttributeLocation.Source);
                if (context.contextType == VFXContextType.Init)
                {
                    r.WriteAssignement(attribute.type, name, context.GetData().GetLoadAttributeCode(attribute, VFXAttributeLocation.Source));
                }
                else
                {
                    if (attributesCurrent.Any(o => o.attrib.name == attribute.name))
                    {
                        var reference = new VFXAttributeExpression(new VFXAttribute(attribute.name, attribute.value), VFXAttributeLocation.Current);
                        r.WriteAssignement(reference.valueType, name, reference.GetCodeString(null));
                    }
                    else
                    {
                        r.WriteAssignement(attribute.type, name, attribute.value.GetCodeString(null));
                    }
                }
                r.WriteLine();
            }
            return(r);
        }
예제 #13
0
        static private StringBuilder Build(VFXContext context, string templatePath, VFXCompilationMode compilationMode, VFXContextCompiledData contextData, HashSet <string> dependencies)
        {
            if (!context.SetupCompilation())
            {
                return(null);
            }
            var stringBuilder = GetFlattenedTemplateContent(templatePath, new List <string>(), context.additionalDefines, dependencies);

            var allCurrentAttributes = context.GetData().GetAttributes().Where(a =>
                                                                               (context.GetData().IsCurrentAttributeUsed(a.attrib, context)) ||
                                                                               (context.contextType == VFXContextType.Init && context.GetData().IsAttributeStored(a.attrib))); // In init, needs to declare all stored attributes for intialization

            var allSourceAttributes = context.GetData().GetAttributes().Where(a => (context.GetData().IsSourceAttributeUsed(a.attrib, context)));

            var globalDeclaration = new VFXShaderWriter();

            globalDeclaration.WriteCBuffer(contextData.uniformMapper, "parameters");
            globalDeclaration.WriteLine();
            globalDeclaration.WriteAttributeStruct(allCurrentAttributes.Select(a => a.attrib), "Attributes");
            globalDeclaration.WriteLine();
            globalDeclaration.WriteAttributeStruct(allSourceAttributes.Select(a => a.attrib), "SourceAttributes");
            globalDeclaration.WriteLine();
            globalDeclaration.WriteTexture(contextData.uniformMapper);

            var linkedEventOut = context.allLinkedOutputSlot.Where(s => ((VFXModel)s.owner).GetFirstOfType <VFXContext>().CanBeCompiled()).ToList();

            globalDeclaration.WriteEventBuffer(eventListOutName, linkedEventOut.Count);

            //< Block processor
            var blockFunction     = new VFXShaderWriter();
            var blockCallFunction = new VFXShaderWriter();
            var blockDeclared     = new HashSet <string>();
            var expressionToName  = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            int cpt = 0;

            foreach (var current in context.activeFlattenedChildrenWithImplicit)
            {
                BuildBlock(contextData, linkedEventOut, blockFunction, blockCallFunction, blockDeclared, expressionToName, current, ref cpt);
            }

            //< Final composition
            var    renderTemplatePipePath = VFXLibrary.currentSRPBinder.templatePath;
            var    renderRuntimePipePath  = VFXLibrary.currentSRPBinder.runtimePath;
            string renderPipeCommon       = context.doesIncludeCommonCompute ? "Packages/com.unity.visualeffectgraph/Shaders/Common/VFXCommonCompute.hlsl" : VFXLibrary.currentSRPBinder.runtimePath + "/VFXCommon.hlsl";
            string renderPipePasses       = null;

            if (!context.codeGeneratorCompute && !string.IsNullOrEmpty(renderTemplatePipePath))
            {
                renderPipePasses = renderTemplatePipePath + "/VFXPasses.template";
            }

            var globalIncludeContent = new VFXShaderWriter();

            globalIncludeContent.WriteLine("#define NB_THREADS_PER_GROUP 64");
            globalIncludeContent.WriteLine("#define HAS_ATTRIBUTES 1");
            globalIncludeContent.WriteLine("#define VFX_PASSDEPTH_ACTUAL (0)");
            globalIncludeContent.WriteLine("#define VFX_PASSDEPTH_MOTION_VECTOR (1)");
            globalIncludeContent.WriteLine("#define VFX_PASSDEPTH_SELECTION (2)");
            globalIncludeContent.WriteLine("#define VFX_PASSDEPTH_SHADOW (3)");

            foreach (var attribute in allCurrentAttributes)
            {
                globalIncludeContent.WriteLineFormat("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(CultureInfo.InvariantCulture), "CURRENT");
            }
            foreach (var attribute in allSourceAttributes)
            {
                globalIncludeContent.WriteLineFormat("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(CultureInfo.InvariantCulture), "SOURCE");
            }

            foreach (var additionnalHeader in context.additionalDataHeaders)
            {
                globalIncludeContent.WriteLine(additionnalHeader);
            }

            foreach (var additionnalDefine in context.additionalDefines)
            {
                globalIncludeContent.WriteLineFormat("#define {0} 1", additionnalDefine);
            }

            if (renderPipePasses != null)
            {
                globalIncludeContent.Write(GetFlattenedTemplateContent(renderPipePasses, new List <string>(), context.additionalDefines, dependencies));
            }

            if (context.GetData() is ISpaceable)
            {
                var spaceable = context.GetData() as ISpaceable;
                globalIncludeContent.WriteLineFormat("#define {0} 1", spaceable.space == VFXCoordinateSpace.World ? "VFX_WORLD_SPACE" : "VFX_LOCAL_SPACE");
            }
            globalIncludeContent.WriteLineFormat("#include \"{0}/VFXDefines.hlsl\"", renderRuntimePipePath);

            var perPassIncludeContent = new VFXShaderWriter();

            perPassIncludeContent.WriteLine("#include \"" + renderPipeCommon + "\"");
            perPassIncludeContent.WriteLine("#include \"Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.hlsl\"");

            // Per-block includes
            var includes = Enumerable.Empty <string>();

            foreach (var block in context.activeFlattenedChildrenWithImplicit)
            {
                includes = includes.Concat(block.includes);
            }
            var uniqueIncludes = new HashSet <string>(includes);

            foreach (var includePath in uniqueIncludes)
            {
                perPassIncludeContent.WriteLine(string.Format("#include \"{0}\"", includePath));
            }


            ReplaceMultiline(stringBuilder, "${VFXGlobalInclude}", globalIncludeContent.builder);
            ReplaceMultiline(stringBuilder, "${VFXGlobalDeclaration}", globalDeclaration.builder);
            ReplaceMultiline(stringBuilder, "${VFXPerPassInclude}", perPassIncludeContent.builder);
            ReplaceMultiline(stringBuilder, "${VFXGeneratedBlockFunction}", blockFunction.builder);
            ReplaceMultiline(stringBuilder, "${VFXProcessBlocks}", blockCallFunction.builder);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            foreach (var match in GetUniqueMatches("\\${VFXLoadParameter:{(.*?)}}", stringBuilder.ToString()))
            {
                var str            = match.Groups[0].Value;
                var pattern        = match.Groups[1].Value;
                var loadParameters = GenerateLoadParameter(pattern, mainParameters, expressionToName);
                ReplaceMultiline(stringBuilder, str, loadParameters.builder);
            }
            var additionalInterpolantsGeneration  = new VFXShaderWriter();
            var additionalInterpolantsDeclaration = new VFXShaderWriter();
            var additionalInterpolantsPreparation = new VFXShaderWriter();


            int normSemantic = 0;

            foreach (string fragmentParameter in context.fragmentParameters)
            {
                var filteredNamedExpression = mainParameters.FirstOrDefault(o => fragmentParameter == o.name &&
                                                                            !(expressionToName.ContainsKey(o.exp) && expressionToName[o.exp] == o.name)); // if parameter already in the global scope, there's nothing to do

                if (filteredNamedExpression.exp != null)
                {
                    additionalInterpolantsDeclaration.WriteDeclaration(filteredNamedExpression.exp.valueType, filteredNamedExpression.name, $"NORMAL{normSemantic++}");
                    additionalInterpolantsGeneration.WriteVariable(filteredNamedExpression.exp.valueType, filteredNamedExpression.name + "__", "0");
                    var expressionToNameLocal = new Dictionary <VFXExpression, string>(expressionToName);
                    additionalInterpolantsGeneration.EnterScope();
                    {
                        if (!expressionToNameLocal.ContainsKey(filteredNamedExpression.exp))
                        {
                            additionalInterpolantsGeneration.WriteVariable(filteredNamedExpression.exp, expressionToNameLocal);
                            additionalInterpolantsGeneration.WriteLine();
                        }
                        additionalInterpolantsGeneration.WriteAssignement(filteredNamedExpression.exp.valueType, filteredNamedExpression.name + "__", expressionToNameLocal[filteredNamedExpression.exp]);
                        additionalInterpolantsGeneration.WriteLine();
                    }
                    additionalInterpolantsGeneration.ExitScope();
                    additionalInterpolantsGeneration.WriteAssignement(filteredNamedExpression.exp.valueType, "o." + filteredNamedExpression.name, filteredNamedExpression.name + "__");
                    additionalInterpolantsPreparation.WriteVariable(filteredNamedExpression.exp.valueType, filteredNamedExpression.name, "i." + filteredNamedExpression.name);
                }
            }
            ReplaceMultiline(stringBuilder, "${VFXAdditionalInterpolantsGeneration}", additionalInterpolantsGeneration.builder);
            ReplaceMultiline(stringBuilder, "${VFXAdditionalInterpolantsDeclaration}", additionalInterpolantsDeclaration.builder);
            ReplaceMultiline(stringBuilder, "${VFXAdditionalInterpolantsPreparation}", additionalInterpolantsPreparation.builder);

            //< Compute sourceIndex
            if (stringBuilder.ToString().Contains("${VFXComputeSourceIndex}"))
            {
                var r = GenerateComputeSourceIndex(context);
                ReplaceMultiline(stringBuilder, "${VFXComputeSourceIndex}", r.builder);
            }

            //< Load Attribute
            if (stringBuilder.ToString().Contains("${VFXLoadAttributes}"))
            {
                var loadAttributes = GenerateLoadAttribute(".*", context);
                ReplaceMultiline(stringBuilder, "${VFXLoadAttributes}", loadAttributes.builder);
            }

            foreach (var match in GetUniqueMatches("\\${VFXLoadAttributes:{(.*?)}}", stringBuilder.ToString()))
            {
                var str            = match.Groups[0].Value;
                var pattern        = match.Groups[1].Value;
                var loadAttributes = GenerateLoadAttribute(pattern, context);
                ReplaceMultiline(stringBuilder, str, loadAttributes.builder);
            }

            //< Store Attribute
            if (stringBuilder.ToString().Contains("${VFXStoreAttributes}"))
            {
                var storeAttribute = GenerateStoreAttribute(".*", context, (uint)linkedEventOut.Count);
                ReplaceMultiline(stringBuilder, "${VFXStoreAttributes}", storeAttribute.builder);
            }

            foreach (var match in GetUniqueMatches("\\${VFXStoreAttributes:{(.*?)}}", stringBuilder.ToString()))
            {
                var str             = match.Groups[0].Value;
                var pattern         = match.Groups[1].Value;
                var storeAttributes = GenerateStoreAttribute(pattern, context, (uint)linkedEventOut.Count);
                ReplaceMultiline(stringBuilder, str, storeAttributes.builder);
            }

            foreach (var addionalReplacement in context.additionalReplacements)
            {
                ReplaceMultiline(stringBuilder, addionalReplacement.Key, addionalReplacement.Value.builder);
            }

            // Replace defines
            SubstituteMacros(stringBuilder);

            if (VFXViewPreference.advancedLogs)
            {
                Debug.LogFormat("GENERATED_OUTPUT_FILE_FOR : {0}\n{1}", context.ToString(), stringBuilder.ToString());
            }

            context.EndCompilation();
            return(stringBuilder);
        }
        static private StringBuilder Build(VFXContext context, string templatePath, VFXCompilationMode compilationMode, VFXContextCompiledData contextData)
        {
            var dependencies = new HashSet <ScriptableObject>();

            context.CollectDependencies(dependencies);

            var stringBuilder = GetFlattenedTemplateContent(templatePath, new List <string>(), context.additionalDefines);

            var globalDeclaration = new VFXShaderWriter();

            globalDeclaration.WriteCBuffer(contextData.uniformMapper, "parameters");
            globalDeclaration.WriteTexture(contextData.uniformMapper);

            var linkedEventOut = context.allLinkedOutputSlot.Where(s => ((VFXModel)s.owner).GetFirstOfType <VFXContext>().CanBeCompiled()).ToList();

            globalDeclaration.WriteEventBuffer(eventListOutName, linkedEventOut.Count);

            //< Block processor
            var blockFunction     = new VFXShaderWriter();
            var blockCallFunction = new VFXShaderWriter();
            var blockDeclared     = new HashSet <string>();
            var expressionToName  = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            foreach (var current in context.activeChildrenWithImplicit.Select((v, i) => new { block = v, blockIndex = i }))
            {
                var block      = current.block;
                var blockIndex = current.blockIndex;

                var parameters = block.mergedAttributes.Select(o =>
                {
                    return(new VFXShaderWriter.FunctionParameter
                    {
                        name = o.attrib.name,
                        expression = new VFXAttributeExpression(o.attrib) as VFXExpression,
                        mode = o.mode
                    });
                }).ToList();

                foreach (var parameter in block.parameters)
                {
                    var expReduced = contextData.gpuMapper.FromNameAndId(parameter.name, blockIndex);
                    if (VFXExpression.IsTypeValidOnGPU(expReduced.valueType))
                    {
                        parameters.Add(new VFXShaderWriter.FunctionParameter
                        {
                            name       = parameter.name,
                            expression = expReduced,
                            mode       = VFXAttributeMode.None
                        });
                    }
                }

                string methodName, commentMethod;
                GetFunctionName(block, out methodName, out commentMethod);
                if (!blockDeclared.Contains(methodName))
                {
                    blockDeclared.Add(methodName);
                    blockFunction.WriteBlockFunction(contextData.gpuMapper,
                                                     methodName,
                                                     block.source,
                                                     parameters,
                                                     commentMethod);
                }

                //< Parameters (computed and/or extracted from uniform)
                var  expressionToNameLocal = expressionToName;
                bool needScope             = parameters.Any(o => !expressionToNameLocal.ContainsKey(o.expression));
                if (needScope)
                {
                    expressionToNameLocal = new Dictionary <VFXExpression, string>(expressionToNameLocal);
                    blockCallFunction.EnterScope();
                    foreach (var exp in parameters.Select(o => o.expression))
                    {
                        if (expressionToNameLocal.ContainsKey(exp))
                        {
                            continue;
                        }
                        blockCallFunction.WriteVariable(exp, expressionToNameLocal);
                    }
                }

                var indexEventCount = parameters.FindIndex(o => o.name == VFXAttribute.EventCount.name);
                if (indexEventCount != -1)
                {
                    if ((parameters[indexEventCount].mode & VFXAttributeMode.Read) != 0)
                    {
                        throw new InvalidOperationException(string.Format("{0} isn't expected as read (special case)", VFXAttribute.EventCount.name));
                    }
                    blockCallFunction.WriteLine(string.Format("{0} = 0u;", VFXAttribute.EventCount.name));
                }

                blockCallFunction.WriteCallFunction(methodName,
                                                    parameters,
                                                    contextData.gpuMapper,
                                                    expressionToNameLocal);

                if (indexEventCount != -1)
                {
                    foreach (var outputSlot in block.outputSlots.SelectMany(o => o.LinkedSlots))
                    {
                        var eventIndex = linkedEventOut.IndexOf(outputSlot);
                        if (eventIndex != -1)
                        {
                            blockCallFunction.WriteLineFormat("{0}_{1} += {0};", VFXAttribute.EventCount.name, VFXCodeGeneratorHelper.GeneratePrefix((uint)eventIndex));
                        }
                    }
                }
                if (needScope)
                {
                    blockCallFunction.ExitScope();
                }
            }

            //< Final composition
            var    renderPipePath   = UnityEngine.Experimental.VFX.VFXManager.renderPipeSettingsPath;
            string renderPipeCommon = "Packages/com.unity.visualeffectgraph/Shaders/Common/VFXCommonCompute.cginc";
            string renderPipePasses = null;

            if (!context.codeGeneratorCompute && !string.IsNullOrEmpty(renderPipePath))
            {
                renderPipeCommon = renderPipePath + "/VFXCommon.cginc";
                renderPipePasses = renderPipePath + "/VFXPasses.template";
            }

            var globalIncludeContent = new VFXShaderWriter();

            globalIncludeContent.WriteLine("#define NB_THREADS_PER_GROUP 64");
            foreach (var attribute in context.GetData().GetAttributes().Where(a => (context.contextType == VFXContextType.kInit && context.GetData().IsAttributeStored(a.attrib)) || (context.GetData().IsAttributeUsed(a.attrib, context))))
            {
                globalIncludeContent.WriteLineFormat("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(), "CURRENT");
            }
            foreach (var attribute in context.GetData().GetAttributes().Where(a => context.GetData().IsSourceAttributeUsed(a.attrib, context)))
            {
                globalIncludeContent.WriteLineFormat("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(), "SOURCE");
            }

            foreach (var additionnalDefine in context.additionalDefines)
            {
                globalIncludeContent.WriteLineFormat("#define {0} 1", additionnalDefine);
            }

            if (renderPipePasses != null)
            {
                globalIncludeContent.Write(GetFlattenedTemplateContent(renderPipePasses, new List <string>(), context.additionalDefines));
            }

            if (context.GetData() is ISpaceable)
            {
                var spaceable = context.GetData() as ISpaceable;
                globalIncludeContent.WriteLineFormat("#define {0} 1", spaceable.space == VFXCoordinateSpace.World ? "VFX_WORLD_SPACE" : "VFX_LOCAL_SPACE");
            }
            globalIncludeContent.WriteLineFormat("#include \"{0}/VFXDefines.hlsl\"", renderPipePath);

            var perPassIncludeContent = new VFXShaderWriter();

            perPassIncludeContent.WriteLine("#include \"" + renderPipeCommon + "\"");
            perPassIncludeContent.WriteLine("#include \"Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.cginc\"");

            // Per-block includes
            var includes = Enumerable.Empty <string>();

            foreach (var block in context.activeChildrenWithImplicit)
            {
                includes = includes.Concat(block.includes);
            }
            var uniqueIncludes = new HashSet <string>(includes);

            foreach (var includePath in uniqueIncludes)
            {
                perPassIncludeContent.WriteLine(string.Format("#include \"{0}\"", includePath));
            }

            ReplaceMultiline(stringBuilder, "${VFXGlobalInclude}", globalIncludeContent.builder);
            ReplaceMultiline(stringBuilder, "${VFXGlobalDeclaration}", globalDeclaration.builder);
            ReplaceMultiline(stringBuilder, "${VFXPerPassInclude}", perPassIncludeContent.builder);
            ReplaceMultiline(stringBuilder, "${VFXGeneratedBlockFunction}", blockFunction.builder);
            ReplaceMultiline(stringBuilder, "${VFXProcessBlocks}", blockCallFunction.builder);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            foreach (var match in GetUniqueMatches("\\${VFXLoadParameter:{(.*?)}}", stringBuilder.ToString()))
            {
                var str            = match.Groups[0].Value;
                var pattern        = match.Groups[1].Value;
                var loadParameters = GenerateLoadParameter(pattern, mainParameters, expressionToName);
                ReplaceMultiline(stringBuilder, str, loadParameters.builder);
            }

            //< Compute sourceIndex
            if (stringBuilder.ToString().Contains("${VFXComputeSourceIndex}"))
            {
                var r = GenerateComputeSourceIndex(context);
                ReplaceMultiline(stringBuilder, "${VFXComputeSourceIndex}", r.builder);
            }

            //< Load Attribute
            if (stringBuilder.ToString().Contains("${VFXLoadAttributes}"))
            {
                var loadAttributes = GenerateLoadAttribute(".*", context);
                ReplaceMultiline(stringBuilder, "${VFXLoadAttributes}", loadAttributes.builder);
            }

            foreach (var match in GetUniqueMatches("\\${VFXLoadAttributes:{(.*?)}}", stringBuilder.ToString()))
            {
                var str            = match.Groups[0].Value;
                var pattern        = match.Groups[1].Value;
                var loadAttributes = GenerateLoadAttribute(pattern, context);
                ReplaceMultiline(stringBuilder, str, loadAttributes.builder);
            }

            //< Store Attribute
            if (stringBuilder.ToString().Contains("${VFXStoreAttributes}"))
            {
                var storeAttribute = GenerateStoreAttribute(".*", context, (uint)linkedEventOut.Count);
                ReplaceMultiline(stringBuilder, "${VFXStoreAttributes}", storeAttribute.builder);
            }

            foreach (var match in GetUniqueMatches("\\${VFXStoreAttributes:{(.*?)}}", stringBuilder.ToString()))
            {
                var str             = match.Groups[0].Value;
                var pattern         = match.Groups[1].Value;
                var storeAttributes = GenerateStoreAttribute(pattern, context, (uint)linkedEventOut.Count);
                ReplaceMultiline(stringBuilder, str, storeAttributes.builder);
            }

            foreach (var addionalReplacement in context.additionalReplacements)
            {
                ReplaceMultiline(stringBuilder, addionalReplacement.Key, addionalReplacement.Value.builder);
            }

            // Replace defines
            SubstituteMacros(stringBuilder);

            if (VFXViewPreference.advancedLogs)
            {
                Debug.LogFormat("GENERATED_OUTPUT_FILE_FOR : {0}\n{1}", context.ToString(), stringBuilder.ToString());
            }

            return(stringBuilder);
        }
예제 #15
0
        static void GenerateVFXAdditionalCommands(VFXContext context, VFXSRPBinder srp, VFXSRPBinder.ShaderGraphBinder shaderGraphBinder, VFXContextCompiledData contextData,
                                                  out AdditionalCommandDescriptor srpCommonInclude,
                                                  out AdditionalCommandDescriptor loadAttributeDescriptor,
                                                  out AdditionalCommandDescriptor blockFunctionDescriptor,
                                                  out AdditionalCommandDescriptor blockCallFunctionDescriptor,
                                                  out AdditionalCommandDescriptor interpolantsGenerationDescriptor,
                                                  out AdditionalCommandDescriptor buildVFXFragInputsDescriptor,
                                                  out AdditionalCommandDescriptor pixelPropertiesAssignDescriptor,
                                                  out AdditionalCommandDescriptor defineSpaceDescriptor,
                                                  out AdditionalCommandDescriptor parameterBufferDescriptor,
                                                  out AdditionalCommandDescriptor additionalDefinesDescriptor,
                                                  out AdditionalCommandDescriptor loadPositionAttributeDescriptor,
                                                  out AdditionalCommandDescriptor loadCropFactorAttributesDescriptor,
                                                  out AdditionalCommandDescriptor loadTexcoordAttributesDescriptor,
                                                  out AdditionalCommandDescriptor vertexPropertiesGenerationDescriptor,
                                                  out AdditionalCommandDescriptor vertexPropertiesAssignDescriptor)
        {
            // TODO: Clean all of this up. Currently just an adapter between VFX Code Gen + SG Code Gen and *everything* has been stuffed here.

            // SRP Common Include
            srpCommonInclude = new AdditionalCommandDescriptor("VFXSRPCommonInclude", string.Format("#include \"{0}\"", srp.runtimePath + "/VFXCommon.hlsl"));

            // Load Attributes
            loadAttributeDescriptor = new AdditionalCommandDescriptor("VFXLoadAttribute", VFXCodeGenerator.GenerateLoadAttribute(".", context).ToString());

            // Graph Blocks
            VFXCodeGenerator.BuildContextBlocks(context, contextData, out var blockFunction, out var blockCallFunction);

            blockFunctionDescriptor     = new AdditionalCommandDescriptor("VFXGeneratedBlockFunction", blockFunction);
            blockCallFunctionDescriptor = new AdditionalCommandDescriptor("VFXProcessBlocks", blockCallFunction);

            // Vertex Input
            VFXCodeGenerator.BuildVertexProperties(context, contextData, out var vertexPropertiesGeneration);
            vertexPropertiesGenerationDescriptor = new AdditionalCommandDescriptor("VFXVertexPropertiesGeneration", vertexPropertiesGeneration);

            VFXCodeGenerator.BuildVertexPropertiesAssign(context, contextData, out var vertexPropertiesAssign);
            vertexPropertiesAssignDescriptor = new AdditionalCommandDescriptor("VFXVertexPropertiesAssign", vertexPropertiesAssign);

            // Interpolator
            VFXCodeGenerator.BuildInterpolatorBlocks(context, contextData, out var interpolatorsGeneration);
            interpolantsGenerationDescriptor = new AdditionalCommandDescriptor("VFXInterpolantsGeneration", interpolatorsGeneration);

            // Frag Inputs - Only VFX will know if frag inputs come from interpolator or the CBuffer.
            VFXCodeGenerator.BuildFragInputsGeneration(context, contextData, shaderGraphBinder.useFragInputs, out var buildFragInputsGeneration);
            buildVFXFragInputsDescriptor = new AdditionalCommandDescriptor("VFXSetFragInputs", buildFragInputsGeneration);

            VFXCodeGenerator.BuildPixelPropertiesAssign(context, contextData, shaderGraphBinder.useFragInputs, out var pixelPropertiesAssign);
            pixelPropertiesAssignDescriptor = new AdditionalCommandDescriptor("VFXPixelPropertiesAssign", pixelPropertiesAssign);

            // Define coordinate space
            var defineSpaceDescriptorContent = string.Empty;

            if (context.GetData() is ISpaceable)
            {
                var spaceable = context.GetData() as ISpaceable;
                defineSpaceDescriptorContent =
                    $"#define {(spaceable.space == VFXCoordinateSpace.World ? "VFX_WORLD_SPACE" : "VFX_LOCAL_SPACE")} 1";
            }
            defineSpaceDescriptor = new AdditionalCommandDescriptor("VFXDefineSpace", defineSpaceDescriptorContent);

            //Texture used as input of the shaderGraph will be declared by the shaderGraph generation
            //However, if we are sampling a texture (or a mesh), we have to declare them before the VFX code generation.
            //Thus, remove texture used in SG from VFX declaration and let the remainder.
            var shaderGraphOutput = context as VFXShaderGraphParticleOutput;

            if (shaderGraphOutput == null)
            {
                throw new InvalidOperationException("Unexpected null VFXShaderGraphParticleOutput");
            }
            var shaderGraphObject = shaderGraphOutput.GetOrRefreshShaderGraphObject();

            if (shaderGraphObject == null)
            {
                throw new InvalidOperationException("Unexpected null GetOrRefreshShaderGraphObject");
            }
            var texureUsedInternallyInSG = shaderGraphObject.textureInfos.Select(o =>
            {
                return(o.name);
            });
            var textureExposedFromSG = context.inputSlots.Where(o =>
            {
                return(VFXExpression.IsTexture(o.property.type));
            }).Select(o => o.property.name);

            var filteredTextureInSG = texureUsedInternallyInSG.Concat(textureExposedFromSG).ToArray();

            // Parameter Cbuffer
            VFXCodeGenerator.BuildParameterBuffer(contextData, filteredTextureInSG, out var parameterBuffer);
            parameterBufferDescriptor = new AdditionalCommandDescriptor("VFXParameterBuffer", parameterBuffer);

            // Defines & Headers - Not all are necessary, however some important ones are mixed in like indirect draw, strips, flipbook, particle strip info...
            ShaderStringBuilder additionalDefines = new ShaderStringBuilder();
            // TODO: Need to add defines for current/source usage (i.e. scale).

            var allCurrentAttributes = context.GetData().GetAttributes().Where(a =>
                                                                               (context.GetData().IsCurrentAttributeUsed(a.attrib, context)) ||
                                                                               (context.contextType == VFXContextType.Init && context.GetData().IsAttributeStored(a.attrib))); // In init, needs to declare all stored attributes for intialization

            var allSourceAttributes = context.GetData().GetAttributes().Where(a => (context.GetData().IsSourceAttributeUsed(a.attrib, context)));

            foreach (var attribute in allCurrentAttributes)
            {
                additionalDefines.AppendLine("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(System.Globalization.CultureInfo.InvariantCulture), "CURRENT");
            }
            foreach (var attribute in allSourceAttributes)
            {
                additionalDefines.AppendLine("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(System.Globalization.CultureInfo.InvariantCulture), "SOURCE");
            }
            foreach (var header in context.additionalDataHeaders)
            {
                additionalDefines.AppendLine(header);
            }
            foreach (var define in context.additionalDefines)
            {
                additionalDefines.AppendLine($"#define {define} 1");
            }
            additionalDefinesDescriptor = new AdditionalCommandDescriptor("VFXDefines", additionalDefines.ToString());

            // Load Position Attribute
            loadPositionAttributeDescriptor = new AdditionalCommandDescriptor("VFXLoadPositionAttribute", VFXCodeGenerator.GenerateLoadAttribute("position", context).ToString().ToString());

            // Load Crop Factor Attribute
            var mainParameters   = contextData.gpuMapper.CollectExpression(-1).ToArray();
            var expressionToName = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);
            loadCropFactorAttributesDescriptor = new AdditionalCommandDescriptor("VFXLoadCropFactorParameter", VFXCodeGenerator.GenerateLoadParameter("cropFactor", mainParameters, expressionToName).ToString().ToString());
            loadTexcoordAttributesDescriptor   = new AdditionalCommandDescriptor("VFXLoadTexcoordParameter", VFXCodeGenerator.GenerateLoadParameter("texCoord", mainParameters, expressionToName).ToString().ToString());
        }
예제 #16
0
        static private StringBuilder Build(VFXContext context, string templatePath, VFXCompilationMode compilationMode, VFXContextCompiledData contextData)
        {
            var stringBuilder = GetFlattenedTemplateContent(templatePath, new List <string>(), context.additionalDefines);

            var globalDeclaration = new VFXShaderWriter();

            globalDeclaration.WriteCBuffer(contextData.uniformMapper, "parameters");
            globalDeclaration.WriteTexture(contextData.uniformMapper);

            var linkedEventOut = context.allLinkedOutputSlot.Where(s => ((VFXModel)s.owner).GetFirstOfType <VFXContext>().CanBeCompiled()).ToList();

            globalDeclaration.WriteEventBuffer(eventListOutName, linkedEventOut.Count);

            //< Block processor
            var blockFunction     = new VFXShaderWriter();
            var blockCallFunction = new VFXShaderWriter();
            var blockDeclared     = new HashSet <string>();
            var expressionToName  = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            int cpt = 0;

            foreach (var current in context.activeFlattenedChildrenWithImplicit)
            {
                BuildBlock(contextData, linkedEventOut, blockFunction, blockCallFunction, blockDeclared, expressionToName, current, ref cpt);
            }

            //< Final composition
            var    renderPipePath   = UnityEngine.Experimental.VFX.VFXManager.renderPipeSettingsPath;
            string renderPipeCommon = "Packages/com.unity.visualeffectgraph/Shaders/Common/VFXCommonCompute.cginc";
            string renderPipePasses = null;

            if (!context.codeGeneratorCompute && !string.IsNullOrEmpty(renderPipePath))
            {
                renderPipeCommon = renderPipePath + "/VFXCommon.cginc";
                renderPipePasses = renderPipePath + "/VFXPasses.template";
            }

            var globalIncludeContent = new VFXShaderWriter();

            globalIncludeContent.WriteLine("#define NB_THREADS_PER_GROUP 64");
            foreach (var attribute in context.GetData().GetAttributes().Where(a => (context.contextType == VFXContextType.Init && context.GetData().IsAttributeStored(a.attrib)) || (context.GetData().IsAttributeUsed(a.attrib, context))))
            {
                globalIncludeContent.WriteLineFormat("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(), "CURRENT");
            }
            foreach (var attribute in context.GetData().GetAttributes().Where(a => context.GetData().IsSourceAttributeUsed(a.attrib, context)))
            {
                globalIncludeContent.WriteLineFormat("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(), "SOURCE");
            }

            foreach (var additionnalDefine in context.additionalDefines)
            {
                globalIncludeContent.WriteLineFormat("#define {0} 1", additionnalDefine);
            }

            if (renderPipePasses != null)
            {
                globalIncludeContent.Write(GetFlattenedTemplateContent(renderPipePasses, new List <string>(), context.additionalDefines));
            }

            if (context.GetData() is ISpaceable)
            {
                var spaceable = context.GetData() as ISpaceable;
                globalIncludeContent.WriteLineFormat("#define {0} 1", spaceable.space == VFXCoordinateSpace.World ? "VFX_WORLD_SPACE" : "VFX_LOCAL_SPACE");
            }
            globalIncludeContent.WriteLineFormat("#include \"{0}/VFXDefines.hlsl\"", renderPipePath);

            var perPassIncludeContent = new VFXShaderWriter();

            perPassIncludeContent.WriteLine("#include \"" + renderPipeCommon + "\"");
            perPassIncludeContent.WriteLine("#include \"Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.cginc\"");

            // Per-block includes
            var includes = Enumerable.Empty <string>();

            foreach (var block in context.activeFlattenedChildrenWithImplicit)
            {
                includes = includes.Concat(block.includes);
            }
            var uniqueIncludes = new HashSet <string>(includes);

            foreach (var includePath in uniqueIncludes)
            {
                perPassIncludeContent.WriteLine(string.Format("#include \"{0}\"", includePath));
            }

            ReplaceMultiline(stringBuilder, "${VFXGlobalInclude}", globalIncludeContent.builder);
            ReplaceMultiline(stringBuilder, "${VFXGlobalDeclaration}", globalDeclaration.builder);
            ReplaceMultiline(stringBuilder, "${VFXPerPassInclude}", perPassIncludeContent.builder);
            ReplaceMultiline(stringBuilder, "${VFXGeneratedBlockFunction}", blockFunction.builder);
            ReplaceMultiline(stringBuilder, "${VFXProcessBlocks}", blockCallFunction.builder);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            foreach (var match in GetUniqueMatches("\\${VFXLoadParameter:{(.*?)}}", stringBuilder.ToString()))
            {
                var str            = match.Groups[0].Value;
                var pattern        = match.Groups[1].Value;
                var loadParameters = GenerateLoadParameter(pattern, mainParameters, expressionToName);
                ReplaceMultiline(stringBuilder, str, loadParameters.builder);
            }

            //< Compute sourceIndex
            if (stringBuilder.ToString().Contains("${VFXComputeSourceIndex}"))
            {
                var r = GenerateComputeSourceIndex(context);
                ReplaceMultiline(stringBuilder, "${VFXComputeSourceIndex}", r.builder);
            }

            //< Load Attribute
            if (stringBuilder.ToString().Contains("${VFXLoadAttributes}"))
            {
                var loadAttributes = GenerateLoadAttribute(".*", context);
                ReplaceMultiline(stringBuilder, "${VFXLoadAttributes}", loadAttributes.builder);
            }

            foreach (var match in GetUniqueMatches("\\${VFXLoadAttributes:{(.*?)}}", stringBuilder.ToString()))
            {
                var str            = match.Groups[0].Value;
                var pattern        = match.Groups[1].Value;
                var loadAttributes = GenerateLoadAttribute(pattern, context);
                ReplaceMultiline(stringBuilder, str, loadAttributes.builder);
            }

            //< Store Attribute
            if (stringBuilder.ToString().Contains("${VFXStoreAttributes}"))
            {
                var storeAttribute = GenerateStoreAttribute(".*", context, (uint)linkedEventOut.Count);
                ReplaceMultiline(stringBuilder, "${VFXStoreAttributes}", storeAttribute.builder);
            }

            foreach (var match in GetUniqueMatches("\\${VFXStoreAttributes:{(.*?)}}", stringBuilder.ToString()))
            {
                var str             = match.Groups[0].Value;
                var pattern         = match.Groups[1].Value;
                var storeAttributes = GenerateStoreAttribute(pattern, context, (uint)linkedEventOut.Count);
                ReplaceMultiline(stringBuilder, str, storeAttributes.builder);
            }

            foreach (var addionalReplacement in context.additionalReplacements)
            {
                ReplaceMultiline(stringBuilder, addionalReplacement.Key, addionalReplacement.Value.builder);
            }

            // Replace defines
            SubstituteMacros(stringBuilder);

            if (VFXViewPreference.advancedLogs)
            {
                Debug.LogFormat("GENERATED_OUTPUT_FILE_FOR : {0}\n{1}", context.ToString(), stringBuilder.ToString());
            }

            return(stringBuilder);
        }