From 8aea89c11ca19db808ed15824d0a9aeb32abb9fa Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Wed, 21 Oct 2020 12:43:52 +0200 Subject: [PATCH 01/25] Fix near edges - remove old alpha normalization code --- .../PostProcessing/Shaders/DoFGather.compute | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index bce710f195f..0c1eb288a9d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -56,10 +56,6 @@ int GetCoCBucket(float cocSize) return 0; #endif -#ifdef UNIFORM_WEIGHTS - return 0; -#endif - // Threshold to split near, far and in-focus range. We don't need to expose this parameter, as the algorithm is robust against it const float dofThreshold = 6; @@ -307,13 +303,10 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // back to front alpha blending of the near, far and in-focus buckets for (int j = 0; j < NUM_BUCKETS; ++j) { - // Reference: "Next Generation Post-Processing in Call of Duty Advanced Warfare", Advances in real-time rendering, Siggraph 2014 - // See slide 102 for the normalization factor for the alpha. The 2x factor (see slide 103) also helps with the far layers for - // large amounts of defocus blur, but this might need more investigation. - float alpha = saturate(totalColor[j].w * 2 * rcp(GetNumSamples(maxCoC[j], maxRadius))* rcp(GetSampleWeight(maxCoC[j]))); - outColor = (1.0 - alpha) * outColor + alpha * totalColor[j]; + float alpha = saturate(totalColor[j].w); + outColor = (1.0 - alpha) * outColor + totalColor[j]; #ifdef ENABLE_ALPHA - outAlpha = (1.0 - alpha) * outAlpha + alpha * totalAlpha[j]; + outAlpha = (1.0 - alpha) * outAlpha + totalAlpha[j]; #endif } outColor.xyz = outColor.xyz * rcp(outColor.w); From 33094ad535481249311198172d995d940ccd6050 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Wed, 21 Oct 2020 13:17:16 +0200 Subject: [PATCH 02/25] Fix alpha output --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 0c1eb288a9d..4df41d1820d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -271,7 +271,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) ringHits[j] += bucketWeight; #endif #ifdef ENABLE_ALPHA - RING_ALPHA[j] = sampleColor.w * weight; + RING_ALPHA[j] += sampleColor.w * weight; #endif } } From c6d9d9f31c1bc53abdc6b8b621bd91432d488675 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Wed, 21 Oct 2020 14:28:05 +0200 Subject: [PATCH 03/25] Dof alpha output: preserve pixels with zero alpha --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 4df41d1820d..c324c775699 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -214,6 +214,10 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // Note: For zero radius we still go through the loop (for one iteration). We can avoid the cost of computing weigths if we early exit (at the cost of extra code complexity). float totalRings = maxRadius > 0 ? NumRings : 0; +#ifdef ENABLE_ALPHA + CTYPE originalColor = LOAD_TEXTURE2D_X(_InputTexture, posInputs.positionSS).CTYPE_SWIZZLE;; +#endif + // Iterate over the octaweb pattern and gather the DoF samples for (float ring = totalRings; ring >= 0; ring -= 1.0) { @@ -312,6 +316,10 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) outColor.xyz = outColor.xyz * rcp(outColor.w); #ifdef ENABLE_ALPHA + // Preserve the original value of the pixels with zero alpha. + // The second line with the lerp+smoothstep combination avoids a hard transition in edge cases + //outColor.xyz = outAlpha > 0 ? outColor.xyz : originalColor.xyz; + outColor.xyz = lerp(originalColor.xyz, outColor.xyz, smoothstep(0, 0.01, outAlpha)); _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = float4(outColor.xyz, outAlpha * rcp(outColor.w)); #else _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = outColor.xyz; From 1a24588aa1c9835edac930058f232e4e0db3e28b Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 14:02:03 +0200 Subject: [PATCH 04/25] Physical DoF: generate color pyramid --- .../PostProcessSystem.RenderGraph.cs | 8 +++-- .../PostProcessing/PostProcessSystem.cs | 33 ++++++++++++++++--- .../Shaders/DepthOfFieldMip.compute | 19 +++++++++-- .../PostProcessing/Shaders/DoFGather.compute | 2 ++ 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs index 40a8b8e0127..dd98efb2d9e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs @@ -458,6 +458,7 @@ TextureHandle DepthOfFieldPass(RenderGraph renderGraph, HDCamera hdCamera, Textu TextureHandle dest = GetPostprocessOutputHandle(renderGraph, "DoF Destination"); passData.destination = builder.WriteTexture(dest); passData.motionVecTexture = builder.ReadTexture(motionVectors); + passData.taaEnabled = taaEnabled; if (!m_DepthOfField.physicallyBased) { @@ -531,8 +532,6 @@ TextureHandle DepthOfFieldPass(RenderGraph renderGraph, HDCamera hdCamera, Textu }); } - passData.taaEnabled = taaEnabled; - passData.bokehNearKernel = builder.CreateTransientComputeBuffer(new ComputeBufferDesc(dofParameters.nearSampleCount * dofParameters.nearSampleCount, sizeof(uint)) { name = "Bokeh Near Kernel" }); passData.bokehFarKernel = builder.CreateTransientComputeBuffer(new ComputeBufferDesc(dofParameters.farSampleCount * dofParameters.farSampleCount, sizeof(uint)) { name = "Bokeh Far Kernel" }); passData.bokehIndirectCmd = builder.CreateTransientComputeBuffer(new ComputeBufferDesc(3 * 2, sizeof(uint), ComputeBufferType.IndirectArguments) { name = "Bokeh Indirect Cmd" }); @@ -565,10 +564,13 @@ TextureHandle DepthOfFieldPass(RenderGraph renderGraph, HDCamera hdCamera, Textu passData.fullresCoC = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = k_CoCFormat, enableRandomWrite = true, useMipMap = true, name = "Full res CoC" }); + passData.pingFarRGB = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) + { colorFormat = m_ColorFormat, useMipMap = true, enableRandomWrite = true, name = "DoF Source Pyramid" }); + builder.SetRenderFunc( (DepthofFieldData data, RenderGraphContext ctx) => { - DoPhysicallyBasedDepthOfField(data.parameters, ctx.cmd, data.source, data.destination, data.fullresCoC, data.prevCoC, data.nextCoC, data.motionVecTexture, data.taaEnabled); + DoPhysicallyBasedDepthOfField(data.parameters, ctx.cmd, data.source, data.destination, data.fullresCoC, data.prevCoC, data.nextCoC, data.motionVecTexture, data.pingFarRGB, data.taaEnabled); }); source = passData.destination; diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 5d7be02279f..6f1418d1522 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -707,7 +707,7 @@ void PoolSource(ref RTHandle src, RTHandle dst) var fullresCoC = m_Pool.Get(Vector2.one, k_CoCFormat, true); - DoPhysicallyBasedDepthOfField(dofParameters, cmd, source, destination, fullresCoC, prevCoC, nextCoC, motionVecTexture, taaEnabled); + DoPhysicallyBasedDepthOfField(dofParameters, cmd, source, destination, fullresCoC, prevCoC, nextCoC, motionVecTexture, null, taaEnabled); m_Pool.Recycle(fullresCoC); } @@ -1863,7 +1863,14 @@ DepthOfFieldParameters PrepareDoFParameters(HDCamera camera) parameters.dofDilateCS = m_Resources.shaders.depthOfFieldDilateCS; parameters.dofDilateKernel = parameters.dofDilateCS.FindKernel("KMain"); parameters.dofMipCS = m_Resources.shaders.depthOfFieldMipCS; - parameters.dofMipColorKernel = parameters.dofMipCS.FindKernel(m_EnableAlpha ? "KMainColorAlpha" : "KMainColor"); + if (!m_DepthOfField.physicallyBased) + { + parameters.dofMipColorKernel = parameters.dofMipCS.FindKernel(m_EnableAlpha ? "KMainColorAlpha" : "KMainColor"); + } + else + { + parameters.dofMipColorKernel = parameters.dofMipCS.FindKernel(m_EnableAlpha ? "KMainColorCopyAlpha" : "KMainColorCopy"); + } parameters.dofMipCoCKernel = parameters.dofMipCS.FindKernel("KMainCoC"); parameters.dofMipSafeCS = m_Resources.shaders.depthOfFieldMipSafeCS; parameters.dofPrefilterCS = m_Resources.shaders.depthOfFieldPrefilterCS; @@ -2536,7 +2543,7 @@ static void GetMipMapDimensions(RTHandle texture, int lod, out int width, out in } } - static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameters, CommandBuffer cmd, RTHandle source, RTHandle destination, RTHandle fullresCoC, RTHandle prevCoCHistory, RTHandle nextCoCHistory, RTHandle motionVecTexture, bool taaEnabled) + static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameters, CommandBuffer cmd, RTHandle source, RTHandle destination, RTHandle fullresCoC, RTHandle prevCoCHistory, RTHandle nextCoCHistory, RTHandle motionVecTexture, RTHandle sourcePyramid, bool taaEnabled) { float scale = 1f / (float)dofParameters.resolution; int targetWidth = Mathf.RoundToInt(dofParameters.camera.actualWidth * scale); @@ -2610,6 +2617,24 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip5, fullresCoC, 5); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip6, fullresCoC, 6); cmd.DispatchCompute(cs, kernel, (dofParameters.camera.actualWidth + 31) / 32, (dofParameters.camera.actualHeight + 31) / 32, dofParameters.camera.viewCount); + + // DoF color pyramid + if (sourcePyramid != null) + { + cs = dofParameters.dofMipCS; + kernel = dofParameters.dofMipColorKernel; + + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, source, 0); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputTexture, sourcePyramid, 0); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip1, sourcePyramid, 1); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip2, sourcePyramid, 2); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip3, sourcePyramid, 3); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip4, sourcePyramid, 4); + + int tx = ((dofParameters.camera.actualWidth >> 1) + 7) / 8; + int ty = ((dofParameters.camera.actualHeight >> 1) + 7) / 8; + cmd.DispatchCompute(cs, kernel, tx, ty, dofParameters.camera.viewCount); + } } using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.DepthOfFieldCombine))) @@ -2623,7 +2648,7 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter GetMipMapDimensions(fullresCoC, (int)mipLevel, out var mipMapWidth, out var mipMapHeight); cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(sampleCount, cocLimit, 0.0f, 0.0f)); cmd.SetComputeVectorParam(cs, HDShaderIDs._Params2, new Vector4(mipLevel, mipMapWidth, mipMapHeight, 0.0f)); - cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, source); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, sourcePyramid != null ? sourcePyramid : source); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputTexture, destination); cmd.DispatchCompute(cs, kernel, (dofParameters.camera.actualWidth + 7) / 8, (dofParameters.camera.actualHeight + 7) / 8, dofParameters.camera.viewCount); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DepthOfFieldMip.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DepthOfFieldMip.compute index 1613d7d7b77..40fecffdef9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DepthOfFieldMip.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DepthOfFieldMip.compute @@ -3,12 +3,18 @@ #pragma only_renderers d3d11 playstation xboxone vulkan metal switch -#pragma kernel KMainColor MAIN=KMainColor CTYPE=float3 -#pragma kernel KMainColorAlpha MAIN=KMainColorAlpha CTYPE=float4 -#pragma kernel KMainCoC MAIN=KMainCoC CTYPE=float +#pragma kernel KMainColor MAIN=KMainColor CTYPE=float3 +#pragma kernel KMainColorAlpha MAIN=KMainColorAlpha CTYPE=float4 +#pragma kernel KMainCoC MAIN=KMainCoC CTYPE=float +#pragma kernel KMainColorCopy MAIN=KMainColorCopy CTYPE=float3 COPY_MIP0 +#pragma kernel KMainColorCopyAlpha MAIN=KMainColorCopyAlpha CTYPE=float4 COPY_MIP0 RW_TEXTURE2D_X(CTYPE, _InputTexture); +#ifdef COPY_MIP0 +RW_TEXTURE2D_X(CTYPE, _OutputTexture); +#endif + RW_TEXTURE2D_X(CTYPE, _OutputMip1); RW_TEXTURE2D_X(CTYPE, _OutputMip2); RW_TEXTURE2D_X(CTYPE, _OutputMip3); @@ -38,6 +44,13 @@ void MAIN(uint3 dispatchThreadId : SV_DispatchThreadID, uint groupIndex : SV_Gro // First mip CTYPE color = _InputTexture[COORD_TEXTURE2D_X(ul)]; +#ifdef COPY_MIP0 + _OutputTexture[COORD_TEXTURE2D_X(ul)] = _InputTexture[COORD_TEXTURE2D_X(ul)]; + _OutputTexture[COORD_TEXTURE2D_X(ul + uint2(1u, 0u))] = _InputTexture[COORD_TEXTURE2D_X(ul + uint2(1u, 0u))]; + _OutputTexture[COORD_TEXTURE2D_X(ul + uint2(0u, 1u))] = _InputTexture[COORD_TEXTURE2D_X(ul + uint2(0u, 1u))]; + _OutputTexture[COORD_TEXTURE2D_X(ul + uint2(1u, 1u))] = _InputTexture[COORD_TEXTURE2D_X(ul + uint2(1u, 1u))]; +#endif + color += _InputTexture[COORD_TEXTURE2D_X(ul + uint2(1u, 0u))]; color += _InputTexture[COORD_TEXTURE2D_X(ul + uint2(0u, 1u))]; color += _InputTexture[COORD_TEXTURE2D_X(ul + uint2(1u, 1u))]; diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index c324c775699..7fc95c46e4b 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -307,6 +307,8 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // back to front alpha blending of the near, far and in-focus buckets for (int j = 0; j < NUM_BUCKETS; ++j) { + // Note: earlier we were also using a normalization term for the alpha from the CoD slides, but it created some artifcats. + // Perhaps this requires more investigation. float alpha = saturate(totalColor[j].w); outColor = (1.0 - alpha) * outColor + totalColor[j]; #ifdef ENABLE_ALPHA From 72cd729cdbaca822834797a0ca80ba9baae07b98 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 15:14:42 +0200 Subject: [PATCH 05/25] Physical DoF: mip map selection based on radius --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 7fc95c46e4b..534c1a93381 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -259,7 +259,10 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) sampleTC = clamp(sampleTC, float2(0, 0), _ScreenSize.xy - float2(1, 1)); int sampleBucket = 0; - CTYPE sampleColor = LOAD_TEXTURE2D_X(_InputTexture, sampleTC).CTYPE_SWIZZLE; + // Select the appropriate mip to sample based on the amount of samples. Lower sample counts will be faster at the cost of "leaking" + // Note: We have generated only 4 additional mip levels, so don't go any deeper than that + float lod = min(4, log2(2 * radius / RING_DENSITY)); + CTYPE sampleColor = SAMPLE_TEXTURE2D_X_LOD(_InputTexture, s_trilinear_clamp_sampler, sampleTC * _ScreenSize.zw, lod).CTYPE_SWIZZLE; float sampleCoC = GetCoCRadius(sampleTC, sampleBucket); if (abs(sampleCoC) >= radius) From d71fe33b9b3520c1382b1683f522736d1c315275 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 17:46:38 +0200 Subject: [PATCH 06/25] Remove the preview indicator from the UI --- .../Editor/PostProcessing/DepthOfFieldEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs index 37721c3ef0b..3d3ed5475b1 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs @@ -19,7 +19,7 @@ static partial class Styles public static GUIContent k_NearFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the near field does not blur anymore."); public static GUIContent k_FarFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the far field blur reaches its maximum blur radius."); - public static GUIContent k_PhysicallyBased = new GUIContent("Physically Based (Preview)", "Uses a more accurate but slower physically based method to compute DoF."); + public static GUIContent k_PhysicallyBased = new GUIContent("Physically Based", "Uses a more accurate but slower physically based method to compute DoF."); public static readonly string InfoBox = "Physically Based DoF currently has a high performance overhead. Enabling TAA is highly recommended when using this option."; } From ecc26e738e69d861838d8859786a750b8a96eefc Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 19:53:32 +0200 Subject: [PATCH 07/25] Old (not rendergraph) pipeline implementation --- .../Runtime/PostProcessing/PostProcessSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 6f1418d1522..5a221c476a2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -706,8 +706,8 @@ void PoolSource(ref RTHandle src, RTHandle dst) GrabCoCHistory(camera, out prevCoC, out nextCoC, useMips: true); var fullresCoC = m_Pool.Get(Vector2.one, k_CoCFormat, true); - - DoPhysicallyBasedDepthOfField(dofParameters, cmd, source, destination, fullresCoC, prevCoC, nextCoC, motionVecTexture, null, taaEnabled); + var colorPyramid = m_Pool.Get(Vector2.one, m_ColorFormat, true); + DoPhysicallyBasedDepthOfField(dofParameters, cmd, source, destination, fullresCoC, prevCoC, nextCoC, motionVecTexture, colorPyramid, taaEnabled); m_Pool.Recycle(fullresCoC); } From 0c923d6318a90910125c1401b6eab66bd36ed2ec Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 20:04:23 +0200 Subject: [PATCH 08/25] fix mem leak --- .../Runtime/PostProcessing/PostProcessSystem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 5a221c476a2..d3ef7e98171 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -710,6 +710,7 @@ void PoolSource(ref RTHandle src, RTHandle dst) DoPhysicallyBasedDepthOfField(dofParameters, cmd, source, destination, fullresCoC, prevCoC, nextCoC, motionVecTexture, colorPyramid, taaEnabled); m_Pool.Recycle(fullresCoC); + m_Pool.Recycle(colorPyramid); } PoolSource(ref source, destination); From 397a346ddcd251479abc86dd961113724b2680ba Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 20:42:35 +0200 Subject: [PATCH 09/25] Support for much larger CoC radii --- .../PostProcessing/PostProcessSystem.cs | 44 +++++++++++++++++-- .../Shaders/DoFCoCPyramid.compute | 21 +++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index d3ef7e98171..b8f64196477 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2552,7 +2552,7 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter // Map the old "max radius" parameters to a bigger range, so we can work on more challenging scenes float maxRadius = Mathf.Max(dofParameters.farMaxBlur, dofParameters.nearMaxBlur); - float cocLimit = Mathf.Clamp(4 * maxRadius, 1, 64); + float cocLimit = Mathf.Clamp(16 * maxRadius, 1, 256); ComputeShader cs; int kernel; @@ -2610,6 +2610,8 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter cs = dofParameters.dofCoCPyramidCS; kernel = dofParameters.dofCoCPyramidKernel; + float numMips = Mathf.Floor(Mathf.Log(Mathf.Max((dofParameters.camera.actualWidth + 31), (dofParameters.camera.actualHeight + 31)), 2)); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, fullresCoC); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip1, fullresCoC, 1); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip2, fullresCoC, 2); @@ -2617,8 +2619,45 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip4, fullresCoC, 4); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip5, fullresCoC, 5); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip6, fullresCoC, 6); + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(numMips, 0, 0, 0)); cmd.DispatchCompute(cs, kernel, (dofParameters.camera.actualWidth + 31) / 32, (dofParameters.camera.actualHeight + 31) / 32, dofParameters.camera.viewCount); + // do we need a second pass for the rest? + if (numMips > 6.0f && cocLimit > 64) + { + GetMipMapDimensions(fullresCoC, 6, out var mipMapWidth, out var mipMapHeight); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, fullresCoC, 6); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip1, fullresCoC, 7); + + if (numMips > 7) + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip2, fullresCoC, 8); + else + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip2, fullresCoC, 1); // we will never write on this, but still need to bind something + + if (numMips > 8) + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip3, fullresCoC, 9); + else + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip3, fullresCoC, 2); // we will never write on this, but still need to bind something + + if (numMips > 9) + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip4, fullresCoC, 10); + else + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip4, fullresCoC, 3); // we will never write on this, but still need to bind something + + if (numMips > 10) + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip5, fullresCoC, 11); + else + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip5, fullresCoC, 4); // we will never write on this, but still need to bind something + + if (numMips > 11) + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip6, fullresCoC, 12); + else + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip6, fullresCoC, 5); // we will never write on this, but still need to bind something + + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(numMips - 6.0f, 0, 0, 0)); + cmd.DispatchCompute(cs, kernel, (mipMapWidth + 31) / 32, (mipMapHeight + 31) / 32, dofParameters.camera.viewCount); + } + // DoF color pyramid if (sourcePyramid != null) { @@ -2644,8 +2683,7 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter kernel = dofParameters.pbDoFGatherKernel; float sampleCount = Mathf.Max(dofParameters.nearSampleCount, dofParameters.farSampleCount); - // We only have up to 6 mip levels - float mipLevel = Mathf.Min(6, 1 + Mathf.Ceil(Mathf.Log(cocLimit, 2))); + float mipLevel = 1 + Mathf.Ceil(Mathf.Log(cocLimit, 2)); GetMipMapDimensions(fullresCoC, (int)mipLevel, out var mipMapWidth, out var mipMapHeight); cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(sampleCount, cocLimit, 0.0f, 0.0f)); cmd.SetComputeVectorParam(cs, HDShaderIDs._Params2, new Vector4(mipLevel, mipMapWidth, mipMapHeight, 0.0f)); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCoCPyramid.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCoCPyramid.compute index c4436f59369..e6dc4e7ee0c 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCoCPyramid.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFCoCPyramid.compute @@ -5,6 +5,12 @@ #pragma kernel KMainCoCPyramid +CBUFFER_START(cb0) +float4 _Params; +CBUFFER_END + +#define NumMips _Params.x + RW_TEXTURE2D_X(float, _InputTexture); RW_TEXTURE2D_X(float, _OutputMip1); @@ -52,6 +58,9 @@ void KMainCoCPyramid(uint3 dispatchThreadId : SV_DispatchThreadID, uint groupInd _OutputMip1[COORD_TEXTURE2D_X(dispatchThreadId.xy)] = color; + if (NumMips <= 1.0) + return; + GroupMemoryBarrierWithGroupSync(); // Second mip - checks that X and Y are even @@ -66,6 +75,9 @@ void KMainCoCPyramid(uint3 dispatchThreadId : SV_DispatchThreadID, uint groupInd _OutputMip2[COORD_TEXTURE2D_X(dispatchThreadId.xy / 2u)] = color; } + if (NumMips <= 2.0) + return; + GroupMemoryBarrierWithGroupSync(); // Third mip - checks that X and Y are multiples of four @@ -79,6 +91,9 @@ void KMainCoCPyramid(uint3 dispatchThreadId : SV_DispatchThreadID, uint groupInd _OutputMip3[COORD_TEXTURE2D_X(dispatchThreadId.xy / 4u)] = color; } + if (NumMips <= 3.0) + return; + GroupMemoryBarrierWithGroupSync(); // Fourth mip - checks that X and Y are multiples of 8 @@ -92,6 +107,9 @@ void KMainCoCPyramid(uint3 dispatchThreadId : SV_DispatchThreadID, uint groupInd _OutputMip4[COORD_TEXTURE2D_X(dispatchThreadId.xy / 8u)] = color; } + if (NumMips <= 4.0) + return; + GroupMemoryBarrierWithGroupSync(); // Fifth mip - checks that X and Y are multiples of 16 @@ -104,6 +122,9 @@ void KMainCoCPyramid(uint3 dispatchThreadId : SV_DispatchThreadID, uint groupInd _OutputMip5[COORD_TEXTURE2D_X(dispatchThreadId.xy / 16u)] = color; } + if (NumMips <= 5.0) + return; + // Last mip - only one thread if (groupIndex == 0) { From 88f90d77ac176ebecc6e8caf2ba924586b3dfb5b Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 22:00:05 +0200 Subject: [PATCH 10/25] Shader cleanup --- .../PostProcessing/Shaders/DoFGather.compute | 29 ++----------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 534c1a93381..6de84cc44fe 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -49,29 +49,6 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); #define GROUP_RES 8u #define GROUP_SIZE (GROUP_RES * GROUP_RES) - -int GetCoCBucket(float cocSize) -{ -#if (NUM_BUCKETS == 1) - return 0; -#endif - - // Threshold to split near, far and in-focus range. We don't need to expose this parameter, as the algorithm is robust against it - const float dofThreshold = 6; - - if (cocSize > dofThreshold) - { - return 0; - } - else if (abs(cocSize) < dofThreshold) - { - return 1; - } - else - { - return 2; - } -} float GetBucketWeight(float sampleCoC, float noise, int bucket) { // Note: we could potentially get higher quality by allowing artists to fine-tune the bucket/cascade transitions, @@ -95,10 +72,9 @@ float GetBucketWeight(float sampleCoC, float noise, int bucket) } } -float GetCoCRadius(int2 positionSS, out int bucketIndex) +float GetCoCRadius(int2 positionSS) { float CoCRadius = LOAD_TEXTURE2D_X(_InputCoCTexture, positionSS).x; - bucketIndex = GetCoCBucket(CoCRadius); return CoCRadius; } @@ -258,12 +234,11 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float2 sampleTC = posInputs.positionSS + radius * PointInCircle(ang); sampleTC = clamp(sampleTC, float2(0, 0), _ScreenSize.xy - float2(1, 1)); - int sampleBucket = 0; // Select the appropriate mip to sample based on the amount of samples. Lower sample counts will be faster at the cost of "leaking" // Note: We have generated only 4 additional mip levels, so don't go any deeper than that float lod = min(4, log2(2 * radius / RING_DENSITY)); CTYPE sampleColor = SAMPLE_TEXTURE2D_X_LOD(_InputTexture, s_trilinear_clamp_sampler, sampleTC * _ScreenSize.zw, lod).CTYPE_SWIZZLE; - float sampleCoC = GetCoCRadius(sampleTC, sampleBucket); + float sampleCoC = GetCoCRadius(sampleTC); if (abs(sampleCoC) >= radius) { From ed2d3c0adf763d29e764e1512a7e56ba74a1c8f4 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 22:25:15 +0200 Subject: [PATCH 11/25] Tweak lod selection --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 6de84cc44fe..4eaa1ce7bf0 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -236,7 +236,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // Select the appropriate mip to sample based on the amount of samples. Lower sample counts will be faster at the cost of "leaking" // Note: We have generated only 4 additional mip levels, so don't go any deeper than that - float lod = min(4, log2(2 * radius / RING_DENSITY)); + float lod = min(4, log2(2 * PI * radius / numSamples)); CTYPE sampleColor = SAMPLE_TEXTURE2D_X_LOD(_InputTexture, s_trilinear_clamp_sampler, sampleTC * _ScreenSize.zw, lod).CTYPE_SWIZZLE; float sampleCoC = GetCoCRadius(sampleTC); From 8fbea7dc12cada440ec3341950a6400e50d123f9 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 22 Oct 2020 23:44:49 +0200 Subject: [PATCH 12/25] Improve sampling noise --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 4eaa1ce7bf0..6aabf87aa84 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -184,8 +184,9 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float stratum = fmod(posInputs.positionSS.x + posInputs.positionSS.y, 2.0f); int sampleOffset = _TaaFrameInfo.w != 0.0 ? _TaaFrameInfo.z : 0; - float noise = InterleavedGradientNoise(posInputs.positionSS.xy, sampleOffset); - float noise2 = InterleavedGradientNoise(posInputs.positionSS.xy, 8 + sampleOffset); + // Note: adjusting pseudo-randomly the sampleOffset for each pixel seems to considerably improve the sampling + float noise = InterleavedGradientNoise(posInputs.positionSS.xy, posInputs.positionSS.x + 3 * posInputs.positionSS.y + sampleOffset); + float noise2 = InterleavedGradientNoise(posInputs.positionSS.xy, 3 * posInputs.positionSS.x + posInputs.positionSS.y + sampleOffset); // Note: For zero radius we still go through the loop (for one iteration). We can avoid the cost of computing weigths if we early exit (at the cost of extra code complexity). float totalRings = maxRadius > 0 ? NumRings : 0; From 82c68428c3f72310fd4b7243b351ea8e1811be90 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 23 Oct 2020 00:56:14 +0200 Subject: [PATCH 13/25] Fix post-dof TAA in rendergraph --- .../Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs index dd98efb2d9e..61c62bf5ecb 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs @@ -582,15 +582,13 @@ TextureHandle DepthOfFieldPass(RenderGraph renderGraph, HDCamera hdCamera, Textu if (taaEnabled && m_DepthOfField.physicallyBased) { bool postDof = true; - var taaParams = PrepareTAAParameters(hdCamera, postDof); - using (var builder = renderGraph.AddRenderPass("Temporal Anti-Aliasing", out var passData, ProfilingSampler.Get(HDProfileId.TemporalAntialiasing))) { GrabTemporalAntialiasingHistoryTextures(hdCamera, out var prevHistory, out var nextHistory, postDof); passData.source = builder.ReadTexture(source); - passData.parameters = PrepareTAAParameters(hdCamera); + passData.parameters = PrepareTAAParameters(hdCamera, postDof); passData.depthBuffer = builder.ReadTexture(depthBuffer); passData.motionVecTexture = builder.ReadTexture(motionVectors); passData.depthMipChain = builder.ReadTexture(depthBufferMipChain); From d7550473d3d592e5d9a7915fd78ccdece81365a6 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 23 Oct 2020 15:30:27 +0200 Subject: [PATCH 14/25] Shader cleanup --- .../PostProcessing/Shaders/DoFGather.compute | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 6aabf87aa84..6f701332d73 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -128,26 +128,10 @@ float GetNumSamples(float radius, float maxRadius) return 1.0 + seriesSum * RING_DENSITY; } -float GetRingWeight(int index, float dR) +float GetRingWeight(int index) { - if (index == 0) - { - return 1.0f; - } - else - { - float ringRadius = index * dR; - float ringArea = PI * ringRadius * ringRadius; - - float prevRingRadius = (index - 1) * dR; - float prevRingArea = PI * prevRingRadius * prevRingRadius; - - ringArea = ringArea - prevRingArea; - - float ringSamples = RING_DENSITY * index; - ringSamples = (index == 1) ? ringSamples + 1.0f : ringSamples; - return ringArea * rcp(ringSamples); - } + // TODO: need to investigate better sampling weights + return 1.0; } [numthreads(GROUP_RES, GROUP_RES, 1)] @@ -209,7 +193,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float ringOffset = noise * dAng; #endif - float ringWeight = GetRingWeight(max(0, ring), dR); + float ringWeight = GetRingWeight(ring); #ifdef OCTAWEB_SORTING float4 ringColor[NUM_BUCKETS]; @@ -237,7 +221,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // Select the appropriate mip to sample based on the amount of samples. Lower sample counts will be faster at the cost of "leaking" // Note: We have generated only 4 additional mip levels, so don't go any deeper than that - float lod = min(4, log2(2 * PI * radius / numSamples)); + float lod = min(4, log2(2 * PI * radius * rcp(numSamples))); CTYPE sampleColor = SAMPLE_TEXTURE2D_X_LOD(_InputTexture, s_trilinear_clamp_sampler, sampleTC * _ScreenSize.zw, lod).CTYPE_SWIZZLE; float sampleCoC = GetCoCRadius(sampleTC); From 31f309dfd11756d39ba1f06b02f820633ee04f17 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 23 Oct 2020 15:34:06 +0200 Subject: [PATCH 15/25] Bugfix for taa in DoF --- .../PostProcessing/PostProcessSystem.RenderGraph.cs | 12 ++++++------ .../Runtime/PostProcessing/PostProcessSystem.cs | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs index 61c62bf5ecb..885787fc296 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs @@ -431,6 +431,12 @@ TextureHandle DepthOfFieldPass(RenderGraph renderGraph, HDCamera hdCamera, Textu // map rather than having to deal with all the implications of doing it before TAA if (m_DepthOfField.IsActive() && !isSceneView && m_DepthOfFieldFS && !isDoFPathTraced) { + // If we switch DoF modes and the old one was not using TAA, make sure we invalidate the history + if (taaEnabled && m_IsDoFHisotoryValid != m_DepthOfField.physicallyBased) + { + hdCamera.resetPostProcessingHistory = true; + } + var dofParameters = PrepareDoFParameters(hdCamera); bool useHistoryMips = m_DepthOfField.physicallyBased; @@ -438,12 +444,6 @@ TextureHandle DepthOfFieldPass(RenderGraph renderGraph, HDCamera hdCamera, Textu var prevCoCHandle = renderGraph.ImportTexture(prevCoC); var nextCoCHandle = renderGraph.ImportTexture(nextCoC); - // If we switch DoF modes and the old one was not using TAA, make sure we invalidate the history - if (taaEnabled && m_IsDoFHisotoryValid != m_DepthOfField.physicallyBased) - { - hdCamera.resetPostProcessingHistory = true; - } - using (var builder = renderGraph.AddRenderPass("Depth of Field", out var passData, ProfilingSampler.Get(HDProfileId.DepthOfField))) { passData.source = builder.ReadTexture(source); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index b8f64196477..3713a357e0c 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -1826,6 +1826,7 @@ struct DepthOfFieldParameters public bool farLayerActive; public bool highQualityFiltering; public bool useTiles; + public bool resetPostProcessingHistory; public DepthOfFieldResolution resolution; public DepthOfFieldMode focusMode; @@ -1894,6 +1895,7 @@ DepthOfFieldParameters PrepareDoFParameters(HDCamera camera) parameters.pbDoFGatherKernel = parameters.pbDoFGatherCS.FindKernel("KMain"); parameters.camera = camera; + parameters.resetPostProcessingHistory = camera.resetPostProcessingHistory; parameters.nearLayerActive = m_DepthOfField.IsNearLayerActive(); parameters.farLayerActive = m_DepthOfField.IsFarLayerActive(); @@ -2520,7 +2522,7 @@ static void ReprojectCoCHistory(in DepthOfFieldParameters parameters, CommandBuf //Note: this reprojection creates some ghosting, we should replace it with something based on the new TAA ComputeShader cs = parameters.dofCoCReprojectCS; int kernel = parameters.dofCoCReprojectKernel; - cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(camera.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); + cmd.SetComputeVectorParam(cs, HDShaderIDs._Params, new Vector4(parameters.resetPostProcessingHistory ? 0f : 0.91f, cocHistoryScale.x, cocHistoryScale.y, 0f)); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputCoCTexture, fullresCoC); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputHistoryCoCTexture, prevCoC); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputCoCTexture, nextCoC); From ccd80119faff00463bd49ec3d236e6a1df1931a0 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 23 Oct 2020 16:57:54 +0200 Subject: [PATCH 16/25] Bugfix for RTHandles: scale and clamp the UVs properly --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 6f701332d73..b083f3ec3f9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -222,7 +222,7 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // Select the appropriate mip to sample based on the amount of samples. Lower sample counts will be faster at the cost of "leaking" // Note: We have generated only 4 additional mip levels, so don't go any deeper than that float lod = min(4, log2(2 * PI * radius * rcp(numSamples))); - CTYPE sampleColor = SAMPLE_TEXTURE2D_X_LOD(_InputTexture, s_trilinear_clamp_sampler, sampleTC * _ScreenSize.zw, lod).CTYPE_SWIZZLE; + CTYPE sampleColor = SAMPLE_TEXTURE2D_X_LOD(_InputTexture, s_trilinear_clamp_sampler, ClampAndScaleUVForBilinear(sampleTC * _ScreenSize.zw), lod).CTYPE_SWIZZLE; float sampleCoC = GetCoCRadius(sampleTC); if (abs(sampleCoC) >= radius) From eaf9e1be42735ff74db601c869d3ab98fe82c1e3 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 23 Oct 2020 18:15:34 +0200 Subject: [PATCH 17/25] Temporary fix for Rendergraph post-dof TAA --- .../PostProcessing/PostProcessSystem.RenderGraph.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs index 885787fc296..075441f5982 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs @@ -616,12 +616,21 @@ TextureHandle DepthOfFieldPass(RenderGraph renderGraph, HDCamera hdCamera, Textu data.nextHistory, data.prevMVLen, data.nextMVLen); + + // Temporary hack to make post-dof TAA work with rendergraph (still the first frame flashes black). We need a better solution. + m_IsDoFHisotoryValid = true; }); source = passData.destination; } postDoFTAAEnabled = true; + + } + else + { + // Temporary hack to make post-dof TAA work with rendergraph (still the first frame flashes black). We need a better solution. + m_IsDoFHisotoryValid = false; } if (!postDoFTAAEnabled) From 8aaf50ff4ce6a60986f30d5dbb733ab92d433bbf Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 23 Oct 2020 18:56:19 +0200 Subject: [PATCH 18/25] Commit minor fixes before rebase --- .../Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs | 1 + .../Runtime/PostProcessing/PostProcessSystem.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs index 075441f5982..957629a4f79 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.RenderGraph.cs @@ -432,6 +432,7 @@ TextureHandle DepthOfFieldPass(RenderGraph renderGraph, HDCamera hdCamera, Textu if (m_DepthOfField.IsActive() && !isSceneView && m_DepthOfFieldFS && !isDoFPathTraced) { // If we switch DoF modes and the old one was not using TAA, make sure we invalidate the history + // Note: for Rendergraph the m_IsDoFHisotoryValid perhaps should be moved to the "pass data" struct if (taaEnabled && m_IsDoFHisotoryValid != m_DepthOfField.physicallyBased) { hdCamera.resetPostProcessingHistory = true; diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 3713a357e0c..468c5d5020d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2612,7 +2612,7 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter cs = dofParameters.dofCoCPyramidCS; kernel = dofParameters.dofCoCPyramidKernel; - float numMips = Mathf.Floor(Mathf.Log(Mathf.Max((dofParameters.camera.actualWidth + 31), (dofParameters.camera.actualHeight + 31)), 2)); + float numMips = Mathf.Floor(Mathf.Log(Mathf.Max(dofParameters.camera.actualWidth, dofParameters.camera.actualHeight), 2)); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, fullresCoC); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputMip1, fullresCoC, 1); From 4bbfc77e213c1825cf97625cf7c43214ff147108 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 23 Oct 2020 19:08:09 +0200 Subject: [PATCH 19/25] Revert "Remove the preview indicator from the UI" This reverts commit b6774cd9a7781927575766c68ba076579bde3c2b. --- .../Editor/PostProcessing/DepthOfFieldEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs index 3d3ed5475b1..37721c3ef0b 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs @@ -19,7 +19,7 @@ static partial class Styles public static GUIContent k_NearFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the near field does not blur anymore."); public static GUIContent k_FarFocusEnd = new GUIContent("End", "Sets the distance from the Camera at which the far field blur reaches its maximum blur radius."); - public static GUIContent k_PhysicallyBased = new GUIContent("Physically Based", "Uses a more accurate but slower physically based method to compute DoF."); + public static GUIContent k_PhysicallyBased = new GUIContent("Physically Based (Preview)", "Uses a more accurate but slower physically based method to compute DoF."); public static readonly string InfoBox = "Physically Based DoF currently has a high performance overhead. Enabling TAA is highly recommended when using this option."; } From c29249bbb04348af9aa5b39612574916ac48c84b Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 23 Oct 2020 19:16:02 +0200 Subject: [PATCH 20/25] Tweak parameter range to a more safe range --- .../Runtime/PostProcessing/PostProcessSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 468c5d5020d..84ac386a5db 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2554,7 +2554,7 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter // Map the old "max radius" parameters to a bigger range, so we can work on more challenging scenes float maxRadius = Mathf.Max(dofParameters.farMaxBlur, dofParameters.nearMaxBlur); - float cocLimit = Mathf.Clamp(16 * maxRadius, 1, 256); + float cocLimit = Mathf.Clamp(8 * maxRadius, 1, 128); //[1, 16] --> [1, 128] ComputeShader cs; int kernel; From a58f1c73d0d38ec23e7119583986583ec6acf19f Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Sun, 25 Oct 2020 05:34:32 +0100 Subject: [PATCH 21/25] Remove unused code --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 6 ------ 1 file changed, 6 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index b083f3ec3f9..210f8bde46e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -29,7 +29,6 @@ RW_TEXTURE2D_X(CTYPE, _OutputTexture); // A set of Defines to fine-tune the algorithm #define NUM_BUCKETS 3 -#define GRADIENT_NOISE #define RING_DENSITY 8.0 #define ADAPTIVE_RADIUS //#define OCTAWEB_SORTING @@ -185,13 +184,8 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float numSamples = max(ring * RING_DENSITY, 1); float dAng = 2.0f * PI / numSamples; -#ifndef GRADIENT_NOISE - float radius = max((ring - 1) * dR + stratum * dR, 0); - float ringOffset = 0.5 * fmod(ring, 2.0f) * dAng; -#else float radius = max((ring - 1) * dR + noise2 * dR, 0); float ringOffset = noise * dAng; -#endif float ringWeight = GetRingWeight(ring); From 95f3b03168e121e5bcae5f8626288cf7af0aca31 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Sun, 25 Oct 2020 05:35:20 +0100 Subject: [PATCH 22/25] Remove unused code 2 --- .../Runtime/PostProcessing/Shaders/DoFGather.compute | 1 - 1 file changed, 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 210f8bde46e..6766e1810e3 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -164,7 +164,6 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float maxRadius = GetCoCMaxRadius(posInputs.positionSS); float dR = maxRadius * rcp(NumRings); - float stratum = fmod(posInputs.positionSS.x + posInputs.positionSS.y, 2.0f); int sampleOffset = _TaaFrameInfo.w != 0.0 ? _TaaFrameInfo.z : 0; // Note: adjusting pseudo-randomly the sampleOffset for each pixel seems to considerably improve the sampling From 5a5bdbec280c382714b18b9845bf836f8e36c660 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Sun, 25 Oct 2020 06:30:06 +0100 Subject: [PATCH 23/25] Dof shader: tweak sampling --- .../Runtime/PostProcessing/PostProcessSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index 84ac386a5db..5386b270f4c 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -2625,7 +2625,7 @@ static void DoPhysicallyBasedDepthOfField(in DepthOfFieldParameters dofParameter cmd.DispatchCompute(cs, kernel, (dofParameters.camera.actualWidth + 31) / 32, (dofParameters.camera.actualHeight + 31) / 32, dofParameters.camera.viewCount); // do we need a second pass for the rest? - if (numMips > 6.0f && cocLimit > 64) + if (numMips > 6.0f && cocLimit > 32) { GetMipMapDimensions(fullresCoC, 6, out var mipMapWidth, out var mipMapHeight); cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._InputTexture, fullresCoC, 6); From a98db855ca4bdfc54e77ba0bbe33a415db00add4 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Sun, 25 Oct 2020 06:36:28 +0100 Subject: [PATCH 24/25] Dof shader: tweak sampling --- .../PostProcessing/Shaders/DoFGather.compute | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute index 6766e1810e3..6685908cb7f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/DoFGather.compute @@ -127,12 +127,6 @@ float GetNumSamples(float radius, float maxRadius) return 1.0 + seriesSum * RING_DENSITY; } -float GetRingWeight(int index) -{ - // TODO: need to investigate better sampling weights - return 1.0; -} - [numthreads(GROUP_RES, GROUP_RES, 1)] void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) { @@ -163,11 +157,11 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) float maxRadius = GetCoCMaxRadius(posInputs.positionSS); - float dR = maxRadius * rcp(NumRings); + float dR = rcp(NumRings); int sampleOffset = _TaaFrameInfo.w != 0.0 ? _TaaFrameInfo.z : 0; // Note: adjusting pseudo-randomly the sampleOffset for each pixel seems to considerably improve the sampling - float noise = InterleavedGradientNoise(posInputs.positionSS.xy, posInputs.positionSS.x + 3 * posInputs.positionSS.y + sampleOffset); + float noise = InterleavedGradientNoise(posInputs.positionSS.xy, sampleOffset); float noise2 = InterleavedGradientNoise(posInputs.positionSS.xy, 3 * posInputs.positionSS.x + posInputs.positionSS.y + sampleOffset); // Note: For zero radius we still go through the loop (for one iteration). We can avoid the cost of computing weigths if we early exit (at the cost of extra code complexity). @@ -180,13 +174,13 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) // Iterate over the octaweb pattern and gather the DoF samples for (float ring = totalRings; ring >= 0; ring -= 1.0) { - float numSamples = max(ring * RING_DENSITY, 1); + float numSamples = (ring > 0) ? RING_DENSITY : 1; float dAng = 2.0f * PI / numSamples; - float radius = max((ring - 1) * dR + noise2 * dR, 0); - float ringOffset = noise * dAng; + float stratum = max((ring - 1) * dR, 0); + float normalizedRadius = (ring > 0) ? stratum + noise2 * dR : 0; - float ringWeight = GetRingWeight(ring); + float ringOffset = noise * dAng; #ifdef OCTAWEB_SORTING float4 ringColor[NUM_BUCKETS]; @@ -209,21 +203,22 @@ void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) for (float ang = ringOffset; ang < 2 * PI; ang += dAng) { - float2 sampleTC = posInputs.positionSS + radius * PointInCircle(ang); + float sampleRadius = sqrt(normalizedRadius) * maxRadius; + float2 sampleTC = posInputs.positionSS + sampleRadius * PointInCircle(ang); sampleTC = clamp(sampleTC, float2(0, 0), _ScreenSize.xy - float2(1, 1)); // Select the appropriate mip to sample based on the amount of samples. Lower sample counts will be faster at the cost of "leaking" // Note: We have generated only 4 additional mip levels, so don't go any deeper than that - float lod = min(4, log2(2 * PI * radius * rcp(numSamples))); + float lod = min(4, log2(2 * PI * sampleRadius * rcp(numSamples))); CTYPE sampleColor = SAMPLE_TEXTURE2D_X_LOD(_InputTexture, s_trilinear_clamp_sampler, ClampAndScaleUVForBilinear(sampleTC * _ScreenSize.zw), lod).CTYPE_SWIZZLE; float sampleCoC = GetCoCRadius(sampleTC); - if (abs(sampleCoC) >= radius) + if (abs(sampleCoC) >= sampleRadius) { for (int j = 0; j < NUM_BUCKETS; ++j) { - float weight = ringWeight * GetSampleWeight(abs(sampleCoC)); - float bucketWeight = GetBucketWeight(sampleCoC, noise, j); + float weight = GetSampleWeight(abs(sampleCoC)); + float bucketWeight = GetBucketWeight(sampleCoC, noise2, j); weight *= bucketWeight; RING_COLOR[j] += float4(sampleColor.xyz * weight, weight); RING_MAXCOC[j] = max(RING_MAXCOC[j] * bucketWeight, abs(sampleCoC)); From 0eeada867ba095be267aeb837b6bd593100eebec Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Sun, 25 Oct 2020 06:47:01 +0100 Subject: [PATCH 25/25] Update changelog --- com.unity.render-pipelines.high-definition/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index 6d7893cba8b..0375781de12 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -43,6 +43,7 @@ The version number for this package has increased due to a version update of a r - Fixed issue where Default Volume Profile Asset change in project settings was not added to the undo stack (case 1285268). - Fixed undo after enabling compositor. - Fixed the ray tracing shadow UI being displayed while it shouldn't (case 1286391). +- Fixed issues with physically-based DoF, improved speed and robustness ### Changed - Combined occlusion meshes into one to reduce draw calls and state changes with XR single-pass.