Esempio n. 1
0
 public StructCollection Add(StructDescriptor descriptor)
 {
     m_Items.Add(new StructCollection.Item(descriptor, null));
     return(this);
 }
Esempio n. 2
0
 public StructCollection Add(StructDescriptor descriptor, FieldCondition[] fieldConditions)
 {
     m_Items.Add(new StructCollection.Item(descriptor, fieldConditions));
     return(this);
 }
Esempio n. 3
0
 public Item(StructDescriptor descriptor, FieldCondition[] fieldConditions)
 {
     this.descriptor      = descriptor;
     this.fieldConditions = fieldConditions;
 }
Esempio n. 4
0
        void GenerateShaderPass(int targetIndex, PassDescriptor pass, ActiveFields activeFields)
        {
            // Early exit if pass is not used in preview
            if (m_Mode == GenerationMode.Preview && !pass.useInPreview)
            {
                return;
            }

            // --------------------------------------------------
            // Debug

            // Get scripting symbols
            BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
            string           defines          = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);

            bool isDebug = defines.Contains(kDebugSymbol);

            // --------------------------------------------------
            // Setup

            // Initiailize Collectors
            var propertyCollector = new PropertyCollector();
            var keywordCollector  = new KeywordCollector();

            m_OutputNode.owner.CollectShaderKeywords(keywordCollector, m_Mode);

            // Get upstream nodes from ShaderPass port mask
            List <AbstractMaterialNode> vertexNodes;
            List <AbstractMaterialNode> pixelNodes;

            GenerationUtils.GetUpstreamNodesForShaderPass(m_OutputNode, pass, out vertexNodes, out pixelNodes);

            // Track permutation indices for all nodes
            List <int>[] vertexNodePermutations = new List <int> [vertexNodes.Count];
            List <int>[] pixelNodePermutations  = new List <int> [pixelNodes.Count];

            // Get active fields from upstream Node requirements
            ShaderGraphRequirementsPerKeyword graphRequirements;

            GenerationUtils.GetActiveFieldsAndPermutationsForNodes(m_OutputNode, pass, keywordCollector, vertexNodes, pixelNodes,
                                                                   vertexNodePermutations, pixelNodePermutations, activeFields, out graphRequirements);

            // GET CUSTOM ACTIVE FIELDS HERE!

            // Get active fields from ShaderPass
            GenerationUtils.AddRequiredFields(pass.requiredFields, activeFields.baseInstance);

            // Get Port references from ShaderPass
            List <MaterialSlot> pixelSlots;
            List <MaterialSlot> vertexSlots;

            if (m_OutputNode is IMasterNode)
            {
                pixelSlots  = GenerationUtils.FindMaterialSlotsOnNode(pass.pixelPorts, m_OutputNode);
                vertexSlots = GenerationUtils.FindMaterialSlotsOnNode(pass.vertexPorts, m_OutputNode);
            }
            else if (m_OutputNode is SubGraphOutputNode)
            {
                pixelSlots = new List <MaterialSlot>()
                {
                    m_OutputNode.GetInputSlots <MaterialSlot>().FirstOrDefault(),
                };
                vertexSlots = new List <MaterialSlot>();
            }
            else
            {
                pixelSlots = new List <MaterialSlot>()
                {
                    new Vector4MaterialSlot(0, "Out", "Out", SlotType.Output, Vector4.zero)
                    {
                        owner = m_OutputNode
                    },
                };
                vertexSlots = new List <MaterialSlot>();
            }

            // Function Registry
            var functionBuilder  = new ShaderStringBuilder();
            var functionRegistry = new FunctionRegistry(functionBuilder);

            // Hash table of named $splice(name) commands
            // Key: splice token
            // Value: string to splice
            Dictionary <string, string> spliceCommands = new Dictionary <string, string>();

            // --------------------------------------------------
            // Dependencies

            // Propagate active field requirements using dependencies
            // Must be executed before types are built
            foreach (var instance in activeFields.all.instances)
            {
                GenerationUtils.ApplyFieldDependencies(instance, pass.fieldDependencies);
            }

            // --------------------------------------------------
            // Pass Setup

            // Name
            if (!string.IsNullOrEmpty(pass.displayName))
            {
                spliceCommands.Add("PassName", $"Name \"{pass.displayName}\"");
            }
            else
            {
                spliceCommands.Add("PassName", "// Name: <None>");
            }

            // Tags
            if (!string.IsNullOrEmpty(pass.lightMode))
            {
                spliceCommands.Add("LightMode", $"\"LightMode\" = \"{pass.lightMode}\"");
            }
            else
            {
                spliceCommands.Add("LightMode", "// LightMode: <None>");
            }

            // --------------------------------------------------
            // Pass Code

            // Render State
            using (var renderStateBuilder = new ShaderStringBuilder())
            {
                // Render states need to be separated by RenderState.Type
                // The first passing ConditionalRenderState of each type is inserted
                foreach (RenderStateType type in Enum.GetValues(typeof(RenderStateType)))
                {
                    var renderStates = pass.renderStates?.Where(x => x.descriptor.type == type);
                    if (renderStates != null)
                    {
                        foreach (RenderStateCollection.Item renderState in renderStates)
                        {
                            if (renderState.TestActive(activeFields))
                            {
                                renderStateBuilder.AppendLine(renderState.value);
                                break;
                            }
                        }
                    }
                }

                string command = GenerationUtils.GetSpliceCommand(renderStateBuilder.ToCodeBlock(), "RenderState");
                spliceCommands.Add("RenderState", command);
            }

            // Pragmas
            using (var passPragmaBuilder = new ShaderStringBuilder())
            {
                if (pass.pragmas != null)
                {
                    foreach (PragmaCollection.Item pragma in pass.pragmas)
                    {
                        if (pragma.TestActive(activeFields))
                        {
                            passPragmaBuilder.AppendLine(pragma.value);
                        }
                    }
                }

                string command = GenerationUtils.GetSpliceCommand(passPragmaBuilder.ToCodeBlock(), "PassPragmas");
                spliceCommands.Add("PassPragmas", command);
            }

            // Includes
            using (var preGraphIncludeBuilder = new ShaderStringBuilder())
            {
                if (pass.includes != null)
                {
                    foreach (IncludeCollection.Item include in pass.includes.Where(x => x.descriptor.location == IncludeLocation.Pregraph))
                    {
                        if (include.TestActive(activeFields))
                        {
                            preGraphIncludeBuilder.AppendLine(include.value);
                        }
                    }
                }

                string command = GenerationUtils.GetSpliceCommand(preGraphIncludeBuilder.ToCodeBlock(), "PreGraphIncludes");
                spliceCommands.Add("PreGraphIncludes", command);
            }
            using (var postGraphIncludeBuilder = new ShaderStringBuilder())
            {
                if (pass.includes != null)
                {
                    foreach (IncludeCollection.Item include in pass.includes.Where(x => x.descriptor.location == IncludeLocation.Postgraph))
                    {
                        if (include.TestActive(activeFields))
                        {
                            postGraphIncludeBuilder.AppendLine(include.value);
                        }
                    }
                }

                string command = GenerationUtils.GetSpliceCommand(postGraphIncludeBuilder.ToCodeBlock(), "PostGraphIncludes");
                spliceCommands.Add("PostGraphIncludes", command);
            }

            // Keywords
            using (var passKeywordBuilder = new ShaderStringBuilder())
            {
                if (pass.keywords != null)
                {
                    foreach (KeywordCollection.Item keyword in pass.keywords)
                    {
                        if (keyword.TestActive(activeFields))
                        {
                            passKeywordBuilder.AppendLine(keyword.value);
                        }
                    }
                }

                string command = GenerationUtils.GetSpliceCommand(passKeywordBuilder.ToCodeBlock(), "PassKeywords");
                spliceCommands.Add("PassKeywords", command);
            }

            // -----------------------------
            // Generated structs and Packing code
            var interpolatorBuilder = new ShaderStringBuilder();
            var passStructs         = new List <StructDescriptor>();

            if (pass.structs != null)
            {
                passStructs.AddRange(pass.structs.Select(x => x.descriptor));

                foreach (StructCollection.Item shaderStruct in pass.structs)
                {
                    if (shaderStruct.descriptor.packFields == false)
                    {
                        continue; //skip structs that do not need interpolator packs
                    }
                    List <int> packedCounts = new List <int>();
                    var        packStruct   = new StructDescriptor();

                    //generate packed functions
                    if (activeFields.permutationCount > 0)
                    {
                        var generatedPackedTypes = new Dictionary <string, (ShaderStringBuilder, List <int>)>();
                        foreach (var instance in activeFields.allPermutations.instances)
                        {
                            var instanceGenerator = new ShaderStringBuilder();
                            GenerationUtils.GenerateInterpolatorFunctions(shaderStruct.descriptor, instance, out instanceGenerator);
                            var key = instanceGenerator.ToCodeBlock();
                            if (generatedPackedTypes.TryGetValue(key, out var value))
                            {
                                value.Item2.Add(instance.permutationIndex);
                            }
                            else
                            {
                                generatedPackedTypes.Add(key, (instanceGenerator, new List <int> {
                                    instance.permutationIndex
                                }));
Esempio n. 5
0
 public void Add(StructDescriptor descriptor, FieldCondition[] fieldConditions)
 {
     m_Items.Add(new StructCollection.Item(descriptor, fieldConditions));
 }
Esempio n. 6
0
 public void Add(StructDescriptor descriptor, FieldCondition fieldCondition)
 {
     m_Items.Add(new StructCollection.Item(descriptor, new FieldCondition[] { fieldCondition }));
 }
Esempio n. 7
0
 public void Add(StructDescriptor descriptor)
 {
     m_Items.Add(new StructCollection.Item(descriptor, null));
 }