Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,8 @@ public void BaseRendererDoesNotCreateRenderTexturesIfStackIsEmpty()
return;

Assert.IsFalse(baseRenderer.createColorTexture);
Assert.AreEqual(RenderTargetHandle.CameraTarget.Identifier(), baseRenderer.cameraColorTarget);

Assert.IsFalse(baseRenderer.createDepthTexture);
Assert.AreEqual(RenderTargetHandle.CameraTarget.Identifier(), baseRenderer.cameraDepthTarget);
}

[Test]
Expand All @@ -70,10 +68,8 @@ public void BaseRendererCreatesRenderTexturesIfStackIsNotEmpty()
Renderer2D baseRenderer = m_BaseCameraData.scriptableRenderer as Renderer2D;

Assert.IsTrue(baseRenderer.createColorTexture);
Assert.AreNotEqual(RenderTargetHandle.CameraTarget.Identifier(), baseRenderer.cameraColorTarget);

Assert.IsTrue(baseRenderer.createDepthTexture);
Assert.AreNotEqual(RenderTargetHandle.CameraTarget.Identifier(), baseRenderer.cameraDepthTarget);
}

[Test]
Expand All @@ -86,10 +82,8 @@ public void BaseRendererUsesDepthAttachmentOfColorTextureIfNoDepthTextureCreated
Renderer2D baseRenderer = m_BaseCameraData.scriptableRenderer as Renderer2D;

Assert.IsTrue(baseRenderer.createColorTexture);
Assert.AreNotEqual(RenderTargetHandle.CameraTarget.Identifier(), baseRenderer.cameraColorTarget);

Assert.IsFalse(baseRenderer.createDepthTexture);
Assert.AreEqual(baseRenderer.cameraColorTarget, baseRenderer.cameraDepthTarget);
}

[Test]
Expand All @@ -101,9 +95,6 @@ public void OverlayRendererUsesRenderTexturesFromBase()

Renderer2D baseRenderer = m_BaseCameraData.scriptableRenderer as Renderer2D;
Renderer2D overlayRenderer = m_OverlayCameraData.scriptableRenderer as Renderer2D;

Assert.AreEqual(baseRenderer.cameraColorTarget, overlayRenderer.cameraColorTarget);
Assert.AreEqual(baseRenderer.cameraDepthTarget, overlayRenderer.cameraDepthTarget);
}

