@@ -88,6 +88,7 @@ public ActiveFields GatherActiveFieldsFromNode(AbstractMaterialNode outputNode,
8888 void BuildShader ( )
8989 {
9090 var activeNodeList = Pool . ListPool < AbstractMaterialNode > . Get ( ) ;
91+ bool ignoreActiveState = ( m_Mode == GenerationMode . Preview ) ; // for previews, we ignore node active state
9192 if ( m_OutputNode == null )
9293 {
9394 foreach ( var block in m_Blocks )
@@ -97,12 +98,12 @@ void BuildShader()
9798 if ( ! block . isActive )
9899 continue ;
99100
100- NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , block , NodeUtils . IncludeSelf . Include ) ;
101+ NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , block , NodeUtils . IncludeSelf . Include , ignoreActiveState : ignoreActiveState ) ;
101102 }
102103 }
103104 else
104105 {
105- NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , m_OutputNode ) ;
106+ NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , m_OutputNode , ignoreActiveState : ignoreActiveState ) ;
106107 }
107108
108109 var shaderProperties = new PropertyCollector ( ) ;
@@ -132,6 +133,10 @@ void BuildShader()
132133 target . CollectShaderProperties ( shaderProperties , m_Mode ) ;
133134 }
134135
136+ // set the property collector to read only
137+ // (to ensure no rogue target or pass starts adding more properties later..)
138+ shaderProperties . SetReadOnly ( ) ;
139+
135140 m_Builder . AppendLine ( @"Shader ""{0}""" , m_Name ) ;
136141 using ( m_Builder . BlockScope ( ) )
137142 {
@@ -144,9 +149,11 @@ void BuildShader()
144149 // Instead of setup target, we can also just do get context
145150 m_Targets [ i ] . Setup ( ref context ) ;
146151
152+ var subShaderProperties = GetSubShaderPropertiesForTarget ( m_Targets [ i ] , m_GraphData , m_Mode , m_OutputNode ) ;
153+
147154 foreach ( var subShader in context . subShaders )
148155 {
149- GenerateSubShader ( i , subShader ) ;
156+ GenerateSubShader ( i , subShader , subShaderProperties ) ;
150157 }
151158
152159 var customEditor = context . defaultShaderGUI ;
@@ -167,7 +174,7 @@ void BuildShader()
167174 m_ConfiguredTextures = shaderProperties . GetConfiguredTexutres ( ) ;
168175 }
169176
170- void GenerateSubShader ( int targetIndex , SubShaderDescriptor descriptor )
177+ void GenerateSubShader ( int targetIndex , SubShaderDescriptor descriptor , PropertyCollector subShaderProperties )
171178 {
172179 if ( descriptor . passes == null )
173180 return ;
@@ -195,12 +202,70 @@ void GenerateSubShader(int targetIndex, SubShaderDescriptor descriptor)
195202
196203 // Check masternode fields for valid passes
197204 if ( pass . TestActive ( activeFields ) )
198- GenerateShaderPass ( targetIndex , pass . descriptor , activeFields , currentBlockDescriptors . Select ( x => x . descriptor ) . ToList ( ) ) ;
205+ GenerateShaderPass ( targetIndex , pass . descriptor , activeFields , currentBlockDescriptors . Select ( x => x . descriptor ) . ToList ( ) , subShaderProperties ) ;
206+ }
207+ }
208+ }
209+
210+ // this builds the list of properties for a Target / Graph combination
211+ static PropertyCollector GetSubShaderPropertiesForTarget ( Target target , GraphData graph , GenerationMode generationMode , AbstractMaterialNode outputNode )
212+ {
213+ PropertyCollector subshaderProperties = new PropertyCollector ( ) ;
214+
215+ // Collect shader properties declared by active nodes
216+ using ( var activeNodes = PooledHashSet < AbstractMaterialNode > . Get ( ) )
217+ {
218+ if ( outputNode == null )
219+ {
220+ // shader graph builds active nodes starting from the set of active blocks
221+ var currentBlocks = graph . GetNodes < BlockNode > ( ) ;
222+ var activeBlockContext = new TargetActiveBlockContext ( currentBlocks . Select ( x => x . descriptor ) . ToList ( ) , null ) ;
223+ target . GetActiveBlocks ( ref activeBlockContext ) ;
224+
225+ foreach ( var blockFieldDesc in activeBlockContext . activeBlocks )
226+ {
227+ // attempt to get BlockNode(s) from the stack
228+ var vertBlockNode = graph . vertexContext . blocks . FirstOrDefault ( x => x . value . descriptor == blockFieldDesc ) . value ;
229+ if ( vertBlockNode != null )
230+ activeNodes . Add ( vertBlockNode ) ;
231+
232+ var fragBlockNode = graph . fragmentContext . blocks . FirstOrDefault ( x => x . value . descriptor == blockFieldDesc ) . value ;
233+ if ( fragBlockNode != null )
234+ activeNodes . Add ( fragBlockNode ) ;
235+ }
236+ }
237+ else
238+ {
239+ // preview and/or subgraphs build their active node set based on the single output node
240+ activeNodes . Add ( outputNode ) ;
199241 }
242+
243+ PreviewManager . PropagateNodes ( activeNodes , PreviewManager . PropagationDirection . Upstream , activeNodes ) ;
244+
245+ // NOTE: this is NOT a deterministic ordering
246+ foreach ( var node in activeNodes )
247+ node . CollectShaderProperties ( subshaderProperties , generationMode ) ;
248+
249+ // So we sort the properties after
250+ subshaderProperties . Sort ( ) ;
251+ }
252+
253+ // Collect graph properties
254+ {
255+ graph . CollectShaderProperties ( subshaderProperties , generationMode ) ;
256+ }
257+
258+ // Collect shader properties declared by the Target
259+ {
260+ target . CollectShaderProperties ( subshaderProperties , generationMode ) ;
200261 }
262+
263+ subshaderProperties . SetReadOnly ( ) ;
264+
265+ return subshaderProperties ;
201266 }
202267
203- void GenerateShaderPass ( int targetIndex , PassDescriptor pass , ActiveFields activeFields , List < BlockFieldDescriptor > currentBlockDescriptors )
268+ void GenerateShaderPass ( int targetIndex , PassDescriptor pass , ActiveFields activeFields , List < BlockFieldDescriptor > currentBlockDescriptors , PropertyCollector subShaderProperties )
204269 {
205270 // Early exit if pass is not used in preview
206271 if ( m_Mode == GenerationMode . Preview && ! pass . useInPreview )
@@ -227,6 +292,7 @@ void GenerateShaderPass(int targetIndex, PassDescriptor pass, ActiveFields activ
227292 CustomInterpSubGen customInterpSubGen = new CustomInterpSubGen ( m_OutputNode != null ) ;
228293
229294 // Initiailize Collectors
295+ // NOTE: propertyCollector is not really used anymore -- we use the subshader PropertyCollector instead
230296 var propertyCollector = new PropertyCollector ( ) ;
231297 var keywordCollector = new KeywordCollector ( ) ;
232298 m_GraphData . CollectShaderKeywords ( keywordCollector , m_Mode ) ;
@@ -663,7 +729,7 @@ void ProcessStackForPass(ContextData contextData, BlockFieldDescriptor[] passBlo
663729
664730 using ( var propertyBuilder = new ShaderStringBuilder ( ) )
665731 {
666- propertyCollector . GetPropertiesDeclaration ( propertyBuilder , m_Mode , m_GraphData . graphDefaultConcretePrecision ) ;
732+ subShaderProperties . GetPropertiesDeclaration ( propertyBuilder , m_Mode , m_GraphData . graphDefaultConcretePrecision ) ;
667733 if ( propertyBuilder . length == 0 )
668734 propertyBuilder . AppendLine ( "// GraphProperties: <None>" ) ;
669735 spliceCommands . Add ( "GraphProperties" , propertyBuilder . ToCodeBlock ( ) ) ;
@@ -672,17 +738,12 @@ void ProcessStackForPass(ContextData contextData, BlockFieldDescriptor[] passBlo
672738 // --------------------------------------------------
673739 // Dots Instanced Graph Properties
674740
675- bool hasDotsProperties = false ;
676- m_GraphData . ForeachHLSLProperty ( h =>
677- {
678- if ( h . declaration == HLSLDeclaration . HybridPerInstance )
679- hasDotsProperties = true ;
680- } ) ;
741+ bool hasDotsProperties = subShaderProperties . HasDotsProperties ( ) ;
681742
682743 using ( var dotsInstancedPropertyBuilder = new ShaderStringBuilder ( ) )
683744 {
684745 if ( hasDotsProperties )
685- dotsInstancedPropertyBuilder . AppendLines ( propertyCollector . GetDotsInstancingPropertiesDeclaration ( m_Mode ) ) ;
746+ dotsInstancedPropertyBuilder . AppendLines ( subShaderProperties . GetDotsInstancingPropertiesDeclaration ( m_Mode ) ) ;
686747 else
687748 dotsInstancedPropertyBuilder . AppendLine ( "// HybridV1InjectedBuiltinProperties: <None>" ) ;
688749 spliceCommands . Add ( "HybridV1InjectedBuiltinProperties" , dotsInstancedPropertyBuilder . ToCodeBlock ( ) ) ;
0 commit comments