Skip to content

Commit 0333658

Browse files
adrien-de-tocquevilleEvergreen
authored andcommitted
[Water System] Optimize foam reprojection
Skip the foam reprojection pass if foam region hasn't moved. Saves like half a millisecond on PS4 without visual change
1 parent 5381c1a commit 0333658

File tree

3 files changed

+37
-31
lines changed

3 files changed

+37
-31
lines changed

Packages/com.unity.render-pipelines.high-definition/Runtime/Water/HDRenderPipeline.WaterSystem.Foam.cs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
using System;
21
using Unity.Collections;
32
using Unity.Mathematics;
43
using UnityEngine.Experimental.Rendering;
5-
using static Unity.Mathematics.math;
64

75
namespace UnityEngine.Rendering.HighDefinition
86
{
@@ -30,11 +28,11 @@ public partial class HDRenderPipeline
3028
// The pass used in the WaterFoam.shader
3129
int m_ShoreWaveFoamGenerationPass;
3230
int m_OtherFoamGenerationPass;
33-
int m_ReprojectionPass;
31+
int m_AttenuationPass;
3432

3533
ComputeShader m_WaterFoamCS;
3634
int m_ReprojectFoamKernel;
37-
int m_PostProcessFoamKernel;
35+
int m_AttenuateFoamKernel;
3836

3937
// Keeps track of maximum possible foam intensity in to estimate when there is no more foam
4038
float m_MaxInjectedFoamIntensity = 0.0f;
@@ -54,11 +52,11 @@ void InitializeWaterFoam()
5452
m_FoamTextureAtlas = new PowerOfTwoTextureAtlas((int)m_Asset.currentPlatformRenderPipelineSettings.foamAtlasSize, 0, GraphicsFormat.R16G16_UNorm, name: "Water Foam Atlas", useMipMap: false);
5553
m_WaterFoamCS = runtimeShaders.waterFoamCS;
5654
m_ReprojectFoamKernel = m_WaterFoamCS.FindKernel("ReprojectFoam");
57-
m_PostProcessFoamKernel = m_WaterFoamCS.FindKernel("PostProcessFoam");
55+
m_AttenuateFoamKernel = m_WaterFoamCS.FindKernel("AttenuateFoam");
5856

5957
m_ShoreWaveFoamGenerationPass = m_FoamMaterial.FindPass("ShoreWaveFoamGeneration");
6058
m_OtherFoamGenerationPass = m_FoamMaterial.FindPass("OtherFoamGeneration");
61-
m_ReprojectionPass = m_FoamMaterial.FindPass("Reprojection");
59+
m_AttenuationPass = m_FoamMaterial.FindPass("Attenuation");
6260
}
6361

6462
void ReleaseWaterFoam()
@@ -216,38 +214,46 @@ void UpdateWaterFoamSimulation(CommandBuffer cmd, WaterSurface currentWater)
216214
else
217215
m_MaxInjectedFoamIntensity = 1.0f;
218216

