@@ -88,6 +88,7 @@ public ActiveFields GatherActiveFieldsFromNode(AbstractMaterialNode outputNode,
88
88
void BuildShader ( )
89
89
{
90
90
var activeNodeList = Pool . ListPool < AbstractMaterialNode > . Get ( ) ;
91
+ bool ignoreActiveState = ( m_Mode == GenerationMode . Preview ) ; // for previews, we ignore node active state
91
92
if ( m_OutputNode == null )
92
93
{
93
94
foreach ( var block in m_Blocks )
@@ -97,12 +98,12 @@ void BuildShader()
97
98
if ( ! block . isActive )
98
99
continue ;
99
100
100
- NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , block , NodeUtils . IncludeSelf . Include ) ;
101
+ NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , block , NodeUtils . IncludeSelf . Include , ignoreActiveState : ignoreActiveState ) ;
101
102
}
102
103
}
103
104
else
104
105
{
105
- NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , m_OutputNode ) ;
106
+ NodeUtils . DepthFirstCollectNodesFromNode ( activeNodeList , m_OutputNode , ignoreActiveState : ignoreActiveState ) ;
106
107
}
107
108
108
109
var shaderProperties = new PropertyCollector ( ) ;
@@ -132,6 +133,10 @@ void BuildShader()
132
133
target . CollectShaderProperties ( shaderProperties , m_Mode ) ;
133
134
}
134
135
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
+
135
140
m_Builder . AppendLine ( @"Shader ""{0}""" , m_Name ) ;
136
141
using ( m_Builder . BlockScope ( ) )
137
142
{
@@ -144,9 +149,11 @@ void BuildShader()
144
149
// Instead of setup target, we can also just do get context
145
150
m_Targets [ i ] . Setup ( ref context ) ;
146
151
152
+ var subShaderProperties = GetSubShaderPropertiesForTarget ( m_Targets [ i ] , m_GraphData , m_Mode , m_OutputNode ) ;
153
+
147
154
foreach ( var subShader in context . subShaders )
148
155
{
149
- GenerateSubShader ( i , subShader ) ;
156
+ GenerateSubShader ( i , subShader , subShaderProperties ) ;
150
157
}
151
158
152
159
var customEditor = context . defaultShaderGUI ;
@@ -167,7 +174,7 @@ void BuildShader()
167
174
m_ConfiguredTextures = shaderProperties . GetConfiguredTexutres ( ) ;
168
175
}
169
176
170
- void GenerateSubShader ( int targetIndex , SubShaderDescriptor descriptor )
177
+ void GenerateSubShader ( int targetIndex , SubShaderDescriptor descriptor , PropertyCollector subShaderProperties )
171
178
{
172
179
if ( descriptor . passes == null )
173
180
return ;
@@ -195,12 +202,70 @@ void GenerateSubShader(int targetIndex, SubShaderDescriptor descriptor)
195
202
196
203
// Check masternode fields for valid passes
197
204
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 ) ;
199
241
}
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 ) ;
200
261
}
262
+
263
+ subshaderProperties . SetReadOnly ( ) ;
264
+
265
+ return subshaderProperties ;
201
266
}
202
267
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 )
204
269
{
205
270
// Early exit if pass is not used in preview
206
271
if ( m_Mode == GenerationMode . Preview && ! pass . useInPreview )
@@ -227,6 +292,7 @@ void GenerateShaderPass(int targetIndex, PassDescriptor pass, ActiveFields activ
227
292
CustomInterpSubGen customInterpSubGen = new CustomInterpSubGen ( m_OutputNode != null ) ;
228
293
229
294
// Initiailize Collectors
295
+ // NOTE: propertyCollector is not really used anymore -- we use the subshader PropertyCollector instead
230
296
var propertyCollector = new PropertyCollector ( ) ;
231
297
var keywordCollector = new KeywordCollector ( ) ;
232
298
m_GraphData . CollectShaderKeywords ( keywordCollector , m_Mode ) ;
@@ -663,7 +729,7 @@ void ProcessStackForPass(ContextData contextData, BlockFieldDescriptor[] passBlo
663
729
664
730
using ( var propertyBuilder = new ShaderStringBuilder ( ) )
665
731
{
666
- propertyCollector . GetPropertiesDeclaration ( propertyBuilder , m_Mode , m_GraphData . graphDefaultConcretePrecision ) ;
732
+ subShaderProperties . GetPropertiesDeclaration ( propertyBuilder , m_Mode , m_GraphData . graphDefaultConcretePrecision ) ;
667
733
if ( propertyBuilder . length == 0 )
668
734
propertyBuilder . AppendLine ( "// GraphProperties: <None>" ) ;
669
735
spliceCommands . Add ( "GraphProperties" , propertyBuilder . ToCodeBlock ( ) ) ;
@@ -672,17 +738,12 @@ void ProcessStackForPass(ContextData contextData, BlockFieldDescriptor[] passBlo
672
738
// --------------------------------------------------
673
739
// Dots Instanced Graph Properties
674
740
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 ( ) ;
681
742
682
743
using ( var dotsInstancedPropertyBuilder = new ShaderStringBuilder ( ) )
683
744
{
684
745
if ( hasDotsProperties )
685
- dotsInstancedPropertyBuilder . AppendLines ( propertyCollector . GetDotsInstancingPropertiesDeclaration ( m_Mode ) ) ;
746
+ dotsInstancedPropertyBuilder . AppendLines ( subShaderProperties . GetDotsInstancingPropertiesDeclaration ( m_Mode ) ) ;
686
747
else
687
748
dotsInstancedPropertyBuilder . AppendLine ( "// HybridV1InjectedBuiltinProperties: <None>" ) ;
688
749
spliceCommands . Add ( "HybridV1InjectedBuiltinProperties" , dotsInstancedPropertyBuilder . ToCodeBlock ( ) ) ;
0 commit comments