private static void InnerUnlink(VFXContext from, VFXContext to, int fromIndex = 0, int toIndex = 0, bool notify = true) { if (from.ownedType == to.ownedType) { 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); } }
public VFXAttributeMode GetAttributeMode(VFXAttribute attrib, VFXContext context) { Dictionary <VFXContext, VFXAttributeMode> contexts; if (m_AttributesToContexts.TryGetValue(attrib, out contexts)) { foreach (var c in contexts) { if (c.Key == context) { return(c.Value); } } } return(VFXAttributeMode.None); }
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); } }
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)) { 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.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); } }
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(); }
internal static void GetFields(ref TargetFieldContext fieldsContext, VFXContext context) { fieldsContext.AddField(Fields.GraphVFX); // Select the primitive implementation. switch (context.taskType) { case VFXTaskType.ParticleMeshOutput: fieldsContext.AddField(VFXFields.ParticleMesh); break; case VFXTaskType.ParticleTriangleOutput: case VFXTaskType.ParticleOctagonOutput: case VFXTaskType.ParticleQuadOutput: fieldsContext.AddField(VFXFields.ParticlePlanarPrimitive); break; } }
public IEnumerable <VFXAttributeInfo> GetAttributesForContext(VFXContext context) { Dictionary <VFXAttribute, VFXAttributeMode> attribs; if (m_ContextsToAttributes.TryGetValue(context, out attribs)) { foreach (var attrib in attribs) { VFXAttributeInfo info; info.attrib = attrib.Key; info.mode = attrib.Value; yield return(info); } } else { throw new ArgumentException("Context does not exist"); } }
internal static void BuildInterpolatorBlocks(VFXContext context, VFXContextCompiledData contextData, out string interpolatorsGeneration) { 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 additionalInterpolantsGeneration = new VFXShaderWriter(); var additionalInterpolantsPreparation = new VFXShaderWriter(); 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) { 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, "output." + filteredNamedExpression.name, filteredNamedExpression.name + "__"); additionalInterpolantsPreparation.WriteVariable(filteredNamedExpression.exp.valueType, filteredNamedExpression.name, "i." + filteredNamedExpression.name); } } interpolatorsGeneration = additionalInterpolantsGeneration.ToString(); }
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(); }
public static void SanitizeOrient(VFXContext model, int version, bool useCustomZAxis) { if (version < 6) { Block.Orient orientBlock = model.children.OfType <Block.Orient>().FirstOrDefault(); if (orientBlock == null) // If no orient block, add one { Debug.Log("Sanitize Graph: Add Orient block to quad strip output"); orientBlock = CreateInstance <Block.Orient>(); if (useCustomZAxis) { orientBlock.SetSettingValue("mode", Block.Orient.Mode.CustomZ); var axisZNode = CreateInstance <VFXAttributeParameter>(); axisZNode.SetSettingValue("attribute", "axisZ"); axisZNode.position = model.position + new Vector2(-225, 150); model.GetGraph().AddChild(axisZNode); axisZNode.GetOutputSlot(0).Link(orientBlock.GetInputSlot(0)); } else { orientBlock.SetSettingValue("mode", Block.Orient.Mode.FaceCameraPosition); } model.AddChild(orientBlock, 0); } else { if ((Block.Orient.Mode)orientBlock.GetSettingValue("mode") == Block.Orient.Mode.FaceCameraPlane) { Debug.Log("Sanitize Graph: Change Orient block mode in quad strip output from \"Face Camera Plane\" to \"Face Camera Position\""); orientBlock.SetSettingValue("mode", Block.Orient.Mode.FaceCameraPosition); } // Other invalid modes (Along Velocity and FixedAxis) will fail and require manual fixing } } }
public static bool CanLink(VFXContext from, VFXContext to, int fromIndex = 0, int toIndex = 0) { if (from == to || from == null || to == null) { return(false); } if (from.outputType == VFXDataType.None || to.inputType == VFXDataType.None || (from.outputType & to.inputType) != to.inputType) { return(false); } if (fromIndex >= from.outputFlowSlot.Length || toIndex >= to.inputFlowSlot.Length) { return(false); } //If link already present, returns false if (from.m_OutputFlowSlot[fromIndex].link.Any(o => o.context == to && o.slotIndex == toIndex) || to.m_InputFlowSlot[toIndex].link.Any(o => o.context == from && o.slotIndex == fromIndex)) { return(false); } //Special incorrect case, GPUEvent use the same type than Spawner which leads to an unexpected allowed link. if (from.m_ContextType == VFXContextType.SpawnerGPU && to.m_ContextType == VFXContextType.OutputEvent) { return(false); } //Can't connect directly event to context (OutputEvent or Initialize) for now if (from.m_ContextType == VFXContextType.Event && to.contextType != VFXContextType.Spawner && to.contextType != VFXContextType.Subgraph) { return(false); } return(true); }
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); }
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)); } } }
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 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(); }
public static bool CanLink(VFXContext from, VFXContext to, int fromIndex = 0, int toIndex = 0) { if (from == to || from == null || to == null) { return(false); } if (from.outputType == VFXDataType.kNone || to.inputType == VFXDataType.kNone || from.outputType != to.inputType) { return(false); } if (fromIndex >= from.outputFlowSlot.Length || toIndex >= to.inputFlowSlot.Length) { return(false); } if (from.m_OutputFlowSlot[fromIndex].link.Any(o => o.context == to) || to.m_InputFlowSlot[toIndex].link.Any(o => o.context == from)) { return(false); } return(true); }
public bool IsCurrentAttributeUsed(VFXAttribute attrib, VFXContext context) { return((GetAttributeMode(attrib, context) & VFXAttributeMode.ReadWrite) != 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); }
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); }
public override IEnumerable <VFXContext> InitImplicitContexts() { var contexts = compilableOwners.ToList(); if (!NeedsGlobalSort() && !contexts.OfType <VFXAbstractParticleOutput>().Any(o => o.NeedsOutputUpdate())) { //Early out with the most common case m_Contexts = contexts; return(Enumerable.Empty <VFXContext>()); } m_Contexts = new List <VFXContext>(contexts.Count + 2); // Allocate max number int index = 0; // First add init and updates for (index = 0; index < contexts.Count; ++index) { if ((contexts[index].contextType == VFXContextType.Output)) { break; } m_Contexts.Add(contexts[index]); } var implicitContext = new List <VFXContext>(); if (NeedsGlobalSort()) { // Then the camera sort var cameraSort = VFXContext.CreateImplicitContext <VFXCameraSort>(this); implicitContext.Add(cameraSort); m_Contexts.Add(cameraSort); } //additional update for (int outputIndex = index; outputIndex < contexts.Count; ++outputIndex) { var currentOutputContext = contexts[outputIndex]; var abstractParticleOutput = currentOutputContext as VFXAbstractParticleOutput; if (abstractParticleOutput == null) { continue; } if (abstractParticleOutput.NeedsOutputUpdate()) { var update = VFXContext.CreateImplicitContext <VFXOutputUpdate>(this); update.SetOutput(abstractParticleOutput); implicitContext.Add(update); m_Contexts.Add(update); } } // And finally output for (; index < contexts.Count; ++index) { m_Contexts.Add(contexts[index]); } return(implicitContext); }
public override VFXDeviceTarget GetCompilationTarget(VFXContext context) { return(VFXDeviceTarget.GPU); }
public bool IsCurrentAttributeWritten(VFXAttribute attrib, VFXContext context) { return((GetAttributeMode(attrib, context) & VFXAttributeMode.Write) != 0); }
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); }
public VFXExpressionMapper BuildGPUMapper(VFXContext context) { return(BuildMapper(context, m_ContextsToGPUExpressions, VFXDeviceTarget.GPU)); }
internal static SubShaderDescriptor PostProcessSubShader(SubShaderDescriptor subShaderDescriptor, VFXContext context, VFXContextCompiledData data) { var srp = VFXLibrary.currentSRPBinder; if (srp == null) { return(subShaderDescriptor); } var shaderGraphSRPInfo = srp.GetShaderGraphDescriptor(context, data); var attributesStruct = GenerateVFXAttributesStruct(context, VFXAttributeType.Current); var sourceAttributesStruct = GenerateVFXAttributesStruct(context, VFXAttributeType.Source); // Defer to VFX to generate various misc. code-gen that ShaderGraph currently can't handle. // We use the AdditionalCommand descriptors for ShaderGraph generation to splice these in. // ( i.e. VFX Graph Block Function declaration + calling, Property Mapping, etc. ) GenerateVFXAdditionalCommands( context, srp, shaderGraphSRPInfo, data, out var srpCommonInclude, out var loadAttributeDescriptor, out var blockFunctionDescriptor, out var blockCallFunctionDescriptor, out var interpolantsGenerationDescriptor, out var buildVFXFragInputs, out var pixelPropertiesAssignDescriptor, out var defineSpaceDescriptor, out var parameterBufferDescriptor, out var additionalDefinesDescriptor, out var loadPositionAttributeDescriptor, out var loadCropFactorAttributesDescriptor, out var loadTexcoordAttributesDescriptor, out var vertexPropertiesGenerationDescriptor, out var vertexPropertiesAssignDescriptor ); // Omit MV or Shadow Pass if disabled on the context. var filteredPasses = subShaderDescriptor.passes.AsEnumerable(); var outputContext = (VFXAbstractParticleOutput)context; if (!outputContext.hasMotionVector) { filteredPasses = filteredPasses.Where(o => o.descriptor.lightMode != "MotionVectors"); } if (!outputContext.hasShadowCasting) { filteredPasses = filteredPasses.Where(o => o.descriptor.lightMode != "ShadowCaster"); } var passes = filteredPasses.ToArray(); PassCollection vfxPasses = new PassCollection(); for (int i = 0; i < passes.Length; i++) { var passDescriptor = passes[i].descriptor; passDescriptor.pragmas = ApplyPragmaReplacement(passDescriptor.pragmas, shaderGraphSRPInfo); // Warning: We are replacing the struct provided in the regular pass. It is ok as for now the VFX editor don't support // tessellation or raytracing passDescriptor.structs = new StructCollection(); passDescriptor.structs.Add(shaderGraphSRPInfo.structs); passDescriptor.structs.Add(attributesStruct); passDescriptor.structs.Add(sourceAttributesStruct); // Add additional VFX dependencies passDescriptor.fieldDependencies = passDescriptor.fieldDependencies == null ? new DependencyCollection() : new DependencyCollection { passDescriptor.fieldDependencies }; // Duplicate fieldDependencies to avoid side effects (static list modification) passDescriptor.fieldDependencies.Add(shaderGraphSRPInfo.fieldDependencies); passDescriptor.additionalCommands = new AdditionalCommandCollection { srpCommonInclude, loadAttributeDescriptor, blockFunctionDescriptor, blockCallFunctionDescriptor, interpolantsGenerationDescriptor, buildVFXFragInputs, pixelPropertiesAssignDescriptor, defineSpaceDescriptor, parameterBufferDescriptor, additionalDefinesDescriptor, loadPositionAttributeDescriptor, loadCropFactorAttributesDescriptor, loadTexcoordAttributesDescriptor, vertexPropertiesGenerationDescriptor, vertexPropertiesAssignDescriptor, GenerateFragInputs(context, data) }; vfxPasses.Add(passDescriptor, passes[i].fieldConditions); } subShaderDescriptor.passes = vfxPasses; return(subShaderDescriptor); }
public bool IsAttributeUsed(VFXAttribute attrib, VFXContext context) { return(GetAttributeMode(attrib, context) != VFXAttributeMode.None); }
static public StringBuilder Build(VFXContext context, VFXCompilationMode compilationMode, VFXContextCompiledData contextData) { var templatePath = string.Format("{0}.template", context.codeGeneratorTemplate); return(Build(context, templatePath, compilationMode, contextData)); }
public bool IsSourceAttributeUsed(VFXAttribute attrib, VFXContext context) { return((GetAttributeMode(attrib, context) & VFXAttributeMode.ReadSource) != 0); }
public void UnlinkTo(VFXContext context, int fromIndex = 0, int toIndex = 0) { InnerUnlink(this, context, fromIndex, toIndex); }
public abstract VFXDeviceTarget GetCompilationTarget(VFXContext context);
public void UnlinkFrom(VFXContext context, int fromIndex = 0, int toIndex = 0) { InnerUnlink(context, this, fromIndex, toIndex); }