Skip to content

Commit 02100d2

Browse files
jmekhEvergreen
authored andcommitted
[HDRP] Simplifying Screen Space Reflection and adding missing fence when async
This PR applies multiple fixes to HDRP Screen Space Reflection: - It removes the SSR lighting texture by reusing the SSR accumulation texture - It adds a fence before async work, so they wait for resources to be cleared when it reuses pooled resources. This fixes flickering on some platform where graphics and async command buffer are more sensitive to missing fences. - It changes the hit point texture and lighting texture clears to be async if the pass is async. Due to the new fence, it couldn't overlap with shadow rendering, but moving the clear to the same queue as the rest of the work, is more optimized and has no fence.
1 parent 66d1d7c commit 02100d2

File tree

5 files changed

+57
-44
lines changed

5 files changed

+57
-44
lines changed

Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2205,12 +2205,13 @@ void PreRenderPassExecute(in CompiledPassInfo passInfo, RenderGraphPass pass, In
22052205
{
22062206
// Need to save the command buffer to restore it later as the one in the context can changed if running a pass async.
22072207
m_PreviousCommandBuffer = rgContext.cmd;
2208-
2208+
2209+
bool executedWorkDuringResourceCreation = false;
22092210
for (int type = 0; type < (int)RenderGraphResourceType.Count; ++type)
22102211
{
22112212
foreach (int resource in passInfo.resourceCreateList[type])
22122213
{
2213-
m_Resources.CreatePooledResource(rgContext, type, resource);
2214+
executedWorkDuringResourceCreation |= m_Resources.CreatePooledResource(rgContext, type, resource);
22142215
}
22152216
}
22162217

@@ -2221,6 +2222,12 @@ void PreRenderPassExecute(in CompiledPassInfo passInfo, RenderGraphPass pass, In
22212222

22222223
if (passInfo.enableAsyncCompute)
22232224
{
2225+
GraphicsFence previousFence = new GraphicsFence();
2226+
if (executedWorkDuringResourceCreation)
2227+
{
2228+
previousFence = rgContext.cmd.CreateGraphicsFence(GraphicsFenceType.AsyncQueueSynchronisation, SynchronisationStageFlags.AllGPUOperations);
2229+
}
2230+
22242231
// Flush current command buffer on the render context before enqueuing async commands.
22252232
if (rgContext.contextlessTesting == false)
22262233
rgContext.renderContext.ExecuteCommandBuffer(rgContext.cmd);
@@ -2229,6 +2236,11 @@ void PreRenderPassExecute(in CompiledPassInfo passInfo, RenderGraphPass pass, In
22292236
CommandBuffer asyncCmd = CommandBufferPool.Get(pass.name);
22302237
asyncCmd.SetExecutionFlags(CommandBufferExecutionFlags.AsyncCompute);
22312238
rgContext.cmd = asyncCmd;
2239+
2240+
if (executedWorkDuringResourceCreation)
2241+
{
2242+
rgContext.cmd.WaitOnAsyncGraphicsFence(previousFence);
2243+
}
22322244
}
22332245

22342246
// Synchronize with graphics or compute pipe if needed.

Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceRegistry.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,16 @@ internal static RenderGraphResourceRegistry current
9191
m_CurrentRegistry = value;
9292
}
9393
}
94-
94+
95+
delegate bool ResourceCreateCallback(InternalRenderGraphContext rgContext, IRenderGraphResource res);
9596
delegate void ResourceCallback(InternalRenderGraphContext rgContext, IRenderGraphResource res);
9697

9798
class RenderGraphResourcesData
9899
{
99100
public DynamicArray<IRenderGraphResource> resourceArray = new DynamicArray<IRenderGraphResource>();
100101
public int sharedResourcesCount;
101102
public IRenderGraphResourcePool pool;
102-
public ResourceCallback createResourceCallback;
103+
public ResourceCreateCallback createResourceCallback;
103104
public ResourceCallback releaseResourceCallback;
104105

105106
public RenderGraphResourcesData()
@@ -1012,10 +1013,11 @@ void ManageSharedRenderGraphResources()
10121013
}
10131014
}
10141015

1015-
internal void CreatePooledResource(InternalRenderGraphContext rgContext, int type, int index)
1016+
internal bool CreatePooledResource(InternalRenderGraphContext rgContext, int type, int index)
10161017
{
10171018
Debug.Assert(index != 0, "Index 0 indicates the null object it can't be used here");
10181019

1020+
bool? executedWork = false;
10191021
var resource = m_RenderGraphResources[type].resourceArray[index];
10201022
if (!resource.imported)
10211023
{
@@ -1024,20 +1026,22 @@ internal void CreatePooledResource(InternalRenderGraphContext rgContext, int typ
10241026
if (m_RenderGraphDebug.enableLogging)
10251027
resource.LogCreation(m_FrameInformationLogger);
10261028

1027-
m_RenderGraphResources[type].createResourceCallback?.Invoke(rgContext, resource);
1029+
executedWork = m_RenderGraphResources[type].createResourceCallback?.Invoke(rgContext, resource);
10281030
}
1031+
1032+
return executedWork ?? false;
10291033
}
10301034

10311035
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1032-
internal void CreatePooledResource(InternalRenderGraphContext rgContext, in ResourceHandle handle)
1036+
internal bool CreatePooledResource(InternalRenderGraphContext rgContext, in ResourceHandle handle)
10331037
{
1034-
CreatePooledResource(rgContext, handle.iType, handle.index);
1038+
return CreatePooledResource(rgContext, handle.iType, handle.index);
10351039
}
10361040

10371041
// Only modified by native compiler when using native render pass
10381042
internal bool forceManualClearOfResource = true;
10391043

1040-
void CreateTextureCallback(InternalRenderGraphContext rgContext, IRenderGraphResource res)
1044+
bool CreateTextureCallback(InternalRenderGraphContext rgContext, IRenderGraphResource res)
10411045
{
10421046
var resource = res as TextureResource;
10431047

@@ -1049,13 +1053,16 @@ void CreateTextureCallback(InternalRenderGraphContext rgContext, IRenderGraphRes
10491053
}
10501054
#endif
10511055

1056+
bool executedWork = false;
10521057
if ((forceManualClearOfResource && resource.desc.clearBuffer) || m_RenderGraphDebug.clearRenderTargetsAtCreation)
10531058
{
10541059
bool debugClear = m_RenderGraphDebug.clearRenderTargetsAtCreation && !resource.desc.clearBuffer;
10551060
var clearFlag = resource.desc.depthBufferBits != DepthBits.None ? ClearFlag.DepthStencil : ClearFlag.Color;
10561061
var clearColor = debugClear ? Color.magenta : resource.desc.clearColor;
10571062
CoreUtils.SetRenderTarget(rgContext.cmd, resource.graphicsResource, clearFlag, clearColor);
1063+
executedWork = true;
10581064
}
1065+
return executedWork;
10591066
}
10601067

10611068
internal void ReleasePooledResource(InternalRenderGraphContext rgContext, int type, int index)

Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/ScreenSpaceReflections.compute

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ TEXTURE2D_X(_DepthTexture);
101101
#else //if defined(SSR_ACCUMULATE)
102102
TEXTURE2D_X( _SsrHitPointTexture);
103103
RW_TEXTURE2D_X(float4, _SsrAccumPrev);
104-
RW_TEXTURE2D_X(float4, _SsrLightingTextureRW);
105104
RW_TEXTURE2D_X(float4, _SSRAccumTexture);
106105
#endif
107106

@@ -835,7 +834,6 @@ void MAIN_ACC(uint3 dispatchThreadId : SV_DispatchThreadID)
835834
result.rgb = isPosFin ? result.rgb : 0;
836835
result.w = isPosFin ? result.w : 0;
837836

838-
_SsrLightingTextureRW[COORD_TEXTURE2D_X(positionSS)] = result;
839837
_SSRAccumTexture[COORD_TEXTURE2D_X(positionSS)] = result;
840838
}
841839

Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,6 @@ class RenderSSRPassData
975975

976976
public bool transparentSSR;
977977
public bool usePBRAlgo;
978-
public bool accumNeedClear;
979978
public bool previousAccumNeedClear;
980979
public bool validColorPyramid;
981980

@@ -993,7 +992,6 @@ class RenderSSRPassData
993992
public TextureHandle stencilBuffer;
994993
public TextureHandle hitPointsTexture;
995994
public TextureHandle ssrAccum;
996-
public TextureHandle lightingTexture;
997995
public TextureHandle ssrAccumPrev;
998996
public TextureHandle clearCoatMask;
999997

@@ -1027,7 +1025,7 @@ static void ClearColorBuffer2D(RenderSSRPassData data, CommandBuffer cmd, Textur
10271025
}
10281026
else
10291027
{
1030-
cmd.SetComputeTextureParam(data.clearBuffer2DCS, data.clearBuffer2DKernel, HDShaderIDs._Buffer2D, data.ssrAccum);
1028+
cmd.SetComputeTextureParam(data.clearBuffer2DCS, data.clearBuffer2DKernel, HDShaderIDs._Buffer2D, rt);
10311029
cmd.SetComputeVectorParam(data.clearBuffer2DCS, HDShaderIDs._ClearValue, clearColor);
10321030
cmd.SetComputeVectorParam(data.clearBuffer2DCS, HDShaderIDs._BufferSize, new Vector4((float)data.width, (float)data.height, 0.0f, 0.0f));
10331031
cmd.DispatchCompute(data.clearBuffer2DCS, data.clearBuffer2DKernel, HDUtils.DivRoundUp(data.width, 8), HDUtils.DivRoundUp(data.height, 8), data.viewCount);
@@ -1128,12 +1126,12 @@ TextureHandle RenderSSR(RenderGraph renderGraph,
11281126
bool useAsync = hdCamera.frameSettings.SSRRunsAsync() && !transparent;
11291127
builder.EnableAsyncCompute(useAsync);
11301128

1131-
hdCamera.AllocateScreenSpaceAccumulationHistoryBuffer(1.0f);
1132-
11331129
bool usePBRAlgo = !transparent && settings.usedAlgorithm.value == ScreenSpaceReflectionAlgorithm.PBRAccumulation;
11341130
var colorPyramid = renderGraph.ImportTexture(colorPyramidRT);
11351131
var volumeSettings = hdCamera.volumeStack.GetComponent<ScreenSpaceReflection>();
11361132

1133+
hdCamera.AllocateScreenSpaceAccumulationHistoryBuffer(1.0f);
1134+
11371135
UpdateSSRConstantBuffer(hdCamera, volumeSettings, transparent, ref passData.cb);
11381136

11391137
passData.hdCamera = hdCamera;
@@ -1167,8 +1165,7 @@ TextureHandle RenderSSR(RenderGraph renderGraph,
11671165
passData.height = hdCamera.actualHeight;
11681166
passData.viewCount = hdCamera.viewCount;
11691167
passData.offsetBufferData = hdCamera.depthBufferMipChainInfo.GetOffsetBufferData(m_DepthPyramidMipLevelOffsetsBuffer);
1170-
passData.accumNeedClear = usePBRAlgo;
1171-
passData.previousAccumNeedClear = usePBRAlgo && (hdCamera.currentSSRAlgorithm == ScreenSpaceReflectionAlgorithm.Approximation || hdCamera.isFirstFrame || hdCamera.resetPostProcessingHistory);
1168+
passData.previousAccumNeedClear = usePBRAlgo && (hdCamera.isFirstFrame || hdCamera.resetPostProcessingHistory);
11721169
hdCamera.currentSSRAlgorithm = volumeSettings.usedAlgorithm.value; // Store for next frame comparison
11731170
passData.validColorPyramid = hdCamera.colorPyramidHistoryValidFrames > 1;
11741171

@@ -1204,42 +1201,45 @@ TextureHandle RenderSSR(RenderGraph renderGraph,
12041201
// In practice, these textures are sparse (mostly black). Therefore, clearing them is fast (due to CMASK),
12051202
// and much faster than fully overwriting them from within SSR shaders.
12061203
passData.hitPointsTexture = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true)
1207-
{ colorFormat = GraphicsFormat.R16G16_UNorm, clearBuffer = true, clearColor = Color.clear, enableRandomWrite = true, name = transparent ? "SSR_Hit_Point_Texture_Trans" : "SSR_Hit_Point_Texture" });
1204+
{ colorFormat = GraphicsFormat.R16G16_UNorm, clearBuffer = !useAsync, clearColor = Color.clear, enableRandomWrite = true, name = transparent ? "SSR_Hit_Point_Texture_Trans" : "SSR_Hit_Point_Texture" });
12081205

12091206
if (usePBRAlgo)
12101207
{
12111208
passData.ssrAccum = builder.WriteTexture(renderGraph.ImportTexture(hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.ScreenSpaceReflectionAccumulation)));
12121209
passData.ssrAccumPrev = builder.WriteTexture(renderGraph.ImportTexture(hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.ScreenSpaceReflectionAccumulation)));
1213-
passData.lightingTexture = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true)
1214-
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.clear, enableRandomWrite = true, name = "SSR_Lighting_Texture" });
12151210
}
12161211
else
12171212
{
1218-
passData.lightingTexture = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
1219-
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.clear, enableRandomWrite = true, name = "SSR_Lighting_Texture" }));
1213+
passData.ssrAccum = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
1214+
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = !useAsync, clearColor = Color.clear, enableRandomWrite = true, name = "SSR_Lighting_Texture" }));
12201215
}
12211216

