diff --git a/com.unity.render-pipelines.universal/Runtime/NativeRenderPass.cs b/com.unity.render-pipelines.universal/Runtime/NativeRenderPass.cs new file mode 100644 index 00000000000..8844b33259c --- /dev/null +++ b/com.unity.render-pipelines.universal/Runtime/NativeRenderPass.cs @@ -0,0 +1,531 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Unity.Collections; +using UnityEngine.Experimental.Rendering; +using UnityEngine.Rendering; + +namespace UnityEngine.Rendering.Universal +{ + public partial class ScriptableRenderer + { + private const int kRenderPassMapSize = 10; + private const int kRenderPassMaxCount = 20; + + // used to keep track of the index of the last pass when we called BeginSubpass + private int m_LastBeginSubpassPassIndex = 0; + + private Dictionary m_MergeableRenderPassesMap = new Dictionary(kRenderPassMapSize); + // static array storing all the mergeableRenderPassesMap arrays. This is used to remove any GC allocs during the frame which would have been introduced by using a dynamic array to store the mergeablePasses per RenderPass + private int[][] m_MergeableRenderPassesMapArrays; + private Hash128[] m_PassIndexToPassHash = new Hash128[kRenderPassMaxCount]; + private Dictionary m_RenderPassesAttachmentCount = new Dictionary(kRenderPassMapSize); + + AttachmentDescriptor[] m_ActiveColorAttachmentDescriptors = new AttachmentDescriptor[] + { + RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment, + RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment, + RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment + }; + AttachmentDescriptor m_ActiveDepthAttachmentDescriptor; + + private static partial class Profiling + { + public static readonly ProfilingSampler setMRTAttachmentsList = new ProfilingSampler($"NativeRenderPass {nameof(SetNativeRenderPassMRTAttachmentList)}"); + public static readonly ProfilingSampler setAttachmentList = new ProfilingSampler($"NativeRenderPass {nameof(SetNativeRenderPassAttachmentList)}"); + public static readonly ProfilingSampler configure = new ProfilingSampler($"NativeRenderPass {nameof(ConfigureNativeRenderPass)}"); + public static readonly ProfilingSampler execute = new ProfilingSampler($"NativeRenderPass {nameof(ExecuteNativeRenderPass)}"); + public static readonly ProfilingSampler setupFrameData = new ProfilingSampler($"NativeRenderPass {nameof(SetupNativeRenderPassFrameData)}"); + } + + internal struct RenderPassDescriptor + { + internal int w, h, samples, depthID; + + internal RenderPassDescriptor(int width, int height, int sampleCount, int rtID) + { + w = width; + h = height; + samples = sampleCount; + depthID = rtID; + } + } + + internal void ResetNativeRenderPassFrameData() + { + if (m_MergeableRenderPassesMapArrays == null) + m_MergeableRenderPassesMapArrays = new int[kRenderPassMapSize][]; + + for (int i = 0; i < kRenderPassMapSize; ++i) + { + if (m_MergeableRenderPassesMapArrays[i] == null) + m_MergeableRenderPassesMapArrays[i] = new int[kRenderPassMaxCount]; + + for (int j = 0; j < kRenderPassMaxCount; ++j) + { + m_MergeableRenderPassesMapArrays[i][j] = -1; + } + } + } + + internal void SetupNativeRenderPassFrameData(CameraData cameraData, bool isRenderPassEnabled) + { + //TODO: edge cases to detect that should affect possible passes to merge + // - total number of color attachment > 8 + + // Go through all the passes and mark the final one as last pass + + using (new ProfilingScope(null, Profiling.setupFrameData)) + { + int lastPassIndex = m_ActiveRenderPassQueue.Count - 1; + + // Make sure the list is already sorted! + + m_MergeableRenderPassesMap.Clear(); + m_RenderPassesAttachmentCount.Clear(); + uint currentHashIndex = 0; + // reset all the passes last pass flag + for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i) + { + var renderPass = m_ActiveRenderPassQueue[i]; + + // Empty configure to setup dimensions/targets and whatever data is needed for merging + // We do not execute this at this time, so render targets are still invalid + var rpDesc = InitializeRenderPassDescriptor(cameraData, renderPass); + + renderPass.isLastPass = false; + renderPass.renderPassQueueIndex = i; + + bool RPEnabled = renderPass.useNativeRenderPass && isRenderPassEnabled; + if (!RPEnabled) + continue; + + Hash128 hash = CreateRenderPassHash(rpDesc, currentHashIndex); + + m_PassIndexToPassHash[i] = hash; + + if (!m_MergeableRenderPassesMap.ContainsKey(hash)) + { + m_MergeableRenderPassesMap.Add(hash, m_MergeableRenderPassesMapArrays[m_MergeableRenderPassesMap.Count]); + m_RenderPassesAttachmentCount.Add(hash, 0); + } + else if (m_MergeableRenderPassesMap[hash][GetValidPassIndexCount(m_MergeableRenderPassesMap[hash]) - 1] != (i - 1)) + { + // if the passes are not sequential we want to split the current mergeable passes list. So we increment the hashIndex and update the hash + + currentHashIndex++; + hash = CreateRenderPassHash(rpDesc, currentHashIndex); + + m_PassIndexToPassHash[i] = hash; + + m_MergeableRenderPassesMap.Add(hash, m_MergeableRenderPassesMapArrays[m_MergeableRenderPassesMap.Count]); + m_RenderPassesAttachmentCount.Add(hash, 0); + } + + m_MergeableRenderPassesMap[hash][GetValidPassIndexCount(m_MergeableRenderPassesMap[hash])] = i; + } + + m_ActiveRenderPassQueue[lastPassIndex].isLastPass = true; + + for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i) + m_ActiveRenderPassQueue[i].m_InputAttachmentIndices = new NativeArray(8, Allocator.Temp); + } + } + + internal void SetNativeRenderPassMRTAttachmentList(ScriptableRenderPass renderPass, ref CameraData cameraData, uint validColorBuffersCount, bool needCustomCameraColorClear, ClearFlag clearFlag) + { + using (new ProfilingScope(null, Profiling.setMRTAttachmentsList)) + { + int currentPassIndex = renderPass.renderPassQueueIndex; + Hash128 currentPassHash = m_PassIndexToPassHash[currentPassIndex]; + int[] currentMergeablePasses = m_MergeableRenderPassesMap[currentPassHash]; + + // Not the first pass + if (currentMergeablePasses.First() != currentPassIndex) + return; + + m_RenderPassesAttachmentCount[currentPassHash] = 0; + + int currentAttachmentIdx = 0; + foreach (var passIdx in currentMergeablePasses) + { + if (passIdx == -1) + break; + ScriptableRenderPass pass = m_ActiveRenderPassQueue[passIdx]; + + for (int i = 0; i < pass.m_InputAttachmentIndices.Length; ++i) + pass.m_InputAttachmentIndices[i] = -1; + + // TODO: review the lastPassToBB logic to mak it work with merged passes + bool isLastPassToBB = false; + + for (int i = 0; i < validColorBuffersCount; ++i) + { + AttachmentDescriptor currentAttachmentDescriptor = + new AttachmentDescriptor(pass.renderTargetFormat[i] != GraphicsFormat.None ? pass.renderTargetFormat[i] : GetDefaultGraphicsFormat(cameraData)); + + // if this is the current camera's last pass, also check if one of the RTs is the backbuffer (BuiltinRenderTextureType.CameraTarget) + isLastPassToBB |= pass.isLastPass && (pass.colorAttachments[i] == BuiltinRenderTextureType.CameraTarget); + + int existingAttachmentIndex = FindAttachmentDescriptorIndexInList(currentAttachmentIdx, + currentAttachmentDescriptor, m_ActiveColorAttachmentDescriptors); + + if (existingAttachmentIndex == -1) + { + // add a new attachment + m_ActiveColorAttachmentDescriptors[currentAttachmentIdx] = currentAttachmentDescriptor; + + m_ActiveColorAttachmentDescriptors[currentAttachmentIdx].ConfigureTarget(pass.colorAttachments[i], (clearFlag & ClearFlag.Color) == 0, true); + + if ((clearFlag & ClearFlag.Color) != 0) + { + var clearColor = (needCustomCameraColorClear && pass.colorAttachments[i] == m_CameraColorTarget) ? cameraData.camera.backgroundColor : renderPass.clearColor; + m_ActiveColorAttachmentDescriptors[currentAttachmentIdx].ConfigureClear(CoreUtils.ConvertSRGBToActiveColorSpace(clearColor), 1.0f, 0); + } + + pass.m_InputAttachmentIndices[i] = currentAttachmentIdx; + + currentAttachmentIdx++; + m_RenderPassesAttachmentCount[currentPassHash]++; + } + else + { + // attachment was already present + pass.m_InputAttachmentIndices[i] = existingAttachmentIndex; + } + } + + // TODO: this is redundant and is being setup for each attachment. Needs to be done only once per mergeable pass list (we need to make sure mergeable passes use the same depth!) + m_ActiveDepthAttachmentDescriptor = new AttachmentDescriptor(GraphicsFormat.DepthAuto); + m_ActiveDepthAttachmentDescriptor.ConfigureTarget(pass.depthAttachment, (clearFlag & ClearFlag.DepthStencil) == 0, !isLastPassToBB); + if ((clearFlag & ClearFlag.DepthStencil) != 0) + m_ActiveDepthAttachmentDescriptor.ConfigureClear(Color.black, 1.0f, 0); + } + } + } + + internal void SetNativeRenderPassAttachmentList(ScriptableRenderPass renderPass, ref CameraData cameraData, RenderTargetIdentifier passColorAttachment, RenderTargetIdentifier passDepthAttachment, ClearFlag finalClearFlag, Color finalClearColor) + { + using (new ProfilingScope(null, Profiling.setAttachmentList)) + { + int currentPassIndex = renderPass.renderPassQueueIndex; + Hash128 currentPassHash = m_PassIndexToPassHash[currentPassIndex]; + int[] currentMergeablePasses = m_MergeableRenderPassesMap[currentPassHash]; + + // Skip if not the first pass + if (currentMergeablePasses.First() != currentPassIndex) + return; + + m_RenderPassesAttachmentCount[currentPassHash] = 0; + + int currentAttachmentIdx = 0; + foreach (var passIdx in currentMergeablePasses) + { + if (passIdx == -1) + break; + ScriptableRenderPass pass = m_ActiveRenderPassQueue[passIdx]; + + for (int i = 0; i < pass.m_InputAttachmentIndices.Length; ++i) + pass.m_InputAttachmentIndices[i] = -1; + + AttachmentDescriptor currentAttachmentDescriptor; + var usesTargetTexture = cameraData.targetTexture != null; + var depthOnly = renderPass.depthOnly || (usesTargetTexture && cameraData.targetTexture.graphicsFormat == GraphicsFormat.DepthAuto); + // Offscreen depth-only cameras need this set explicitly + if (depthOnly && usesTargetTexture) + { + if (cameraData.targetTexture.graphicsFormat == GraphicsFormat.DepthAuto && !pass.overrideCameraTarget) + passColorAttachment = new RenderTargetIdentifier(cameraData.targetTexture); + else + passColorAttachment = renderPass.colorAttachment; + currentAttachmentDescriptor = new AttachmentDescriptor(GraphicsFormat.DepthAuto); + } + else + currentAttachmentDescriptor = + new AttachmentDescriptor(cameraData.cameraTargetDescriptor.graphicsFormat); + + if (pass.overrideCameraTarget) + currentAttachmentDescriptor = new AttachmentDescriptor(pass.renderTargetFormat[0] != GraphicsFormat.None ? pass.renderTargetFormat[0] : GetDefaultGraphicsFormat(cameraData)); + + var samples = pass.renderTargetSampleCount != -1 + ? pass.renderTargetSampleCount + : cameraData.cameraTargetDescriptor.msaaSamples; + + var colorAttachmentTarget = + (depthOnly || passColorAttachment != BuiltinRenderTextureType.CameraTarget) + ? passColorAttachment : (usesTargetTexture + ? new RenderTargetIdentifier(cameraData.targetTexture.colorBuffer) + : BuiltinRenderTextureType.CameraTarget); + + var depthAttachmentTarget = (passDepthAttachment != BuiltinRenderTextureType.CameraTarget) ? + passDepthAttachment : (usesTargetTexture + ? new RenderTargetIdentifier(cameraData.targetTexture.depthBuffer) + : BuiltinRenderTextureType.Depth); + + // TODO: review the lastPassToBB logic to mak it work with merged passes + // keep track if this is the current camera's last pass and the RT is the backbuffer (BuiltinRenderTextureType.CameraTarget) + // knowing isLastPassToBB can help decide the optimal store action as it gives us additional information about the current frame + bool isLastPassToBB = pass.isLastPass && (colorAttachmentTarget == BuiltinRenderTextureType.CameraTarget); + currentAttachmentDescriptor.ConfigureTarget(colorAttachmentTarget, ((uint)finalClearFlag & (uint)ClearFlag.Color) == 0, !(samples > 1 && isLastPassToBB)); + + // TODO: this is redundant and is being setup for each attachment. Needs to be done only once per mergeable pass list (we need to make sure mergeable passes use the same depth!) + m_ActiveDepthAttachmentDescriptor = new AttachmentDescriptor(GraphicsFormat.DepthAuto); + m_ActiveDepthAttachmentDescriptor.ConfigureTarget(depthAttachmentTarget, + ((uint)finalClearFlag & (uint)ClearFlag.Depth) == 0, !isLastPassToBB); + + if (finalClearFlag != ClearFlag.None) + { + // We don't clear color for Overlay render targets, however pipeline set's up depth only render passes as color attachments which we do need to clear + if ((cameraData.renderType != CameraRenderType.Overlay || depthOnly && ((uint)finalClearFlag & (uint)ClearFlag.Color) != 0)) + currentAttachmentDescriptor.ConfigureClear(finalClearColor, 1.0f, 0); + if (((uint)finalClearFlag & (uint)ClearFlag.Depth) != 0) + m_ActiveDepthAttachmentDescriptor.ConfigureClear(Color.black, 1.0f, 0); + } + + // resolving to the implicit color target's resolve surface TODO: handle m_CameraResolveTarget if present? + if (samples > 1) + currentAttachmentDescriptor.ConfigureResolveTarget(colorAttachmentTarget); + + int existingAttachmentIndex = FindAttachmentDescriptorIndexInList(currentAttachmentIdx, + currentAttachmentDescriptor, m_ActiveColorAttachmentDescriptors); + + if (existingAttachmentIndex == -1) + { + // add a new attachment + pass.m_InputAttachmentIndices[0] = currentAttachmentIdx; + m_ActiveColorAttachmentDescriptors[currentAttachmentIdx] = currentAttachmentDescriptor; + currentAttachmentIdx++; + m_RenderPassesAttachmentCount[currentPassHash]++; + } + else + { + // attachment was already present + pass.m_InputAttachmentIndices[0] = existingAttachmentIndex; + } + } + } + } + + internal void ConfigureNativeRenderPass(CommandBuffer cmd, ScriptableRenderPass renderPass, CameraData cameraData) + { + using (new ProfilingScope(null, Profiling.configure)) + { + int currentPassIndex = renderPass.renderPassQueueIndex; + Hash128 currentPassHash = m_PassIndexToPassHash[currentPassIndex]; + int[] currentMergeablePasses = m_MergeableRenderPassesMap[currentPassHash]; + + // If it's the first pass, configure the whole merge block + if (currentMergeablePasses.First() == currentPassIndex) + { + foreach (var passIdx in currentMergeablePasses) + { + if (passIdx == -1) + break; + ScriptableRenderPass pass = m_ActiveRenderPassQueue[passIdx]; + pass.Configure(cmd, cameraData.cameraTargetDescriptor); + } + } + } + } + + internal void ExecuteNativeRenderPass(ScriptableRenderContext context, ScriptableRenderPass renderPass, CameraData cameraData, ref RenderingData renderingData) + { + using (new ProfilingScope(null, Profiling.execute)) + { + int currentPassIndex = renderPass.renderPassQueueIndex; + Hash128 currentPassHash = m_PassIndexToPassHash[currentPassIndex]; + int[] currentMergeablePasses = m_MergeableRenderPassesMap[currentPassHash]; + + int validColorBuffersCount = m_RenderPassesAttachmentCount[currentPassHash]; + + bool isLastPass = renderPass.isLastPass; + // TODO: review the lastPassToBB logic to mak it work with merged passes + // keep track if this is the current camera's last pass and the RT is the backbuffer (BuiltinRenderTextureType.CameraTarget) + bool isLastPassToBB = isLastPass && (m_ActiveColorAttachmentDescriptors[0].loadStoreTarget == + BuiltinRenderTextureType.CameraTarget); + var depthOnly = renderPass.depthOnly || (cameraData.targetTexture != null && cameraData.targetTexture.graphicsFormat == GraphicsFormat.DepthAuto); + bool useDepth = depthOnly || (!renderPass.overrideCameraTarget || (renderPass.overrideCameraTarget && renderPass.depthAttachment != BuiltinRenderTextureType.CameraTarget)) && + (!(isLastPassToBB || (isLastPass && cameraData.camera.targetTexture != null))); + + var attachments = + new NativeArray(useDepth && !depthOnly ? validColorBuffersCount + 1 : 1, + Allocator.Temp); + + for (int i = 0; i < validColorBuffersCount; ++i) + attachments[i] = m_ActiveColorAttachmentDescriptors[i]; + + if (useDepth && !depthOnly) + attachments[validColorBuffersCount] = m_ActiveDepthAttachmentDescriptor; + + var rpDesc = InitializeRenderPassDescriptor(cameraData, renderPass); + + int validPassCount = GetValidPassIndexCount(currentMergeablePasses); + + var attachmentIndicesCount = GetSubPassAttachmentIndicesCount(renderPass); + + var attachmentIndices = new NativeArray(!depthOnly ? (int)attachmentIndicesCount : 0, Allocator.Temp); + if (!depthOnly) + { + for (int i = 0; i < attachmentIndicesCount; ++i) + { + attachmentIndices[i] = renderPass.m_InputAttachmentIndices[i]; + } + } + + if (validPassCount == 1 || currentMergeablePasses[0] == currentPassIndex) // Check if it's the first pass + { + context.BeginRenderPass(rpDesc.w, rpDesc.h, Math.Max(rpDesc.samples, 1), attachments, + useDepth ? (!depthOnly ? validColorBuffersCount : 0) : -1); + attachments.Dispose(); + + context.BeginSubPass(attachmentIndices); + + m_LastBeginSubpassPassIndex = currentPassIndex; + } + else + { + if (!AreAttachmentIndicesCompatible(m_ActiveRenderPassQueue[m_LastBeginSubpassPassIndex], m_ActiveRenderPassQueue[currentPassIndex])) + { + context.EndSubPass(); + context.BeginSubPass(attachmentIndices); + + m_LastBeginSubpassPassIndex = currentPassIndex; + } + } + + attachmentIndices.Dispose(); + + renderPass.Execute(context, ref renderingData); + + if (validPassCount == 1 || currentMergeablePasses[validPassCount - 1] == currentPassIndex) // Check if it's the last pass + { + context.EndSubPass(); + context.EndRenderPass(); + + m_LastBeginSubpassPassIndex = 0; + } + + for (int i = 0; i < m_ActiveColorAttachmentDescriptors.Length; ++i) + { + m_ActiveColorAttachmentDescriptors[i] = RenderingUtils.emptyAttachment; + } + + m_ActiveDepthAttachmentDescriptor = RenderingUtils.emptyAttachment; + } + } + + internal static uint GetSubPassAttachmentIndicesCount(ScriptableRenderPass pass) + { + uint numValidAttachments = 0; + + foreach (var attIdx in pass.m_InputAttachmentIndices) + { + if (attIdx >= 0) + ++numValidAttachments; + } + + return numValidAttachments; + } + + internal static bool AreAttachmentIndicesCompatible(ScriptableRenderPass lastSubPass, ScriptableRenderPass currentSubPass) + { + uint lastSubPassAttCount = GetSubPassAttachmentIndicesCount(lastSubPass); + uint currentSubPassAttCount = GetSubPassAttachmentIndicesCount(currentSubPass); + + if (currentSubPassAttCount > lastSubPassAttCount) + return false; + + uint numEqualAttachments = 0; + for (int currPassIdx = 0; currPassIdx < currentSubPassAttCount; ++currPassIdx) + { + for (int lastPassIdx = 0; lastPassIdx < lastSubPassAttCount; ++lastPassIdx) + { + if (currentSubPass.m_InputAttachmentIndices[currPassIdx] == lastSubPass.m_InputAttachmentIndices[lastPassIdx]) + numEqualAttachments++; + } + } + + return (numEqualAttachments == currentSubPassAttCount); + } + + internal static uint GetValidColorAttachmentCount(AttachmentDescriptor[] colorAttachments) + { + uint nonNullColorBuffers = 0; + if (colorAttachments != null) + { + foreach (var attachment in colorAttachments) + { + if (attachment != RenderingUtils.emptyAttachment) + ++nonNullColorBuffers; + } + } + return nonNullColorBuffers; + } + + internal static int FindAttachmentDescriptorIndexInList(int attachmentIdx, AttachmentDescriptor attachmentDescriptor, AttachmentDescriptor[] attachmentDescriptors) + { + int existingAttachmentIndex = -1; + for (int i = 0; i < attachmentIdx; ++i) + { + AttachmentDescriptor att = attachmentDescriptors[i]; + + if (att.loadStoreTarget == attachmentDescriptor.loadStoreTarget) + { + existingAttachmentIndex = i; + break; + } + } + + return existingAttachmentIndex; + } + + internal static int GetValidPassIndexCount(int[] array) + { + for (int i = 0; i < array.Length; ++i) + if (array[i] == -1) + return i; + return array.Length - 1; + } + + internal static Hash128 CreateRenderPassHash(int width, int height, int depthID, int sample, uint hashIndex) + { + return new Hash128((uint)(width << 4) + (uint)height, (uint)depthID, (uint)sample, hashIndex); + } + + internal static Hash128 CreateRenderPassHash(RenderPassDescriptor desc, uint hashIndex) + { + return CreateRenderPassHash(desc.w, desc.h, desc.depthID, desc.samples, hashIndex); + } + + private static RenderPassDescriptor InitializeRenderPassDescriptor(CameraData cameraData, ScriptableRenderPass renderPass) + { + var w = (renderPass.renderTargetWidth != -1) ? renderPass.renderTargetWidth : cameraData.cameraTargetDescriptor.width; + var h = (renderPass.renderTargetHeight != -1) ? renderPass.renderTargetHeight : cameraData.cameraTargetDescriptor.height; + var samples = (renderPass.renderTargetSampleCount != -1) ? renderPass.renderTargetSampleCount : cameraData.cameraTargetDescriptor.msaaSamples; + var depthID = renderPass.depthOnly ? renderPass.colorAttachment.GetHashCode() : renderPass.depthAttachment.GetHashCode(); + return new RenderPassDescriptor(w, h, samples, depthID); + } + + private static GraphicsFormat GetDefaultGraphicsFormat(CameraData cameraData) + { + if (cameraData.isHdrEnabled) + { + GraphicsFormat hdrFormat = GraphicsFormat.None; + + if (!Graphics.preserveFramebufferAlpha && + RenderingUtils.SupportsGraphicsFormat(GraphicsFormat.B10G11R11_UFloatPack32, + FormatUsage.Linear | FormatUsage.Render)) + hdrFormat = GraphicsFormat.B10G11R11_UFloatPack32; + else if (RenderingUtils.SupportsGraphicsFormat(GraphicsFormat.R16G16B16A16_SFloat, + FormatUsage.Linear | FormatUsage.Render)) + hdrFormat = GraphicsFormat.R16G16B16A16_SFloat; + else + hdrFormat = SystemInfo.GetGraphicsFormat(DefaultFormat.HDR); + + return hdrFormat; + } + + return SystemInfo.GetGraphicsFormat(DefaultFormat.LDR); + } + } +} diff --git a/com.unity.render-pipelines.universal/Runtime/NativeRenderPass.cs.meta b/com.unity.render-pipelines.universal/Runtime/NativeRenderPass.cs.meta new file mode 100644 index 00000000000..a705876477f --- /dev/null +++ b/com.unity.render-pipelines.universal/Runtime/NativeRenderPass.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5bda898891014be6a6c570d69d4e75d6 +timeCreated: 1616679760 \ No newline at end of file diff --git a/com.unity.render-pipelines.universal/Runtime/Passes/AdditionalLightsShadowCasterPass.cs b/com.unity.render-pipelines.universal/Runtime/Passes/AdditionalLightsShadowCasterPass.cs index 7bd211343a4..64a046878dc 100644 --- a/com.unity.render-pipelines.universal/Runtime/Passes/AdditionalLightsShadowCasterPass.cs +++ b/com.unity.render-pipelines.universal/Runtime/Passes/AdditionalLightsShadowCasterPass.cs @@ -56,8 +56,6 @@ public ShadowResolutionRequest(int _visibleLightIndex, int _perLightShadowSliceI private RenderTargetHandle m_AdditionalLightsShadowmap; internal RenderTexture m_AdditionalLightsShadowmapTexture; - int m_ShadowmapWidth; - int m_ShadowmapHeight; float m_MaxShadowDistanceSq; float m_CascadeBorder; @@ -479,8 +477,8 @@ public bool Setup(ref RenderingData renderingData) Clear(); - m_ShadowmapWidth = renderingData.shadowData.additionalLightsShadowmapWidth; - m_ShadowmapHeight = renderingData.shadowData.additionalLightsShadowmapHeight; + renderTargetWidth = renderingData.shadowData.additionalLightsShadowmapWidth; + renderTargetHeight = renderingData.shadowData.additionalLightsShadowmapHeight; var visibleLights = renderingData.lightData.visibleLights; int additionalLightsCount = renderingData.lightData.additionalLightsCount; @@ -747,11 +745,12 @@ public bool Setup(ref RenderingData renderingData) atlasMaxY = Mathf.Max(atlasMaxY, shadowResolutionRequest.offsetY + shadowResolutionRequest.allocatedResolution); } // ...but make sure we still use power-of-two dimensions (might perform better on some hardware) - m_ShadowmapWidth = Mathf.NextPowerOfTwo(atlasMaxX); - m_ShadowmapHeight = Mathf.NextPowerOfTwo(atlasMaxY); - float oneOverAtlasWidth = 1.0f / m_ShadowmapWidth; - float oneOverAtlasHeight = 1.0f / m_ShadowmapHeight; + renderTargetWidth = Mathf.NextPowerOfTwo(atlasMaxX); + renderTargetHeight = Mathf.NextPowerOfTwo(atlasMaxY); + + float oneOverAtlasWidth = 1.0f / renderTargetWidth; + float oneOverAtlasHeight = 1.0f / renderTargetHeight; Matrix4x4 sliceTransform; for (int globalShadowSliceIndex = 0; globalShadowSliceIndex < shadowCastingLightsBufferCount; ++globalShadowSliceIndex) @@ -784,7 +783,7 @@ public bool Setup(ref RenderingData renderingData) m_AdditionalLightShadowSliceIndexTo_WorldShadowMatrix[globalShadowSliceIndex] = sliceTransform * m_AdditionalLightShadowSliceIndexTo_WorldShadowMatrix[globalShadowSliceIndex]; } - m_AdditionalLightsShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(m_ShadowmapWidth, m_ShadowmapHeight, k_ShadowmapBufferBits); + m_AdditionalLightsShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(renderTargetWidth, renderTargetHeight, k_ShadowmapBufferBits); m_MaxShadowDistanceSq = renderingData.cameraData.maxShadowDistance * renderingData.cameraData.maxShadowDistance; m_CascadeBorder = renderingData.shadowData.mainLightShadowCascadeBorder; @@ -793,7 +792,7 @@ public bool Setup(ref RenderingData renderingData) public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { - ConfigureTarget(new RenderTargetIdentifier(m_AdditionalLightsShadowmapTexture), GraphicsFormat.ShadowAuto, m_ShadowmapWidth, m_ShadowmapHeight, 1, true); + ConfigureTarget(new RenderTargetIdentifier(m_AdditionalLightsShadowmapTexture), GraphicsFormat.ShadowAuto, renderTargetWidth, renderTargetHeight, 1, true); ConfigureClear(ClearFlag.All, Color.black); } diff --git a/com.unity.render-pipelines.universal/Runtime/Passes/MainLightShadowCasterPass.cs b/com.unity.render-pipelines.universal/Runtime/Passes/MainLightShadowCasterPass.cs index 03d80e758b4..21668abe96d 100644 --- a/com.unity.render-pipelines.universal/Runtime/Passes/MainLightShadowCasterPass.cs +++ b/com.unity.render-pipelines.universal/Runtime/Passes/MainLightShadowCasterPass.cs @@ -28,8 +28,6 @@ private static class MainLightShadowConstantBuffer const int k_ShadowmapBufferBits = 16; float m_CascadeBorder; float m_MaxShadowDistanceSq; - int m_ShadowmapWidth; - int m_ShadowmapHeight; int m_ShadowCasterCascadesCount; bool m_SupportsBoxFilterForShadows; @@ -98,22 +96,22 @@ public bool Setup(ref RenderingData renderingData) int shadowResolution = ShadowUtils.GetMaxTileResolutionInAtlas(renderingData.shadowData.mainLightShadowmapWidth, renderingData.shadowData.mainLightShadowmapHeight, m_ShadowCasterCascadesCount); - m_ShadowmapWidth = renderingData.shadowData.mainLightShadowmapWidth; - m_ShadowmapHeight = (m_ShadowCasterCascadesCount == 2) ? + renderTargetWidth = renderingData.shadowData.mainLightShadowmapWidth; + renderTargetHeight = (m_ShadowCasterCascadesCount == 2) ? renderingData.shadowData.mainLightShadowmapHeight >> 1 : renderingData.shadowData.mainLightShadowmapHeight; for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { bool success = ShadowUtils.ExtractDirectionalLightMatrix(ref renderingData.cullResults, ref renderingData.shadowData, - shadowLightIndex, cascadeIndex, m_ShadowmapWidth, m_ShadowmapHeight, shadowResolution, light.shadowNearPlane, + shadowLightIndex, cascadeIndex, renderTargetWidth, renderTargetHeight, shadowResolution, light.shadowNearPlane, out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex]); if (!success) return false; } - m_MainLightShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(m_ShadowmapWidth, m_ShadowmapHeight, k_ShadowmapBufferBits); + m_MainLightShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(renderTargetWidth, renderTargetHeight, k_ShadowmapBufferBits); m_MaxShadowDistanceSq = renderingData.cameraData.maxShadowDistance * renderingData.cameraData.maxShadowDistance; m_CascadeBorder = renderingData.shadowData.mainLightShadowCascadeBorder; @@ -122,7 +120,7 @@ public bool Setup(ref RenderingData renderingData) public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { - ConfigureTarget(new RenderTargetIdentifier(m_MainLightShadowmapTexture), GraphicsFormat.ShadowAuto, m_ShadowmapWidth, m_ShadowmapHeight, 1, true); + ConfigureTarget(new RenderTargetIdentifier(m_MainLightShadowmapTexture), GraphicsFormat.ShadowAuto, renderTargetWidth, renderTargetHeight, 1, true); ConfigureClear(ClearFlag.All, Color.black); } @@ -215,8 +213,8 @@ void SetupMainLightShadowReceiverConstants(CommandBuffer cmd, VisibleLight shado for (int i = cascadeCount; i <= k_MaxCascades; ++i) m_MainLightShadowMatrices[i] = noOpShadowMatrix; - float invShadowAtlasWidth = 1.0f / m_ShadowmapWidth; - float invShadowAtlasHeight = 1.0f / m_ShadowmapHeight; + float invShadowAtlasWidth = 1.0f / renderTargetWidth; + float invShadowAtlasHeight = 1.0f / renderTargetHeight; float invHalfShadowAtlasWidth = 0.5f * invShadowAtlasWidth; float invHalfShadowAtlasHeight = 0.5f * invShadowAtlasHeight; float softShadowsProp = softShadows ? 1.0f : 0.0f; @@ -267,7 +265,7 @@ void SetupMainLightShadowReceiverConstants(CommandBuffer cmd, VisibleLight shado // enough so custom shaders might use it. cmd.SetGlobalVector(MainLightShadowConstantBuffer._ShadowmapSize, new Vector4(invShadowAtlasWidth, invShadowAtlasHeight, - m_ShadowmapWidth, m_ShadowmapHeight)); + renderTargetWidth, renderTargetHeight)); } } }; diff --git a/com.unity.render-pipelines.universal/Runtime/Passes/ScriptableRenderPass.cs b/com.unity.render-pipelines.universal/Runtime/Passes/ScriptableRenderPass.cs index c0ad2e0b25e..b1c382f17d2 100644 --- a/com.unity.render-pipelines.universal/Runtime/Passes/ScriptableRenderPass.cs +++ b/com.unity.render-pipelines.universal/Runtime/Passes/ScriptableRenderPass.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using Unity.Collections; using UnityEngine.Scripting.APIUpdating; using UnityEngine.Experimental.Rendering; @@ -201,7 +202,10 @@ public Color clearColor internal bool depthOnly { get; set; } // this flag is updated each frame to keep track of which pass is the last for the current camera internal bool isLastPass { get; set; } + // index to track the position in the current frame + internal int renderPassQueueIndex { get; set; } + internal NativeArray m_InputAttachmentIndices; internal GraphicsFormat[] renderTargetFormat { get; set; } RenderTargetIdentifier[] m_ColorAttachments = new RenderTargetIdentifier[] {BuiltinRenderTextureType.CameraTarget}; @@ -228,6 +232,7 @@ public ScriptableRenderPass() renderTargetWidth = -1; renderTargetHeight = -1; renderTargetSampleCount = -1; + renderPassQueueIndex = -1; renderTargetFormat = new GraphicsFormat[] { GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None, diff --git a/com.unity.render-pipelines.universal/Runtime/RendererFeatures/RenderObjects.cs b/com.unity.render-pipelines.universal/Runtime/RendererFeatures/RenderObjects.cs index fb341196730..8db95800876 100644 --- a/com.unity.render-pipelines.universal/Runtime/RendererFeatures/RenderObjects.cs +++ b/com.unity.render-pipelines.universal/Runtime/RendererFeatures/RenderObjects.cs @@ -92,5 +92,10 @@ public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingD { renderer.EnqueuePass(renderObjectsPass); } + + internal override bool SupportsNativeRenderPass() + { + return true; + } } } diff --git a/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs b/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs index 0d156dc51e1..15e0c61bd11 100644 --- a/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs +++ b/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs @@ -349,20 +349,6 @@ internal static uint GetValidColorBufferCount(RenderTargetIdentifier[] colorBuff return nonNullColorBuffers; } - internal static uint GetValidColorAttachmentCount(AttachmentDescriptor[] colorAttachments) - { - uint nonNullColorBuffers = 0; - if (colorAttachments != null) - { - foreach (var attachment in colorAttachments) - { - if (attachment != RenderingUtils.emptyAttachment) - ++nonNullColorBuffers; - } - } - return nonNullColorBuffers; - } - /// /// Return true if colorBuffers is an actual MRT setup /// diff --git a/com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs b/com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs index ba9b24919c8..facc900a0c7 100644 --- a/com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs +++ b/com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs @@ -24,7 +24,7 @@ namespace UnityEngine.Rendering.Universal /// public abstract partial class ScriptableRenderer : IDisposable { - private static class Profiling + private static partial class Profiling { private const string k_Name = nameof(ScriptableRenderer); public static readonly ProfilingSampler setPerCameraShaderVariables = new ProfilingSampler($"{k_Name}.{nameof(SetPerCameraShaderVariables)}"); @@ -428,6 +428,10 @@ static class RenderPassBlock // This should be removed when early camera color target assignment is removed. internal bool isCameraColorTargetValid = false; + // Temporary variable to disable custom passes using render pass ( due to it potentially breaking projects with custom render features ) + // To enable it - override SupportsNativeRenderPass method in the feature and return true + internal bool disableNativeRenderPassInFeatures = false; + internal bool useRenderPassEnabled = false; static RenderTargetIdentifier[] m_ActiveColorAttachments = new RenderTargetIdentifier[] {0, 0, 0, 0, 0, 0, 0, 0 }; static RenderTargetIdentifier m_ActiveDepthAttachment; @@ -440,14 +444,6 @@ static class RenderPassBlock private static RenderBufferStoreAction m_ActiveDepthStoreAction = RenderBufferStoreAction.Store; - static AttachmentDescriptor[] m_ActiveColorAttachmentDescriptors = new AttachmentDescriptor[] - { - RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment, - RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment, - RenderingUtils.emptyAttachment, RenderingUtils.emptyAttachment - }; - static AttachmentDescriptor m_ActiveDepthAttachmentDescriptor; - // CommandBuffer.SetRenderTarget(RenderTargetIdentifier[] colors, RenderTargetIdentifier depth, int mipLevel, CubemapFace cubemapFace, int depthSlice); // called from CoreUtils.SetRenderTarget will issue a warning assert from native c++ side if "colors" array contains some invalid RTIDs. // To avoid that warning assert we trim the RenderTargetIdentifier[] arrays we pass to CoreUtils.SetRenderTarget. @@ -494,6 +490,8 @@ public ScriptableRenderer(ScriptableRendererData data) m_RendererFeatures.Add(feature); } + ResetNativeRenderPassFrameData(); + useRenderPassEnabled = data.useNativeRenderPass; Clear(CameraRenderType.Base); m_ActiveRenderPassQueue.Clear(); @@ -589,21 +587,6 @@ public virtual void FinishRendering(CommandBuffer cmd) { } - private void SetLastPassFlag() - { - // Go through all the passes and mark the final one as last pass - - int lastPassIndex = m_ActiveRenderPassQueue.Count - 1; - - // Make sure the list is already sorted! - - // reset all the passes last pass flag - for (int i = 0; i < m_ActiveRenderPassQueue.Count - 1; ++i) - m_ActiveRenderPassQueue[i].isLastPass = false; - - m_ActiveRenderPassQueue[lastPassIndex].isLastPass = true; - } - /// /// Execute the enqueued render passes. This automatically handles editor and stereo rendering. /// @@ -652,7 +635,7 @@ public void Execute(ScriptableRenderContext context, ref RenderingData rendering SortStable(m_ActiveRenderPassQueue); } - SetLastPassFlag(); + SetupNativeRenderPassFrameData(cameraData, useRenderPassEnabled); using var renderBlocks = new RenderBlocks(m_ActiveRenderPassQueue); @@ -752,6 +735,9 @@ public void Execute(ScriptableRenderContext context, ref RenderingData rendering } InternalFinishRendering(context, cameraData.resolveFinalTarget); + + for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i) + m_ActiveRenderPassQueue[i].m_InputAttachmentIndices.Dispose(); } context.ExecuteCommandBuffer(cmd); @@ -765,6 +751,8 @@ public void Execute(ScriptableRenderContext context, ref RenderingData rendering public void EnqueuePass(ScriptableRenderPass pass) { m_ActiveRenderPassQueue.Add(pass); + if (disableNativeRenderPassInFeatures) + pass.useNativeRenderPass = false; } /// @@ -832,7 +820,12 @@ protected void AddRenderPasses(ref RenderingData renderingData) { continue; } + + if (!rendererFeatures[i].SupportsNativeRenderPass()) + disableNativeRenderPassInFeatures = true; + rendererFeatures[i].AddRenderPasses(this, ref renderingData); + disableNativeRenderPassInFeatures = false; } // Remove any null render pass that might have been added by user by mistake @@ -916,7 +909,11 @@ void ExecuteRenderPass(ScriptableRenderContext context, ScriptableRenderPass ren // Track CPU only as GPU markers for this scope were "too noisy". using (new ProfilingScope(null, Profiling.RenderPass.configure)) { - renderPass.Configure(cmd, cameraData.cameraTargetDescriptor); + if (IsRenderPassEnabled(renderPass) && cameraData.cameraType == CameraType.Game) + ConfigureNativeRenderPass(cmd, renderPass, cameraData); + else + renderPass.Configure(cmd, cameraData.cameraTargetDescriptor); + SetRenderPassAttachments(cmd, renderPass, ref cameraData); } @@ -925,54 +922,7 @@ void ExecuteRenderPass(ScriptableRenderContext context, ScriptableRenderPass ren CommandBufferPool.Release(cmd); if (IsRenderPassEnabled(renderPass) && cameraData.cameraType == CameraType.Game) - { - int validColorBuffersCount = (int)RenderingUtils.GetValidColorBufferCount(renderPass.colorAttachments); - - bool isLastPass = renderPass.isLastPass; - // keep track if this is the current camera's last pass and the RT is the backbuffer (BuiltinRenderTextureType.CameraTarget) - bool isLastPassToBB = isLastPass && (m_ActiveColorAttachmentDescriptors[0].loadStoreTarget == BuiltinRenderTextureType.CameraTarget); - bool useDepth = m_ActiveDepthAttachment == RenderTargetHandle.CameraTarget.Identifier() && (!(isLastPassToBB || (isLastPass && cameraData.camera.targetTexture != null))); - - var attachments = - new NativeArray(useDepth && !renderPass.depthOnly ? validColorBuffersCount + 1 : 1, Allocator.Temp); - - for (int i = 0; i < validColorBuffersCount; ++i) - attachments[i] = m_ActiveColorAttachmentDescriptors[i]; - - if (useDepth && !renderPass.depthOnly) - attachments[validColorBuffersCount] = m_ActiveDepthAttachmentDescriptor; - - var desc = renderingData.cameraData.cameraTargetDescriptor; - var sampleCount = desc.msaaSamples; - int width = renderPass.renderTargetWidth != -1 ? renderPass.renderTargetWidth : desc.width; - int height = renderPass.renderTargetHeight != -1 ? renderPass.renderTargetHeight : desc.height; - sampleCount = renderPass.renderTargetSampleCount != -1 - ? renderPass.renderTargetSampleCount - : sampleCount; - - context.BeginRenderPass(width, height, Math.Max(sampleCount, 1), attachments, - useDepth ? (!renderPass.depthOnly ? validColorBuffersCount : 0) : -1); - attachments.Dispose(); - var attachmentIndices = new NativeArray(!renderPass.depthOnly ? validColorBuffersCount : 0, Allocator.Temp); - if (!renderPass.depthOnly) - { - for (int i = 0; i < validColorBuffersCount; ++i) - { - attachmentIndices[i] = i; - } - } - context.BeginSubPass(attachmentIndices); - attachmentIndices.Dispose(); - renderPass.Execute(context, ref renderingData); - context.EndSubPass(); - context.EndRenderPass(); - - for (int i = 0; i < m_ActiveColorAttachmentDescriptors.Length; ++i) - { - m_ActiveColorAttachmentDescriptors[i] = RenderingUtils.emptyAttachment; - } - m_ActiveDepthAttachmentDescriptor = RenderingUtils.emptyAttachment; - } + ExecuteNativeRenderPass(context, renderPass, cameraData, ref renderingData); else renderPass.Execute(context, ref renderingData); } @@ -1060,33 +1010,13 @@ void SetRenderPassAttachments(CommandBuffer cmd, ScriptableRenderPass renderPass } } - if (IsRenderPassEnabled(renderPass) && cameraData.cameraType == CameraType.Game) - { - bool isLastPass = renderPass.isLastPass; - bool isLastPassToBB = false; - - for (int i = 0; i < validColorBuffersCount; ++i) - { - // if this is the current camera's last pass, also check if one of the RTs is the backbuffer (BuiltinRenderTextureType.CameraTarget) - isLastPassToBB |= isLastPass && (renderPass.colorAttachments[i] == BuiltinRenderTextureType.CameraTarget); - - m_ActiveColorAttachmentDescriptors[i] = - new AttachmentDescriptor(renderPass.renderTargetFormat[i] != GraphicsFormat.None ? renderPass.renderTargetFormat[i] : SystemInfo.GetGraphicsFormat(DefaultFormat.LDR)); - m_ActiveColorAttachmentDescriptors[i].ConfigureTarget(renderPass.colorAttachments[i], false, true); - if (needCustomCameraColorClear) - m_ActiveColorAttachmentDescriptors[i].ConfigureClear(Color.black, 1.0f, 0); - } - - m_ActiveDepthAttachmentDescriptor = new AttachmentDescriptor(GraphicsFormat.DepthAuto); - m_ActiveDepthAttachmentDescriptor.ConfigureTarget(renderPass.depthAttachment, !needCustomCameraDepthClear, !isLastPassToBB); - if (needCustomCameraDepthClear) - m_ActiveDepthAttachmentDescriptor.ConfigureClear(Color.black, 1.0f, 0); - } - // Bind all attachments, clear color only if there was no custom behaviour for cameraColorTarget, clear depth as needed. ClearFlag finalClearFlag = ClearFlag.None; finalClearFlag |= needCustomCameraDepthClear ? (cameraClearFlag & ClearFlag.DepthStencil) : (renderPass.clearFlag & ClearFlag.DepthStencil); - finalClearFlag |= needCustomCameraColorClear ? 0 : (renderPass.clearFlag & ClearFlag.Color); + finalClearFlag |= needCustomCameraColorClear ? (IsRenderPassEnabled(renderPass) ? (cameraClearFlag & ClearFlag.Color) : 0) : (renderPass.clearFlag & ClearFlag.Color); + + if (IsRenderPassEnabled(renderPass) && cameraData.cameraType == CameraType.Game) + SetNativeRenderPassMRTAttachmentList(renderPass, ref cameraData, validColorBuffersCount, needCustomCameraColorClear, finalClearFlag); // Only setup render target if current render pass attachments are different from the active ones. if (!RenderingUtils.SequenceEqual(renderPass.colorAttachments, m_ActiveColorAttachments) || renderPass.depthAttachment != m_ActiveDepthAttachment || finalClearFlag != ClearFlag.None) @@ -1188,59 +1118,7 @@ void SetRenderPassAttachments(CommandBuffer cmd, ScriptableRenderPass renderPass if (IsRenderPassEnabled(renderPass) && cameraData.cameraType == CameraType.Game) { - if (!renderPass.overrideCameraTarget) - m_ActiveColorAttachmentDescriptors[0] = new AttachmentDescriptor(cameraData.cameraTargetDescriptor.graphicsFormat); - else - { - GraphicsFormat hdrFormat = GraphicsFormat.None; - if (cameraData.isHdrEnabled) - { - if (!Graphics.preserveFramebufferAlpha && RenderingUtils.SupportsGraphicsFormat(GraphicsFormat.B10G11R11_UFloatPack32, FormatUsage.Linear | FormatUsage.Render)) - hdrFormat = GraphicsFormat.B10G11R11_UFloatPack32; - else if (RenderingUtils.SupportsGraphicsFormat(GraphicsFormat.R16G16B16A16_SFloat, FormatUsage.Linear | FormatUsage.Render)) - hdrFormat = GraphicsFormat.R16G16B16A16_SFloat; - else - hdrFormat = SystemInfo.GetGraphicsFormat(DefaultFormat.HDR); - } - - var defaultFormat = cameraData.isHdrEnabled ? hdrFormat : SystemInfo.GetGraphicsFormat(DefaultFormat.LDR); - m_ActiveColorAttachmentDescriptors[0] = new AttachmentDescriptor(renderPass.renderTargetFormat[0] != GraphicsFormat.None ? renderPass.renderTargetFormat[0] : defaultFormat); - } - - bool isLastPass = renderPass.isLastPass; - var samples = renderPass.renderTargetSampleCount != -1 ? renderPass.renderTargetSampleCount : cameraData.cameraTargetDescriptor.msaaSamples; - - var colorAttachmentTarget = (renderPass.depthOnly || passColorAttachment != BuiltinRenderTextureType.CameraTarget) - ? passColorAttachment - : (cameraData.targetTexture != null - ? new RenderTargetIdentifier(cameraData.targetTexture.colorBuffer) - : BuiltinRenderTextureType.CameraTarget); - - var depthAttachmentTarget = (passDepthAttachment != BuiltinRenderTextureType.CameraTarget) - ? passDepthAttachment - : (cameraData.targetTexture != null - ? new RenderTargetIdentifier(cameraData.targetTexture.depthBuffer) - : BuiltinRenderTextureType.Depth); - - // keep track if this is the current camera's last pass and the RT is the backbuffer (BuiltinRenderTextureType.CameraTarget) - // knowing isLastPassToBB can help decide the optimal store action as it gives us additional information about the current frame - bool isLastPassToBB = isLastPass && (colorAttachmentTarget == BuiltinRenderTextureType.CameraTarget); - m_ActiveColorAttachmentDescriptors[0].ConfigureTarget(colorAttachmentTarget, ((uint)finalClearFlag & (uint)ClearFlag.Color) == 0, !(samples > 1 && isLastPassToBB)); - - m_ActiveDepthAttachmentDescriptor = new AttachmentDescriptor(GraphicsFormat.DepthAuto); - m_ActiveDepthAttachmentDescriptor.ConfigureTarget(depthAttachmentTarget, ((uint)finalClearFlag & (uint)ClearFlag.Depth) == 0 , !isLastPassToBB); - - if (finalClearFlag != ClearFlag.None) - { - // We don't clear color for Overlay render targets, however pipeline set's up depth only render passes as color attachments which we do need to clear - if ((cameraData.renderType != CameraRenderType.Overlay || renderPass.depthOnly && ((uint)finalClearFlag & (uint)ClearFlag.Color) != 0)) - m_ActiveColorAttachmentDescriptors[0].ConfigureClear(finalClearColor, 1.0f, 0); - if (((uint)finalClearFlag & (uint)ClearFlag.Depth) != 0) - m_ActiveDepthAttachmentDescriptor.ConfigureClear(Color.black, 1.0f, 0); - } - - if (samples > 1) - m_ActiveColorAttachmentDescriptors[0].ConfigureResolveTarget(m_CameraResolveTarget); + SetNativeRenderPassAttachmentList(renderPass, ref cameraData, passColorAttachment, passDepthAttachment, finalClearFlag, finalClearColor); } else { @@ -1449,6 +1327,8 @@ void InternalFinishRendering(ScriptableRenderContext context, bool resolveFinalT m_ActiveRenderPassQueue.Clear(); } + ResetNativeRenderPassFrameData(); + context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } diff --git a/com.unity.render-pipelines.universal/Runtime/ScriptableRendererFeature.cs b/com.unity.render-pipelines.universal/Runtime/ScriptableRendererFeature.cs index aa6630b18ca..a7c109dbb3b 100644 --- a/com.unity.render-pipelines.universal/Runtime/ScriptableRendererFeature.cs +++ b/com.unity.render-pipelines.universal/Runtime/ScriptableRendererFeature.cs @@ -39,6 +39,14 @@ void OnValidate() Create(); } + /// + /// Override this method and return true if the feature should use the Native RenderPass API + /// + internal virtual bool SupportsNativeRenderPass() + { + return false; + } + /// /// Sets the state of ScriptableRenderFeature (true: the feature is active, false: the feature is inactive). /// If the feature is active, it is added to the renderer it is attached to, otherwise the feature is skipped while rendering. diff --git a/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs b/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs index 58172df9814..cd03f9ee888 100644 --- a/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs +++ b/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs @@ -400,6 +400,11 @@ static void RenderSingleCamera(ScriptableRenderContext context, CameraData camer using (new ProfilingScope(null, Profiling.Pipeline.Context.submit)) { + if (renderer.useRenderPassEnabled && !context.SubmitForRenderPassValidation()) + { + renderer.useRenderPassEnabled = false; + Debug.LogWarning("Rendering command not supported inside a native RenderPass found. Falling back to non-RenderPass rendering path"); + } context.Submit(); // Actually execute the commands that we previously sent to the ScriptableRenderContext context } diff --git a/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs b/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs index 338bfd5ee90..20219febbb5 100644 --- a/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs +++ b/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs @@ -245,10 +245,6 @@ public UniversalRenderer(UniversalRendererData data) : base(data) GraphicsDeviceType.OpenGLES3 }; } - - // MSAA is temporary disabled when using the RenderPass API. TODO: enable it back once the handling of resolving to implicit resolve textures and Vulkan backbuffer is fixed in trunk! - if (useRenderPassEnabled) - this.supportedRenderingFeatures.msaa = false; } ///