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.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(); } blockIndex++; }
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 = VFXLibrary.currentSRPBinder.templatePath; 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); }
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)"); foreach (var attribute in allCurrentAttributes) { globalIncludeContent.WriteLineFormat("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(), "CURRENT"); } foreach (var attribute in allSourceAttributes) { globalIncludeContent.WriteLineFormat("#define VFX_USE_{0}_{1} 1", attribute.attrib.name.ToUpper(), "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 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); }
protected override void WriteBlendMode(VFXShaderWriter writer) { writer.WriteLine("Blend One One"); }