@@ -87,7 +87,8 @@ public ActiveFields GatherActiveFieldsFromNode(AbstractMaterialNode outputNode,
8787 void BuildShader ( )
8888 {
8989 var activeNodeList = Graphing . ListPool < AbstractMaterialNode > . Get ( ) ;
90- if ( m_OutputNode == null )
90+ bool ignoreActiveState = ( m_Mode == GenerationMode . Preview ) ; // for previews, we ignore node active state
91+ if ( m_OutputNode == null )
9192 {
9293 foreach ( var block in m_Blocks )
9394 {
@@ -96,12 +97,12 @@ void BuildShader()
9697 if ( ! block . isActive )
9798 continue ;
9899
99- NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , block , NodeUtils . IncludeSelf . Include ) ;
100+ NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , block , NodeUtils . IncludeSelf . Include , ignoreActiveState : ignoreActiveState ) ;
100101 }
101102 }
102103 else
103104 {
104- NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , m_OutputNode ) ;
105+ NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , m_OutputNode , ignoreActiveState : ignoreActiveState ) ;
105106 }
106107
107108 var shaderProperties = new PropertyCollector ( ) ;
@@ -131,6 +132,10 @@ void BuildShader()
131132 target . CollectShaderProperties ( shaderProperties , m_Mode ) ;
132133 }
133134
135+ // set the property collector to read only
136+ // (to ensure no rogue target or pass starts adding more properties later..)
137+ shaderProperties . SetReadOnly ( ) ;
138+
134139 m_Builder . AppendLine ( @"Shader ""{0}""" , m_Name ) ;
135140 using ( m_Builder . BlockScope ( ) )
136141 {
@@ -143,9 +148,11 @@ void BuildShader()
143148 // Instead of setup target, we can also just do get context
144149 m_Targets [ i ] . Setup ( ref context ) ;
145150
146- foreach ( var subShader in context . subShaders )
151+ var subShaderProperties = GetSubShaderPropertiesForTarget ( m_Targets [ i ] , m_GraphData , m_Mode , m_OutputNode ) ;
152+
153+ foreach ( var subShader in context . subShaders )
147154 {
148- GenerateSubShader ( i , subShader ) ;
155+ GenerateSubShader ( i , subShader , subShaderProperties ) ;
149156 }
150157
151158 var customEditor = context . defaultShaderGUI ;
@@ -161,7 +168,7 @@ void BuildShader()
161168 m_ConfiguredTextures = shaderProperties . GetConfiguredTexutres ( ) ;
162169 }
163170
164- void GenerateSubShader ( int targetIndex , SubShaderDescriptor descriptor )
171+ void GenerateSubShader ( int targetIndex , SubShaderDescriptor descriptor , PropertyCollector subShaderProperties )
165172 {
166173 if ( descriptor . passes == null )
167174 return ;
@@ -189,12 +196,70 @@ void GenerateSubShader(int targetIndex, SubShaderDescriptor descriptor)
189196
190197 // Check masternode fields for valid passes
191198 if ( pass . TestActive ( activeFields ) )
192- GenerateShaderPass ( targetIndex , pass . descriptor , activeFields , currentBlockDescriptors . Select ( x => x . descriptor ) . ToList ( ) ) ;
199+ GenerateShaderPass ( targetIndex , pass . descriptor , activeFields , currentBlockDescriptors . Select ( x => x . descriptor ) . ToList ( ) , subShaderProperties ) ;
193200 }
194201 }
195202 }
196203
197- void GenerateShaderPass ( int targetIndex , PassDescriptor pass , ActiveFields activeFields , List < BlockFieldDescriptor > currentBlockDescriptors )
204+ // this builds the list of properties for a Target / Graph combination
205+ static PropertyCollector GetSubShaderPropertiesForTarget ( Target target , GraphData graph , GenerationMode generationMode , AbstractMaterialNode outputNode )
206+ {
207+ PropertyCollector subshaderProperties = new PropertyCollector ( ) ;
208+
209+ // Collect shader properties declared by active nodes
210+ using ( var activeNodes = PooledHashSet < AbstractMaterialNode > . Get ( ) )
211+ {
212+ if ( outputNode == null )
213+ {
214+ // shader graph builds active nodes starting from the set of active blocks
215+ var currentBlocks = graph . GetNodes < BlockNode > ( ) ;
216+ var activeBlockContext = new TargetActiveBlockContext ( currentBlocks . Select ( x => x . descriptor ) . ToList ( ) , null ) ;
217+ target . GetActiveBlocks ( ref activeBlockContext ) ;
218+
219+ foreach ( var blockFieldDesc in activeBlockContext . activeBlocks )
220+ {
221+ // attempt to get BlockNode(s) from the stack
222+ var vertBlockNode = graph . vertexContext . blocks . FirstOrDefault ( x => x . value . descriptor == blockFieldDesc ) . value ;
223+ if ( vertBlockNode != null )
224+ activeNodes . Add ( vertBlockNode ) ;
225+
226+ var fragBlockNode = graph . fragmentContext . blocks . FirstOrDefault ( x => x . value . descriptor == blockFieldDesc ) . value ;
227+ if ( fragBlockNode != null )
228+ activeNodes . Add ( fragBlockNode ) ;
229+ }
230+ }
231+ else
232+ {
233+ // preview and/or subgraphs build their active node set based on the single output node
234+ activeNodes . Add ( outputNode ) ;
235+ }
236+
237+ PreviewManager . PropagateNodes ( activeNodes , PreviewManager . PropagationDirection . Upstream , activeNodes ) ;
238+
239+ // NOTE: this is NOT a deterministic ordering
240+ foreach ( var node in activeNodes )
241+ node . CollectShaderProperties ( subshaderProperties , generationMode ) ;
242+
243+ // So we sort the properties after
244+ subshaderProperties . Sort ( ) ;
245+ }
246+
247+ // Collect graph properties
248+ {
249+ graph . CollectShaderProperties ( subshaderProperties , generationMode ) ;
250+ }
251+
252+ // Collect shader properties declared by the Target
253+ {
254+ target . CollectShaderProperties ( subshaderProperties , generationMode ) ;
255+ }
256+
257+ subshaderProperties . SetReadOnly ( ) ;
258+
259+ return subshaderProperties ;
260+ }
261+
262+ void GenerateShaderPass ( int targetIndex , PassDescriptor pass , ActiveFields activeFields , List < BlockFieldDescriptor > currentBlockDescriptors , PropertyCollector subShaderProperties )
198263 {
199264 // Early exit if pass is not used in preview
200265 if ( m_Mode == GenerationMode . Preview && ! pass . useInPreview )
@@ -647,7 +712,7 @@ void ProcessStackForPass(ContextData contextData, BlockFieldDescriptor[] passBlo
647712
648713 using ( var propertyBuilder = new ShaderStringBuilder ( ) )
649714 {
650- propertyCollector . GetPropertiesDeclaration ( propertyBuilder , m_Mode , m_GraphData . concretePrecision ) ;
715+ subShaderProperties . GetPropertiesDeclaration ( propertyBuilder , m_Mode , m_GraphData . concretePrecision ) ;
651716 if ( propertyBuilder . length == 0 )
652717 propertyBuilder . AppendLine ( "// GraphProperties: <None>" ) ;
653718 spliceCommands . Add ( "GraphProperties" , propertyBuilder . ToCodeBlock ( ) ) ;
@@ -656,17 +721,12 @@ void ProcessStackForPass(ContextData contextData, BlockFieldDescriptor[] passBlo
656721 // --------------------------------------------------
657722 // Dots Instanced Graph Properties
658723
659- bool hasDotsProperties = false ;
660- m_GraphData . ForeachHLSLProperty ( h =>
661- {
662- if ( h . declaration == HLSLDeclaration . HybridPerInstance )
663- hasDotsProperties = true ;
664- } ) ;
724+ bool hasDotsProperties = subShaderProperties . HasDotsProperties ( ) ;
665725
666726 using ( var dotsInstancedPropertyBuilder = new ShaderStringBuilder ( ) )
667727 {
668728 if ( hasDotsProperties )
669- dotsInstancedPropertyBuilder . AppendLines ( propertyCollector . GetDotsInstancingPropertiesDeclaration ( m_Mode ) ) ;
729+ dotsInstancedPropertyBuilder . AppendLines ( subShaderProperties . GetDotsInstancingPropertiesDeclaration ( m_Mode ) ) ;
670730 else
671731 dotsInstancedPropertyBuilder . AppendLine ( "// HybridV1InjectedBuiltinProperties: <None>" ) ;
672732 spliceCommands . Add ( "HybridV1InjectedBuiltinProperties" , dotsInstancedPropertyBuilder . ToCodeBlock ( ) ) ;
0 commit comments