Skip to content

Commit 55e7615

Browse files
jenniferd-unityEvergreen
authored andcommitted
[Port] UUM-116480: Updated SSAO pass to use Raster render passes
1 parent 09b9609 commit 55e7615

3 files changed

Lines changed: 150 additions & 93 deletions

File tree

Packages/com.unity.render-pipelines.universal/Runtime/Passes/ScreenSpaceAmbientOcclusionPass.cs

Lines changed: 138 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)