@@ -14,7 +14,8 @@ enum VFXExpressionContextOption
14
14
CPUEvaluation = 1 << 1 ,
15
15
ConstantFolding = 1 << 2 ,
16
16
GPUDataTransformation = 1 << 3 ,
17
- PatchReadToEventAttribute = 1 << 4
17
+ PatchReadToEventAttribute = 1 << 4 ,
18
+ CollectPerContextData = 1 << 5
18
19
}
19
20
20
21
abstract partial class VFXExpression
@@ -61,62 +62,162 @@ public void UnregisterExpression(VFXExpression expression)
61
62
m_EndExpressions . Remove ( expression ) ;
62
63
}
63
64
64
- static readonly ProfilerMarker s_CompileExpressionContext = new ProfilerMarker ( "VFXEditor.CompileExpressionContext" ) ;
65
+ class CollectedData
66
+ {
67
+ public readonly HashSet < VFXExpression > processedExpressions = new ( ) ;
68
+ public readonly HashSet < VFXExpression > markedExpressions = new ( ) ;
69
+ public readonly Dictionary < IHLSLCodeHolder , HashSet < VFXExpression > > childrenExpressionHLSLCodeHolder = new ( ) ;
70
+ public readonly Dictionary < VFXExpressionBufferWithType , HashSet < VFXExpression > > childrenExpressionBufferWithType = new ( ) ;
71
+ }
65
72
66
- public void Compile ( )
73
+ private void CollectPerContextDataRecursive ( VFXExpression node , Stack < VFXExpression > currentChildren , CollectedData data )
67
74
{
68
- using ( s_CompileExpressionContext . Auto ( ) )
75
+ if ( data . processedExpressions . Contains ( node ) )
69
76
{
70
- bool needToPatch = HasAny ( VFXExpressionContextOption . GPUDataTransformation | VFXExpressionContextOption . PatchReadToEventAttribute ) ;
71
- var gpuTransformation = needToPatch && Has ( VFXExpressionContextOption . GPUDataTransformation ) ;
72
- var spawnEventPath = needToPatch && Has ( VFXExpressionContextOption . PatchReadToEventAttribute ) ;
73
-
74
- var collectedData = new CompileCollectedData ( )
75
- {
76
- bufferTypeUsages = new ( ) ,
77
- hlslCodeHolders = new ( )
78
- } ;
79
-
80
- foreach ( var exp in m_EndExpressions )
77
+ if ( data . markedExpressions . Contains ( node ) )
81
78
{
82
- Compile ( exp . Key , collectedData ) ;
83
- if ( needToPatch )
84
- m_ReducedCache [ exp . Key ] = PatchVFXExpression ( GetReduced ( exp . Key ) , null /* no source in end expression */ , gpuTransformation , spawnEventPath , m_GlobalEventAttribute , collectedData ) ;
79
+ foreach ( var hlslCodeHolderCollection in data . childrenExpressionHLSLCodeHolder )
80
+ {
81
+ if ( hlslCodeHolderCollection . Value . Contains ( node ) )
82
+ {
83
+ foreach ( var child in currentChildren )
84
+ {
85
+ data . markedExpressions . Add ( child ) ;
86
+ hlslCodeHolderCollection . Value . Add ( child ) ;
87
+ }
88
+ }
89
+ }
85
90
86
- if ( collectedData . bufferTypeUsages . Count > 0 )
91
+ foreach ( var expressionBufferWithTypeCollection in data . childrenExpressionBufferWithType )
87
92
{
88
- foreach ( var context in exp . Value )
93
+ if ( expressionBufferWithTypeCollection . Value . Contains ( node ) )
89
94
{
90
- if ( ! m_GraphicsBufferTypeUsagePerContext . TryGetValue ( context , out var usages ) )
95
+ foreach ( var child in currentChildren )
91
96
{
92
- usages = new Dictionary < VFXExpression , BufferUsage > ( ) ;
93
- m_GraphicsBufferTypeUsagePerContext . Add ( context , usages ) ;
97
+ data . markedExpressions . Add ( child ) ;
98
+ expressionBufferWithTypeCollection . Value . Add ( child ) ;
94
99
}
100
+ }
101
+ }
102
+ }
103
+ return ;
104
+ }
105
+
106
+ currentChildren . Push ( node ) ;
107
+ if ( node is IHLSLCodeHolder hlslCodeHolder )
108
+ {
109
+ if ( ! data . childrenExpressionHLSLCodeHolder . TryGetValue ( hlslCodeHolder , out var childCollection ) )
110
+ {
111
+ childCollection = new ( ) ;
112
+ data . childrenExpressionHLSLCodeHolder . Add ( hlslCodeHolder , childCollection ) ;
113
+ }
114
+
115
+ foreach ( var child in currentChildren )
116
+ {
117
+ data . markedExpressions . Add ( child ) ;
118
+ childCollection . Add ( child ) ;
119
+ }
120
+ }
121
+
122
+ if ( node is VFXExpressionBufferWithType expressionWithType )
123
+ {
124
+ if ( ! data . childrenExpressionBufferWithType . TryGetValue ( expressionWithType , out var childCollection ) )
125
+ {
126
+ childCollection = new ( ) ;
127
+ data . childrenExpressionBufferWithType . Add ( expressionWithType , childCollection ) ;
128
+ }
129
+
130
+ foreach ( var child in currentChildren )
131
+ {
132
+ data . markedExpressions . Add ( child ) ;
133
+ childCollection . Add ( child ) ;
134
+ }
135
+ }
136
+
137
+ foreach ( var parent in node . parents )
138
+ CollectPerContextDataRecursive ( parent , currentChildren , data ) ;
139
+
140
+ data . processedExpressions . Add ( node ) ;
141
+ currentChildren . Pop ( ) ;
142
+ }
143
+
144
+ private void CollectPerContextData ( )
145
+ {
146
+ var collectedDataCache = new CollectedData ( ) ;
147
+ var childrenStackCache = new Stack < VFXExpression > ( ) ;
148
+ foreach ( var exp in m_EndExpressions )
149
+ {
150
+ if ( childrenStackCache . Count > 0 )
151
+ throw new InvalidOperationException ( "Unexpected Children Stack after dependency collection." ) ;
152
+ CollectPerContextDataRecursive ( exp . Key , childrenStackCache , collectedDataCache ) ;
95
153
96
- foreach ( var expressionTypeUsage in collectedData . bufferTypeUsages )
154
+ if ( collectedDataCache . markedExpressions . Contains ( exp . Key ) )
155
+ {
156
+ foreach ( var hlslCodeHolderCollection in collectedDataCache . childrenExpressionHLSLCodeHolder )
157
+ {
158
+ if ( hlslCodeHolderCollection . Value . Contains ( exp . Key ) )
159
+ {
160
+ foreach ( var context in exp . Value )
97
161
{
98
- if ( ! usages . TryAdd ( expressionTypeUsage . Key , expressionTypeUsage . Value ) && usages [ expressionTypeUsage . Key ] != expressionTypeUsage . Value )
162
+ if ( ! m_HLSLCollectionPerContext . TryGetValue ( context , out var codeHolders ) )
99
163
{
100
- throw new InvalidOperationException ( $ "Diverging type usage for GraphicsBuffer : { usages [ expressionTypeUsage . Key ] } , { expressionTypeUsage . Value } ") ;
164
+ codeHolders = new ( ) ;
165
+ m_HLSLCollectionPerContext . Add ( context , codeHolders ) ;
101
166
}
167
+ codeHolders . Add ( hlslCodeHolderCollection . Key ) ;
102
168
}
103
169
}
104
170
}
105
- collectedData . bufferTypeUsages . Clear ( ) ;
106
171
107
- if ( collectedData . hlslCodeHolders . Count > 0 )
172
+ foreach ( var expressionBufferWithTypeCollection in collectedDataCache . childrenExpressionBufferWithType )
108
173
{
109
- foreach ( var context in exp . Value )
174
+ if ( expressionBufferWithTypeCollection . Value . Contains ( exp . Key ) )
110
175
{
111
- if ( ! m_HLSLCollectionPerContext . TryGetValue ( context , out var codeHolders ) )
176
+ foreach ( var context in exp . Value )
112
177
{
113
- codeHolders = new List < IHLSLCodeHolder > ( ) ;
114
- m_HLSLCollectionPerContext . Add ( context , codeHolders ) ;
178
+ if ( ! m_GraphicsBufferTypeUsagePerContext . TryGetValue ( context , out var usages ) )
179
+ {
180
+ usages = new ( ) ;
181
+ m_GraphicsBufferTypeUsagePerContext . Add ( context , usages ) ;
182
+ }
183
+
184
+ var usage = expressionBufferWithTypeCollection . Key . usage ;
185
+ var buffer = expressionBufferWithTypeCollection . Key . parents [ 0 ] ;
186
+ if ( ! usages . TryAdd ( buffer , usage ) && usages [ buffer ] != usage )
187
+ {
188
+ throw new InvalidOperationException ( $ "Diverging type usage for GraphicsBuffer : { buffer } , { usage } ") ;
189
+ }
115
190
}
116
- codeHolders . AddRange ( collectedData . hlslCodeHolders ) ;
117
191
}
118
192
}
119
- collectedData . hlslCodeHolders . Clear ( ) ;
193
+ }
194
+ }
195
+ }
196
+
197
+ static readonly ProfilerMarker s_CollectPerContextData = new ProfilerMarker ( "VFXEditor.CollectPerContextData" ) ;
198
+ static readonly ProfilerMarker s_CompileExpressionContext = new ProfilerMarker ( "VFXEditor.CompileExpressionContext" ) ;
199
+
200
+ public void Compile ( )
201
+ {
202
+ if ( Has ( VFXExpressionContextOption . CollectPerContextData ) )
203
+ {
204
+ using ( s_CollectPerContextData . Auto ( ) )
205
+ {
206
+ CollectPerContextData ( ) ;
207
+ }
208
+ }
209
+
210
+ using ( s_CompileExpressionContext . Auto ( ) )
211
+ {
212
+ bool needToPatch = HasAny ( VFXExpressionContextOption . GPUDataTransformation | VFXExpressionContextOption . PatchReadToEventAttribute ) ;
213
+ var gpuTransformation = needToPatch && Has ( VFXExpressionContextOption . GPUDataTransformation ) ;
214
+ var spawnEventPath = needToPatch && Has ( VFXExpressionContextOption . PatchReadToEventAttribute ) ;
215
+
216
+ foreach ( var exp in m_EndExpressions )
217
+ {
218
+ Compile ( exp . Key ) ;
219
+ if ( needToPatch )
220
+ m_ReducedCache [ exp . Key ] = PatchVFXExpression ( GetReduced ( exp . Key ) , null /* no source in end expression */ , gpuTransformation , spawnEventPath , m_GlobalEventAttribute ) ;
120
221
}
121
222
}
122
223
}
@@ -157,7 +258,7 @@ private bool ShouldEvaluate(VFXExpression exp, VFXExpression[] reducedParents)
157
258
return true ;
158
259
}
159
260
160
- private VFXExpression PatchVFXExpression ( VFXExpression input , VFXExpression targetExpression , bool insertGPUTransformation , bool patchReadAttributeForSpawn , IEnumerable < VFXLayoutElementDesc > globalEventAttribute , CompileCollectedData collectedData )
261
+ private VFXExpression PatchVFXExpression ( VFXExpression input , VFXExpression targetExpression , bool insertGPUTransformation , bool patchReadAttributeForSpawn , IEnumerable < VFXLayoutElementDesc > globalEventAttribute )
161
262
{
162
263
if ( insertGPUTransformation )
163
264
{
@@ -184,7 +285,7 @@ private VFXExpression PatchVFXExpression(VFXExpression input, VFXExpression targ
184
285
case VFXExpressionOperation . SampleMeshVertexFloat4 :
185
286
case VFXExpressionOperation . SampleMeshVertexColor :
186
287
var channelFormatAndDimensionAndStream = targetExpression . parents [ 2 ] ;
187
- channelFormatAndDimensionAndStream = Compile ( channelFormatAndDimensionAndStream , collectedData ) ;
288
+ channelFormatAndDimensionAndStream = Compile ( channelFormatAndDimensionAndStream ) ;
188
289
if ( ! ( channelFormatAndDimensionAndStream is VFXExpressionMeshChannelInfos ) )
189
290
throw new InvalidOperationException ( "Unexpected type of expression in mesh sampling : " + channelFormatAndDimensionAndStream ) ;
190
291
input = new VFXExpressionVertexBufferFromMesh ( input , channelFormatAndDimensionAndStream ) ;
@@ -201,7 +302,7 @@ private VFXExpression PatchVFXExpression(VFXExpression input, VFXExpression targ
201
302
if ( targetExpression is IVFXExpressionSampleSkinnedMesh skinnedMeshExpression )
202
303
{
203
304
var channelFormatAndDimensionAndStream = targetExpression . parents [ 2 ] ;
204
- channelFormatAndDimensionAndStream = Compile ( channelFormatAndDimensionAndStream , collectedData ) ;
305
+ channelFormatAndDimensionAndStream = Compile ( channelFormatAndDimensionAndStream ) ;
205
306
if ( ! ( channelFormatAndDimensionAndStream is VFXExpressionMeshChannelInfos ) )
206
307
throw new InvalidOperationException ( "Unexpected type of expression in skinned mesh sampling : " + channelFormatAndDimensionAndStream ) ;
207
308
input = new VFXExpressionVertexBufferFromSkinnedMeshRenderer ( input , channelFormatAndDimensionAndStream , skinnedMeshExpression . frame ) ;
@@ -223,18 +324,6 @@ private VFXExpression PatchVFXExpression(VFXExpression input, VFXExpression targ
223
324
if ( input . valueType == VFXValueType . Buffer && input is VFXExpressionBufferWithType bufferWithType )
224
325
{
225
326
input = input . parents [ 0 ] ; //Explicitly skip NoOp expression
226
- if ( collectedData . bufferTypeUsages != null )
227
- {
228
- var usageType = bufferWithType . usage ;
229
- if ( ! collectedData . bufferTypeUsages . TryGetValue ( input , out var registeredType ) )
230
- {
231
- collectedData . bufferTypeUsages . Add ( input , usageType ) ;
232
- }
233
- else if ( registeredType != usageType )
234
- {
235
- throw new InvalidOperationException ( $ "Diverging type usage for GraphicsBuffer : { registeredType } , { usageType } ") ;
236
- }
237
- }
238
327
}
239
328
240
329
if ( patchReadAttributeForSpawn && input is VFXAttributeExpression attribute )
@@ -261,13 +350,7 @@ private VFXExpression PatchVFXExpression(VFXExpression input, VFXExpression targ
261
350
return input ;
262
351
}
263
352
264
- public struct CompileCollectedData
265
- {
266
- public Dictionary < VFXExpression , BufferUsage > bufferTypeUsages ;
267
- public List < IHLSLCodeHolder > hlslCodeHolders ;
268
- }
269
-
270
- public VFXExpression Compile ( VFXExpression expression , CompileCollectedData collectedData = default ( CompileCollectedData ) )
353
+ public VFXExpression Compile ( VFXExpression expression )
271
354
{
272
355
var gpuTransformation = Has ( VFXExpressionContextOption . GPUDataTransformation ) ;
273
356
var patchReadAttributeForSpawn = Has ( VFXExpressionContextOption . PatchReadToEventAttribute ) ;
@@ -278,11 +361,11 @@ public struct CompileCollectedData
278
361
var parents = new VFXExpression [ expression . parents . Length ] ;
279
362
for ( var i = 0 ; i < expression . parents . Length ; i ++ )
280
363
{
281
- var parent = Compile ( expression . parents [ i ] , collectedData ) ;
364
+ var parent = Compile ( expression . parents [ i ] ) ;
282
365
bool currentGPUTransformation = gpuTransformation
283
366
&& expression . IsAny ( VFXExpression . Flags . NotCompilableOnCPU )
284
367
&& ! parent . IsAny ( VFXExpression . Flags . NotCompilableOnCPU ) ;
285
- parent = PatchVFXExpression ( parent , expression , currentGPUTransformation , patchReadAttributeForSpawn , m_GlobalEventAttribute , collectedData ) ;
368
+ parent = PatchVFXExpression ( parent , expression , currentGPUTransformation , patchReadAttributeForSpawn , m_GlobalEventAttribute ) ;
286
369
parents [ i ] = parent ;
287
370
}
288
371
@@ -299,11 +382,6 @@ public struct CompileCollectedData
299
382
reduced = expression ;
300
383
}
301
384
302
- if ( expression is IHLSLCodeHolder hlslCodeHolder && collectedData . hlslCodeHolders != null )
303
- {
304
- if ( ! collectedData . hlslCodeHolders . Contains ( hlslCodeHolder ) )
305
- collectedData . hlslCodeHolders . Add ( hlslCodeHolder ) ;
306
- }
307
385
m_ReducedCache [ expression ] = reduced ;
308
386
}
309
387
return reduced ;
0 commit comments