@@ -13,14 +13,14 @@ class CloudLayerRenderer : CloudRenderer
1313
1414 private float lastTime = 0.0f ;
1515 int m_LastPrecomputationParamHash ;
16+ ComputeShader m_BakeCloudTextureCS , m_BakeCloudShadowsCS ;
17+ int m_BakeCloudTextureKernel , m_BakeCloudShadowsKernel ;
1618
1719 static readonly int _CloudTexture = Shader . PropertyToID ( "_CloudTexture" ) ;
1820 static readonly int _CloudShadows = Shader . PropertyToID ( "_CloudShadows" ) ;
1921 static readonly int _FlowmapA = Shader . PropertyToID ( "_FlowmapA" ) , _FlowmapB = Shader . PropertyToID ( "_FlowmapB" ) ;
2022 static readonly int _CloudMapA = Shader . PropertyToID ( "_CloudMapA" ) , _CloudMapB = Shader . PropertyToID ( "_CloudMapB" ) ;
2123 static readonly int _AmbientProbeBuffer = Shader . PropertyToID ( "_AmbientProbeBuffer" ) ;
22- static ComputeShader s_BakeCloudTextureCS , s_BakeCloudShadowsCS ;
23- static int s_BakeCloudTextureKernel , s_BakeCloudShadowsKernel ;
2424 static readonly Vector4 [ ] s_VectorArray = new Vector4 [ 2 ] ;
2525
2626 public RTHandle cloudTexture { get { return m_PrecomputedData . cloudTextureRT ; } }
@@ -38,20 +38,23 @@ public override void Build()
3838
3939 m_CloudLayerMaterial = CoreUtils . CreateEngineMaterial ( shaders . cloudLayerPS ) ;
4040
41- s_BakeCloudTextureCS = shaders . bakeCloudTextureCS ;
42- s_BakeCloudTextureKernel = s_BakeCloudTextureCS . FindKernel ( "BakeCloudTexture" ) ;
41+ m_BakeCloudTextureCS = shaders . bakeCloudTextureCS ;
42+ m_BakeCloudTextureKernel = m_BakeCloudTextureCS . FindKernel ( "BakeCloudTexture" ) ;
4343
44- s_BakeCloudShadowsCS = shaders . bakeCloudShadowsCS ;
45- s_BakeCloudShadowsKernel = s_BakeCloudShadowsCS . FindKernel ( "BakeCloudShadows" ) ;
44+ m_BakeCloudShadowsCS = shaders . bakeCloudShadowsCS ;
45+ m_BakeCloudShadowsKernel = m_BakeCloudShadowsCS . FindKernel ( "BakeCloudShadows" ) ;
4646 }
4747
4848 public override void Cleanup ( )
4949 {
5050 CoreUtils . Destroy ( m_CloudLayerMaterial ) ;
5151
52+ m_BakeCloudTextureCS = null ;
53+ m_BakeCloudShadowsCS = null ;
54+
5255 if ( m_PrecomputedData != null )
5356 {
54- s_PrecomputationCache . Release ( m_LastPrecomputationParamHash ) ;
57+ PrecomputationCacheInstance . Release ( m_LastPrecomputationParamHash ) ;
5558 m_LastPrecomputationParamHash = 0 ;
5659 m_PrecomputedData = null ;
5760 }
@@ -62,8 +65,8 @@ bool UpdateCache(CloudLayer cloudLayer, Light sunLight)
6265 int currPrecomputationParamHash = cloudLayer . GetBakingHashCode ( sunLight ) ;
6366 if ( currPrecomputationParamHash != m_LastPrecomputationParamHash )
6467 {
65- s_PrecomputationCache . Release ( m_LastPrecomputationParamHash ) ;
66- m_PrecomputedData = s_PrecomputationCache . Get ( cloudLayer , currPrecomputationParamHash ) ;
68+ PrecomputationCacheInstance . Release ( m_LastPrecomputationParamHash ) ;
69+ m_PrecomputedData = PrecomputationCacheInstance . Get ( cloudLayer , currPrecomputationParamHash ) ;
6770 m_LastPrecomputationParamHash = currPrecomputationParamHash ;
6871 return true ;
6972 }
@@ -89,7 +92,7 @@ public override bool GetSunLightCookieParameters(CloudSettings settings, ref Coo
8992 }
9093
9194 public override void RenderSunLightCookie ( BuiltinSunCookieParameters builtinParams )
92- => m_PrecomputedData . BakeCloudShadows ( ( CloudLayer ) builtinParams . cloudSettings , builtinParams . sunLight , builtinParams . hdCamera , builtinParams . commandBuffer ) ;
95+ => m_PrecomputedData . BakeCloudShadows ( this , ( CloudLayer ) builtinParams . cloudSettings , builtinParams . sunLight , builtinParams . hdCamera , builtinParams . commandBuffer ) ;
9396
9497 public override void RenderClouds ( BuiltinSkyParameters builtinParams , bool renderForCubemap )
9598 {
@@ -108,7 +111,7 @@ public override void RenderClouds(BuiltinSkyParameters builtinParams, bool rende
108111 if ( ! hdCamera . animateMaterials )
109112 cloudLayer . layerA . scrollFactor = cloudLayer . layerB . scrollFactor = 0.0f ;
110113
111- m_PrecomputedData . InitIfNeeded ( cloudLayer , builtinParams . sunLight , hdCamera , builtinParams . commandBuffer ) ;
114+ m_PrecomputedData . InitIfNeeded ( this , cloudLayer , builtinParams . sunLight , hdCamera , builtinParams . commandBuffer ) ;
112115 m_CloudLayerMaterial . SetTexture ( _CloudTexture , m_PrecomputedData . cloudTextureRT ) ;
113116
114117 // Parameters
@@ -252,6 +255,18 @@ public void Release(int hash)
252255 }
253256 }
254257 }
258+
259+ public void Clear ( )
260+ {
261+ foreach ( var refCountData in m_CachedData . Values )
262+ {
263+ refCountData . refCount = 0 ;
264+ refCountData . data . Release ( ) ;
265+ m_DataPool . Release ( refCountData ) ;
266+ }
267+
268+ m_CachedData . Clear ( ) ;
269+ }
255270 }
256271
257272 class PrecomputationData
@@ -280,10 +295,31 @@ public void Cache(int textureWidth, int textureHeight, RTHandle texture)
280295 height = textureHeight ;
281296 rt = texture ;
282297 }
298+
299+ public void Clear ( )
300+ {
301+ width = 0 ;
302+ height = 0 ;
303+
304+ if ( rt != null )
305+ {
306+ RTHandles . Release ( rt ) ;
307+ rt = null ;
308+ }
309+ }
283310 }
284- static TextureCache cloudTextureCache ;
285- static TextureCache cloudShadowsCache ;
286311
312+ static TextureCache s_CloudTextureCache ;
313+ static TextureCache s_CloudShadowsCache ;
314+
315+ #if UNITY_EDITOR
316+ [ RuntimeInitializeOnLoadMethod ( RuntimeInitializeLoadType . SubsystemRegistration ) ]
317+ static void ResetStaticsOnLoad ( )
318+ {
319+ s_CloudTextureCache . Clear ( ) ;
320+ s_CloudShadowsCache . Clear ( ) ;
321+ }
322+ #endif
287323 bool initialized = false ;
288324 int cloudTextureWidth , cloudTextureHeight , cloudShadowsResolution ;
289325 public RTHandle cloudTextureRT = null ;
@@ -294,126 +330,144 @@ public void Allocate(CloudLayer cloudLayer)
294330 initialized = false ;
295331 cloudTextureWidth = ( int ) cloudLayer . resolution . value ;
296332 cloudTextureHeight = cloudLayer . upperHemisphereOnly . value ? cloudTextureWidth / 2 : cloudTextureWidth ;
297- if ( ! cloudTextureCache . TryGet ( cloudTextureWidth , cloudTextureHeight , ref cloudTextureRT ) )
333+ if ( ! s_CloudTextureCache . TryGet ( cloudTextureWidth , cloudTextureHeight , ref cloudTextureRT ) )
298334 cloudTextureRT = RTHandles . Alloc ( cloudTextureWidth , cloudTextureHeight , TextureWrapMode . Repeat , TextureWrapMode . Clamp ,
299335 slices : cloudLayer . NumLayers , colorFormat : GraphicsFormat . R16G16_SFloat , dimension : TextureDimension . Tex2DArray ,
300336 enableRandomWrite : true , useMipMap : false , filterMode : FilterMode . Bilinear , name : "Cloud Texture" ) ;
301337
302338 cloudShadowsRT = null ;
303339 cloudShadowsResolution = ( int ) cloudLayer . shadowResolution . value ;
304- if ( cloudLayer . CastShadows && ! cloudShadowsCache . TryGet ( cloudShadowsResolution , cloudShadowsResolution , ref cloudShadowsRT ) )
340+ if ( cloudLayer . CastShadows && ! s_CloudShadowsCache . TryGet ( cloudShadowsResolution , cloudShadowsResolution , ref cloudShadowsRT ) )
305341 cloudShadowsRT = RTHandles . Alloc ( cloudShadowsResolution , cloudShadowsResolution ,
306342 colorFormat : GraphicsFormat . B10G11R11_UFloatPack32 , dimension : TextureDimension . Tex2D ,
307343 enableRandomWrite : true , useMipMap : false , filterMode : FilterMode . Bilinear , name : "Cloud Shadows" ) ;
308344 }
309345
310346 public void Release ( )
311347 {
312- cloudTextureCache . Cache ( cloudTextureHeight , cloudTextureHeight , cloudTextureRT ) ;
313- cloudShadowsCache . Cache ( cloudShadowsResolution , cloudShadowsResolution , cloudShadowsRT ) ;
348+ s_CloudTextureCache . Cache ( cloudTextureHeight , cloudTextureHeight , cloudTextureRT ) ;
349+ s_CloudShadowsCache . Cache ( cloudShadowsResolution , cloudShadowsResolution , cloudShadowsRT ) ;
314350 }
315351
316- public bool InitIfNeeded ( CloudLayer cloudLayer , Light sunLight , HDCamera hdCamera , CommandBuffer cmd )
352+ public bool InitIfNeeded ( CloudLayerRenderer cloudLayerRenderer , CloudLayer cloudLayer , Light sunLight , HDCamera hdCamera , CommandBuffer cmd )
317353 {
318354 if ( initialized ) return false ;
319355
356+ var bakeCloudTextureCS = cloudLayerRenderer . m_BakeCloudTextureCS ;
357+ var bakeCloudTextureKernel = cloudLayerRenderer . m_BakeCloudTextureKernel ;
358+
320359 Vector4 params1 = sunLight == null ? Vector3 . zero : - sunLight . transform . forward ;
321360 params1 . w = ( cloudLayer . upperHemisphereOnly . value ? 1.0f : - 1.0f ) * hdCamera . planet . radius ;
322361
323- cmd . SetComputeVectorParam ( s_BakeCloudTextureCS , HDShaderIDs . _Params , params1 ) ;
324- cmd . SetComputeTextureParam ( s_BakeCloudTextureCS , s_BakeCloudTextureKernel , _CloudTexture , cloudTextureRT ) ;
362+ cmd . SetComputeVectorParam ( bakeCloudTextureCS , HDShaderIDs . _Params , params1 ) ;
363+ cmd . SetComputeTextureParam ( bakeCloudTextureCS , bakeCloudTextureKernel , _CloudTexture , cloudTextureRT ) ;
325364
326- cmd . SetComputeTextureParam ( s_BakeCloudTextureCS , s_BakeCloudTextureKernel , _CloudMapA , cloudLayer . layerA . cloudMap . value ) ;
365+ cmd . SetComputeTextureParam ( bakeCloudTextureCS , bakeCloudTextureKernel , _CloudMapA , cloudLayer . layerA . cloudMap . value ) ;
327366 var paramsA = cloudLayer . layerA . GetBakingParameters ( ) ;
328367
329368 if ( cloudLayer . NumLayers == 1 )
330369 {
331- s_BakeCloudTextureCS . DisableKeyword ( "USE_SECOND_CLOUD_LAYER" ) ;
332- cmd . SetComputeVectorParam ( s_BakeCloudTextureCS , HDShaderIDs . _Params1 , paramsA . Item1 ) ;
333- cmd . SetComputeVectorParam ( s_BakeCloudTextureCS , HDShaderIDs . _Params2 , paramsA . Item2 ) ;
370+ bakeCloudTextureCS . DisableKeyword ( "USE_SECOND_CLOUD_LAYER" ) ;
371+ cmd . SetComputeVectorParam ( bakeCloudTextureCS , HDShaderIDs . _Params1 , paramsA . Item1 ) ;
372+ cmd . SetComputeVectorParam ( bakeCloudTextureCS , HDShaderIDs . _Params2 , paramsA . Item2 ) ;
334373 }
335374 else
336375 {
337- cmd . SetComputeTextureParam ( s_BakeCloudTextureCS , s_BakeCloudTextureKernel , _CloudMapB , cloudLayer . layerB . cloudMap . value ) ;
376+ cmd . SetComputeTextureParam ( bakeCloudTextureCS , bakeCloudTextureKernel , _CloudMapB , cloudLayer . layerB . cloudMap . value ) ;
338377 var paramsB = cloudLayer . layerB . GetBakingParameters ( ) ;
339378
340- s_BakeCloudTextureCS . EnableKeyword ( "USE_SECOND_CLOUD_LAYER" ) ;
379+ bakeCloudTextureCS . EnableKeyword ( "USE_SECOND_CLOUD_LAYER" ) ;
341380 s_VectorArray [ 0 ] = paramsA . Item1 ; s_VectorArray [ 1 ] = paramsB . Item1 ;
342- cmd . SetComputeVectorArrayParam ( s_BakeCloudTextureCS , HDShaderIDs . _Params1 , s_VectorArray ) ;
381+ cmd . SetComputeVectorArrayParam ( bakeCloudTextureCS , HDShaderIDs . _Params1 , s_VectorArray ) ;
343382 s_VectorArray [ 0 ] = paramsA . Item2 ; s_VectorArray [ 1 ] = paramsB . Item2 ;
344- cmd . SetComputeVectorArrayParam ( s_BakeCloudTextureCS , HDShaderIDs . _Params2 , s_VectorArray ) ;
383+ cmd . SetComputeVectorArrayParam ( bakeCloudTextureCS , HDShaderIDs . _Params2 , s_VectorArray ) ;
345384 }
346385
347- cmd . SetComputeFloatParam ( s_BakeCloudTextureCS , HDShaderIDs . _Resolution , 1.0f / cloudTextureWidth ) ;
386+ cmd . SetComputeFloatParam ( bakeCloudTextureCS , HDShaderIDs . _Resolution , 1.0f / cloudTextureWidth ) ;
348387
349388 const int groupSizeX = 8 ;
350389 const int groupSizeY = 8 ;
351390 int threadGroupX = ( cloudTextureWidth + ( groupSizeX - 1 ) ) / groupSizeX ;
352391 int threadGroupY = ( cloudTextureHeight + ( groupSizeY - 1 ) ) / groupSizeY ;
353392
354- cmd . DispatchCompute ( s_BakeCloudTextureCS , s_BakeCloudTextureKernel , threadGroupX , threadGroupY , 1 ) ;
393+ cmd . DispatchCompute ( bakeCloudTextureCS , bakeCloudTextureKernel , threadGroupX , threadGroupY , 1 ) ;
355394
356395 initialized = true ;
357396 return true ;
358397 }
359398
360- public void BakeCloudShadows ( CloudLayer cloudLayer , Light sunLight , HDCamera hdCamera , CommandBuffer cmd )
399+ public void BakeCloudShadows ( CloudLayerRenderer cloudLayerRenderer , CloudLayer cloudLayer , Light sunLight , HDCamera hdCamera , CommandBuffer cmd )
361400 {
362- InitIfNeeded ( cloudLayer , sunLight , hdCamera , cmd ) ;
401+ InitIfNeeded ( cloudLayerRenderer , cloudLayer , sunLight , hdCamera , cmd ) ;
402+
403+ var bakeCloudShadowsCS = cloudLayerRenderer . m_BakeCloudShadowsCS ;
404+ var bakeCloudShadowsKernel = cloudLayerRenderer . m_BakeCloudShadowsKernel ;
405+
363406 Vector4 _Params = cloudLayer . shadowTint . value ;
364407 _Params . w = cloudLayer . shadowMultiplier . value * 8.0f ;
365408
366409 // Parameters
367- cmd . SetComputeFloatParam ( s_BakeCloudShadowsCS , HDShaderIDs . _Resolution , 1.0f / cloudShadowsResolution ) ;
368- cmd . SetComputeVectorParam ( s_BakeCloudShadowsCS , HDShaderIDs . _Params , _Params ) ;
410+ cmd . SetComputeFloatParam ( bakeCloudShadowsCS , HDShaderIDs . _Resolution , 1.0f / cloudShadowsResolution ) ;
411+ cmd . SetComputeVectorParam ( bakeCloudShadowsCS , HDShaderIDs . _Params , _Params ) ;
369412
370- cmd . SetComputeTextureParam ( s_BakeCloudShadowsCS , s_BakeCloudShadowsKernel , _CloudTexture , cloudTextureRT ) ;
371- cmd . SetComputeTextureParam ( s_BakeCloudShadowsCS , s_BakeCloudShadowsKernel , _CloudShadows , cloudShadowsRT ) ;
413+ cmd . SetComputeTextureParam ( bakeCloudShadowsCS , bakeCloudShadowsKernel , _CloudTexture , cloudTextureRT ) ;
414+ cmd . SetComputeTextureParam ( bakeCloudShadowsCS , bakeCloudShadowsKernel , _CloudShadows , cloudShadowsRT ) ;
372415
373416 var _FlowmapParamA = cloudLayer . layerA . GetRenderingParameters ( hdCamera ) ;
374417 var _FlowmapParamB = cloudLayer . layerB . GetRenderingParameters ( hdCamera ) ;
375418 _FlowmapParamA . w = cloudLayer . upperHemisphereOnly . value ? 1 : 0 ;
376419 _FlowmapParamB . w = cloudLayer . opacity . value ;
377420
378421 s_VectorArray [ 0 ] = _FlowmapParamA ; s_VectorArray [ 1 ] = _FlowmapParamB ;
379- cmd . SetComputeVectorArrayParam ( s_BakeCloudShadowsCS , HDShaderIDs . _FlowmapParam , s_VectorArray ) ;
422+ cmd . SetComputeVectorArrayParam ( bakeCloudShadowsCS , HDShaderIDs . _FlowmapParam , s_VectorArray ) ;
380423
381424 s_VectorArray [ 0 ] = sunLight . transform . right ; s_VectorArray [ 1 ] = sunLight . transform . up ;
382425 s_VectorArray [ 0 ] . w = cloudLayer . layerA . altitude . value ; s_VectorArray [ 1 ] . w = cloudLayer . layerB . altitude . value ;
383- cmd . SetComputeVectorArrayParam ( s_BakeCloudShadowsCS , HDShaderIDs . _Params1 , s_VectorArray ) ;
426+ cmd . SetComputeVectorArrayParam ( bakeCloudShadowsCS , HDShaderIDs . _Params1 , s_VectorArray ) ;
384427
385- cmd . SetComputeVectorParam ( s_BakeCloudShadowsCS , HDShaderIDs . _SunDirection , - sunLight . transform . forward ) ;
428+ cmd . SetComputeVectorParam ( bakeCloudShadowsCS , HDShaderIDs . _SunDirection , - sunLight . transform . forward ) ;
386429
387- cmd . SetComputeTextureParam ( s_BakeCloudShadowsCS , s_BakeCloudShadowsKernel , _FlowmapA , cloudLayer . layerA . flowmap . value ) ;
388- cmd . SetComputeTextureParam ( s_BakeCloudShadowsCS , s_BakeCloudShadowsKernel , _FlowmapB , cloudLayer . layerB . flowmap . value ) ;
430+ cmd . SetComputeTextureParam ( bakeCloudShadowsCS , bakeCloudShadowsKernel , _FlowmapA , cloudLayer . layerA . flowmap . value ) ;
431+ cmd . SetComputeTextureParam ( bakeCloudShadowsCS , bakeCloudShadowsKernel , _FlowmapB , cloudLayer . layerB . flowmap . value ) ;
389432
390433 // Keywords
391434 bool enabled1 = cloudLayer . layerA . castShadows . value ;
392435 var mode1 = cloudLayer . layerA . distortionMode . value ;
393- CoreUtils . SetKeyword ( s_BakeCloudShadowsCS , "LAYER1_OFF" , ! enabled1 ) ;
394- CoreUtils . SetKeyword ( s_BakeCloudShadowsCS , "LAYER1_STATIC" , enabled1 && mode1 == CloudDistortionMode . None ) ;
395- CoreUtils . SetKeyword ( s_BakeCloudShadowsCS , "LAYER1_PROCEDURAL" , enabled1 && mode1 == CloudDistortionMode . Procedural ) ;
396- CoreUtils . SetKeyword ( s_BakeCloudShadowsCS , "LAYER1_FLOWMAP" , enabled1 && mode1 == CloudDistortionMode . Flowmap ) ;
436+ CoreUtils . SetKeyword ( bakeCloudShadowsCS , "LAYER1_OFF" , ! enabled1 ) ;
437+ CoreUtils . SetKeyword ( bakeCloudShadowsCS , "LAYER1_STATIC" , enabled1 && mode1 == CloudDistortionMode . None ) ;
438+ CoreUtils . SetKeyword ( bakeCloudShadowsCS , "LAYER1_PROCEDURAL" , enabled1 && mode1 == CloudDistortionMode . Procedural ) ;
439+ CoreUtils . SetKeyword ( bakeCloudShadowsCS , "LAYER1_FLOWMAP" , enabled1 && mode1 == CloudDistortionMode . Flowmap ) ;
397440
398441 bool enabled2 = ( cloudLayer . layers . value == CloudMapMode . Double ) && cloudLayer . layerB . castShadows . value ;
399442 var mode2 = cloudLayer . layerB . distortionMode . value ;
400- CoreUtils . SetKeyword ( s_BakeCloudShadowsCS , "LAYER2_OFF" , ! enabled2 ) ;
401- CoreUtils . SetKeyword ( s_BakeCloudShadowsCS , "LAYER2_STATIC" , enabled2 && mode2 == CloudDistortionMode . None ) ;
402- CoreUtils . SetKeyword ( s_BakeCloudShadowsCS , "LAYER2_PROCEDURAL" , enabled2 && mode2 == CloudDistortionMode . Procedural ) ;
403- CoreUtils . SetKeyword ( s_BakeCloudShadowsCS , "LAYER2_FLOWMAP" , enabled2 && mode2 == CloudDistortionMode . Flowmap ) ;
443+ CoreUtils . SetKeyword ( bakeCloudShadowsCS , "LAYER2_OFF" , ! enabled2 ) ;
444+ CoreUtils . SetKeyword ( bakeCloudShadowsCS , "LAYER2_STATIC" , enabled2 && mode2 == CloudDistortionMode . None ) ;
445+ CoreUtils . SetKeyword ( bakeCloudShadowsCS , "LAYER2_PROCEDURAL" , enabled2 && mode2 == CloudDistortionMode . Procedural ) ;
446+ CoreUtils . SetKeyword ( bakeCloudShadowsCS , "LAYER2_FLOWMAP" , enabled2 && mode2 == CloudDistortionMode . Flowmap ) ;
404447
405448 // Dispatch
406449 const int groupSizeX = 8 ;
407450 const int groupSizeY = 8 ;
408451 int threadGroupX = ( cloudShadowsResolution + ( groupSizeX - 1 ) ) / groupSizeX ;
409452 int threadGroupY = ( cloudShadowsResolution + ( groupSizeY - 1 ) ) / groupSizeY ;
410453
411- cmd . DispatchCompute ( s_BakeCloudShadowsCS , s_BakeCloudShadowsKernel , threadGroupX , threadGroupY , 1 ) ;
454+ cmd . DispatchCompute ( bakeCloudShadowsCS , bakeCloudShadowsKernel , threadGroupX , threadGroupY , 1 ) ;
412455 cloudShadowsRT . rt . IncrementUpdateCount ( ) ;
413456 }
414457 }
415458
416- static PrecomputationCache s_PrecomputationCache = new PrecomputationCache ( ) ;
459+ static PrecomputationCache s_PrecomputationCache = null ;
460+ static PrecomputationCache PrecomputationCacheInstance => s_PrecomputationCache ??= new PrecomputationCache ( ) ;
461+
417462 PrecomputationData m_PrecomputedData ;
463+
464+ #if UNITY_EDITOR
465+ [ RuntimeInitializeOnLoadMethod ( RuntimeInitializeLoadType . SubsystemRegistration ) ]
466+ static void ResetStaticsOnLoad ( )
467+ {
468+ s_PrecomputationCache ? . Clear ( ) ;
469+ s_PrecomputationCache = null ;
470+ }
471+ #endif
418472 }
419473}
0 commit comments