219-
// Grab the foam buffers
220-
RTHandle currentFoamBuffer = currentWater.foamBuffers[0];
221-
RTHandle tmpFoamBuffer = currentWater.foamBuffers[1];
222-
223217
using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.WaterSurfaceFoam)))
224218
{
219+
RTHandle currentFoamBuffer = currentWater.FoamBuffer();
225220
BindPerSurfaceConstantBuffer(cmd, m_WaterFoamCS, m_ShaderVariablesWaterPerSurface[currentWater.surfaceIndex]);
226221

227-
// Reproject the previous frame's foam buffer
228-
int tileC = HDUtils.DivRoundUp((int)currentWater.foamResolution, 8);
229-
cmd.SetComputeVectorParam(m_WaterFoamCS, HDShaderIDs._PreviousFoamRegionScaleOffset, currentWater.previousFoamRegionScaleOffset);
230-
cmd.SetComputeTextureParam(m_WaterFoamCS, m_ReprojectFoamKernel, HDShaderIDs._WaterFoamBuffer, currentFoamBuffer);
231-
cmd.SetComputeTextureParam(m_WaterFoamCS, m_ReprojectFoamKernel, HDShaderIDs._WaterFoamBufferRW, tmpFoamBuffer);
232-
cmd.DispatchCompute(m_WaterFoamCS, m_ReprojectFoamKernel, tileC, tileC, 1);
233-
234-
// Apply an attenuation on the existing foam
235-
CoreUtils.SetRenderTarget(cmd, tmpFoamBuffer);
236-
cmd.DrawProcedural(Matrix4x4.identity, m_FoamMaterial, m_ReprojectionPass, MeshTopology.Triangles, 3, 1, currentWater.mpb);
222+
// Check if we need to reproj
223+
if (currentWater.previousFoamRegionScaleOffset.x != cb._FoamRegionScale.x ||
224+
currentWater.previousFoamRegionScaleOffset.y != cb._FoamRegionScale.y ||
225+
currentWater.previousFoamRegionScaleOffset.z != cb._FoamRegionOffset.x ||
226+
currentWater.previousFoamRegionScaleOffset.w != cb._FoamRegionOffset.y)
227+
{
228+
RTHandle tmpFoamBuffer = currentWater.TmpFoamBuffer();
229+
230+
// Reproject the previous frame's foam buffer
231+
int tileC = HDUtils.DivRoundUp((int)currentWater.foamResolution, 8);
232+
cmd.SetComputeVectorParam(m_WaterFoamCS, HDShaderIDs._PreviousFoamRegionScaleOffset, currentWater.previousFoamRegionScaleOffset);
233+
cmd.SetComputeTextureParam(m_WaterFoamCS, m_ReprojectFoamKernel, HDShaderIDs._WaterFoamBuffer, currentFoamBuffer);
234+
cmd.SetComputeTextureParam(m_WaterFoamCS, m_ReprojectFoamKernel, HDShaderIDs._WaterFoamBufferRW, tmpFoamBuffer);
235+
cmd.DispatchCompute(m_WaterFoamCS, m_ReprojectFoamKernel, tileC, tileC, 1);
236+
237+
// Attenuate the foam buffer
238+
cmd.SetComputeTextureParam(m_WaterFoamCS, m_AttenuateFoamKernel, HDShaderIDs._WaterFoamBuffer, tmpFoamBuffer);
239+
cmd.SetComputeTextureParam(m_WaterFoamCS, m_AttenuateFoamKernel, HDShaderIDs._WaterFoamBufferRW, currentFoamBuffer);
240+
cmd.DispatchCompute(m_WaterFoamCS, m_AttenuateFoamKernel, tileC, tileC, 1);
241+
242+
// Update the foam data for the next frame
243+
currentWater.previousFoamRegionScaleOffset = new float4(cb._FoamRegionScale, cb._FoamRegionOffset);
244+
}
245+
else
246+
{
247+
// Attenuate the foam buffer
248+
CoreUtils.SetRenderTarget(cmd, currentFoamBuffer);
249+
cmd.DrawProcedural(Matrix4x4.identity, m_FoamMaterial, m_AttenuationPass, MeshTopology.Triangles, 3, 1, currentWater.mpb);
250+
}
237251

238252
// Then we render the deformers and the generators
239253
if (waterDeformers)
240254
cmd.DrawProcedural(Matrix4x4.identity, m_FoamMaterial, m_ShoreWaveFoamGenerationPass, MeshTopology.Triangles, 6, m_ActiveWaterDeformers, currentWater.mpb);
241255
if (foamGenerators)
242256
cmd.DrawProcedural(Matrix4x4.identity, m_FoamMaterial, m_OtherFoamGenerationPass, MeshTopology.Triangles, 6, m_ActiveWaterFoamGenerators, currentWater.mpb);
243-
244-
// To avoid the swap in swap out of the textures, we do this.
245-
cmd.SetComputeTextureParam(m_WaterFoamCS, m_PostProcessFoamKernel, HDShaderIDs._WaterFoamBuffer, tmpFoamBuffer);
246-
cmd.SetComputeTextureParam(m_WaterFoamCS, m_PostProcessFoamKernel, HDShaderIDs._WaterFoamBufferRW, currentFoamBuffer);
247-
cmd.DispatchCompute(m_WaterFoamCS, m_PostProcessFoamKernel, tileC, tileC, 1);
248-
249-
// Update the foam data for the next frame
250-
currentWater.previousFoamRegionScaleOffset = new float4(cb._FoamRegionScale, cb._FoamRegionOffset);
251257
}
252258
}
253259
}

Packages/com.unity.render-pipelines.high-definition/Runtime/Water/Shaders/WaterFoam.compute

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#pragma kernel ReprojectFoam
2-
#pragma kernel PostProcessFoam
2+
#pragma kernel AttenuateFoam
33

44
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
55

@@ -71,7 +71,7 @@ void ReprojectFoam(uint3 currentThread : SV_DispatchThreadID,
7171

7272

7373
[numthreads(8, 8, 1)]
74-
void PostProcessFoam(uint3 currentThread : SV_DispatchThreadID,
74+
void AttenuateFoam(uint3 currentThread : SV_DispatchThreadID,
7575
int groupIndex : SV_GroupIndex,
7676
uint2 groupId : SV_GroupID,
7777
uint2 groupThreadId : SV_GroupThreadID)

Packages/com.unity.render-pipelines.high-definition/Runtime/Water/Shaders/WaterFoam.shader

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ Shader "Hidden/HDRP/WaterFoam"
238238

239239
Pass
240240
{
241-
Name "Reprojection"
241+
Name "Attenuation"
242242
// This program doesn't require any culling or ztesting
243243
Cull Off
244244
ZTest Off

0 commit comments

Comments
 (0)