[Test]
Expand Down
1 change: 1 addition & 0 deletions com.unity.render-pipelines.universal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed unlit shader function name ambiguity
- Fixed Terrain holes not appearing in shadows [case 1349305]
- VFX: Compilation issue with ShaderGraph and planar lit outputs [case 1349894](https://issuetracker.unity3d.com/product/unity/issues/guid/1349894/)
- Fixed an issue where _AfterPostProcessTexture was no longer being assigned in UniversalRenderer.
- Fixed an issue where TerrainLit was rendering color lighter than Lit [case 1340751] (https://issuetracker.unity3d.com/product/unity/issues/guid/1340751/)
- Fixed Camera rendering when capture action and post processing present. [case 1350313]
- Fixed artifacts in Speed Tree 8 billboard LODs due to SpeedTree LOD smoothing/crossfading [case 1348407]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public override void Execute(ScriptableRenderContext context, ref RenderingData
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, // color
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare); // depth
cmd.Blit(m_Source, cameraTarget, m_BlitMaterial);
cameraData.renderer.ConfigureCameraTarget(cameraTarget, cameraTarget);
}
else
{
Expand All @@ -116,6 +117,7 @@ public override void Execute(ScriptableRenderContext context, ref RenderingData
cmd.SetViewport(cameraData.pixelRect);
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, m_BlitMaterial);
cmd.SetViewProjectionMatrices(camera.worldToCameraMatrix, camera.projectionMatrix);
cameraData.renderer.ConfigureCameraTarget(cameraTarget, cameraTarget);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ public void SetupFinalPass(in RenderTargetHandle source, bool useSwapBuffer = fa
/// <inheritdoc/>
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
overrideCameraTarget = true;

if (m_Destination == RenderTargetHandle.CameraTarget)
return;

Expand Down Expand Up @@ -329,14 +331,31 @@ void Render(CommandBuffer cmd, ref RenderingData renderingData)
{
ref CameraData cameraData = ref renderingData.cameraData;
ref ScriptableRenderer renderer = ref cameraData.renderer;
bool isSceneViewCamera = cameraData.isSceneViewCamera;

//Check amount of swaps we have to do
//We blit back and forth without msaa untill the last blit.
bool useStopNan = cameraData.isStopNaNEnabled && m_Materials.stopNaN != null;
bool useSubPixeMorpAA = cameraData.antialiasing == AntialiasingMode.SubpixelMorphologicalAntiAliasing && SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES2;
var dofMaterial = m_DepthOfField.mode.value == DepthOfFieldMode.Gaussian ? m_Materials.gaussianDepthOfField : m_Materials.bokehDepthOfField;
bool useDepthOfField = m_DepthOfField.IsActive() && !isSceneViewCamera && dofMaterial != null;
bool useLensFlare = !LensFlareCommonSRP.Instance.IsEmpty();
bool useMotionBlur = m_MotionBlur.IsActive() && !isSceneViewCamera;
bool usePaniniProjection = m_PaniniProjection.IsActive() && !isSceneViewCamera;

int amountOfPassesRemaining = (useStopNan ? 1 : 0) + (useSubPixeMorpAA ? 1 : 0) + (useDepthOfField ? 1 : 0) + (useLensFlare ? 1 : 0) + (useMotionBlur ? 1 : 0) + (usePaniniProjection ? 1 : 0);

if (m_UseSwapBuffer && amountOfPassesRemaining > 0)
{
renderer.EnableSwapBufferMSAA(false);
}

// Don't use these directly unless you have a good reason to, use GetSource() and
// GetDestination() instead
bool tempTargetUsed = false;
bool tempTarget2Used = false;
RenderTargetIdentifier source = m_UseSwapBuffer ? renderer.cameraColorTarget : m_Source;
RenderTargetIdentifier destination = m_UseSwapBuffer ? renderer.GetCameraColorFrontBuffer(cmd) : -1;
bool isSceneViewCamera = cameraData.isSceneViewCamera;

RenderTargetIdentifier GetSource() => source;

Expand Down Expand Up @@ -365,8 +384,15 @@ RenderTargetIdentifier GetDestination()

void Swap(ref ScriptableRenderer r)
{
--amountOfPassesRemaining;
if (m_UseSwapBuffer)
{
//we want the last blit to be to MSAA
if (amountOfPassesRemaining == 0 && !m_HasFinalPass)
{
r.EnableSwapBufferMSAA(true);
}

r.SwapColorBuffer(cmd);
source = r.cameraColorTarget;
destination = r.GetCameraColorFrontBuffer(cmd);
Expand All @@ -382,7 +408,7 @@ void Swap(ref ScriptableRenderer r)

// Optional NaN killer before post-processing kicks in
// stopNaN may be null on Adreno 3xx. It doesn't support full shader level 3.5, but SystemInfo.graphicsShaderLevel is 35.
if (cameraData.isStopNaNEnabled && m_Materials.stopNaN != null)
if (useStopNan)
{
using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.StopNaNs)))
{
Expand All @@ -396,7 +422,7 @@ void Swap(ref ScriptableRenderer r)
}

// Anti-aliasing
if (cameraData.antialiasing == AntialiasingMode.SubpixelMorphologicalAntiAliasing && SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES2)
if (useSubPixeMorpAA)
{
using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.SMAA)))
{
Expand All @@ -408,8 +434,7 @@ void Swap(ref ScriptableRenderer r)
// Depth of Field
// Adreno 3xx SystemInfo.graphicsShaderLevel is 35, but instancing support is disabled due to buggy drivers.
// DOF shader uses #pragma target 3.5 which adds requirement for instancing support, thus marking the shader unsupported on those devices.
var dofMaterial = m_DepthOfField.mode.value == DepthOfFieldMode.Gaussian ? m_Materials.gaussianDepthOfField : m_Materials.bokehDepthOfField;
if (m_DepthOfField.IsActive() && !isSceneViewCamera && dofMaterial != null)
if (useDepthOfField)
{
var markerName = m_DepthOfField.mode.value == DepthOfFieldMode.Gaussian
? URPProfileId.GaussianDepthOfField
Expand All @@ -423,7 +448,7 @@ void Swap(ref ScriptableRenderer r)
}

// Motion blur
if (m_MotionBlur.IsActive() && !isSceneViewCamera)
if (useMotionBlur)
{
using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.MotionBlur)))
{
Expand All @@ -434,7 +459,7 @@ void Swap(ref ScriptableRenderer r)

// Panini projection is done as a fullscreen pass after all depth-based effects are done
// and before bloom kicks in
if (m_PaniniProjection.IsActive() && !isSceneViewCamera)
if (usePaniniProjection)
{
using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.PaniniProjection)))
{
Expand All @@ -444,7 +469,7 @@ void Swap(ref ScriptableRenderer r)
}

