@@ -14,7 +14,8 @@ enum VFXExpressionContextOption
1414 CPUEvaluation = 1 << 1 ,
1515 ConstantFolding = 1 << 2 ,
1616 GPUDataTransformation = 1 << 3 ,
17- PatchReadToEventAttribute = 1 << 4
17+ PatchReadToEventAttribute = 1 << 4 ,
18+ CollectPerContextData = 1 << 5
1819 }
1920
2021 abstract partial class VFXExpression
@@ -61,62 +62,162 @@ public void UnregisterExpression(VFXExpression expression)
6162 m_EndExpressions . Remove ( expression ) ;
6263 }
6364
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+ }
6572
66- public void Compile ( )
73+ private void CollectPerContextDataRecursive ( VFXExpression node , Stack < VFXExpression > currentChildren , CollectedData data )
6774 {
68- using ( s_CompileExpressionContext . Auto ( ) )
75+ if ( data . processedExpressions . Contains ( node ) )
6976 {
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 ) )
8178 {
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+ }
8590
86- if ( collectedData . bufferTypeUsages . Count > 0 )
91+ foreach ( var expressionBufferWithTypeCollection in data . childrenExpressionBufferWithType )
8792 {
88- foreach ( var context in exp . Value )
93+ if ( expressionBufferWithTypeCollection . Value . Contains ( node ) )
8994 {
90- if ( ! m_GraphicsBufferTypeUsagePerContext . TryGetValue ( context , out var usages ) )
95+ foreach ( var child in currentChildren )
9196 {
92- usages = new Dictionary < VFXExpression , BufferUsage > ( ) ;
93- m_GraphicsBufferTypeUsagePerContext . Add ( context , usages ) ;
97+ data . markedExpressions . Add ( child ) ;
98+ expressionBufferWithTypeCollection . Value . Add ( child ) ;
9499 }
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 ) ;
95153
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 )
97161 {
98- if ( ! usages . TryAdd ( expressionTypeUsage . Key , expressionTypeUsage . Value ) && usages [ expressionTypeUsage . Key ] != expressionTypeUsage . Value )
162+ if ( ! m_HLSLCollectionPerContext . TryGetValue ( context , out var codeHolders ) )
99163 {
100- throw new InvalidOperationException ( $ "Diverging type usage for GraphicsBuffer : { usages [ expressionTypeUsage . Key ] } , { expressionTypeUsage . Value } ") ;
164+ codeHolders = new ( ) ;
165+ m_HLSLCollectionPerContext . Add ( context , codeHolders ) ;
101166 }
167+ codeHolders . Add ( hlslCodeHolderCollection . Key ) ;
102168 }
103169 }
104170 }
105- collectedData . bufferTypeUsages . Clear ( ) ;
106171
107- if ( collectedData . hlslCodeHolders . Count > 0 )
172+ foreach ( var expressionBufferWithTypeCollection in collectedDataCache . childrenExpressionBufferWithType )
108173 {
109- foreach ( var context in exp . Value )
174+ if ( expressionBufferWithTypeCollection . Value . Contains ( exp . Key ) )
110175 {
111- if ( ! m_HLSLCollectionPerContext . TryGetValue ( context , out var codeHolders ) )
176+ foreach ( var context in exp . Value )
112177 {
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+ }
115190 }
116- codeHolders . AddRange ( collectedData . hlslCodeHolders ) ;
117191 }
118192 }
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 ) ;
120221 }
121222 }
122223 }
@@ -157,7 +258,7 @@ private bool ShouldEvaluate(VFXExpression exp, VFXExpression[] reducedParents)
157258 return true ;
158259 }
159260
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 )
161262 {
162263 if ( insertGPUTransformation )
163264 {
@@ -184,7 +285,7 @@ private VFXExpression PatchVFXExpression(VFXExpression input, VFXExpression targ
184285 case VFXExpressionOperation . SampleMeshVertexFloat4 :
185286 case VFXExpressionOperation . SampleMeshVertexColor :
186287 var channelFormatAndDimensionAndStream = targetExpression . parents [ 2 ] ;
187- channelFormatAndDimensionAndStream = Compile ( channelFormatAndDimensionAndStream , collectedData ) ;
288+ channelFormatAndDimensionAndStream = Compile ( channelFormatAndDimensionAndStream ) ;
188289 if ( ! ( channelFormatAndDimensionAndStream is VFXExpressionMeshChannelInfos ) )
189290 throw new InvalidOperationException ( "Unexpected type of expression in mesh sampling : " + channelFormatAndDimensionAndStream ) ;
190291 input = new VFXExpressionVertexBufferFromMesh ( input , channelFormatAndDimensionAndStream ) ;
@@ -201,7 +302,7 @@ private VFXExpression PatchVFXExpression(VFXExpression input, VFXExpression targ
201302 if ( targetExpression is IVFXExpressionSampleSkinnedMesh skinnedMeshExpression )
202303 {
203304 var channelFormatAndDimensionAndStream = targetExpression . parents [ 2 ] ;
204- channelFormatAndDimensionAndStream = Compile ( channelFormatAndDimensionAndStream , collectedData ) ;
305+ channelFormatAndDimensionAndStream = Compile ( channelFormatAndDimensionAndStream ) ;
205306 if ( ! ( channelFormatAndDimensionAndStream is VFXExpressionMeshChannelInfos ) )
206307 throw new InvalidOperationException ( "Unexpected type of expression in skinned mesh sampling : " + channelFormatAndDimensionAndStream ) ;
207308 input = new VFXExpressionVertexBufferFromSkinnedMeshRenderer ( input , channelFormatAndDimensionAndStream , skinnedMeshExpression . frame ) ;
@@ -223,18 +324,6 @@ private VFXExpression PatchVFXExpression(VFXExpression input, VFXExpression targ
223324 if ( input . valueType == VFXValueType . Buffer && input is VFXExpressionBufferWithType bufferWithType )
224325 {
225326 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- }
238327 }
239328
240329 if ( patchReadAttributeForSpawn && input is VFXAttributeExpression attribute )
@@ -261,13 +350,7 @@ private VFXExpression PatchVFXExpression(VFXExpression input, VFXExpression targ
261350 return input ;
262351 }
263352
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 )
271354 {
272355 var gpuTransformation = Has ( VFXExpressionContextOption . GPUDataTransformation ) ;
273356 var patchReadAttributeForSpawn = Has ( VFXExpressionContextOption . PatchReadToEventAttribute ) ;
@@ -278,11 +361,11 @@ public struct CompileCollectedData
278361 var parents = new VFXExpression [ expression . parents . Length ] ;
279362 for ( var i = 0 ; i < expression . parents . Length ; i ++ )
280363 {
281- var parent = Compile ( expression . parents [ i ] , collectedData ) ;
364+ var parent = Compile ( expression . parents [ i ] ) ;
282365 bool currentGPUTransformation = gpuTransformation
283366 && expression . IsAny ( VFXExpression . Flags . NotCompilableOnCPU )
284367 && ! parent . IsAny ( VFXExpression . Flags . NotCompilableOnCPU ) ;
285- parent = PatchVFXExpression ( parent , expression , currentGPUTransformation , patchReadAttributeForSpawn , m_GlobalEventAttribute , collectedData ) ;
368+ parent = PatchVFXExpression ( parent , expression , currentGPUTransformation , patchReadAttributeForSpawn , m_GlobalEventAttribute ) ;
286369 parents [ i ] = parent ;
287370 }
288371
@@ -299,11 +382,6 @@ public struct CompileCollectedData
299382 reduced = expression ;
300383 }
301384
302- if ( expression is IHLSLCodeHolder hlslCodeHolder && collectedData . hlslCodeHolders != null )
303- {
304- if ( ! collectedData . hlslCodeHolders . Contains ( hlslCodeHolder ) )
305- collectedData . hlslCodeHolders . Add ( hlslCodeHolder ) ;
306- }
307385 m_ReducedCache [ expression ] = reduced ;
308386 }
309387 return reduced ;
0 commit comments