12221217
builder.SetRenderFunc(
12231218
(RenderSSRPassData data, RenderGraphContext ctx) =>
12241219
{
12251220
var cs = data.ssrCS;
12261221

1227-
if (!data.usePBRAlgo)
1228-
ctx.cmd.EnableShaderKeyword("SSR_APPROX");
1229-
else
1222+
CoreUtils.SetKeyword(ctx.cmd, "SSR_APPROX", !data.usePBRAlgo);
1223+
CoreUtils.SetKeyword(ctx.cmd, "DEPTH_SOURCE_NOT_FROM_MIP_CHAIN", data.transparentSSR);
1224+
1225+
if (data.usePBRAlgo)
12301226
{
1231-
if (data.accumNeedClear || data.debugDisplaySpeed)
1232-
ClearColorBuffer2D(data, ctx.cmd, data.ssrAccum, Color.clear, data.useAsync);
1227+
ClearColorBuffer2D(data, ctx.cmd, data.ssrAccum, Color.clear, data.useAsync);
1228+
12331229
if (data.previousAccumNeedClear || data.debugDisplaySpeed)
12341230
ClearColorBuffer2D(data, ctx.cmd, data.ssrAccumPrev, Color.clear, data.useAsync);
1235-
1236-
ctx.cmd.DisableShaderKeyword("SSR_APPROX");
1231+
}
1232+
else if (data.useAsync)
1233+
{
1234+
// If the pass is synchronous, clear is done when the accumulation texture is created
1235+
ClearColorBuffer2D(data, ctx.cmd, data.ssrAccum, Color.clear, data.useAsync);
12371236
}
12381237

1239-
if (data.transparentSSR)
1240-
ctx.cmd.EnableShaderKeyword("DEPTH_SOURCE_NOT_FROM_MIP_CHAIN");
1241-
else
1242-
ctx.cmd.DisableShaderKeyword("DEPTH_SOURCE_NOT_FROM_MIP_CHAIN");
1238+
if (data.useAsync)
1239+
{
1240+
// If the pass is synchronous, clear is done when the hit point texture is created
1241+
ClearColorBuffer2D(data, ctx.cmd, data.hitPointsTexture, Color.clear, data.useAsync);
1242+
}
12431243

12441244
using (new ProfilingScope(ctx.cmd, ProfilingSampler.Get(HDProfileId.SsrTracing)))
12451245
{
@@ -1276,7 +1276,7 @@ TextureHandle RenderSSR(RenderGraph renderGraph,
12761276
ctx.cmd.SetComputeTextureParam(cs, data.reprojectionKernel, HDShaderIDs._ColorPyramidTexture, data.colorPyramid);
12771277
ctx.cmd.SetComputeTextureParam(cs, data.reprojectionKernel, HDShaderIDs._NormalBufferTexture, data.normalBuffer);
12781278
ctx.cmd.SetComputeTextureParam(cs, data.reprojectionKernel, HDShaderIDs._SsrHitPointTexture, data.hitPointsTexture);
1279-
ctx.cmd.SetComputeTextureParam(cs, data.reprojectionKernel, HDShaderIDs._SSRAccumTexture, data.usePBRAlgo ? data.ssrAccum : data.lightingTexture);
1279+
ctx.cmd.SetComputeTextureParam(cs, data.reprojectionKernel, HDShaderIDs._SSRAccumTexture, data.ssrAccum);
12801280
ctx.cmd.SetComputeTextureParam(cs, data.reprojectionKernel, HDShaderIDs._SsrClearCoatMaskTexture, data.clearCoatMask);
12811281
ctx.cmd.SetComputeTextureParam(cs, data.reprojectionKernel, HDShaderIDs._CameraMotionVectorsTexture, data.motionVectorsBuffer);
12821282

@@ -1370,7 +1370,6 @@ TextureHandle RenderSSR(RenderGraph renderGraph,
13701370
ctx.cmd.SetComputeTextureParam(cs, pass, HDShaderIDs._ColorPyramidTexture, data.colorPyramid);
13711371
ctx.cmd.SetComputeTextureParam(cs, pass, HDShaderIDs._SsrHitPointTexture, data.hitPointsTexture);
13721372
ctx.cmd.SetComputeTextureParam(cs, pass, HDShaderIDs._SSRAccumTexture, data.ssrAccum);
1373-
ctx.cmd.SetComputeTextureParam(cs, pass, HDShaderIDs._SsrLightingTextureRW, data.lightingTexture);
13741373
ctx.cmd.SetComputeTextureParam(cs, pass, HDShaderIDs._SsrAccumPrev, data.ssrAccumPrev);
13751374
ctx.cmd.SetComputeTextureParam(cs, pass, HDShaderIDs._SsrClearCoatMaskTexture, data.clearCoatMask);
13761375
ctx.cmd.SetComputeTextureParam(cs, pass, HDShaderIDs._CameraMotionVectorsTexture, data.motionVectorsBuffer);
@@ -1388,17 +1387,13 @@ TextureHandle RenderSSR(RenderGraph renderGraph,
13881387

13891388
if (usePBRAlgo)
13901389
{
1391-
result = passData.ssrAccum;
1392-
13931390
PushFullScreenDebugTexture(renderGraph, passData.ssrAccum, FullScreenDebugMode.ScreenSpaceReflectionsAccum);
13941391
PushFullScreenDebugTexture(renderGraph, passData.ssrAccumPrev, FullScreenDebugMode.ScreenSpaceReflectionsPrev);
1395-
PushFullScreenDebugTexture(renderGraph, passData.ssrAccum, FullScreenDebugMode.ScreenSpaceReflectionSpeedRejection);
1396-
}
1397-
else
1398-
{
1399-
result = passData.lightingTexture;
1400-
PushFullScreenDebugTexture(renderGraph, result, FullScreenDebugMode.ScreenSpaceReflectionSpeedRejection);
14011392
}
1393+
1394+
PushFullScreenDebugTexture(renderGraph, passData.ssrAccum, FullScreenDebugMode.ScreenSpaceReflectionSpeedRejection);
1395+
1396+
result = passData.ssrAccum;
14021397
}
14031398

14041399
if (!hdCamera.colorPyramidHistoryIsValid)

Tests/SRPTests/Projects/HDRP_RuntimeTests/Assets/ShaderVariantLists/Default.shadervariantlist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Compiled compute shader: BloomPrefilter, kernel: KMain, keywords ENABLE_ALPHA LO
88
Compiled compute shader: BloomPrefilter, kernel: KMain, keywords LOW_QUALITY
99
Compiled compute shader: BloomUpsample, kernel: KMain, keywords HIGH_QUALITY
1010
Compiled compute shader: BloomUpsample, kernel: KMain, keywords LOW_QUALITY
11+
Compiled compute shader: ClearBuffer2D, kernel: ClearBuffer2DMain, keywords <no keywords>
1112
Compiled compute shader: ClearLightLists, kernel: ClearList, keywords <no keywords>
1213
Compiled compute shader: ClearUIntTextureArray, kernel: ClearUIntTexture, keywords <no keywords>
1314
Compiled compute shader: ClearUIntTextureArray, kernel: ClearUIntTextureArray, keywords <no keywords>

0 commit comments

Comments
 (0)