@@ -67,21 +67,21 @@ private enum ShaderPasses
6767 }
6868
6969 // Structs
70- private struct SSAOMaterialParams
70+ private readonly struct SSAOMaterialParams
7171 {
72- internal bool orthographicCamera ;
73- internal bool aoBlueNoise ;
74- internal bool aoInterleavedGradient ;
75- internal bool sampleCountHigh ;
76- internal bool sampleCountMedium ;
77- internal bool sampleCountLow ;
78- internal bool sourceDepthNormals ;
79- internal bool sourceDepthHigh ;
80- internal bool sourceDepthMedium ;
81- internal bool sourceDepthLow ;
82- internal Vector4 ssaoParams ;
83-
84- internal SSAOMaterialParams ( ref ScreenSpaceAmbientOcclusionSettings settings , bool isOrthographic )
72+ internal readonly bool orthographicCamera ;
73+ internal readonly bool aoBlueNoise ;
74+ internal readonly bool aoInterleavedGradient ;
75+ internal readonly bool sampleCountHigh ;
76+ internal readonly bool sampleCountMedium ;
77+ internal readonly bool sampleCountLow ;
78+ internal readonly bool sourceDepthNormals ;
79+ internal readonly bool sourceDepthHigh ;
80+ internal readonly bool sourceDepthMedium ;
81+ internal readonly bool sourceDepthLow ;
82+ internal readonly Vector4 ssaoParams ;
83+
84+ internal SSAOMaterialParams ( ScreenSpaceAmbientOcclusionSettings settings , bool isOrthographic )
8585 {
8686 bool isUsingDepthNormals = settings . Source == ScreenSpaceAmbientOcclusionSettings . DepthSource . DepthNormals ;
8787 float radiusMultiplier = settings . AOMethod == ScreenSpaceAmbientOcclusionSettings . AOMethodOptions . BlueNoise ? 1.5f : 1 ;
@@ -103,7 +103,7 @@ internal SSAOMaterialParams(ref ScreenSpaceAmbientOcclusionSettings settings, bo
103103 ) ;
104104 }
105105
106- internal bool Equals ( ref SSAOMaterialParams other )
106+ internal bool Equals ( in SSAOMaterialParams other )
107107 {
108108 return orthographicCamera == other . orthographicCamera
109109 && aoBlueNoise == other . aoBlueNoise
@@ -126,7 +126,7 @@ internal ScreenSpaceAmbientOcclusionPass()
126126 m_CurrentSettings = new ScreenSpaceAmbientOcclusionSettings ( ) ;
127127 }
128128
129- internal bool Setup ( ref ScreenSpaceAmbientOcclusionSettings featureSettings , ref ScriptableRenderer renderer , ref Material material , ref Texture2D [ ] blueNoiseTextures )
129+ internal bool Setup ( ScreenSpaceAmbientOcclusionSettings featureSettings , ScriptableRenderer renderer , Material material , Texture2D [ ] blueNoiseTextures )
130130 {
131131 m_BlueNoiseTextures = blueNoiseTextures ;
132132 m_Material = material ;
@@ -135,7 +135,7 @@ internal bool Setup(ref ScreenSpaceAmbientOcclusionSettings featureSettings, ref
135135 // RenderPass Event + Source Settings (Depth / Depth&Normals
136136 if ( renderer is UniversalRenderer { usesDeferredLighting : true } )
137137 {
138- renderPassEvent = m_CurrentSettings . AfterOpaque ? RenderPassEvent . AfterRenderingOpaques : RenderPassEvent . AfterRenderingGbuffer ;
138+ renderPassEvent = m_CurrentSettings . AfterOpaque ? RenderPassEvent . AfterRenderingOpaques : RenderPassEvent . AfterRenderingPrePasses ;
139139
140140 m_CurrentSettings . Source = ScreenSpaceAmbientOcclusionSettings . DepthSource . DepthNormals ;
141141 }
@@ -243,8 +243,8 @@ private void SetupKeywordsAndParameters(ref ScreenSpaceAmbientOcclusionSettings
243243
244244 // Setting keywords can be somewhat expensive on low-end platforms.
245245 // Previous params are cached to avoid setting the same keywords every frame.
246- SSAOMaterialParams matParams = new SSAOMaterialParams ( ref settings , cameraData . camera . orthographic ) ;
247- bool ssaoParamsDirty = ! m_SSAOParamsPrev . Equals ( ref matParams ) ; // Checks if the parameters have changed.
246+ SSAOMaterialParams matParams = new SSAOMaterialParams ( settings , cameraData . camera . orthographic ) ;
247+ bool ssaoParamsDirty = ! m_SSAOParamsPrev . Equals ( in matParams ) ; // Checks if the parameters have changed.
248248 bool isParamsPropertySet = m_Material . HasProperty ( s_SSAOParamsID ) ; // Checks if the parameters have been set on the material.
249249 if ( ! ssaoParamsDirty && isParamsPropertySet )
250250 return ;
@@ -271,6 +271,7 @@ private class SSAOPassData
271271 {
272272 internal bool afterOpaque ;
273273 internal ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions BlurQuality ;
274+ internal MaterialPropertyBlock materialPropertyBlock ;
274275 internal Material material ;
275276 internal float directLightingStrength ;
276277 internal TextureHandle cameraColor ;
@@ -281,35 +282,92 @@ private class SSAOPassData
281282 internal UniversalCameraData cameraData ;
282283 }
283284
284- private void InitSSAOPassData ( ref SSAOPassData data )
285+ private class SSAOBlurPassData
286+ {
287+ internal TextureHandle srcTexture ;
288+ internal TextureHandle dstTexture ;
289+ internal MaterialPropertyBlock materialPropertyBlock ;
290+ internal Material material ;
291+ internal UniversalCameraData cameraData ;
292+ internal int pass ;
293+ internal ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions BlurQuality ;
294+ internal bool afterOpaque ;
295+ }
296+
297+ private class SSAOFinalPassData
298+ {
299+ internal float directLightingStrength ;
300+ }
301+
302+ private void InitSSAOPassData ( SSAOPassData data )
285303 {
286304 data . material = m_Material ;
287305 data . BlurQuality = m_CurrentSettings . BlurQuality ;
288306 data . afterOpaque = m_CurrentSettings . AfterOpaque ;
289307 data . directLightingStrength = m_CurrentSettings . DirectLightingStrength ;
290308 }
291309
292- private static Vector4 ComputeScaleBias ( in UnsafeGraphContext context , in TextureHandle source , in TextureHandle destination )
310+ private void InitSSAOBlurPassData ( SSAOBlurPassData data )
311+ {
312+ data . material = m_Material ;
313+ data . BlurQuality = m_CurrentSettings . BlurQuality ;
314+ data . afterOpaque = m_CurrentSettings . AfterOpaque ;
315+ }
316+
317+ private static Vector4 ComputeScaleBias ( in TextureHandle source , bool yFlip )
293318 {
294319 RTHandle srcRTHandle = source ;
295320 Vector2 viewportScale ;
296321 if ( srcRTHandle is { useScaling : true } )
297322 {
298- viewportScale . x = srcRTHandle . rtHandleProperties . rtHandleScale . x ;
299- viewportScale . y = srcRTHandle . rtHandleProperties . rtHandleScale . y ;
323+ var scale = srcRTHandle . rtHandleProperties . rtHandleScale ;
324+ viewportScale . x = scale . x ;
325+ viewportScale . y = scale . y ;
300326 }
301327 else
302328 {
303329 viewportScale = Vector2 . one ;
304330 }
305331
306- bool yFlip = context . GetTextureUVOrigin ( in source ) != context . GetTextureUVOrigin ( in destination ) ;
307332 if ( yFlip )
308333 return new Vector4 ( viewportScale . x , - viewportScale . y , 0 , viewportScale . y ) ;
309334 else
310335 return new Vector4 ( viewportScale . x , viewportScale . y , 0 , 0 ) ;
311336 }
312337
338+ private static readonly int _BlitScaleBias = Shader . PropertyToID ( nameof ( _BlitScaleBias ) ) ;
339+ private static readonly int _BlitTexture = Shader . PropertyToID ( nameof ( _BlitTexture ) ) ;
340+
341+ private void RecordBlurStep ( RenderGraph renderGraph , UniversalCameraData cameraData , string blurPassName , in TextureHandle src , in TextureHandle dst , int pass , bool isLastPass )
342+ {
343+ using ( var builder = renderGraph . AddRasterRenderPass < SSAOBlurPassData > ( blurPassName , out var passData , m_ProfilingSampler ) )
344+ {
345+ // Fill in the Pass data...
346+ InitSSAOBlurPassData ( passData ) ;
347+ passData . srcTexture = src ;
348+ passData . dstTexture = dst ;
349+ passData . cameraData = cameraData ;
350+ passData . pass = pass ;
351+ passData . materialPropertyBlock ??= new ( ) ;
352+
353+ builder . UseTexture ( passData . srcTexture ) ;
354+
355+ AccessFlags finalDstAccess = passData . afterOpaque && isLastPass ? AccessFlags . Write : AccessFlags . WriteAll ;
356+ builder . SetRenderAttachment ( passData . dstTexture , 0 , finalDstAccess ) ;
357+
358+ builder . SetRenderFunc ( static ( SSAOBlurPassData data , RasterGraphContext ctx ) =>
359+ {
360+ bool yFlip = ctx . GetTextureUVOrigin ( in data . srcTexture ) != ctx . GetTextureUVOrigin ( in data . dstTexture ) ;
361+ Vector4 viewScaleBias = ComputeScaleBias ( data . srcTexture , yFlip ) ;
362+
363+ data . materialPropertyBlock . Clear ( ) ;
364+ data . materialPropertyBlock . SetVector ( _BlitScaleBias , viewScaleBias ) ;
365+ data . materialPropertyBlock . SetTexture ( _BlitTexture , data . srcTexture ) ;
366+ CoreUtils . DrawFullScreen ( ctx . cmd , data . material , data . materialPropertyBlock , data . pass ) ;
367+ } ) ;
368+ }
369+ }
370+
313371 /// <inheritdoc cref="IRenderGraphRecorder.RecordRenderGraph"/>
314372 public override void RecordRenderGraph ( RenderGraph renderGraph , ContextContainer frameData )
315373 {
@@ -331,31 +389,29 @@ public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer
331389 // Update keywords and other shader params
332390 SetupKeywordsAndParameters ( ref m_CurrentSettings , ref cameraData ) ;
333391
334- using ( IUnsafeRenderGraphBuilder builder = renderGraph . AddUnsafePass < SSAOPassData > ( "Blit SSAO" , out var passData , m_ProfilingSampler ) )
392+ using ( var builder = renderGraph . AddRasterRenderPass < SSAOPassData > ( "Blit SSAO" , out var passData , m_ProfilingSampler ) )
335393 {
336394 // Shader keyword changes are considered as global state modifications
337395 builder . AllowGlobalStateModification ( true ) ;
338396
339397 // Fill in the Pass data...
340- InitSSAOPassData ( ref passData ) ;
398+ InitSSAOPassData ( passData ) ;
341399 passData . cameraColor = resourceData . cameraColor ;
342400 passData . AOTexture = aoTexture ;
343401 passData . finalTexture = finalTexture ;
344402 passData . blurTexture = blurTexture ;
345403 passData . cameraData = cameraData ;
404+ passData . materialPropertyBlock ??= new ( ) ;
346405
347406 // Declare input textures
348- builder . UseTexture ( passData . AOTexture , AccessFlags . ReadWrite ) ;
407+ builder . SetRenderAttachment ( passData . AOTexture , 0 , AccessFlags . WriteAll ) ;
349408
350409 // TODO: Refactor to eliminate the need for 'UseTexture'.
351410 // Currently required only because 'PostProcessUtils.SetSourceSize' allocates an RTHandle,
352411 // which expects a valid graphicsResource. Without this call, 'cameraColor.graphicsResource'
353412 // may be null if it wasn't initialized in an earlier pass (e.g., DrawOpaque).
354- if ( resourceData . cameraColor . IsValid ( ) )
355- builder . UseTexture ( resourceData . cameraColor , AccessFlags . Read ) ;
356-
357- if ( passData . BlurQuality != ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions . Low )
358- builder . UseTexture ( passData . blurTexture , AccessFlags . ReadWrite ) ;
413+ if ( passData . cameraColor . IsValid ( ) )
414+ builder . UseTexture ( passData . cameraColor , AccessFlags . Read ) ;
359415
360416 if ( cameraDepthTexture . IsValid ( ) )
361417 builder . UseTexture ( cameraDepthTexture , AccessFlags . Read ) ;
@@ -366,64 +422,64 @@ public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer
366422 passData . cameraNormalsTexture = cameraNormalsTexture ;
367423 }
368424
369- // The global SSAO texture only needs to be set if After Opaque is disabled...
370- if ( ! passData . afterOpaque && finalTexture . IsValid ( ) )
425+ builder . SetRenderFunc ( static ( SSAOPassData data , RasterGraphContext ctx ) =>
371426 {
372- builder . UseTexture ( passData . finalTexture , AccessFlags . Write ) ;
373- builder . SetGlobalTextureAfterPass ( finalTexture , s_SSAOFinalTextureID ) ;
374- }
375-
376- builder . SetRenderFunc ( static ( SSAOPassData data , UnsafeGraphContext rgContext ) =>
377- {
378- CommandBuffer cmd = CommandBufferHelpers . GetNativeCommandBuffer ( rgContext . cmd ) ;
379- RenderBufferLoadAction finalLoadAction = data . afterOpaque ? RenderBufferLoadAction . Load : RenderBufferLoadAction . DontCare ;
380-
381427 // Setup
382- PostProcessUtils . SetGlobalShaderSourceSize ( cmd , data . cameraData . cameraTargetDescriptor . width , data . cameraData . cameraTargetDescriptor . height , data . cameraColor ) ;
428+ PostProcessUtils . SetGlobalShaderSourceSize ( ctx . cmd , data . cameraData . cameraTargetDescriptor . width , data . cameraData . cameraTargetDescriptor . height , data . cameraColor ) ;
429+
430+ data . materialPropertyBlock . Clear ( ) ;
383431
384432 if ( data . cameraNormalsTexture . IsValid ( ) )
385- data . material . SetTexture ( s_CameraNormalsTextureID , data . cameraNormalsTexture ) ;
433+ data . materialPropertyBlock . SetTexture ( s_CameraNormalsTextureID , data . cameraNormalsTexture ) ;
386434
387- // AO Pass
388- Blitter . BlitCameraTexture ( cmd , data . AOTexture , data . AOTexture , RenderBufferLoadAction . DontCare , RenderBufferStoreAction . Store , data . material , ( int ) ShaderPasses . AmbientOcclusion ) ;
435+ Vector4 viewScaleBias = new ( 1 , 1 , 0 , 0 ) ;
436+ data . materialPropertyBlock . SetVector ( _BlitScaleBias , viewScaleBias ) ;
389437
390- // Blur passes
391- Vector4 viewScaleBias ;
392- switch ( data . BlurQuality )
393- {
394- // Bilateral
395- case ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions . High :
396- Blitter . BlitCameraTexture ( cmd , data . AOTexture , data . blurTexture , RenderBufferLoadAction . DontCare , RenderBufferStoreAction . Store , data . material , ( int ) ShaderPasses . BilateralBlurHorizontal ) ;
397- Blitter . BlitCameraTexture ( cmd , data . blurTexture , data . AOTexture , RenderBufferLoadAction . DontCare , RenderBufferStoreAction . Store , data . material , ( int ) ShaderPasses . BilateralBlurVertical ) ;
398- viewScaleBias = ComputeScaleBias ( in rgContext , in data . AOTexture , in data . finalTexture ) ;
399- Blitter . BlitCameraTexture ( cmd , data . AOTexture , data . finalTexture , viewScaleBias , finalLoadAction , RenderBufferStoreAction . Store , data . material , ( int ) ( data . afterOpaque ? ShaderPasses . BilateralAfterOpaque : ShaderPasses . BilateralBlurFinal ) ) ;
400- break ;
401-
402- // Gaussian
403- case ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions . Medium :
404- Blitter . BlitCameraTexture ( cmd , data . AOTexture , data . blurTexture , RenderBufferLoadAction . Load , RenderBufferStoreAction . Store , data . material , ( int ) ShaderPasses . GaussianBlurHorizontal ) ;
405- viewScaleBias = ComputeScaleBias ( in rgContext , in data . blurTexture , in data . finalTexture ) ;
406- Blitter . BlitCameraTexture ( cmd , data . blurTexture , data . finalTexture , viewScaleBias , finalLoadAction , RenderBufferStoreAction . Store , data . material , ( int ) ( data . afterOpaque ? ShaderPasses . GaussianAfterOpaque : ShaderPasses . GaussianBlurVertical ) ) ;
407- break ;
408-
409- // Kawase
410- case ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions . Low :
411- viewScaleBias = ComputeScaleBias ( in rgContext , in data . AOTexture , in data . finalTexture ) ;
412- Blitter . BlitCameraTexture ( cmd , data . AOTexture , data . finalTexture , viewScaleBias , finalLoadAction , RenderBufferStoreAction . Store , data . material , ( int ) ( data . afterOpaque ? ShaderPasses . KawaseAfterOpaque : ShaderPasses . KawaseBlur ) ) ;
413- break ;
414-
415- default :
416- throw new ArgumentOutOfRangeException ( ) ;
417- }
418-
419- // We only want URP shaders to sample SSAO if After Opaque is disabled...
420- if ( ! data . afterOpaque )
421- {
422- rgContext . cmd . SetKeyword ( ShaderGlobalKeywords . ScreenSpaceOcclusion , true ) ;
423- rgContext . cmd . SetGlobalVector ( s_AmbientOcclusionParamID , new Vector4 ( 1f , 0f , 0f , data . directLightingStrength ) ) ;
424- }
438+ CoreUtils . DrawFullScreen ( ctx . cmd , data . material , data . materialPropertyBlock , ( int ) ShaderPasses . AmbientOcclusion ) ;
425439 } ) ;
426440 }
441+
442+ switch ( m_CurrentSettings . BlurQuality )
443+ {
444+ case ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions . High :
445+ RecordBlurStep ( renderGraph , cameraData , "Blur SSAO Horizontal (High)" , aoTexture , blurTexture , ( int ) ShaderPasses . BilateralBlurHorizontal , false ) ;
446+ RecordBlurStep ( renderGraph , cameraData , "Blur SSAO Vertical (High)" , blurTexture , aoTexture , ( int ) ShaderPasses . BilateralBlurVertical , false ) ;
447+ RecordBlurStep ( renderGraph , cameraData , "Blur SSAO Final (High)" , aoTexture , finalTexture , ( int ) ( m_CurrentSettings . AfterOpaque ? ShaderPasses . BilateralAfterOpaque : ShaderPasses . BilateralBlurFinal ) , true ) ;
448+ break ;
449+ case ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions . Medium :
450+ RecordBlurStep ( renderGraph , cameraData , "Blur SSAO Horizontal (Medium)" , aoTexture , blurTexture , ( int ) ShaderPasses . GaussianBlurHorizontal , false ) ;
451+ RecordBlurStep ( renderGraph , cameraData , "Blur SSAO Final (Medium)" , blurTexture , finalTexture , ( int ) ( m_CurrentSettings . AfterOpaque ? ShaderPasses . GaussianAfterOpaque : ShaderPasses . GaussianBlurVertical ) , true ) ;
452+ break ;
453+ case ScreenSpaceAmbientOcclusionSettings . BlurQualityOptions . Low :
454+ RecordBlurStep ( renderGraph , cameraData , "Blur SSAO (Low)" , aoTexture , finalTexture , ( int ) ( m_CurrentSettings . AfterOpaque ? ShaderPasses . KawaseAfterOpaque : ShaderPasses . KawaseBlur ) , true ) ;
455+ break ;
456+ default :
457+ throw new ArgumentOutOfRangeException ( ) ;
458+ }
459+
460+ if ( ! m_CurrentSettings . AfterOpaque )
461+ {
462+ // Add cleanup pass to:
463+ // - Set global keywords for next passes
464+ // - Set global texture as there is a limitation in Render Graph where an input texture cannot be set as a global texture after the pass runs
465+ // A Raster pass is used so it can be merged easily with the blur passes.
466+ using ( var builder = renderGraph . AddRasterRenderPass < SSAOFinalPassData > ( "Cleanup SSAO" , out var passData , m_ProfilingSampler ) )
467+ {
468+ passData . directLightingStrength = m_CurrentSettings . DirectLightingStrength ;
469+
470+ builder . AllowGlobalStateModification ( true ) ;
471+
472+ builder . UseTexture ( finalTexture , AccessFlags . Read ) ;
473+ builder . SetGlobalTextureAfterPass ( finalTexture , s_SSAOFinalTextureID ) ;
474+
475+ builder . SetRenderFunc ( static ( SSAOFinalPassData data , RasterGraphContext ctx ) =>
476+ {
477+ // We only want URP shaders to sample SSAO if After Opaque is disabled...
478+ ctx . cmd . SetKeyword ( ShaderGlobalKeywords . ScreenSpaceOcclusion , true ) ;
479+ ctx . cmd . SetGlobalVector ( s_AmbientOcclusionParamID , new Vector4 ( 1f , 0f , 0f , data . directLightingStrength ) ) ;
480+ } ) ;
481+ }
482+ }
427483 }
428484
429485 private void CreateRenderTextureHandles ( RenderGraph renderGraph , UniversalResourceData resourceData ,
0 commit comments