// Lens Flare
if (!LensFlareCommonSRP.Instance.IsEmpty())
if (useLensFlare)
{
bool usePanini;
float paniniDistance;
Expand Down Expand Up @@ -565,6 +590,7 @@ void Swap(ref ScriptableRenderer r)
#endif
{
cmd.SetRenderTarget(cameraTarget, colorLoadAction, RenderBufferStoreAction.Store, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);
cameraData.renderer.ConfigureCameraTarget(cameraTarget, cameraTarget);
cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);

if ((m_Destination == RenderTargetHandle.CameraTarget && !m_UseSwapBuffer) || m_ResolveToScreen)
Expand Down Expand Up @@ -600,6 +626,8 @@ void Swap(ref ScriptableRenderer r)

if (tempTarget2Used)
cmd.ReleaseTemporaryRT(ShaderConstants._TempTarget2);

cmd.ReleaseTemporaryRT(m_InternalLut.id);
}
}

Expand Down Expand Up @@ -1401,6 +1429,7 @@ void RenderFinalPass(CommandBuffer cmd, ref RenderingData renderingData)
cmd.SetViewport(cameraData.pixelRect);
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, material);
cmd.SetViewProjectionMatrices(cameraData.camera.worldToCameraMatrix, cameraData.camera.projectionMatrix);
cameraData.renderer.ConfigureCameraTarget(cameraTarget, cameraTarget);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,68 +10,115 @@ namespace UnityEngine.Rendering.Universal.Internal
//NOTE: This class is meant to be removed when RTHandles get implemented in urp
internal sealed class RenderTargetBufferSystem
{
RenderTargetHandle RTA;
RenderTargetHandle RTB;
bool m_FirstIsBackBuffer = true;
RenderTextureDescriptor m_Desc;
FilterMode m_FilterMode;

int m_NameA;
int m_NameB;
struct SwapBuffer
{
public RenderTargetHandle rt;
public int name;
public int msaa;
}
SwapBuffer m_A, m_B;
static bool m_AisBackBuffer = true;

static RenderTextureDescriptor m_Desc;
FilterMode m_FilterMode;
bool m_AllowMSAA = true;
bool m_RTisAllocated = false;

SwapBuffer backBuffer { get { return m_AisBackBuffer ? m_A : m_B; } }
SwapBuffer frontBuffer { get { return m_AisBackBuffer ? m_B : m_A; } }

public RenderTargetBufferSystem(string name)
{
m_NameA = Shader.PropertyToID(name + "A");
m_NameB = Shader.PropertyToID(name + "B");
RTA.Init(name + "A");
RTB.Init(name + "B");
m_A.name = Shader.PropertyToID(name + "A");
m_B.name = Shader.PropertyToID(name + "B");
m_A.rt.Init(name + "A");
m_B.rt.Init(name + "B");
}

public RenderTargetHandle GetBackBuffer()
{
return m_FirstIsBackBuffer ? RTA : RTB;
return backBuffer.rt;
}

public RenderTargetHandle GetBackBuffer(CommandBuffer cmd)
{
if (!m_RTisAllocated)
Initialize(cmd);
return m_FirstIsBackBuffer ? RTA : RTB;
return backBuffer.rt;
}

public RenderTargetHandle GetFrontBuffer(CommandBuffer cmd)
{
if (!m_RTisAllocated)
Initialize(cmd);
return m_FirstIsBackBuffer ? RTB : RTA;

int pipelineMSAA = m_Desc.msaaSamples;
int bufferMSAA = frontBuffer.msaa;

if (m_AllowMSAA && bufferMSAA != pipelineMSAA)
{
//We don't want a depth buffer on B buffer
var desc = m_Desc;
if (m_AisBackBuffer)
desc.depthBufferBits = 0;

cmd.ReleaseTemporaryRT(frontBuffer.name);
cmd.GetTemporaryRT(frontBuffer.name, desc, m_FilterMode);

if (m_AisBackBuffer)
m_B.msaa = desc.msaaSamples;
else m_A.msaa = desc.msaaSamples;
}
else if (!m_AllowMSAA && bufferMSAA > 1)
{
//We don't want a depth buffer on B buffer
var desc = m_Desc;
desc.msaaSamples = 1;
if (m_AisBackBuffer)
desc.depthBufferBits = 0;

cmd.ReleaseTemporaryRT(frontBuffer.name);
cmd.GetTemporaryRT(frontBuffer.name, desc, m_FilterMode);

if (m_AisBackBuffer)
m_B.msaa = desc.msaaSamples;
else m_A.msaa = desc.msaaSamples;
}

return frontBuffer.rt;
}

public void Swap()
{
m_FirstIsBackBuffer = !m_FirstIsBackBuffer;
m_AisBackBuffer = !m_AisBackBuffer;
}

void Initialize(CommandBuffer cmd)
{
cmd.GetTemporaryRT(m_NameA, m_Desc, m_FilterMode);
m_A.msaa = m_Desc.msaaSamples;
m_B.msaa = m_Desc.msaaSamples;

cmd.GetTemporaryRT(m_A.name, m_Desc, m_FilterMode);
var descB = m_Desc;
descB.depthBufferBits = 0;
cmd.GetTemporaryRT(m_NameB, m_Desc, m_FilterMode);
//descB.depthBufferBits = 0;
cmd.GetTemporaryRT(m_B.name, descB, m_FilterMode);

m_RTisAllocated = true;
}

public void Clear(CommandBuffer cmd)
{
cmd.ReleaseTemporaryRT(m_NameA);
cmd.ReleaseTemporaryRT(m_NameB);
cmd.ReleaseTemporaryRT(m_A.name);
cmd.ReleaseTemporaryRT(m_B.name);

m_FirstIsBackBuffer = true;
m_AisBackBuffer = true;
m_AllowMSAA = true;
}

public void SetCameraSettings(CommandBuffer cmd, RenderTextureDescriptor desc, FilterMode filterMode)
{
Clear(cmd); //SetCameraSettings is called when new stack starts rendering. Make sure the targets are updated to use the new descriptor.

m_Desc = desc;
m_FilterMode = filterMode;

Expand All @@ -80,7 +127,12 @@ public void SetCameraSettings(CommandBuffer cmd, RenderTextureDescriptor desc, F

public RenderTargetHandle GetBufferA()
{
return RTA;
return m_A.rt;
}

public void EnableMSAA(bool enable)
{
m_AllowMSAA = enable;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,7 @@ static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorAtt
}

internal virtual void SwapColorBuffer(CommandBuffer cmd) { }
internal virtual void EnableSwapBufferMSAA(bool enable) { }

[Conditional("UNITY_EDITOR")]
void DrawGizmos(ScriptableRenderContext context, Camera camera, GizmoSubset gizmoSubset)
Expand Down
Loading