From 77f3a104105d875f9dc420ff11c239aae4e6f14b Mon Sep 17 00:00:00 2001 From: TW0 Date: Mon, 6 Apr 2026 22:30:42 +0100 Subject: [PATCH] Imported changes from Oculus-VR:Unity-Graphics:6000.0/17.0.4-subpass --- .../Compiler/CompilerContextData.cs | 20 ++++++ .../Compiler/NativePassCompiler.cs | 7 ++ .../RenderGraph/IRenderGraphBuilder.cs | 9 +++ .../RenderGraph/RenderGraph.Compiler.cs | 5 ++ .../Runtime/RenderGraph/RenderGraph.cs | 4 ++ .../RenderGraph/RenderGraphBuilders.cs | 25 +++++-- .../Runtime/RenderGraph/RenderGraphPass.cs | 13 ++++ .../RenderGraph/RenderGraphResourceTexture.cs | 2 + .../Runtime/XR/XRSystem.cs | 1 + .../RenderObjectsPassFeatureEditor.cs | 10 +++ .../Runtime/Passes/FinalBlitPass.cs | 1 + .../Passes/PostProcessPassRenderGraph.cs | 70 ++++++++++++++++++- .../Runtime/Passes/RenderObjectsPass.cs | 17 ++++- .../Runtime/RendererFeatures/RenderObjects.cs | 12 ++++ .../Runtime/RenderingUtils.cs | 4 +- .../Runtime/ScriptableRenderer.cs | 4 +- .../Runtime/UniversalRenderPipelineCore.cs | 3 + .../Runtime/UniversalRenderer.cs | 4 +- .../Runtime/UniversalRendererRenderGraph.cs | 26 ++++++- .../ShaderLibrary/ShaderGraphFunctions.hlsl | 9 +++ .../Shaders/PostProcessing/UberPost.shader | 42 +++++++++++ 21 files changed, 272 insertions(+), 16 deletions(-) diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/CompilerContextData.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/CompilerContextData.cs index 49b0d721fbf..27aae095bd7 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/CompilerContextData.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/CompilerContextData.cs @@ -154,6 +154,26 @@ public ref ResourceReaderData ResourceReader(in ResourceHandle h, int i) // Data per native renderpas public NativeList nativePassData; public NativeList nativeSubPassData; //Tighty packed list of per nrp subpasses + + public bool passMerged(int passId1, int passId2) + { + return passData[passId1].nativePassIndex == passData[passId2].nativePassIndex; + } + + public bool nativepassFragmentsContain(int passId, int fragIndex) + { + int nativePassId = passData[passId].nativePassIndex; + if (nativePassId <= nativePassData.Length) + { + NativePassData data = nativePassData[nativePassId]; + for (int i = 0; i < data.fragments.size; i++) + { + if (data.fragments[i].resource.index == fragIndex) + return true; + } + } + return false; + } // resources can be added as fragment both as input and output so make sure not to add them twice (return true upon new addition) public bool TryAddToFragmentList(in TextureAccess access, int listFirstIndex, int numItems, out string errorMessage) diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.cs index 90c5918a442..af5a7c0d4ea 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.cs @@ -2022,6 +2022,13 @@ public void ExecuteGraph(InternalRenderGraphContext rgContext, RenderGraphResour ExecuteBeginRenderPass(rgContext, resources, ref nativePass); nrpBegan = true; inRenderPass = true; + + for (int subpassIndex = nativePass.firstGraphPass; subpassIndex <= nativePass.lastGraphPass; subpassIndex++) + { + ref var subpassData = ref contextData.passData.ElementAt(subpassIndex); + rgContext.executingPass = passes[subpassData.passId]; + passes[subpassData.passId].PreExecute(rgContext); + } } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/IRenderGraphBuilder.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/IRenderGraphBuilder.cs index 5b53db80e89..268fb3021a3 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/IRenderGraphBuilder.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/IRenderGraphBuilder.cs @@ -273,6 +273,15 @@ void SetRenderAttachmentDepth(TextureHandle tex, AccessFlags flags = AccessFlags /// How this pass will access the buffer. Default value is set to AccessFlag.Read. /// The value passed to 'input'. You should not use the returned value it will be removed in the future. BufferHandle UseBufferRandomAccess(BufferHandle tex, int index, bool preserveCounterValue, AccessFlags flags = AccessFlags.Read); + + /// + /// Specify the pre-render function to use for this pass. + /// The call happens when a native render pass starts + /// + /// The Type of the class that provides data to the Render Pass. + /// Render function for the pass. + public void SetPreRenderFunc(BaseRenderFunc preRenderFunc) + where PassData : class, new(); } /// diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.Compiler.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.Compiler.cs index dbe3f0dab2d..417f1b797d3 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.Compiler.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.Compiler.cs @@ -40,5 +40,10 @@ void ExecuteNativeRenderGraph() nativeCompiler.ExecuteGraph(m_RenderGraphContext, m_Resources, m_RenderPasses); } } + + public bool IsPassUsingRenderTarget(int passId, int resourceId) + { + return nativeCompiler.contextData.nativepassFragmentsContain(passId, resourceId); + } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs index 3d3c9d994e0..c6e10329d4b 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -209,6 +209,10 @@ public void FromInternalContext(InternalRenderGraphContext context) rastercmd.m_ExecutingPass = context.executingPass; cmd = rastercmd; } + + public int CurrentRGPassId() { + return cmd.m_ExecutingPass.index; + } /// public readonly TextureUVOrigin GetTextureUVOrigin(in TextureHandle textureHandle) diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilders.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilders.cs index 0418d32c776..2055ba1b875 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilders.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilders.cs @@ -350,7 +350,7 @@ public void SetGlobalTextureAfterPass(in TextureHandle input, int propertyId) // Shared validation between SetRenderAttachment/SetRenderAttachmentDepth [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")] - private void CheckUseFragment(in TextureHandle tex, bool isDepth) + private void CheckUseFragment(in TextureHandle tex, bool isDepth, bool ignoreReadTextureCheck = false) { if (RenderGraph.enableValidityChecks) { @@ -362,12 +362,15 @@ private void CheckUseFragment(in TextureHandle tex, bool isDepth) // SetRenderAttachment() // UseTexture(grab) // will work but not the other way around - for (int i = 0; i < m_RenderPass.resourceReadLists[tex.handle.iType].Count; i++) + if (!ignoreReadTextureCheck) { - if (m_RenderPass.resourceReadLists[tex.handle.iType][i].index == tex.handle.index) + for (int i = 0; i < m_RenderPass.resourceReadLists[tex.handle.iType].Count; i++) { - alreadyUsed = true; - break; + if (m_RenderPass.resourceReadLists[tex.handle.iType][i].index == tex.handle.index) + { + alreadyUsed = true; + break; + } } } @@ -478,7 +481,12 @@ public void SetInputAttachment(TextureHandle tex, int index, AccessFlags flags, { CheckFrameBufferFetchEmulationIsSupported(tex); - CheckUseFragment(tex, false); + // Depth texture can be bind as input attachment, bypass the depth format check inside CheckUseFragment + m_Resources.GetRenderTargetInfo(tex.handle, out var info); + bool isDepth = GraphicsFormatUtility.IsDepthFormat(info.format); + // Bypass the already used check for texture read, so that an attachment can be used as depth and input in one subpass + bool ignoreReadTextureCheck = true; + CheckUseFragment(tex, isDepth, ignoreReadTextureCheck); var versionedTextureHandle = new TextureHandle(UseResource(tex.handle, flags)); m_RenderPass.SetFragmentInputRaw(versionedTextureHandle, index, flags, mipLevel, depthSlice); } @@ -518,6 +526,11 @@ public BufferHandle UseBufferRandomAccess(BufferHandle input, int index, bool pr m_RenderPass.SetRandomWriteResourceRaw(h.handle, index, preserveCounterValue, flags); return input; } + + public void SetPreRenderFunc(BaseRenderFunc preRenderFunc) where PassData : class, new() + { + ((RasterRenderGraphPass)m_RenderPass).preRenderFunc = preRenderFunc; + } public void SetRenderFunc(BaseRenderFunc renderFunc) where PassData : class, new() { diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs index eeee3981578..3e22e5cdb96 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs @@ -8,6 +8,7 @@ namespace UnityEngine.Rendering.RenderGraphModule [DebuggerDisplay("RenderPass: {name} (Index:{index} Async:{enableAsyncCompute})")] abstract class RenderGraphPass { + public virtual void PreExecute(InternalRenderGraphContext renderGraphContext) { return; } public abstract void Execute(InternalRenderGraphContext renderGraphContext); public abstract void Release(RenderGraphObjectPool pool); public abstract bool HasRenderFunc(); @@ -701,6 +702,18 @@ internal sealed class RasterRenderGraphPass : BaseRenderGraphPass preRenderFunc; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override void PreExecute(InternalRenderGraphContext renderGraphContext) + { + if (preRenderFunc != null) + { + RasterGraphContext temp_c = new RasterGraphContext(); + temp_c.FromInternalContext(renderGraphContext); + preRenderFunc(data, temp_c); + } + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public override void Execute(InternalRenderGraphContext renderGraphContext) diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceTexture.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceTexture.cs index 77917f95fa7..41008a79128 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceTexture.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResourceTexture.cs @@ -217,6 +217,8 @@ internal TextureHandle(int handle, bool shared = false, bool builtin = false) /// The rendergraph instance that was used to create the texture on. Texture handles are a lightweight object, all information is stored on the RenderGraph itself. /// The texture descriptor for the given texture handle. public TextureDesc GetDescriptor(RenderGraph renderGraph) { return renderGraph.GetTextureDesc(this); } + + public int GetResourceId() { return handle.index; } } /// diff --git a/Packages/com.unity.render-pipelines.core/Runtime/XR/XRSystem.cs b/Packages/com.unity.render-pipelines.core/Runtime/XR/XRSystem.cs index 9d9d1a97fda..7c46ac1ad00 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/XR/XRSystem.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/XR/XRSystem.cs @@ -538,6 +538,7 @@ private static RenderTextureDescriptor XrRenderTextureDescToUnityRenderTextureDe rtDesc.volumeDepth = xrDesc.volumeDepth; rtDesc.vrUsage = xrDesc.vrUsage; rtDesc.sRGB = xrDesc.sRGB; + rtDesc.msaaSamples = xrDesc.msaaSamples; rtDesc.shadowSamplingMode = xrDesc.shadowSamplingMode; return rtDesc; } diff --git a/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/RenderObjectsPassFeatureEditor.cs b/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/RenderObjectsPassFeatureEditor.cs index 5b2861bfa4b..cc168fa99f7 100644 --- a/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/RenderObjectsPassFeatureEditor.cs +++ b/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/RenderObjectsPassFeatureEditor.cs @@ -52,6 +52,7 @@ internal class Styles public static GUIContent overrideDepth = new GUIContent("Depth", "Select this option to specify how this Renderer Feature affects or uses the values in the Depth buffer."); public static GUIContent writeDepth = new GUIContent("Write Depth", "Choose to write depth to the screen."); public static GUIContent depthState = new GUIContent("Depth Test", "Choose a new depth test function."); + public static GUIContent depthInput = new GUIContent("Depth Input", "Choose to bind depth as an input attachment."); //Camera Settings public static GUIContent overrideCamera = new GUIContent("Camera", "Override camera matrices. Toggling this setting will make camera use perspective projection."); @@ -86,6 +87,7 @@ internal class Styles private SerializedProperty m_OverrideDepth; private SerializedProperty m_WriteDepth; private SerializedProperty m_DepthState; + private SerializedProperty m_DepthInput; //Stencil props private SerializedProperty m_StencilSettings; //Caemra props @@ -140,6 +142,7 @@ private void Init(SerializedProperty property) m_OverrideDepth = property.FindPropertyRelative("overrideDepthState"); m_WriteDepth = property.FindPropertyRelative("enableWrite"); m_DepthState = property.FindPropertyRelative("depthCompareFunction"); + m_DepthInput = property.FindPropertyRelative("depthInput"); //Stencil m_StencilSettings = property.FindPropertyRelative("stencilSettings"); @@ -278,6 +281,13 @@ void DoDepthOverride(ref Rect rect) EditorGUI.indentLevel++; //Write depth EditorGUI.PropertyField(rect, m_WriteDepth, Styles.writeDepth); + rect.y += Styles.defaultLineSpace; + EditorGUI.PropertyField(rect, m_DepthInput, Styles.depthInput); + if (m_DepthInput.boolValue && m_WriteDepth.boolValue) { + Debug.LogWarning("Depth Input and Write Depth can't be used at the same time. Write Depth has been disabled."); + m_WriteDepth.boolValue = false; + } + rect.y += Styles.defaultLineSpace; //Depth testing options EditorGUI.PropertyField(rect, m_DepthState, Styles.depthState); diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/FinalBlitPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/FinalBlitPass.cs index 6b3e8cc8a65..9eab1c77f9f 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/FinalBlitPass.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/FinalBlitPass.cs @@ -219,6 +219,7 @@ public override void Execute(ScriptableRenderContext context, ref RenderingData #endif CoreUtils.SetRenderTarget(renderingData.commandBuffer, cameraTargetHandle.nameID, loadAction, RenderBufferStoreAction.Store, ClearFlag.None, Color.clear); + // The final blit can't be easily avoided for the logo screen when using HDR, manually correct the scale bias when using nrp with render graph Vector4 scaleBias = RenderingUtils.GetFinalBlitScaleBias(m_Source, cameraTargetHandle, cameraData); ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer), m_PassData, m_Source, cameraTargetHandle, cameraData, scaleBias); cameraData.renderer.ConfigureCameraTarget(cameraTargetHandle, cameraTargetHandle); diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPassRenderGraph.cs b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPassRenderGraph.cs index d5600ae88c8..01b2e6732c1 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPassRenderGraph.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPassRenderGraph.cs @@ -2465,6 +2465,11 @@ private class UberPostPassData internal bool isBackbuffer; internal bool enableAlphaOutput; internal bool hasFinalPass; + internal bool isPassMerged; + + // For handling yFlip + internal int backBufferResourceId; + internal Vector2Int cameraTargetSizeCopy; } TextureHandle TryGetCachedUserLutTextureHandle(RenderGraph renderGraph) @@ -2526,9 +2531,25 @@ public void RenderUberPost(RenderGraph renderGraph, ContextContainer frameData, builder.AllowGlobalStateModification(true); passData.destinationTexture = destTexture; - builder.SetRenderAttachment(destTexture, 0, AccessFlags.Write); - passData.sourceTexture = sourceTexture; - builder.UseTexture(sourceTexture, AccessFlags.Read); + builder.SetRenderAttachment(destTexture, 0, AccessFlags.WriteAll); + bool tileCompatible = !( + m_Bloom.IsActive() || + m_ChromaticAberration.IsActive() || + m_DepthOfField.IsActive() || + m_LensDistortion.IsActive() || + m_MotionBlur.IsActive() || + m_PaniniProjection.IsActive()); + bool passMerged = SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan && tileCompatible; + + if (passMerged) + { + builder.SetInputAttachment(sourceTexture, index: 0, AccessFlags.Read); + } + else + { + passData.sourceTexture = sourceTexture; + builder.UseTexture(sourceTexture, AccessFlags.Read); + } passData.lutTexture = lutTexture; builder.UseTexture(lutTexture, AccessFlags.Read); passData.lutParams = lutParams; @@ -2551,6 +2572,17 @@ public void RenderUberPost(RenderGraph renderGraph, ContextContainer frameData, passData.isHdrGrading = hdrGrading; passData.enableAlphaOutput = enableAlphaOutput; passData.hasFinalPass = hasFinalPass; + passData.isPassMerged = passMerged; + + // Reset the camera data in the pre-render function where we know if the native pass need y flip or not + passData.cameraTargetSizeCopy = new Vector2Int(passData.cameraData.cameraTargetDescriptor.width, passData.cameraData.cameraTargetDescriptor.height); + passData.backBufferResourceId = frameData.Get().backBufferColor.GetResourceId(); + + builder.SetPreRenderFunc((UberPostPassData data, RasterGraphContext context) => + { + bool yFlip = !SystemInfo.graphicsUVStartsAtTop || (renderGraph.nativeRenderPassesEnabled && renderGraph.IsPassUsingRenderTarget(context.CurrentRGPassId(), data.backBufferResourceId)); + data.cameraData.renderer.SetPerCameraShaderVariables(context.cmd, data.cameraData, data.cameraTargetSizeCopy, !yFlip); + }); builder.SetRenderFunc(static (UberPostPassData data, RasterGraphContext context) => { @@ -2583,6 +2615,7 @@ public void RenderUberPost(RenderGraph renderGraph, ContextContainer frameData, } CoreUtils.SetKeyword(material, ShaderKeywordStrings._ENABLE_ALPHA_OUTPUT, data.enableAlphaOutput); + CoreUtils.SetKeyword(material, "SUBPASS_INPUT_ATTACHMENT", data.isPassMerged); // Done with Uber, blit it #if ENABLE_VR && ENABLE_XR_MODULE @@ -2590,6 +2623,37 @@ public void RenderUberPost(RenderGraph renderGraph, ContextContainer frameData, ScaleViewportAndDrawVisibilityMesh(in context, in data.sourceTexture, in data.destinationTexture, data.cameraData, material, data.hasFinalPass); else #endif + if (data.isPassMerged) + { + switch (data.cameraData.cameraTargetDescriptor.msaaSamples) + { + case 8: + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa2, false); + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa4, false); + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa8, true); + break; + case 4: + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa2, false); + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa4, true); + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa8, false); + break; + case 2: + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa2, true); + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa4, false); + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa8, false); + break; + default: + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa2, false); + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa4, false); + CoreUtils.SetKeyword(material, ShaderKeywordStrings.Msaa8, false); + break; + } + + + Vector4 scaleBias = new Vector4(1, 1, 0, 0); + Blitter.BlitTexture(cmd, scaleBias, material, 0); + } + else ScaleViewportAndBlit(in context, in data.sourceTexture, in data.destinationTexture, data.cameraData, material, data.hasFinalPass); }); diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/RenderObjectsPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/RenderObjectsPass.cs index 4d8557dec4f..25808a7bd30 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/RenderObjectsPass.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/RenderObjectsPass.cs @@ -15,6 +15,9 @@ public partial class RenderObjectsPass : ScriptableRenderPass RenderQueueType renderQueueType; FilteringSettings m_FilteringSettings; RenderObjects.CustomCameraSettings m_CameraSettings; + + private const string DEPTH_INPUT_ATTACHMENT = "_DEPTH_INPUT_ATTACHMENT"; + private static GlobalKeyword m_depthInputKeyword; /// /// The override material to use. @@ -35,6 +38,8 @@ public partial class RenderObjectsPass : ScriptableRenderPass /// The pass index to use with the override shader. /// public int overrideShaderPassIndex { get; set; } + + public bool useDepthInputAttachment { get; set; } = false; List m_ShaderTagIdList = new List(); private PassData m_PassData; @@ -135,6 +140,8 @@ internal void Init(RenderPassEvent renderPassEvent, string[] shaderTags, RenderQ m_RenderStateBlock = new RenderStateBlock(RenderStateMask.Nothing); m_CameraSettings = cameraSettings; + + m_depthInputKeyword = GlobalKeyword.Create(DEPTH_INPUT_ATTACHMENT); } #if URP_COMPATIBILITY_MODE @@ -280,8 +287,15 @@ public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer passData.color = resourceData.activeColorTexture; builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.Write); - if (cameraData.imageScalingMode != ImageScalingMode.Upscaling || passData.renderPassEvent != RenderPassEvent.AfterRenderingPostProcessing) + if (useDepthInputAttachment && SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan) + { + builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.Read); + builder.SetInputAttachment(resourceData.activeDepthTexture, index: 0, AccessFlags.Read); + } + else if (cameraData.imageScalingMode != ImageScalingMode.Upscaling || passData.renderPassEvent != RenderPassEvent.AfterRenderingPostProcessing) + { builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.Write); + } TextureHandle mainShadowsTexture = resourceData.mainShadowsTexture; TextureHandle additionalShadowsTexture = resourceData.additionalShadowsTexture; @@ -324,6 +338,7 @@ public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => { + rgContext.cmd.SetKeyword(m_depthInputKeyword, useDepthInputAttachment && SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan); var isYFlipped = RenderingUtils.IsHandleYFlipped(rgContext, in data.color); ExecutePass(data, rgContext.cmd, data.rendererListHdl, isYFlipped); }); diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/RenderObjects.cs b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/RenderObjects.cs index 70ad2ac5cde..cb8115de570 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/RenderObjects.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/RenderObjects.cs @@ -119,6 +119,11 @@ public enum OverrideMaterialMode /// The camera settings to use. /// public CustomCameraSettings cameraSettings = new CustomCameraSettings(); + + /// + /// Sets whether it should have depth as an input attachment or not. + /// + public bool depthInput = false; } /// @@ -223,7 +228,14 @@ public override void Create() } if (settings.overrideDepthState) + { + // In edit mode, the camera being used is the sceneview camera, which causes issues for depth input + if (Application.isPlaying) + { + renderObjectsPass.useDepthInputAttachment = settings.depthInput; + } renderObjectsPass.SetDepthState(settings.enableWrite, settings.depthCompareFunction); + } if (settings.stencilSettings.overrideStencilState) renderObjectsPass.SetStencilState(settings.stencilSettings.stencilReference, diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs b/Packages/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs index 38920622892..ea07b52ead7 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs @@ -1137,10 +1137,10 @@ internal static bool IsHandleYFlipped(in RasterGraphContext renderGraphContext, /// /// /// - internal static Vector4 GetFinalBlitScaleBias(RTHandle source, RTHandle destination, UniversalCameraData cameraData) + internal static Vector4 GetFinalBlitScaleBias(RTHandle source, RTHandle destination, UniversalCameraData cameraData, bool nrpRenderGraph = false) { Vector2 scale = source.useScaling ? new Vector2(source.rtHandleProperties.rtHandleScale.x, source.rtHandleProperties.rtHandleScale.y) : Vector2.one; - var yflip = cameraData.IsRenderTargetProjectionMatrixFlipped(destination); + var yflip = cameraData.IsRenderTargetProjectionMatrixFlipped(destination) || (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan && nrpRenderGraph); Vector4 scaleBias = !yflip ? new Vector4(scale.x, -scale.y, 0, scale.y) : new Vector4(scale.x, scale.y, 0, 0); return scaleBias; diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs b/Packages/com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs index 2620ecccb6a..b68e51a1462 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs @@ -290,7 +290,7 @@ void SetPerCameraShaderVariables(RasterCommandBuffer cmd, UniversalCameraData ca } #endif - void SetPerCameraShaderVariables(RasterCommandBuffer cmd, UniversalCameraData cameraData, Vector2Int cameraTargetSizeCopy, bool isTargetFlipped) + public void SetPerCameraShaderVariables(RasterCommandBuffer cmd, UniversalCameraData cameraData, Vector2Int cameraTargetSizeCopy, bool isTargetFlipped) { using var profScope = new ProfilingScope(Profiling.setPerCameraShaderVariables); @@ -1001,7 +1001,7 @@ internal void SetupRenderGraphCameraProperties(RenderGraph renderGraph, TextureH builder.SetRenderFunc((PassData data, RasterGraphContext context) => { - bool yFlipped = SystemInfo.graphicsUVStartsAtTop && RenderingUtils.IsHandleYFlipped(context, in data.target); + bool yFlipped = SystemInfo.graphicsUVStartsAtTop && RenderingUtils.IsHandleYFlipped(context, in data.target) && !(renderGraph.nativeRenderPassesEnabled && SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan); // This is still required because of the following reasons: // - Camera billboard properties. diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs index 8ecef590ee4..00153fe1a1b 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs @@ -1485,6 +1485,9 @@ public static class ShaderKeywordStrings /// Keyword used for Multi Sampling Anti-Aliasing (MSAA) with 4 per pixel sample count. public const string Msaa4 = "_MSAA_4"; + + /// Keyword used for Multi Sampling Anti-Aliasing (MSAA) with 8 per pixel sample count. + public const string Msaa8 = "_MSAA_8"; } public sealed partial class UniversalRenderPipeline diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs index bf5c2bd6cb8..1279674ebd8 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs @@ -2025,7 +2025,9 @@ static bool RequiresIntermediateColorTexture(UniversalCameraData cameraData, in bool isScaledRender = cameraData.imageScalingMode != ImageScalingMode.None; bool isScalableBufferManagerUsed = IsScalableBufferManagerUsed(cameraData); bool isCompatibleBackbufferTextureDimension = cameraTargetDescriptor.dimension == TextureDimension.Tex2D; - bool requiresExplicitMsaaResolve = msaaSamples > 1 && PlatformRequiresExplicitMsaaResolve(); + // In XR when the eye buffer have msaa auto resolve (the render target has msaa samples > 1), we don't need an explicit resolve. + // This will avoid the finalBlit pass when using MSAA. + bool requiresExplicitMsaaResolve = msaaSamples > 1 && !(cameraData.xr.enabled && cameraData.xr.renderTargetDesc.msaaSamples > 1) && PlatformRequiresExplicitMsaaResolve(); bool isOffscreenRender = cameraData.targetTexture != null && !isSceneViewCamera; bool isCapturing = cameraData.captureActions != null; diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRendererRenderGraph.cs b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRendererRenderGraph.cs index a96d7119a67..9d1d087f0a1 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRendererRenderGraph.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRendererRenderGraph.cs @@ -1049,6 +1049,9 @@ private void OnMainRendering(RenderGraph renderGraph, ScriptableRenderContext co // Record depthMotion pass and import XR resources into the rendergraph. m_XRDepthMotionPass?.Render(renderGraph, frameData); + + // Depth motion pass will break the subpass merge assumption, reset the projection matrix before draw opaque pass + SetupRenderGraphCameraProperties(renderGraph, resourceData.backBufferColor); } #endif @@ -1388,7 +1391,6 @@ private void OnAfterRendering(RenderGraph renderGraph, bool applyPostProcessing) bool resolvePostProcessingToCameraTarget = !hasCaptureActions && !hasPassesAfterPostProcessing && !applyFinalPostProcessing; bool needsColorEncoding = DebugHandler == null || !DebugHandler.HDRDebugViewIsActive(cameraData.resolveFinalTarget); - bool xrDepthTargetResolved = resourceData.activeDepthID == UniversalResourceData.ActiveID.BackBuffer; DebugHandler debugHandler = ScriptableRenderPass.GetActiveDebugHandler(cameraData); bool resolveToDebugScreen = debugHandler != null && debugHandler.WriteToDebugScreenTexture(cameraData.resolveFinalTarget); @@ -1562,6 +1564,9 @@ private void OnAfterRendering(RenderGraph renderGraph, bool applyPostProcessing) #if ENABLE_VR && ENABLE_XR_MODULE if (cameraData.xr.enabled) { + // Resolve might happen in post processing pass + bool xrDepthTargetResolved = resourceData.activeDepthID == UniversalResourceData.ActiveID.BackBuffer; + // Populate XR depth as requested by XR provider. if (!xrDepthTargetResolved && cameraData.xr.copyDepth) { @@ -1775,6 +1780,13 @@ void ImportBackBuffers(RenderGraph renderGraph, UniversalCameraData cameraData, importInfoDepth = importInfo; importInfoDepth.format = cameraData.cameraTargetDescriptor.depthStencilFormat; +#if UNITY_EDITOR + // In game window, Unity will use the scaled resolution, but the back buffer is still using pixel resolution + // This will prevent the subpass from working as the camera target's resolution is different from the backbuffer + cameraData.cameraTargetDescriptor.width = Screen.width; + cameraData.cameraTargetDescriptor.height = Screen.height; + cameraData.cameraTargetDescriptor.msaaSamples = numSamples; +#endif } else { @@ -1812,9 +1824,18 @@ void ImportBackBuffers(RenderGraph renderGraph, UniversalCameraData cameraData, Debug.LogWarning("In the render graph API, the output Render Texture must have a depth buffer. When you select a Render Texture in any camera's Output Texture property, the Depth Stencil Format property of the texture must be set to a value other than None."); } } + + if (importInfo.msaaSamples > 1) + { + // This will discard the MSAA texture and store the resolved texture + importBackbufferColorParams.discardOnLastUse = true; + } if (!isCameraTargetOffscreenDepth) + { resourceData.backBufferColor = renderGraph.ImportTexture(m_TargetColorHandle, importInfo, importBackbufferColorParams); + cameraData.cameraTargetDescriptor.bindMS = importInfo.msaaSamples > 1; // When using MSAA and post processing, the _CameraTargetAttachment should be a MSAA only texture, as we don't need to resolve it. + } resourceData.backBufferDepth = renderGraph.ImportTexture(m_TargetDepthHandle, importInfoDepth, importBackbufferDepthParams); } @@ -1854,6 +1875,9 @@ void CreateIntermediateCameraColorAttachment(RenderGraph renderGraph, UniversalC importColorParams.clearOnFirstUse = clearColor; importColorParams.clearColor = clearBackgroundColor; importColorParams.discardOnLastUse = cameraData.resolveFinalTarget; // Last camera in stack + + // We don't need to store the camera target + importColorParams.discardOnLastUse = true; resourceData.cameraColor = renderGraph.ImportTexture(currentRenderGraphCameraColorHandle, importColorParams); } diff --git a/Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl b/Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl index aa1e314bd5f..e516fdfec31 100644 --- a/Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl +++ b/Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl @@ -26,8 +26,17 @@ #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl" #endif +#if defined(_DEPTH_INPUT_ATTACHMENT) + #define depth_input 0 + FRAMEBUFFER_INPUT_FLOAT_MS(depth_input); +#endif + float shadergraph_LWSampleSceneDepth(float2 uv) { +#if defined(_DEPTH_INPUT_ATTACHMENT) + return LOAD_FRAMEBUFFER_INPUT_MS(depth_input, 0, float2(0,0)); +#endif + #if defined(REQUIRE_DEPTH_TEXTURE) return SampleSceneDepth(uv); #else diff --git a/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/UberPost.shader b/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/UberPost.shader index 3fb34366c8e..10bb1aaf7e9 100644 --- a/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/UberPost.shader +++ b/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/UberPost.shader @@ -14,6 +14,9 @@ Shader "Hidden/Universal Render Pipeline/UberPost" #pragma multi_compile_fragment _ DEBUG_DISPLAY #pragma multi_compile_fragment _ SCREEN_COORD_OVERRIDE #pragma multi_compile_local_fragment _ HDR_INPUT HDR_ENCODING + + #pragma multi_compile_local_fragment _ SUBPASS_INPUT_ATTACHMENT + #pragma multi_compile _ _MSAA_2 _MSAA_4 _MSAA_8 #pragma dynamic_branch_local_fragment _ _HDR_OVERLAY @@ -42,6 +45,16 @@ Shader "Hidden/Universal Render Pipeline/UberPost" #define BLOOM_DIRT #endif #endif + + #if defined(_MSAA_2) + #define MSAA_SAMPLES 2 + #elif defined(_MSAA_4) + #define MSAA_SAMPLES 4 + #elif defined(_MSAA_8) + #define MSAA_SAMPLES 8 + #else + #define MSAA_SAMPLES 1 + #endif TEXTURE2D_X(_Bloom_Texture); TEXTURE2D(_LensDirt_Texture); @@ -50,6 +63,15 @@ Shader "Hidden/Universal Render Pipeline/UberPost" TEXTURE2D(_UserLut); TEXTURE2D(_BlueNoise_Texture); TEXTURE2D_X(_OverlayUITexture); + + #if SUBPASS_INPUT_ATTACHMENT + #define urp_cameraColor 0 + #if MSAA_SAMPLES == 1 + FRAMEBUFFER_INPUT_HALF(urp_cameraColor); + #else + FRAMEBUFFER_INPUT_HALF_MS(urp_cameraColor); + #endif + #endif float4 _BloomTexture_TexelSize; float4 _Lut_Params; @@ -153,9 +175,29 @@ Shader "Hidden/Universal Render Pipeline/UberPost" float2 uv = SCREEN_COORD_APPLY_SCALEBIAS(UnityStereoTransformScreenSpaceTex(input.texcoord)); float2 uvDistorted = DistortUV(uv); +#if 0 // NOTE: Hlsl specifies missing input.a to fill 1 (0 for .rgb). // InputColor is a "bottom" layer for alpha output. half4 inputColor = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, ClampUVForBilinear(SCREEN_COORD_REMOVE_SCALEBIAS(uvDistorted), _BlitTexture_TexelSize.xy)); +#else + half4 inputColor = half4(0.0, 0.0, 0.0, 0.0); + #if SUBPASS_INPUT_ATTACHMENT + #if MSAA_SAMPLES == 1 + inputColor = LOAD_FRAMEBUFFER_INPUT(urp_cameraColor, float2(0,0)); + #else + UNITY_UNROLL + for(int i = 0; i < MSAA_SAMPLES; ++i) { + half4 col = LOAD_FRAMEBUFFER_INPUT_MS(urp_cameraColor, i, float2(0,0)); + inputColor = inputColor + col; + } + inputColor = inputColor / MSAA_SAMPLES; + #endif + #else + // NOTE: Hlsl specifies missing input.a to fill 1 (0 for .rgb). + // InputColor is a "bottom" layer for alpha output. + inputColor = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, ClampUVForBilinear(SCREEN_COORD_REMOVE_SCALEBIAS(uvDistorted), _BlitTexture_TexelSize.xy)); + #endif +#endif // 0 half3 color = inputColor.rgb; #if _CHROMATIC_ABERRATION