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(); }
internal static VFXShaderWriter GenerateLoadParameter(string matching, VFXNamedExpression[] namedExpressions, Dictionary<VFXExpression, string> expressionToName) { var r = new VFXShaderWriter(); var regex = new Regex(matching); var filteredNamedExpressions = namedExpressions.Where(o => regex.IsMatch(o.name) && !(expressionToName.ContainsKey(o.exp) && expressionToName[o.exp] == o.name)); // if parameter already in the global scope, there's nothing to do bool needScope = false; foreach (var namedExpression in filteredNamedExpressions) { r.WriteVariable(namedExpression.exp.valueType, namedExpression.name, "0"); r.WriteLine(); needScope = true; } if (needScope) { var expressionToNameLocal = new Dictionary<VFXExpression, string>(expressionToName); r.EnterScope(); foreach (var namedExpression in filteredNamedExpressions) { if (!expressionToNameLocal.ContainsKey(namedExpression.exp)) { r.WriteVariable(namedExpression.exp, expressionToNameLocal); r.WriteLine(); } r.WriteAssignement(namedExpression.exp.valueType, namedExpression.name, expressionToNameLocal[namedExpression.exp]); r.WriteLine(); } r.ExitScope(); } return r; }
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); }
private static void BuildBlock(VFXContextCompiledData contextData, List <VFXSlot> linkedEventOut, VFXShaderWriter blockFunction, VFXShaderWriter blockCallFunction, HashSet <string> blockDeclared, Dictionary <VFXExpression, string> expressionToName, VFXBlock block, ref int 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.GetNameInCode(VFXAttributeLocation.Current))); } 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} += {2};", VFXAttribute.EventCount.name, VFXCodeGeneratorHelper.GeneratePrefix((uint)eventIndex), VFXAttribute.EventCount.GetNameInCode(VFXAttributeLocation.Current)); } } } if (needScope) { blockCallFunction.ExitScope(); } blockIndex++; }
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); }