diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/TableOfContents.md b/Packages/com.unity.render-pipelines.core/Documentation~/TableOfContents.md index 6adc3f35232..37f4d650a5a 100644 --- a/Packages/com.unity.render-pipelines.core/Documentation~/TableOfContents.md +++ b/Packages/com.unity.render-pipelines.core/Documentation~/TableOfContents.md @@ -2,6 +2,7 @@ * [What's new](whats-new.md) * [12](whats-new-12.md) * [13](whats-new-13.md) + * [17](whats-new-17.md) * [Creating a custom render pipeline](srp-custom.md) * [Create a custom Scriptable Render Pipeline](srp-custom-getting-started.md) * [Create a Render Pipeline Asset and Render Pipeline Instance in a custom render pipeline](srp-creating-render-pipeline-asset-and-render-pipeline-instance.md) diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBuildProcessor.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBuildProcessor.cs index 65fbc5026a8..7e751855587 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBuildProcessor.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeBuildProcessor.cs @@ -4,11 +4,10 @@ using UnityEditor.Build.Reporting; using UnityEngine; using UnityEngine.Rendering; -using UnityEngine.SceneManagement; namespace UnityEditor.Rendering { - class ProbeVolumeBuildProcessor : BuildPlayerProcessor, IProcessSceneWithReport + class ProbeVolumeBuildProcessor : BuildPlayerProcessor, IPostprocessBuildWithReport { const string kTempAPVStreamingAssetsPath = "TempAPVStreamingAssets"; @@ -18,15 +17,27 @@ string GetTempAPVStreamingAssetsPath() return Path.Combine(libraryPath, kTempAPVStreamingAssetsPath); } - void PrepareStreamableAsset(ProbeVolumeStreamableAsset asset, string basePath, bool useStreamingAsset) + // Include an asset in the build. The mechanism for doing so depends on whether we are using StreamingAssets path. + static void IncludeStreamableAsset(ProbeVolumeStreamableAsset asset, string basePath, bool useStreamingAsset) { - asset.UpdateAssetReference(useStreamingAsset); - if (useStreamingAsset) + { + asset.ClearAssetReferenceForBuild(); CopyStreamableAsset(asset, basePath); + } + else + { + asset.EnsureAssetLoaded(); + } + } + + // Ensure that an asset is not included in the build. + static void StripStreambleAsset(ProbeVolumeStreamableAsset asset) + { + asset.ClearAssetReferenceForBuild(); } - void CopyStreamableAsset(ProbeVolumeStreamableAsset asset, string basePath) + static void CopyStreamableAsset(ProbeVolumeStreamableAsset asset, string basePath) { var assetPath = asset.GetAssetPath(); if (!File.Exists(assetPath)) @@ -60,6 +71,9 @@ void GetProbeVolumeProjectSettings(BuildTarget target, out bool supportProbeVolu } } + // Keep track of which assets we touched during the build, so we can restore them after the build. + private static HashSet s_BakingSetsProcessedLastBuild = new(); + public override void PrepareForBuild(BuildPlayerContext buildPlayerContext) { GetProbeVolumeProjectSettings(buildPlayerContext.BuildPlayerOptions.target, out bool supportProbeVolume, out var maxSHBands); @@ -89,8 +103,7 @@ public override void PrepareForBuild(BuildPlayerContext buildPlayerContext) Directory.CreateDirectory(tempStreamingAssetsPath); - HashSet processedBakingSets = new HashSet(); - + s_BakingSetsProcessedLastBuild.Clear(); foreach (var scene in buildPlayerContext.BuildPlayerOptions.scenes) { var sceneGUID = AssetDatabase.AssetPathToGUID(scene); @@ -98,7 +111,7 @@ public override void PrepareForBuild(BuildPlayerContext buildPlayerContext) if (bakingSet != null) { // Already processed (different scenes can belong to the same baking set). - if (processedBakingSets.Contains(bakingSet)) + if (s_BakingSetsProcessedLastBuild.Contains(bakingSet)) continue; if (!bakingSet.cellSharedDataAsset.IsValid()) // Not baked @@ -111,89 +124,53 @@ public override void PrepareForBuild(BuildPlayerContext buildPlayerContext) bool useStreamingAsset = !GraphicsSettings.GetRenderPipelineSettings().probeVolumeDisableStreamingAssets; - PrepareStreamableAsset(bakingSet.cellSharedDataAsset, basePath, useStreamingAsset); - PrepareStreamableAsset(bakingSet.cellBricksDataAsset, basePath, useStreamingAsset); + IncludeStreamableAsset(bakingSet.cellSharedDataAsset, basePath, useStreamingAsset); + IncludeStreamableAsset(bakingSet.cellBricksDataAsset, basePath, useStreamingAsset); // For now we always strip support data in build as it's mostly unsupported. // Later we'll need a proper option to strip it or not. bool stripSupportData = true; - if (!stripSupportData) - PrepareStreamableAsset(bakingSet.cellSupportDataAsset, basePath, useStreamingAsset); + if (stripSupportData) + StripStreambleAsset(bakingSet.cellSupportDataAsset); + else + IncludeStreamableAsset(bakingSet.cellSupportDataAsset, basePath, useStreamingAsset); foreach (var scenario in bakingSet.scenarios) { - PrepareStreamableAsset(scenario.Value.cellDataAsset, basePath, useStreamingAsset); + IncludeStreamableAsset(scenario.Value.cellDataAsset, basePath, useStreamingAsset); if (maxSHBands == ProbeVolumeSHBands.SphericalHarmonicsL2) - PrepareStreamableAsset(scenario.Value.cellOptionalDataAsset, basePath, useStreamingAsset); - PrepareStreamableAsset(scenario.Value.cellProbeOcclusionDataAsset, basePath, useStreamingAsset); + IncludeStreamableAsset(scenario.Value.cellOptionalDataAsset, basePath, useStreamingAsset); + else + StripStreambleAsset(scenario.Value.cellOptionalDataAsset); + IncludeStreamableAsset(scenario.Value.cellProbeOcclusionDataAsset, basePath, useStreamingAsset); } - processedBakingSets.Add(bakingSet); + s_BakingSetsProcessedLastBuild.Add(bakingSet); } } buildPlayerContext.AddAdditionalPathToStreamingAssets(tempStreamingAssetsPath, AdaptiveProbeVolumes.kAPVStreamingAssetsPath); } - private static bool IsBundleBuild(BuildReport report, bool isPlaying) - { - // We are entering playmode, so not building a bundle. - if (isPlaying) - return false; - - // Addressable builds do not provide a BuildReport. Because the Addressables package - // only supports AssetBundle builds, we infer that this is not a player build. - if (report == null) - return true; - - return report.summary.buildType == BuildType.AssetBundle; - } - - // This codepath handles the case of building asset bundles, i.e. not a full player build. It updates the references - // to individual data assets in the baking sets for each scene, such that the assets are included in the bundle. - public override int callbackOrder => 1; - public void OnProcessScene(Scene scene, BuildReport report) + public void OnPostprocessBuild(BuildReport report) { - // Only run for bundle builds. - if (!IsBundleBuild(report, Application.isPlaying)) - return; - - // Only run when APV is enabled. - GetProbeVolumeProjectSettings(EditorUserBuildSettings.activeBuildTarget, out bool supportProbeVolume, out var maxSHBands); - if (!supportProbeVolume) - return; - - // Reload the map from scene to baking set if we couldn't find the specific baking set. - if (ProbeVolumeBakingSet.sceneToBakingSet == null || ProbeVolumeBakingSet.sceneToBakingSet.Count == 0) - ProbeVolumeBakingSet.SyncBakingSets(); - - // Get the baking set for the scene. - var bakingSet = ProbeVolumeBakingSet.GetBakingSetForScene(scene.GetGUID()); - if (bakingSet == null || !bakingSet.cellSharedDataAsset.IsValid()) + if (s_BakingSetsProcessedLastBuild == null || s_BakingSetsProcessedLastBuild.Count == 0) return; - bool useStreamingAsset = !GraphicsSettings.GetRenderPipelineSettings().probeVolumeDisableStreamingAssets; - if (useStreamingAsset) + // Go over each asset reference we touched during the last build, make sure asset references are intact. + foreach (var bakingSet in s_BakingSetsProcessedLastBuild) { - Debug.LogWarning( - "Attempted to build an Asset Bundle containing Adaptive Probe Volume data, but streaming assets are enabled. This is unsupported. " + - "To use Adaptive Probe Volumes with Asset Bundles, please check 'Probe Volume Disable Streaming Assets' under Graphics Settings."); + bakingSet.cellBricksDataAsset.EnsureAssetLoaded(); + bakingSet.cellSharedDataAsset.EnsureAssetLoaded(); + bakingSet.cellSupportDataAsset.EnsureAssetLoaded(); + foreach (var scenario in bakingSet.scenarios) + { + scenario.Value.cellDataAsset.EnsureAssetLoaded(); + scenario.Value.cellOptionalDataAsset.EnsureAssetLoaded(); + scenario.Value.cellProbeOcclusionDataAsset.EnsureAssetLoaded(); + } } - // Update all the asset references. - bakingSet.cellSharedDataAsset.UpdateAssetReference(useStreamingAsset); - bakingSet.cellBricksDataAsset.UpdateAssetReference(useStreamingAsset); - - bool stripSupportData = true; - if (!stripSupportData) - bakingSet.cellSupportDataAsset.UpdateAssetReference(false); - - foreach (var scenario in bakingSet.scenarios) - { - scenario.Value.cellDataAsset.UpdateAssetReference(useStreamingAsset); - if (maxSHBands == ProbeVolumeSHBands.SphericalHarmonicsL2) - scenario.Value.cellOptionalDataAsset.UpdateAssetReference(useStreamingAsset); - scenario.Value.cellProbeOcclusionDataAsset.UpdateAssetReference(useStreamingAsset); - } + s_BakingSetsProcessedLastBuild.Clear(); } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/AssemblyInfo.cs b/Packages/com.unity.render-pipelines.core/Runtime/AssemblyInfo.cs index 8bf49b24911..96162f18722 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/AssemblyInfo.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/AssemblyInfo.cs @@ -5,3 +5,7 @@ [assembly: InternalsVisibleTo("Unity.RenderPipelines.Core.Runtime.Tests")] [assembly: InternalsVisibleTo("Unity.GraphicTests.Performance.RPCore.Runtime")] [assembly: InternalsVisibleTo("Unity.GraphicTests.Performance.Universal.Runtime")] // access to internal ProfileIds + +// Smoke test project visibility +[assembly: InternalsVisibleTo("SRPSmoke.Runtime.Tests")] +[assembly: InternalsVisibleTo("SRPSmoke.Editor.Tests")] diff --git a/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.cs b/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.cs index 666a7cb3706..aabf6728f7b 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.cs @@ -334,7 +334,7 @@ private static void Recreate(GPUResidentDrawerSettings settings) private NativeList m_FrameCameraIDs; private bool m_FrameUpdateNeeded = false; - private bool m_SelectionChanged; + private bool m_IsSelectionDirty; static GPUResidentDrawer() { @@ -399,6 +399,7 @@ private GPUResidentDrawer(GPUResidentDrawerSettings settings, int maxInstanceCou #if UNITY_EDITOR AssemblyReloadEvents.beforeAssemblyReload += OnAssemblyReload; m_FrameCameraIDs = new NativeList(1, Allocator.Persistent); + m_IsSelectionDirty = true; // Force at least one selection update #endif SceneManager.sceneLoaded += OnSceneLoaded; @@ -429,6 +430,7 @@ private void Dispose() #endif SceneManager.sceneLoaded -= OnSceneLoaded; + // Note: Those RenderPipelineManager callbacks do not run when using built-in editor debug views such as lightmap, shadowmask etc RenderPipelineManager.beginContextRendering -= OnBeginContextRendering; RenderPipelineManager.endContextRendering -= OnEndContextRendering; RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; @@ -487,6 +489,7 @@ private void OnBeginContextRendering(ScriptableRenderContext context, List cameras) { bool newFrame = false; @@ -508,21 +511,16 @@ private void EditorFrameUpdate(List cameras) else m_FrameUpdateNeeded = true; } - - ProcessSelection(); } private void OnSelectionChanged() { - m_SelectionChanged = true; + m_IsSelectionDirty = true; } - private void ProcessSelection() + private void UpdateSelection() { - if(!m_SelectionChanged) - return; - - m_SelectionChanged = false; + Profiler.BeginSample("GPUResidentDrawer.UpdateSelection"); Object[] renderers = Selection.GetFiltered(typeof(MeshRenderer), SelectionMode.Deep); @@ -532,8 +530,10 @@ private void ProcessSelection() rendererIDs[i] = renderers[i] ? renderers[i].GetInstanceID() : 0; m_Batcher.UpdateSelectedRenderers(rendererIDs); - + rendererIDs.Dispose(); + + Profiler.EndSample(); } #endif @@ -612,10 +612,15 @@ private void PostPostLateUpdate() supportedChangedPackedMaterialDatas.Dispose(); m_BatchersContext.UpdateInstanceMotions(); - m_Batcher.UpdateFrame(); #if UNITY_EDITOR + if (m_IsSelectionDirty) + { + UpdateSelection(); + m_IsSelectionDirty = false; + } + m_FrameUpdateNeeded = false; #endif } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingSet.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingSet.cs index d6d9a6d0c48..17e19c83793 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingSet.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeBakingSet.cs @@ -31,7 +31,8 @@ public sealed partial class ProbeVolumeBakingSet : ScriptableObject, ISerializat internal enum Version { Initial, - RemoveProbeVolumeSceneData + RemoveProbeVolumeSceneData, + AssetsAlwaysReferenced, } [Serializable] @@ -345,6 +346,28 @@ internal void Migrate() #endif } + // Upgrade baking sets from before we always stored asset references. + if (version < Version.AssetsAlwaysReferenced && ProbeReferenceVolume.instance.isInitialized) + { +#if UNITY_EDITOR + cellBricksDataAsset.EnsureAssetLoaded(); + cellSharedDataAsset.EnsureAssetLoaded(); + cellSupportDataAsset.EnsureAssetLoaded(); + foreach (var scenario in scenarios) + { + scenario.Value.cellDataAsset.EnsureAssetLoaded(); + scenario.Value.cellOptionalDataAsset.EnsureAssetLoaded(); + scenario.Value.cellProbeOcclusionDataAsset.EnsureAssetLoaded(); + } + + version = Version.AssetsAlwaysReferenced; + + // Save immediately since these references must be written to disk for certain functionality + // to work, such as exporting a .unitypackage. Changing in memory is not enough. + UnityEditor.EditorUtility.SetDirty(this); + UnityEditor.AssetDatabase.SaveAssetIfDirty(this); +#endif + } #pragma warning restore 618 } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeStreamableAsset.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeStreamableAsset.cs index 4f60b151350..e3806ed3f96 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeStreamableAsset.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeStreamableAsset.cs @@ -43,6 +43,9 @@ public ProbeVolumeStreamableAsset(string apvStreamingAssetsPath, SerializedDicti m_StreamableCellDescs = cellDescs; m_ElementSize = elementSize; m_StreamableAssetPath = Path.Combine(Path.Combine(apvStreamingAssetsPath, bakingSetGUID), m_AssetGUID + ".bytes"); +#if UNITY_EDITOR + EnsureAssetLoaded(); +#endif } internal void RefreshAssetPath() @@ -89,9 +92,16 @@ public void RenameAsset(string newName) m_FinalAssetPath = ""; } - public void UpdateAssetReference(bool useStreamingAsset) + // Ensures that the asset is referenced via Unity's serialization layer. + public void EnsureAssetLoaded() + { + m_Asset = AssetDatabase.LoadAssetAtPath(GetAssetPath()); + } + + // Temporarily clear the asset reference. Used to prevent serialization of the asset when we are using the StreamingAssets codepath. + public void ClearAssetReferenceForBuild() { - m_Asset = useStreamingAsset ? null : AssetDatabase.LoadAssetAtPath(GetAssetPath()); + m_Asset = null; } #endif diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/PassesData.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/PassesData.cs index ba880599e08..b5c71918c6c 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/PassesData.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/PassesData.cs @@ -4,6 +4,7 @@ using Unity.Collections.LowLevel.Unsafe; using UnityEngine.Rendering; using System.Collections.Generic; +using Unity.Collections; namespace UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler { @@ -594,7 +595,9 @@ public readonly ReadOnlySpan GraphPasses(CompilerContextData ctx) return ctx.passData.MakeReadOnlySpan(firstGraphPass, numGraphPasses); } - var actualPasses = new PassData[numGraphPasses]; + var actualPasses = + new NativeArray(numGraphPasses, Allocator.Temp, + NativeArrayOptions.UninitializedMemory); for (int i = firstGraphPass, index = 0; i < lastGraphPass + 1; ++i) { 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 a59c8efba8c..46f5ec44601 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs @@ -2519,7 +2519,7 @@ void GenerateCompilerDebugData(ref DebugData debugData) newPass.syncFromPassIndex = passInfo.syncFromPassIndex; newPass.syncToPassIndex = passInfo.syncToPassIndex; - DebugData.s_PassScriptMetadata.TryGetValue(pass.name, out newPass.scriptInfo); + DebugData.s_PassScriptMetadata.TryGetValue(pass, out newPass.scriptInfo); for (int type = 0; type < (int)RenderGraphResourceType.Count; ++type) { diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/AssemblyInfo.cs b/Packages/com.unity.render-pipelines.core/Tests/Editor/AssemblyInfo.cs new file mode 100644 index 00000000000..21d14073caf --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Tests/Editor/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("SRPSmoke.Editor.Tests")] diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/AssemblyInfo.cs.meta b/Packages/com.unity.render-pipelines.core/Tests/Editor/AssemblyInfo.cs.meta new file mode 100644 index 00000000000..e8c59f801cb --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Tests/Editor/AssemblyInfo.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 79d9da7a81239e744bc809717c68ae47 \ No newline at end of file diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/NativePassCompilerRenderGraphTests.cs b/Packages/com.unity.render-pipelines.core/Tests/Editor/NativePassCompilerRenderGraphTests.cs index 3ad5f36cfb1..abece210ec4 100644 --- a/Packages/com.unity.render-pipelines.core/Tests/Editor/NativePassCompilerRenderGraphTests.cs +++ b/Packages/com.unity.render-pipelines.core/Tests/Editor/NativePassCompilerRenderGraphTests.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using UnityEngine.Experimental.Rendering; +using UnityEngine.Profiling; using UnityEngine.Rendering.RenderGraphModule; using UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler; @@ -9,6 +10,8 @@ namespace UnityEngine.Rendering.Tests { class NativePassCompilerRenderGraphTests { + static Recorder gcAllocRecorder = Recorder.Get("GC.Alloc"); + class RenderGraphTestPassData { public TextureHandle[] textures = new TextureHandle[8]; @@ -1145,5 +1148,64 @@ public void ChangingGlobalStateDisablesCulling() Assert.IsTrue(firstNativePass.numGraphPasses == 2); } + + [Test] + public void GraphPassesDoesNotAlloc() + { + var g = AllocateRenderGraph(); + using (var builder = g.AddRasterRenderPass("TestPass0", out var passData)) + { + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + builder.AllowPassCulling(false); + } + using (var builder = g.AddRasterRenderPass("TestPass1_Culled", out var passData)) + { + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + builder.AllowPassCulling(true); + } + using (var builder = g.AddRasterRenderPass("TestPass2", out var passData)) + { + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + builder.AllowPassCulling(false); + } + + // First pass is preserved as requested but second pass is culled + var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); + var passes = result.contextData.GetNativePasses(); + + // Second pass has been culled + Assert.IsTrue(passes != null && passes.Count == 1 && passes[0].numGraphPasses == 2); + // Goes into possible alloc path + Assert.IsFalse(passes[0].lastGraphPass - passes[0].firstGraphPass + 1 == passes[0].numGraphPasses); + + + ValidateNoGCAllocs(() => + { + passes[0].GraphPasses(result.contextData); + }); + + // From RenderPassCullingTests.cs + void ValidateNoGCAllocs(Action action) + { + // Warmup - this will catch static c'tors etc. + CountGCAllocs(action); + + // Actual test. + var count = CountGCAllocs(action); + if (count != 0) + throw new AssertionException($"Expected 0 GC allocations but there were {count}"); + } + + int CountGCAllocs(Action action) + { + gcAllocRecorder.FilterToCurrentThread(); + gcAllocRecorder.enabled = true; + + action(); + + gcAllocRecorder.enabled = false; + return gcAllocRecorder.sampleBlockCount; + } + } } } diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/Unity.RenderPipelines.Core.Editor.Tests.asmdef b/Packages/com.unity.render-pipelines.core/Tests/Editor/Unity.RenderPipelines.Core.Editor.Tests.asmdef index cd34a7d1f6d..1d43eb285b9 100644 --- a/Packages/com.unity.render-pipelines.core/Tests/Editor/Unity.RenderPipelines.Core.Editor.Tests.asmdef +++ b/Packages/com.unity.render-pipelines.core/Tests/Editor/Unity.RenderPipelines.Core.Editor.Tests.asmdef @@ -9,7 +9,8 @@ "GUID:d8b63aba1907145bea998dd612889d6b", "GUID:4fd6538c1c56b409fb53fdf0183170ec", "GUID:e0cd26848372d4e5c891c569017e11f1", - "GUID:bf043f86dbf1bda4398ec83eebe40b8c" + "GUID:bf043f86dbf1bda4398ec83eebe40b8c", + "GUID:aa4a944c34c4c5449b84975fb1570dad" ], "includePlatforms": [ "Editor" @@ -26,4 +27,4 @@ ], "versionDefines": [], "noEngineReferences": false -} +} \ No newline at end of file diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/RenderPipelineTests.cs b/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/RenderPipelineTests.cs index 02f7e8eb621..65a1988f560 100644 --- a/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/RenderPipelineTests.cs +++ b/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/RenderPipelineTests.cs @@ -5,7 +5,7 @@ namespace UnityEditor.Rendering.Tests { - class RenderPipelineTests + internal class RenderPipelineTests { RenderPipelineAsset m_PreviousRenderPipelineAssetInGraphicsSettings; RenderPipelineAsset m_PreviousRenderPipelineAssetInQualitySettings; diff --git a/Packages/com.unity.render-pipelines.core/Tests/Runtime/AssemblyInfos.cs b/Packages/com.unity.render-pipelines.core/Tests/Runtime/AssemblyInfos.cs index 89789ef4a5e..d1f436bab46 100644 --- a/Packages/com.unity.render-pipelines.core/Tests/Runtime/AssemblyInfos.cs +++ b/Packages/com.unity.render-pipelines.core/Tests/Runtime/AssemblyInfos.cs @@ -1,3 +1,5 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Unity.RenderPipelines.Core.Editor.Tests")] +[assembly: InternalsVisibleTo("SRPSmoke.Runtime.Tests")] +[assembly: InternalsVisibleTo("SRPSmoke.Editor.Tests")] diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Ray-Tracing-Getting-Started.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Ray-Tracing-Getting-Started.md index 5bcc53bf216..38cb0144ab4 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Ray-Tracing-Getting-Started.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Ray-Tracing-Getting-Started.md @@ -140,4 +140,4 @@ To build your Project to a Unity Player, ray tracing requires that the build use To check whether it's possible to use ray tracing in a Scene, HDRP includes a menu option that validates each GameObject in the Scene. If you don't setup GameObjects correctly, this process throws warnings in the Console window. For the list of things this option checks for, see [Menu items](Menu-Items.md#other). To use it: 1. Click **Edit** > **Render Pipeline** > **HD Render Pipeline** > **Check Scene Content for Ray Tracing**. -2. In the Console window, check if there are any warnings. \ No newline at end of file +2. In the Console window, check if there are any warnings. diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/path-tracing-limitations.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/path-tracing-limitations.md index fa57b017aed..f8ea1811302 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/path-tracing-limitations.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/path-tracing-limitations.md @@ -22,6 +22,7 @@ HDRP path tracing in Unity currently has the following limitations: - Emissive Decals. - [Graphics.DrawMesh](https://docs.unity3d.com/ScriptReference/Graphics.DrawMesh.html) or [Graphics.RenderMesh](https://docs.unity3d.com/2022.1/Documentation/ScriptReference/Graphics.RenderMesh.html), because rasterization and ray tracing are different ways of generating an image. - [Streaming Virtual Texturing](https://docs.unity3d.com/Documentation/Manual/svt-streaming-virtual-texturing.html). + - Vertex animation, for example wind deformation of vegetation. ### Unsupported shader graph nodes for path tracing diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/ray-tracing-introduction.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/ray-tracing-introduction.md index 22801f4a256..a546fc56015 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/ray-tracing-introduction.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/ray-tracing-introduction.md @@ -73,6 +73,7 @@ Ray tracing in HDRP isn't compatible with the following features. - Box-shaped spot lights. - Fully accurate shadow culling. You might see missing shadows in ray-traced effects. To improve the accuracy of shadow culling, use the **Extend Shadow Culling** property in [Ray Tracing Settings](reference-ray-tracing-settings.md). - Volumetric [fog](create-a-local-fog-effect.md). +- Water. #### Geometry and materials diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/rendering-debugger-window-reference.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/rendering-debugger-window-reference.md index 7cd61d6725d..0b3bb1b5be1 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/rendering-debugger-window-reference.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/rendering-debugger-window-reference.md @@ -648,12 +648,15 @@ The **Color monitors** are a set of industry-standard monitors to help artists c | **Size** | The size ratio of the color monitors. | | **Property** | **Description** | -| ----------------- | ------------------------------------------------------------ | -| **Clear Render Targets at creation** | Enable the checkbox to make the Render Graph system clear render targets the first time it uses them | -| **Disable Pass Culling** | Enable the checkbox to render passes which have no impact on the final render. | -| **Immediate Mode** | Enable the checkbox to make the Render Graph system evaluate passes immediately after it creates them. | -| **Log Frame Information** | Press the button to log in the Console informations about the passes rendered during a frame. | -| **Log Resources** | Press the button to log in the Console the list of resources used when rendering a frame. | +| --- | --- | +| **Clear Render Targets At Creation** | Clears render textures the first time the render graph system uses them. | +| **Clear Render Targets When Freed** | Clears render textures when they're no longer used by render graph. | +| **Disable Pass Culling** | Disables HDRP culling render passes that have no impact on the final render. | +| **Disable Pass Merging** | Disables HDRP merging render passes. | +| **Immediate Mode** | Enables the render graph system evaluating passes immediately after it creates them. | +| **Enable Logging** | Enables logging to the **Console** window. | +| **Log Frame Information** | Logs how HDRP uses the resources during the frame, in the **Console** window. | +| **Log Resources** | Logs the resources HDRP uses during the frame, in the **Console** window. | The **NVIDIA device debug view** is a panel that displays a list of the current feature states of NVIDIA Deep Learning Super Sampling (DLSS). Each row represents an active screen in which DLSS is running. diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/HDSubTarget.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/HDSubTarget.cs index 49ef88a43ee..02c1f8fbab2 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/HDSubTarget.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/HDSubTarget.cs @@ -213,7 +213,9 @@ protected SubShaderDescriptor PostProcessSubShader(SubShaderDescriptor subShader { if (passDescriptor.defines == null) passDescriptor.defines = new(); - passDescriptor.defines.Add(CoreDefines.SupportGlobalMipBias); + + if (!passDescriptor.defines.Any(d => d.descriptor.referenceName == CoreDefines.SupportGlobalMipBias.First().descriptor.referenceName)) + passDescriptor.defines.Add(CoreDefines.SupportGlobalMipBias); } CollectPassKeywords(ref passDescriptor); @@ -287,7 +289,9 @@ protected KernelDescriptor PostProcessKernel(KernelDescriptor kernel) { if (passDescriptor.defines == null) passDescriptor.defines = new(); - passDescriptor.defines.Add(CoreDefines.SupportGlobalMipBias); + + if (!passDescriptor.defines.Any(d => d.descriptor.referenceName == CoreDefines.SupportGlobalMipBias.First().descriptor.referenceName)) + passDescriptor.defines.Add(CoreDefines.SupportGlobalMipBias); } CollectPassKeywords(ref passDescriptor); diff --git a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl index e9fe4012c22..618237713b0 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl +++ b/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl @@ -126,6 +126,12 @@ VaryingsToDS InterpolateWithBaryCoordsToDS(VaryingsToDS input0, VaryingsToDS inp #define PackVaryingsType PackVaryingsToPS #endif +#if defined(HAVE_VFX_MODIFICATION) +//compiler shows warning when using intermediate returns (see vfx culling), disable this. +#pragma warning(push) +#pragma warning(disable : 4000) +#endif + // TODO: Here we will also have all the vertex deformation (GPU skinning, vertex animation, morph target...) or we will need to generate a compute shaders instead (better! but require work to deal with unpacking like fp16) VaryingsMeshType VertMesh(AttributesMesh input, float3 worldSpaceOffset #ifdef HAVE_VFX_MODIFICATION @@ -245,6 +251,10 @@ VaryingsMeshType VertMesh(AttributesMesh input, float3 worldSpaceOffset return output; } +#if defined(HAVE_VFX_MODIFICATION) +#pragma warning(pop) +#endif + VaryingsMeshType VertMesh(AttributesMesh input) { #ifdef HAVE_VFX_MODIFICATION diff --git a/Packages/com.unity.render-pipelines.universal/Editor/2D/Renderer2DDataEditor.cs b/Packages/com.unity.render-pipelines.universal/Editor/2D/Renderer2DDataEditor.cs index a59f2d74237..ced1ddbee80 100644 --- a/Packages/com.unity.render-pipelines.universal/Editor/2D/Renderer2DDataEditor.cs +++ b/Packages/com.unity.render-pipelines.universal/Editor/2D/Renderer2DDataEditor.cs @@ -13,6 +13,9 @@ class Styles public static readonly GUIContent lightBlendStylesHeader = EditorGUIUtility.TrTextContent("Light Blend Styles", "A Light Blend Style is a collection of properties that describe a particular way of applying lighting."); public static readonly GUIContent postProcessHeader = EditorGUIUtility.TrTextContent("Post-processing"); + public static readonly GUIContent filteringSectionLabel = EditorGUIUtility.TrTextContent("Filtering", "Settings that controls and define which layers the renderer draws."); + public static readonly GUIContent layerMask = EditorGUIUtility.TrTextContent("Layer Mask", "Controls which transparent layers this renderer draws."); + public static readonly GUIContent transparencySortMode = EditorGUIUtility.TrTextContent("Transparency Sort Mode", "Default sorting mode used for transparent objects"); public static readonly GUIContent transparencySortAxis = EditorGUIUtility.TrTextContent("Transparency Sort Axis", "Axis used for custom axis sorting mode"); public static readonly GUIContent hdrEmulationScale = EditorGUIUtility.TrTextContent("HDR Emulation Scale", "Describes the scaling used by lighting to remap dynamic range between LDR and HDR"); @@ -43,6 +46,7 @@ struct LightBlendStyleProps public SerializedProperty blendFactorAdditive; } + SerializedProperty m_LayerMask; SerializedProperty m_TransparencySortMode; SerializedProperty m_TransparencySortAxis; SerializedProperty m_HDREmulationScale; @@ -60,6 +64,7 @@ struct LightBlendStyleProps SerializedProperty m_CameraSortingLayersTextureBound; SerializedProperty m_CameraSortingLayerDownsamplingMethod; + SavedBool m_FilteringFoldout; SavedBool m_GeneralFoldout; SavedBool m_LightRenderTexturesFoldout; SavedBool m_LightBlendStylesFoldout; @@ -84,6 +89,7 @@ void OnEnable() m_WasModified = false; m_Renderer2DData = (Renderer2DData)serializedObject.targetObject; + m_LayerMask = serializedObject.FindProperty("m_LayerMask"); m_TransparencySortMode = serializedObject.FindProperty("m_TransparencySortMode"); m_TransparencySortAxis = serializedObject.FindProperty("m_TransparencySortAxis"); m_HDREmulationScale = serializedObject.FindProperty("m_HDREmulationScale"); @@ -121,6 +127,7 @@ void OnEnable() m_DefaultMaterialType = serializedObject.FindProperty("m_DefaultMaterialType"); m_DefaultCustomMaterial = serializedObject.FindProperty("m_DefaultCustomMaterial"); + m_FilteringFoldout = new SavedBool($"{target.GetType()}.FilteringFoldout", true); m_GeneralFoldout = new SavedBool($"{target.GetType()}.GeneralFoldout", true); m_LightRenderTexturesFoldout = new SavedBool($"{target.GetType()}.LightRenderTexturesFoldout", true); m_LightBlendStylesFoldout = new SavedBool($"{target.GetType()}.LightBlendStylesFoldout", true); @@ -137,6 +144,7 @@ public override void OnInspectorGUI() { serializedObject.Update(); + DrawFiltering(); DrawGeneral(); DrawLightRenderTextures(); DrawLightBlendStyles(); @@ -184,6 +192,18 @@ public void DrawCameraSortingLayerTexture() EditorGUI.EndDisabledGroup(); } + private void DrawFiltering() + { + CoreEditorUtils.DrawSplitter(); + m_FilteringFoldout.value = CoreEditorUtils.DrawHeaderFoldout(Styles.filteringSectionLabel, m_FilteringFoldout.value); + if (!m_FilteringFoldout.value) + return; + + EditorGUILayout.PropertyField(m_LayerMask, Styles.layerMask); + + EditorGUILayout.Space(); + } + private void DrawGeneral() { CoreEditorUtils.DrawSplitter(); diff --git a/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/FullScreenPassRendererFeatureEditor.cs b/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/FullScreenPassRendererFeatureEditor.cs index d8fccb87677..92691710b72 100644 --- a/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/FullScreenPassRendererFeatureEditor.cs +++ b/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/FullScreenPassRendererFeatureEditor.cs @@ -1,85 +1,88 @@ using System.Collections.Generic; -using UnityEditor; -using UnityEditor.Rendering; using UnityEngine; +using UnityEngine.Rendering.Universal; -/// -/// Custom editor for FullScreenPassRendererFeature class responsible for drawing unavailable by default properties -/// such as custom drop down items and additional properties. -/// -[CustomEditor(typeof(FullScreenPassRendererFeature))] -public class FullScreenPassRendererFeatureEditor : Editor +namespace UnityEditor.Rendering.Universal { - private SerializedProperty m_InjectionPointProperty; - private SerializedProperty m_RequirementsProperty; - private SerializedProperty m_FetchColorBufferProperty; - private SerializedProperty m_BindDepthStencilAttachmentProperty; - private SerializedProperty m_PassMaterialProperty; - private SerializedProperty m_PassIndexProperty; - - private static readonly GUIContent k_InjectionPointGuiContent = new GUIContent("Injection Point", "Specifies where in the frame this pass will be injected."); - private static readonly GUIContent k_RequirementsGuiContent = new GUIContent("Requirements", "A mask of URP internal textures that will need to be generated and bound for sampling.\n\nNote that 'Color' here corresponds to '_CameraOpaqueTexture' so most of the time you will want to use the 'Fetch Color Buffer' option instead."); - private static readonly GUIContent k_FetchColorBufferGuiContent = new GUIContent("Fetch Color Buffer", "Enable this if the assigned material will need to sample the active color target. The active color will be bound to the '_BlitTexture' shader property for sampling. Note that this will introduce an internal color copy pass."); - private static readonly GUIContent k_BindDepthStencilAttachmentGuiContent = new GUIContent("Bind Depth-Stencil", "Enable this to bind the active camera's depth-stencil attachment to the framebuffer (only use this if depth-stencil ops are used by the assigned material as this could have a performance impact)."); - private static readonly GUIContent k_PassMaterialGuiContent = new GUIContent("Pass Material", "The material used to render the full screen pass."); - private static readonly GUIContent k_PassGuiContent = new GUIContent("Pass", "The name of the shader pass to use from the assigned material."); - - private void OnEnable() - { - m_InjectionPointProperty = serializedObject.FindProperty("injectionPoint"); - m_RequirementsProperty = serializedObject.FindProperty("requirements"); - m_FetchColorBufferProperty = serializedObject.FindProperty("fetchColorBuffer"); - m_BindDepthStencilAttachmentProperty = serializedObject.FindProperty("bindDepthStencilAttachment"); - m_PassMaterialProperty = serializedObject.FindProperty("passMaterial"); - m_PassIndexProperty = serializedObject.FindProperty("passIndex"); - } - /// - /// Implementation for a custom inspector + /// Custom editor for FullScreenPassRendererFeature class responsible for drawing unavailable by default properties + /// such as custom drop down items and additional properties. /// - public override void OnInspectorGUI() + [UnityEngine.Scripting.APIUpdating.MovedFrom("")] + [CustomEditor(typeof(FullScreenPassRendererFeature))] + public class FullScreenPassRendererFeatureEditor : Editor { - var currentFeature = target as FullScreenPassRendererFeature; + private SerializedProperty m_InjectionPointProperty; + private SerializedProperty m_RequirementsProperty; + private SerializedProperty m_FetchColorBufferProperty; + private SerializedProperty m_BindDepthStencilAttachmentProperty; + private SerializedProperty m_PassMaterialProperty; + private SerializedProperty m_PassIndexProperty; - if (currentFeature.passMaterial == null || currentFeature.passIndex >= currentFeature.passMaterial.passCount) - currentFeature.passIndex = 0; + private static readonly GUIContent k_InjectionPointGuiContent = new GUIContent("Injection Point", "Specifies where in the frame this pass will be injected."); + private static readonly GUIContent k_RequirementsGuiContent = new GUIContent("Requirements", "A mask of URP internal textures that will need to be generated and bound for sampling.\n\nNote that 'Color' here corresponds to '_CameraOpaqueTexture' so most of the time you will want to use the 'Fetch Color Buffer' option instead."); + private static readonly GUIContent k_FetchColorBufferGuiContent = new GUIContent("Fetch Color Buffer", "Enable this if the assigned material will need to sample the active color target. The active color will be bound to the '_BlitTexture' shader property for sampling. Note that this will introduce an internal color copy pass."); + private static readonly GUIContent k_BindDepthStencilAttachmentGuiContent = new GUIContent("Bind Depth-Stencil", "Enable this to bind the active camera's depth-stencil attachment to the framebuffer (only use this if depth-stencil ops are used by the assigned material as this could have a performance impact)."); + private static readonly GUIContent k_PassMaterialGuiContent = new GUIContent("Pass Material", "The material used to render the full screen pass."); + private static readonly GUIContent k_PassGuiContent = new GUIContent("Pass", "The name of the shader pass to use from the assigned material."); - EditorGUILayout.PropertyField(m_InjectionPointProperty, k_InjectionPointGuiContent); - EditorGUILayout.PropertyField(m_RequirementsProperty, k_RequirementsGuiContent); - EditorGUILayout.PropertyField(m_FetchColorBufferProperty, k_FetchColorBufferGuiContent); - EditorGUILayout.PropertyField(m_BindDepthStencilAttachmentProperty, k_BindDepthStencilAttachmentGuiContent); - EditorGUILayout.PropertyField(m_PassMaterialProperty, k_PassMaterialGuiContent); - - if (AdvancedProperties.BeginGroup()) + private void OnEnable() { - DrawMaterialPassProperty(currentFeature); + m_InjectionPointProperty = serializedObject.FindProperty("injectionPoint"); + m_RequirementsProperty = serializedObject.FindProperty("requirements"); + m_FetchColorBufferProperty = serializedObject.FindProperty("fetchColorBuffer"); + m_BindDepthStencilAttachmentProperty = serializedObject.FindProperty("bindDepthStencilAttachment"); + m_PassMaterialProperty = serializedObject.FindProperty("passMaterial"); + m_PassIndexProperty = serializedObject.FindProperty("passIndex"); } - AdvancedProperties.EndGroup(); - serializedObject.ApplyModifiedProperties(); - } + /// + /// Implementation for a custom inspector + /// + public override void OnInspectorGUI() + { + var currentFeature = target as FullScreenPassRendererFeature; - private void DrawMaterialPassProperty(FullScreenPassRendererFeature feature) - { - List selectablePasses; - bool isMaterialValid = feature.passMaterial != null; - selectablePasses = isMaterialValid ? GetPassIndexStringEntries(feature) : new List() {"No material"}; + if (currentFeature.passMaterial == null || currentFeature.passIndex >= currentFeature.passMaterial.passCount) + currentFeature.passIndex = 0; - // If material is invalid 0'th index is selected automatically, so it stays on "No material" entry - // It is invalid index, but FullScreenPassRendererFeature wont execute until material is valid - m_PassIndexProperty.intValue = EditorGUILayout.Popup(k_PassGuiContent, m_PassIndexProperty.intValue, selectablePasses.ToArray()); - } + EditorGUILayout.PropertyField(m_InjectionPointProperty, k_InjectionPointGuiContent); + EditorGUILayout.PropertyField(m_RequirementsProperty, k_RequirementsGuiContent); + EditorGUILayout.PropertyField(m_FetchColorBufferProperty, k_FetchColorBufferGuiContent); + EditorGUILayout.PropertyField(m_BindDepthStencilAttachmentProperty, k_BindDepthStencilAttachmentGuiContent); + EditorGUILayout.PropertyField(m_PassMaterialProperty, k_PassMaterialGuiContent); - private static List GetPassIndexStringEntries(FullScreenPassRendererFeature component) - { - List passIndexEntries = new List(); - for (int i = 0; i < component.passMaterial.passCount; ++i) + if (AdvancedProperties.BeginGroup()) + { + DrawMaterialPassProperty(currentFeature); + } + AdvancedProperties.EndGroup(); + + serializedObject.ApplyModifiedProperties(); + } + + private void DrawMaterialPassProperty(FullScreenPassRendererFeature feature) { - // "Name of a pass (index)" - "PassAlpha (1)" - string entry = $"{component.passMaterial.GetPassName(i)} ({i})"; - passIndexEntries.Add(entry); + List selectablePasses; + bool isMaterialValid = feature.passMaterial != null; + selectablePasses = isMaterialValid ? GetPassIndexStringEntries(feature) : new List() {"No material"}; + + // If material is invalid 0'th index is selected automatically, so it stays on "No material" entry + // It is invalid index, but FullScreenPassRendererFeature wont execute until material is valid + m_PassIndexProperty.intValue = EditorGUILayout.Popup(k_PassGuiContent, m_PassIndexProperty.intValue, selectablePasses.ToArray()); } - return passIndexEntries; + private static List GetPassIndexStringEntries(FullScreenPassRendererFeature component) + { + List passIndexEntries = new List(); + for (int i = 0; i < component.passMaterial.passCount; ++i) + { + // "Name of a pass (index)" - "PassAlpha (1)" + string entry = $"{component.passMaterial.GetPassName(i)} ({i})"; + passIndexEntries.Add(entry); + } + + return passIndexEntries; + } } } diff --git a/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/NewPostProcessRendererFeature.cs.txt b/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/NewPostProcessRendererFeature.cs.txt index 7779aa5ce68..60a7ebe1f67 100644 --- a/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/NewPostProcessRendererFeature.cs.txt +++ b/Packages/com.unity.render-pipelines.universal/Editor/RendererFeatures/NewPostProcessRendererFeature.cs.txt @@ -3,43 +3,31 @@ using UnityEngine.Rendering; using UnityEngine.Rendering.RenderGraphModule; using UnityEngine.Rendering.Universal; -// This is the script template for creating a ScriptableRendererFeature meant for a post-processing effect -// -// To see how this feature is made to work with on a custom VolumeComponent observe the "AddRenderPasses" and "ExecuteMainPass" methods -// -// For a general guide on how to create custom ScriptableRendererFeatures see the following URP documentation page: -// https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@latest/index.html?subfolder=/manual/renderer-features/create-custom-renderer-feature.html +// Create a Scriptable Renderer Feature that implements a post-processing effect when the camera is inside a custom volume. +// For more information about creating scriptable renderer features, refer to https://docs.unity3d.com/Manual/urp/customizing-urp.html public sealed class #FEATURE_TYPE# : ScriptableRendererFeature { #region FEATURE_FIELDS - // * The material used to render the post-processing effect - // * The 'SerializeField' attribute makes sure that the private material reference we assign in the "Create" method - // while in the editor will be serialised and the referenced material will be included in the player build - // * To not clutter the renderer feature UI we're keeping this field hidden, but if you'd like to be able to change - // the material in the editor UI you could just make this field public and remove the current attributes + // Declare the material used to render the post-processing effect. + // Add a [SerializeField] attribute so Unity serializes the property and includes it in builds. [SerializeField] [HideInInspector] private Material m_Material; - // The user defined ScriptableRenderPass that is responsible for the actual rendering of the effect + // Declare the render pass that renders the effect. private CustomPostRenderPass m_FullScreenPass; #endregion #region FEATURE_METHODS + // Override the Create method. + // Unity calls this method when the Scriptable Renderer Feature loads for the first time, and when you change a property. public override void Create() { #if UNITY_EDITOR - // * This assigns a material asset reference while in the editor and the "[SerializeField]" attribute on the - // private `m_Material` field will make sure that the referenced material will be included in player builds - // * Alternatively, you could create a material from the shader at runtime e.g.: - // 'm_Material = new Material(m_Shader);' - // In this case for the shader referenced by 'm_Shader' to be included in builds you will have to either: - // 1) Assign 'm_Shader = Shader.Find("Shader Graphs/FullscreenInvertColors")' behind UNITY_EDITOR only and make sure 'm_Shader' is a "[SerializedField]" - // 2) Or add "Shader Graphs/FullscreenInvertColors" to the "Always Included Shaders List" under "ProjectSettings"-> "Graphics" -> "Shader Settings" - // and call 'm_Shader = Shader.Find("Shader Graphs/FullscreenInvertColors")' outside of the UNITY_EDITOR section + // Assign a material asset to m_Material in the Unity Editor. if (m_Material == null) m_Material = UnityEditor.AssetDatabase.LoadAssetAtPath("Packages/com.unity.render-pipelines.universal/Runtime/Materials/FullscreenInvertColors.mat"); #endif @@ -48,87 +36,63 @@ public sealed class #FEATURE_TYPE# : ScriptableRendererFeature m_FullScreenPass = new CustomPostRenderPass(name, m_Material); } - // Here you can inject one or multiple render passes in the renderer. - // This method is called when setting up the renderer once per-camera. + // Override the AddRenderPasses method to inject passes into the renderer. Unity calls AddRenderPasses once per camera. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { - // Skip rendering if m_Material or the pass instance are null for whatever reason + // Skip rendering if m_Material or the pass instance are null. if (m_Material == null || m_FullScreenPass == null) return; - // This check makes sure to not render the effect to reflection probes or preview cameras as post-processing is typically not desired there + // Skip rendering if the target is a Reflection Probe or a preview camera. if (renderingData.cameraData.cameraType == CameraType.Preview || renderingData.cameraData.cameraType == CameraType.Reflection) return; - // You can control the rendering of your feature using custom post-processing VolumeComponents - // - // E.g. when controlling rendering with a VolumeComponent you will typically want to skip rendering as an optimization when the component - // has settings which would make it imperceptible (e.g. the implementation of IsActive() might return false when some "intensity" value is 0). - // - // N.B. if your volume component type is actually defined in C# it is unlikely that VolumeManager would return a "null" instance of it as - // GlobalSettings should always contain an instance of all VolumeComponents in the project even if if they're not overriden in the scene + // Skip rendering if the camera is outside the custom volume. #VOLUME_TYPE# myVolume = VolumeManager.instance.stack?.GetComponent<#VOLUME_TYPE#>(); if (myVolume == null || !myVolume.IsActive()) return; - // Here you specify at which part of the frame the effect will execute - // - // When creating post-processing effects you will almost always want to use on of the following injection points: - // BeforeRenderingTransparents - in cases you want your effect to be visible behind transparent objects - // BeforeRenderingPostProcessing - in cases where your effect is supposed to run before the URP post-processing stack - // AfterRenderingPostProcessing - in cases where your effect is supposed to run after the URP post-processing stack, but before FXAA, upscaling or color grading + // Specify when the effect will execute during the frame. + // For a post-processing effect, the injection point is usually BeforeRenderingTransparents, BeforeRenderingPostProcessing, or AfterRenderingPostProcessing. + // For more information, refer to https://docs.unity3d.com/Manual/urp/customize/custom-pass-injection-points.html m_FullScreenPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; - // You can specify if your effect needs scene depth, normals, motion vectors or a downscaled opaque color as input - // - // You specify them as a mask e.g. ScriptableRenderPassInput.Normals | ScriptableRenderPassInput.Motion and URP - // will either reuse these if they've been generated earlier in the frame or will add passes to generate them. - // - // The inputs will get bound as global shader texture properties and can be sampled in the shader using using the following: - // * Depth - use "SampleSceneDepth" after including "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl" - // * Normal - use "SampleSceneNormals" after including "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl" - // * Opaque Scene Color - use "SampleSceneColor" after including "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl". - // Note that "OpaqueSceneColor" is a texture containing a possibly downscaled copy of the framebuffer from before rendering transparent objects which - // should not be your first choice when wanting to do a post-processing effect, for that this template will copy the active texture for sampling which is more expensive - // * Motion Vectors - you currently need to declare and sample the texture as follows: - // TEXTURE2D_X(_MotionVectorTexture); - // ... - // LOAD_TEXTURE2D_X_LOD(_MotionVectorTexture, pixelCoords, 0).xy - // - // N.B. when using the FullScreenPass Shader Graph target you should simply use the "URP Sample Buffer" node which will handle the above for you + // Specify that the effect doesn't need scene depth, normals, motion vectors, or the color texture as input. m_FullScreenPass.ConfigureInput(ScriptableRenderPassInput.None); + // Add the render pass to the renderer. renderer.EnqueuePass(m_FullScreenPass); } protected override void Dispose(bool disposing) { - // We dispose the pass we created to free the resources it might be holding onto + // Free the resources the render pass uses. m_FullScreenPass.Dispose(); } #endregion + // Create the custom render pass. private class CustomPostRenderPass : ScriptableRenderPass { #region PASS_FIELDS - // The material used to render the post-processing effect + // Declare the material used to render the post-processing effect. private Material m_Material; - // The handle to the temporary color copy texture (only used in the non-render graph path) + // Declare a texture to use as a temporary color copy. This texture is used only in the Compatibility Mode path. private RTHandle m_CopiedColor; - // The property block used to set additional properties for the material + // Declare a property block to set additional properties for the material. private static MaterialPropertyBlock s_SharedPropertyBlock = new MaterialPropertyBlock(); - // This constant is meant to showcase how to create a copy color pass that is needed for most post-processing effects + // Declare a property that enables or disables the render pass that samples the color texture. private static readonly bool kSampleActiveColor = true; - // This constant is meant to showcase how you can add dept-stencil support to your main pass + // Declare a property that adds or removes depth-stencil support. private static readonly bool kBindDepthStencilAttachment = false; - // Creating some shader properties in advance as this is slightly more efficient than referencing them by string + // Create shader properties in advance, which is more efficient than referencing them by string. private static readonly int kBlitTexturePropertyId = Shader.PropertyToID("_BlitTexture"); private static readonly int kBlitScaleBiasPropertyId = Shader.PropertyToID("_BlitScaleBias"); @@ -136,55 +100,55 @@ public sealed class #FEATURE_TYPE# : ScriptableRendererFeature public CustomPostRenderPass(string passName, Material material) { + // Add a profiling sampler. profilingSampler = new ProfilingSampler(passName); + + // Assign the material to the render pass. m_Material = material; - // * The 'requiresIntermediateTexture' field needs to be set to 'true' when a ScriptableRenderPass intends to sample - // the active color buffer - // * This will make sure that URP will not apply the optimization of rendering the entire frame to the write-only backbuffer, - // but will instead render to intermediate textures that can be sampled, which is typically needed for post-processing + // To make sure the render pass can sample the active color buffer, set URP to render to intermediate textures instead of directly to the backbuffer. requiresIntermediateTexture = kSampleActiveColor; } #region PASS_SHARED_RENDERING_CODE - // This method contains the shared rendering logic for doing the temporary color copy pass (used by both the non-render graph and render graph paths) + // Add a command to create the temporary color copy texture. + // This method is used in both the render graph system path and the Compatibility Mode path. private static void ExecuteCopyColorPass(RasterCommandBuffer cmd, RTHandle sourceTexture) { Blitter.BlitTexture(cmd, sourceTexture, new Vector4(1, 1, 0, 0), 0.0f, false); } - // This method contains the shared rendering logic for doing the main post-processing pass (used by both the non-render graph and render graph paths) + // Add commands to render the effect. + // This method is used in both the render graph system path and the Compatibility Mode path. private static void ExecuteMainPass(RasterCommandBuffer cmd, RTHandle sourceTexture, Material material) { + // Clear the material properties. s_SharedPropertyBlock.Clear(); if(sourceTexture != null) s_SharedPropertyBlock.SetTexture(kBlitTexturePropertyId, sourceTexture); - // This uniform needs to be set for user materials with shaders relying on core Blit.hlsl to work as expected + // Set the scale and bias so shaders that use Blit.hlsl work correctly. s_SharedPropertyBlock.SetVector(kBlitScaleBiasPropertyId, new Vector4(1, 1, 0, 0)); - // USING A CUSTOM VOLUME COMPONENT: - // - // To control the rendering of your effect using a custom VolumeComponent you can set the material's properties - // based on the blended values of your VolumeComponent by querying them with the core VolumeManager API e.g.: + // Set the material properties based on the blended values of the custom volume. + // For more information, refer to https://docs.unity3d.com/Manual/urp/post-processing/custom-post-processing-with-volume.html #VOLUME_TYPE# myVolume = VolumeManager.instance.stack?.GetComponent<#VOLUME_TYPE#>(); if (myVolume != null) s_SharedPropertyBlock.SetFloat("_Intensity", myVolume.intensity.value); + // Draw to the current render target. cmd.DrawProcedural(Matrix4x4.identity, material, 0, MeshTopology.Triangles, 3, 1, s_SharedPropertyBlock); } - // This method is used to get the descriptor used for creating the temporary color copy texture that will enable the main pass to sample the screen color + // Get the texture descriptor needed to create the temporary color copy texture. + // This method is used in both the render graph system path and the Compatibility Mode path. private static RenderTextureDescriptor GetCopyPassTextureDescriptor(RenderTextureDescriptor desc) { - // Unless 'desc.bindMS = true' for an MSAA texture a resolve pass will be inserted before it is bound for sampling. - // Since our main pass shader does not expect to sample an MSAA target we will leave 'bindMS = false'. - // If the camera target has MSAA enabled an MSAA resolve will still happen before our copy-color pass but - // with this change we will avoid an unnecessary MSAA resolve before our main pass. + // Avoid an unnecessary multisample anti-aliasing (MSAA) resolve before the main render pass. desc.msaaSamples = 1; - // This avoids copying the depth buffer tied to the current descriptor as the main pass in this example does not use it + // Avoid copying the depth buffer, as the main pass render in this example doesn't use depth. desc.depthBufferBits = (int)DepthBits.None; return desc; @@ -194,35 +158,36 @@ public sealed class #FEATURE_TYPE# : ScriptableRendererFeature #region PASS_NON_RENDER_GRAPH_PATH - // This method is called before executing the render pass (non-render graph path only). - // It can be used to configure render targets and their clear state. Also to create temporary render target textures. - // When empty this render pass will render to the active camera render target. - // You should never call CommandBuffer.SetRenderTarget. Instead call ConfigureTarget and ConfigureClear. - // The render pipeline will ensure target setup and clearing happens in a performant manner. - [System.Obsolete("This rendering path is for compatibility mode only (when Render Graph is disabled). Use Render Graph API instead.", false)] + // Override the OnCameraSetup method to configure render targets and their clear states, and create temporary render target textures. + // Unity calls this method before executing the render pass. + // This method is used only in the Compatibility Mode path. + // Use ConfigureTarget or ConfigureClear in this method. Don't use CommandBuffer.SetRenderTarget. + [System.Obsolete("This rendering path works in Compatibility Mode only, which is deprecated. Use the render graph API instead.", false)] public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { - // This ScriptableRenderPass manages its own RenderTarget. - // ResetTarget here so that ScriptableRenderer's active attachment can be invalidated when processing this ScriptableRenderPass. + // Reset the render target to default. ResetTarget(); - // This allocates our intermediate texture for the non-RG path and makes sure it's reallocated if some settings on the camera target change (e.g. resolution) + // Allocate a temporary texture, and reallocate it if there's a change to camera settings, for example resolution. if (kSampleActiveColor) RenderingUtils.ReAllocateHandleIfNeeded(ref m_CopiedColor, GetCopyPassTextureDescriptor(renderingData.cameraData.cameraTargetDescriptor), name: "_CustomPostPassCopyColor"); } - // Here you can implement the rendering logic (non-render graph path only). - // Use ScriptableRenderContext to issue drawing commands or execute command buffers - // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html - // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline. - [System.Obsolete("This rendering path is for compatibility mode only (when Render Graph is disabled). Use Render Graph API instead.", false)] + // Override the Execute method to implement the rendering logic. Use ScriptableRenderContext to issue drawing commands or execute command buffers. + // You don't need to call ScriptableRenderContext.Submit. + // This method is used only in the Compatibility Mode path. + [System.Obsolete("This rendering path works in Compatibility Mode only, which is deprecated. Use the render graph API instead.", false)] public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { + + // Get the camera data and command buffer. ref var cameraData = ref renderingData.cameraData; var cmd = CommandBufferPool.Get(); + // Add a profiling sampler. using (new ProfilingScope(cmd, profilingSampler)) { + // Create a command buffer to execute the render pass. RasterCommandBuffer rasterCmd = CommandBufferHelpers.GetRasterCommandBuffer(cmd); if (kSampleActiveColor) { @@ -230,25 +195,32 @@ public sealed class #FEATURE_TYPE# : ScriptableRendererFeature ExecuteCopyColorPass(rasterCmd, cameraData.renderer.cameraColorTargetHandle); } + // Set the render target based on the depth-stencil attachment. if(kBindDepthStencilAttachment) CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle, cameraData.renderer.cameraDepthTargetHandle); else CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle); + // Execute the main render pass. ExecuteMainPass(rasterCmd, kSampleActiveColor ? m_CopiedColor : null, m_Material); } + // Execute the command buffer. context.ExecuteCommandBuffer(cmd); cmd.Clear(); + // Release the command buffer. CommandBufferPool.Release(cmd); } - // Cleanup any allocated resources that were created during the execution of this render pass (non-render graph path only) + // Free the resources the camera uses. + // This method is used only in the Compatibility Mode path. public override void OnCameraCleanup(CommandBuffer cmd) { } + // Free the resources the texture uses. + // This method is used only in the Compatibility Mode path. public void Dispose() { m_CopiedColor?.Release(); @@ -258,13 +230,15 @@ public sealed class #FEATURE_TYPE# : ScriptableRendererFeature #region PASS_RENDER_GRAPH_PATH - // The custom copy color pass data that will be passed at render graph execution to the lambda we set with "SetRenderFunc" during render graph setup + // Declare the resource the copy render pass uses. + // This method is used only in the render graph system path. private class CopyPassData { public TextureHandle inputTexture; } - // The custom main pass data that will be passed at render graph execution to the lambda we set with "SetRenderFunc" during render graph setup + // Declare the resources the main render pass uses. + // This method is used only in the render graph system path. private class MainPassData { public Material material; @@ -281,26 +255,23 @@ public sealed class #FEATURE_TYPE# : ScriptableRendererFeature ExecuteMainPass(context.cmd, data.inputTexture.IsValid() ? data.inputTexture : null, data.material); } - // Here you can implement the rendering logic for the render graph path - // The implementation diverges from the non-rendergraph path because we don't need a copy here when sampling the active color. However, this means that every pixel needs to be written in your material, a partial write (eg using stencil) will not be visually correct and requires a copy first. + // Override the RecordRenderGraph method to implement the rendering logic. + // This method is used only in the render graph system path. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { + + // Get the resources the pass uses. UniversalResourceData resourcesData = frameData.Get(); UniversalCameraData cameraData = frameData.Get(); - // Below is an example of a typical post-processing effect which samples from the current color - // Feel free modify/rename/add additional or remove the existing passes based on the needs of your custom post-processing effect - + // Sample from the current color texture. using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData, profilingSampler)) { passData.material = m_Material; TextureHandle destination; - // GPU graphics pipelines don't allow to sample the texture bound as the active color target, ie the cameraColor cannot both be an input and the render target. - // Before, this required us to first copy the cameraColor to then blit back to it while sampling from the copy. Now that we have the ContextContainer, we can swap the cameraColor to - // another (temp) resource so that the next pass uses the temp resource. We don't need the copy anymore. However, this only works if you are writing to every - // pixel of the frame, a partial write will need the copy first to add to the existing content. See FullScreenPassRendererFeature.cs for an example. + // Copy cameraColor to a temporary texture, if the kSampleActiveColor property is set to true. if (kSampleActiveColor) { var cameraColorDesc = renderGraph.GetTextureDesc(resourcesData.cameraColor); @@ -310,7 +281,7 @@ public sealed class #FEATURE_TYPE# : ScriptableRendererFeature destination = renderGraph.CreateTexture(cameraColorDesc); passData.inputTexture = resourcesData.cameraColor; - //If you use framebuffer fetch in your material then you need to use builder.SetInputAttachment. If the pass can be merged then this will reduce GPU bandwidth usage / power consumption and improve GPU performance. + // If you use framebuffer fetch in your material, use builder.SetInputAttachment to reduce GPU bandwidth usage and power consumption. builder.UseTexture(passData.inputTexture, AccessFlags.Read); } else @@ -319,15 +290,19 @@ public sealed class #FEATURE_TYPE# : ScriptableRendererFeature passData.inputTexture = TextureHandle.nullHandle; } + + // Set the render graph to render to the temporary texture. builder.SetRenderAttachment(destination, 0, AccessFlags.Write); - // This branch is currently not taken, but if your pass needed the depth and/or stencil buffer to be bound this is how you would do it + // Bind the depth-stencil buffer. + // This is a demonstration. The code isn't used in the example. if (kBindDepthStencilAttachment) builder.SetRenderAttachmentDepth(resourcesData.activeDepthTexture, AccessFlags.Write); + // Set the render method. builder.SetRenderFunc((MainPassData data, RasterGraphContext context) => ExecuteMainPass(data, context)); - //Swap cameraColor to the new temp resource (destination) for the next pass + // Set cameraColor to the new temporary texture so the next render pass can use it. You don't need to blit to and from cameraColor if you use the render graph system. if (kSampleActiveColor) { resourcesData.cameraColor = destination; diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Passes/Utility/LayerUtility.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Passes/Utility/LayerUtility.cs index 586b32a2d5e..edee92d883a 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Passes/Utility/LayerUtility.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Passes/Utility/LayerUtility.cs @@ -217,7 +217,7 @@ public static void GetFilterSettings(Renderer2DData rendererData, ref LayerBatch { filterSettings = FilteringSettings.defaultValue; filterSettings.renderQueueRange = RenderQueueRange.all; - filterSettings.layerMask = -1; + filterSettings.layerMask = rendererData.layerMask; filterSettings.renderingLayerMask = 0xFFFFFFFF; filterSettings.sortingLayerRange = layerBatch.layerRange; } diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Renderer2DData.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Renderer2DData.cs index e561721c773..d3bc0b7af17 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Renderer2DData.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Renderer2DData.cs @@ -25,6 +25,9 @@ internal enum Renderer2DDefaultMaterialType Custom } + [SerializeField] + LayerMask m_LayerMask = -1; + [SerializeField] TransparencySortMode m_TransparencySortMode = TransparencySortMode.Default; @@ -80,6 +83,7 @@ internal enum Renderer2DDefaultMaterialType internal bool useCameraSortingLayerTexture => m_UseCameraSortingLayersTexture; internal int cameraSortingLayerTextureBound => m_CameraSortingLayersTextureBound; internal Downsampling cameraSortingLayerDownsamplingMethod => m_CameraSortingLayerDownsamplingMethod; + internal LayerMask layerMask => m_LayerMask; /// /// Creates the instance of the Renderer2D. diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/DrawRenderer2DPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/DrawRenderer2DPass.cs index 1e4c00e4dc1..1cac87e6610 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/DrawRenderer2DPass.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Rendergraph/DrawRenderer2DPass.cs @@ -194,7 +194,8 @@ void SetGlobalLightTextures(RenderGraph graph, IRasterRenderGraphBuilder builder } else if (rendererData.lightCullResult.IsSceneLit()) { - builder.SetGlobalTextureAfterPass(graph.defaultResources.blackTexture, Shader.PropertyToID(RendererLighting.k_ShapeLightTextureIDs[0])); + for (var i = 0; i < RendererLighting.k_ShapeLightTextureIDs.Length; i++) + builder.SetGlobalTextureAfterPass(graph.defaultResources.blackTexture, Shader.PropertyToID(RendererLighting.k_ShapeLightTextureIDs[i])); } } } diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Shadows/ShadowCaster2D.cs b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Shadows/ShadowCaster2D.cs index 76a8855668b..6f106123cad 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/2D/Shadows/ShadowCaster2D.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/2D/Shadows/ShadowCaster2D.cs @@ -197,7 +197,7 @@ public ShadowCastingOptions castingOption /// /// If selfShadows is true, useRendererSilhoutte specifies that the renderer's sihouette should be considered part of the shadow. If selfShadows is false, useRendererSilhoutte specifies that the renderer's sihouette should be excluded from the shadow /// - [Obsolete("useRendererSilhoutte is deprecated. Use rendererSilhoutte instead")] + [Obsolete("useRendererSilhoutte is deprecated. Use selfShadows instead")] public bool useRendererSilhouette { set { m_UseRendererSilhouette = value; } diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/AdditionalLightsShadowCasterPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/AdditionalLightsShadowCasterPass.cs index 0f55988759a..f6d65fff5ed 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/AdditionalLightsShadowCasterPass.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/AdditionalLightsShadowCasterPass.cs @@ -438,14 +438,17 @@ public bool Setup(UniversalRenderingData renderingData, UniversalCameraData came short additionalLightCount = 0; short validShadowCastingLightsCount = 0; bool supportsSoftShadows = shadowData.supportsSoftShadows; - bool isDeferred = ((UniversalRenderer)cameraData.renderer).renderingModeActual == RenderingMode.Deferred; + UniversalRenderer universalRenderer = (UniversalRenderer)cameraData.renderer; + bool isDeferred = universalRenderer.renderingModeActual == RenderingMode.Deferred; + bool shadowTransparentReceive = universalRenderer.shadowTransparentReceive; + bool hasForwardShadowPass = !isDeferred || shadowTransparentReceive; for (int visibleLightIndex = 0; visibleLightIndex < visibleLights.Length; ++visibleLightIndex) { // Skip main directional light as it is not packed into the shadow atlas if (visibleLightIndex == lightData.mainLightIndex) continue; - short lightIndexToUse = isDeferred ? validShadowCastingLightsCount : additionalLightCount++; + short lightIndexToUse = !hasForwardShadowPass ? validShadowCastingLightsCount : additionalLightCount++; // We need to always set these indices, even if the light is not shadow casting or doesn't fit in the shadow slices (UUM-46577) m_VisibleLightIndexToAdditionalLightIndex[visibleLightIndex] = lightIndexToUse; 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 48282b7dbf9..f1c102e401c 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPassRenderGraph.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/PostProcessPassRenderGraph.cs @@ -1554,7 +1554,7 @@ public void RenderFinalBlit(RenderGraph renderGraph, UniversalCameraData cameraD passData.material = m_Materials.finalPass; passData.settings = settings; - if (settings.requireHDROutput && m_EnableColorEncodingIfNeeded) + if (settings.requireHDROutput && m_EnableColorEncodingIfNeeded && cameraData.rendersOverlayUI) builder.UseTexture(overlayUITexture, AccessFlags.Read); #if ENABLE_VR && ENABLE_XR_MODULE diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/ScriptableRenderPass.cs b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/ScriptableRenderPass.cs index 9888dcb275f..f6a7383a06d 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/Passes/ScriptableRenderPass.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/Passes/ScriptableRenderPass.cs @@ -11,6 +11,10 @@ namespace UnityEngine.Rendering.Universal { /// /// Input requirements for ScriptableRenderPass. + /// + /// URP adds render passes to generate the inputs, or reuses inputs that are already available from earlier in the frame. + /// + /// URP binds the inputs as global shader texture properties. /// /// [Flags] @@ -23,21 +27,31 @@ public enum ScriptableRenderPassInput /// /// Used when a ScriptableRenderPass requires a depth texture. + /// + /// To sample the depth texture in a shader, include `Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl`, then use the `SampleSceneDepth` method. /// Depth = 1 << 0, /// /// Used when a ScriptableRenderPass requires a normal texture. + /// + /// To sample the normals texture in a shader, include `Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl`, then use the `SampleSceneNormals` method. /// Normal = 1 << 1, /// /// Used when a ScriptableRenderPass requires a color texture. + /// + /// To sample the color texture in a shader, include `Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl`, then use the `SampleSceneColor` method. + /// + /// **Note:** The opaque texture might be a downscaled copy of the framebuffer from before rendering transparent objects. /// Color = 1 << 2, /// /// Used when a ScriptableRenderPass requires a motion vectors texture. + /// + /// To sample the motion vectors texture in a shader, use `TEXTURE2D_X(_MotionVectorTexture)`, then `LOAD_TEXTURE2D_X_LOD(_MotionVectorTexture, pixelCoords, 0).xy`. /// Motion = 1 << 3, } diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature.cs b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature.cs index 8704ee80de3..f54a6a7032d 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature.cs @@ -1,316 +1,316 @@ using System; -using UnityEngine; using UnityEngine.Rendering.RenderGraphModule; -using UnityEngine.Rendering; -using UnityEngine.Rendering.Universal; using UnityEngine.Experimental.Rendering; -/// -/// This renderer feature lets you create single-pass full screen post processing effects without needing to write code. -/// -[URPHelpURL("renderer-features/renderer-feature-full-screen-pass")] -public partial class FullScreenPassRendererFeature : ScriptableRendererFeature +namespace UnityEngine.Rendering.Universal { /// - /// An injection point for the full screen pass. This is similar to the RenderPassEvent enum but limited to only supported events. + /// This renderer feature lets you create single-pass full screen post processing effects without needing to write code. /// - public enum InjectionPoint + [URPHelpURL("renderer-features/renderer-feature-full-screen-pass")] + public partial class FullScreenPassRendererFeature : ScriptableRendererFeature { /// - /// Inject a full screen pass before transparents are rendered. + /// An injection point for the full screen pass. This is similar to the RenderPassEvent enum but limited to only supported events. /// - BeforeRenderingTransparents = RenderPassEvent.BeforeRenderingTransparents, + public enum InjectionPoint + { + /// + /// Inject a full screen pass before transparents are rendered. + /// + BeforeRenderingTransparents = RenderPassEvent.BeforeRenderingTransparents, + + /// + /// Inject a full screen pass before post processing is rendered. + /// + BeforeRenderingPostProcessing = RenderPassEvent.BeforeRenderingPostProcessing, + + /// + /// Inject a full screen pass after post processing is rendered. + /// + AfterRenderingPostProcessing = RenderPassEvent.AfterRenderingPostProcessing + } /// - /// Inject a full screen pass before post processing is rendered. + /// Specifies at which injection point the pass will be rendered. /// - BeforeRenderingPostProcessing = RenderPassEvent.BeforeRenderingPostProcessing, + public InjectionPoint injectionPoint = InjectionPoint.AfterRenderingPostProcessing; /// - /// Inject a full screen pass after post processing is rendered. + /// Specifies whether the assigned material will need to use the current screen contents as an input texture. + /// Disable this to optimize away an extra color copy pass when you know that the assigned material will only need + /// to write on top of or hardware blend with the contents of the active color target. /// - AfterRenderingPostProcessing = RenderPassEvent.AfterRenderingPostProcessing - } - - /// - /// Specifies at which injection point the pass will be rendered. - /// - public InjectionPoint injectionPoint = InjectionPoint.AfterRenderingPostProcessing; - - /// - /// Specifies whether the assigned material will need to use the current screen contents as an input texture. - /// Disable this to optimize away an extra color copy pass when you know that the assigned material will only need - /// to write on top of or hardware blend with the contents of the active color target. - /// - public bool fetchColorBuffer = true; - - /// - /// A mask of URP textures that the assigned material will need access to. Requesting unused requirements can degrade - /// performance unnecessarily as URP might need to run additional rendering passes to generate them. - /// - public ScriptableRenderPassInput requirements = ScriptableRenderPassInput.None; + public bool fetchColorBuffer = true; - /// - /// The material used to render the full screen pass (typically based on the Fullscreen Shader Graph target). - /// - public Material passMaterial; - - /// - /// The shader pass index that should be used when rendering the assigned material. - /// - public int passIndex = 0; - - /// - /// Specifies if the active camera's depth-stencil buffer should be bound when rendering the full screen pass. - /// Disabling this will ensure that the material's depth and stencil commands will have no effect (this could also have a slight performance benefit). - /// - public bool bindDepthStencilAttachment = false; + /// + /// A mask of URP textures that the assigned material will need access to. Requesting unused requirements can degrade + /// performance unnecessarily as URP might need to run additional rendering passes to generate them. + /// + public ScriptableRenderPassInput requirements = ScriptableRenderPassInput.None; - private FullScreenRenderPass m_FullScreenPass; + /// + /// The material used to render the full screen pass (typically based on the Fullscreen Shader Graph target). + /// + public Material passMaterial; - /// - public override void Create() - { - m_FullScreenPass = new FullScreenRenderPass(name); - } + /// + /// The shader pass index that should be used when rendering the assigned material. + /// + public int passIndex = 0; - internal override bool RequireRenderingLayers(bool isDeferred, bool needsGBufferAccurateNormals, out RenderingLayerUtils.Event atEvent, out RenderingLayerUtils.MaskSize maskSize) - { - atEvent = RenderingLayerUtils.Event.Opaque; - maskSize = RenderingLayerUtils.MaskSize.Bits8; - return false; - } + /// + /// Specifies if the active camera's depth-stencil buffer should be bound when rendering the full screen pass. + /// Disabling this will ensure that the material's depth and stencil commands will have no effect (this could also have a slight performance benefit). + /// + public bool bindDepthStencilAttachment = false; - /// - public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) - { - if (renderingData.cameraData.cameraType == CameraType.Preview - || renderingData.cameraData.cameraType == CameraType.Reflection - || UniversalRenderer.IsOffscreenDepthTexture(ref renderingData.cameraData)) - return; + private FullScreenRenderPass m_FullScreenPass; - if (passMaterial == null) + /// + public override void Create() { - Debug.LogWarningFormat("The full screen feature \"{0}\" will not execute - no material is assigned. Please make sure a material is assigned for this feature on the renderer asset.", name); - return; + m_FullScreenPass = new FullScreenRenderPass(name); } - if (passIndex < 0 || passIndex >= passMaterial.passCount) + internal override bool RequireRenderingLayers(bool isDeferred, bool needsGBufferAccurateNormals, out RenderingLayerUtils.Event atEvent, out RenderingLayerUtils.MaskSize maskSize) { - Debug.LogWarningFormat("The full screen feature \"{0}\" will not execute - the pass index is out of bounds for the material.", name); - return; + atEvent = RenderingLayerUtils.Event.Opaque; + maskSize = RenderingLayerUtils.MaskSize.Bits8; + return false; } - m_FullScreenPass.renderPassEvent = (RenderPassEvent)injectionPoint; - m_FullScreenPass.ConfigureInput(requirements); - m_FullScreenPass.SetupMembers(passMaterial, passIndex, fetchColorBuffer, bindDepthStencilAttachment); - - m_FullScreenPass.requiresIntermediateTexture = fetchColorBuffer; - - renderer.EnqueuePass(m_FullScreenPass); - } - - /// - protected override void Dispose(bool disposing) - { - m_FullScreenPass.Dispose(); - } - - internal class FullScreenRenderPass : ScriptableRenderPass - { - private Material m_Material; - private int m_PassIndex; - private bool m_FetchActiveColor; - private bool m_BindDepthStencilAttachment; - private RTHandle m_CopiedColor; - - private static MaterialPropertyBlock s_SharedPropertyBlock = new MaterialPropertyBlock(); - - public FullScreenRenderPass(string passName) + /// + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { - profilingSampler = new ProfilingSampler(passName); - } + if (renderingData.cameraData.cameraType == CameraType.Preview + || renderingData.cameraData.cameraType == CameraType.Reflection + || UniversalRenderer.IsOffscreenDepthTexture(ref renderingData.cameraData)) + return; - public void SetupMembers(Material material, int passIndex, bool fetchActiveColor, bool bindDepthStencilAttachment) - { - m_Material = material; - m_PassIndex = passIndex; - m_FetchActiveColor = fetchActiveColor; - m_BindDepthStencilAttachment = bindDepthStencilAttachment; - } + if (passMaterial == null) + { + Debug.LogWarningFormat("The full screen feature \"{0}\" will not execute - no material is assigned. Please make sure a material is assigned for this feature on the renderer asset.", name); + return; + } - [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)] - public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) - { - // Disable obsolete warning for internal usage - #pragma warning disable CS0618 - // FullScreenPass manages its own RenderTarget. - // ResetTarget here so that ScriptableRenderer's active attachement can be invalidated when processing this ScriptableRenderPass. - ResetTarget(); - #pragma warning restore CS0618 - - if (m_FetchActiveColor) - ReAllocate(renderingData.cameraData.cameraTargetDescriptor); - } + if (passIndex < 0 || passIndex >= passMaterial.passCount) + { + Debug.LogWarningFormat("The full screen feature \"{0}\" will not execute - the pass index is out of bounds for the material.", name); + return; + } - internal void ReAllocate(RenderTextureDescriptor desc) - { - desc.msaaSamples = 1; - desc.depthStencilFormat = GraphicsFormat.None; - RenderingUtils.ReAllocateHandleIfNeeded(ref m_CopiedColor, desc, name: "_FullscreenPassColorCopy"); - } + m_FullScreenPass.renderPassEvent = (RenderPassEvent)injectionPoint; + m_FullScreenPass.ConfigureInput(requirements); + m_FullScreenPass.SetupMembers(passMaterial, passIndex, fetchColorBuffer, bindDepthStencilAttachment); - public void Dispose() - { - m_CopiedColor?.Release(); + m_FullScreenPass.requiresIntermediateTexture = fetchColorBuffer; + + renderer.EnqueuePass(m_FullScreenPass); } - private static void ExecuteCopyColorPass(RasterCommandBuffer cmd, RTHandle sourceTexture) + /// + protected override void Dispose(bool disposing) { - Blitter.BlitTexture(cmd, sourceTexture, new Vector4(1, 1, 0, 0), 0.0f, false); + m_FullScreenPass.Dispose(); } - private static void ExecuteMainPass(RasterCommandBuffer cmd, RTHandle sourceTexture, Material material, int passIndex) + internal class FullScreenRenderPass : ScriptableRenderPass { - s_SharedPropertyBlock.Clear(); - if (sourceTexture != null) - s_SharedPropertyBlock.SetTexture(ShaderPropertyId.blitTexture, sourceTexture); + private Material m_Material; + private int m_PassIndex; + private bool m_FetchActiveColor; + private bool m_BindDepthStencilAttachment; + private RTHandle m_CopiedColor; - // We need to set the "_BlitScaleBias" uniform for user materials with shaders relying on core Blit.hlsl to work - s_SharedPropertyBlock.SetVector(ShaderPropertyId.blitScaleBias, new Vector4(1, 1, 0, 0)); + private static MaterialPropertyBlock s_SharedPropertyBlock = new MaterialPropertyBlock(); - cmd.DrawProcedural(Matrix4x4.identity, material, passIndex, MeshTopology.Triangles, 3, 1, s_SharedPropertyBlock); - } + public FullScreenRenderPass(string passName) + { + profilingSampler = new ProfilingSampler(passName); + } - [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)] - public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) - { - ref var cameraData = ref renderingData.cameraData; - var cmd = renderingData.commandBuffer; + public void SetupMembers(Material material, int passIndex, bool fetchActiveColor, bool bindDepthStencilAttachment) + { + m_Material = material; + m_PassIndex = passIndex; + m_FetchActiveColor = fetchActiveColor; + m_BindDepthStencilAttachment = bindDepthStencilAttachment; + } - using (new ProfilingScope(cmd, profilingSampler)) + [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)] + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { - RasterCommandBuffer rasterCmd = CommandBufferHelpers.GetRasterCommandBuffer(cmd); + // Disable obsolete warning for internal usage + #pragma warning disable CS0618 + // FullScreenPass manages its own RenderTarget. + // ResetTarget here so that ScriptableRenderer's active attachement can be invalidated when processing this ScriptableRenderPass. + ResetTarget(); + #pragma warning restore CS0618 + if (m_FetchActiveColor) - { - CoreUtils.SetRenderTarget(cmd, m_CopiedColor); - ExecuteCopyColorPass(rasterCmd, cameraData.renderer.cameraColorTargetHandle); - } + ReAllocate(renderingData.cameraData.cameraTargetDescriptor); + } - if (m_BindDepthStencilAttachment) - CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle, cameraData.renderer.cameraDepthTargetHandle); - else - CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle); + internal void ReAllocate(RenderTextureDescriptor desc) + { + desc.msaaSamples = 1; + desc.depthStencilFormat = GraphicsFormat.None; + RenderingUtils.ReAllocateHandleIfNeeded(ref m_CopiedColor, desc, name: "_FullscreenPassColorCopy"); + } - ExecuteMainPass(rasterCmd, m_FetchActiveColor ? m_CopiedColor : null, m_Material, m_PassIndex); + public void Dispose() + { + m_CopiedColor?.Release(); } - } - public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) - { - UniversalResourceData resourcesData = frameData.Get(); - UniversalCameraData cameraData = frameData.Get(); + private static void ExecuteCopyColorPass(RasterCommandBuffer cmd, RTHandle sourceTexture) + { + Blitter.BlitTexture(cmd, sourceTexture, new Vector4(1, 1, 0, 0), 0.0f, false); + } + + private static void ExecuteMainPass(RasterCommandBuffer cmd, RTHandle sourceTexture, Material material, int passIndex) + { + s_SharedPropertyBlock.Clear(); + if (sourceTexture != null) + s_SharedPropertyBlock.SetTexture(ShaderPropertyId.blitTexture, sourceTexture); - TextureHandle source, destination; + // We need to set the "_BlitScaleBias" uniform for user materials with shaders relying on core Blit.hlsl to work + s_SharedPropertyBlock.SetVector(ShaderPropertyId.blitScaleBias, new Vector4(1, 1, 0, 0)); - Debug.Assert(resourcesData.cameraColor.IsValid()); + cmd.DrawProcedural(Matrix4x4.identity, material, passIndex, MeshTopology.Triangles, 3, 1, s_SharedPropertyBlock); + } - if (m_FetchActiveColor) + [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)] + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { - var targetDesc = renderGraph.GetTextureDesc(resourcesData.cameraColor); - targetDesc.name = "_CameraColorFullScreenPass"; - targetDesc.clearBuffer = false; + ref var cameraData = ref renderingData.cameraData; + var cmd = renderingData.commandBuffer; - source = resourcesData.activeColorTexture; - destination = renderGraph.CreateTexture(targetDesc); - - using (var builder = renderGraph.AddRasterRenderPass("Copy Color Full Screen", out var passData, profilingSampler)) + using (new ProfilingScope(cmd, profilingSampler)) { - passData.inputTexture = source; - builder.UseTexture(passData.inputTexture, AccessFlags.Read); + RasterCommandBuffer rasterCmd = CommandBufferHelpers.GetRasterCommandBuffer(cmd); + if (m_FetchActiveColor) + { + CoreUtils.SetRenderTarget(cmd, m_CopiedColor); + ExecuteCopyColorPass(rasterCmd, cameraData.renderer.cameraColorTargetHandle); + } - builder.SetRenderAttachment(destination, 0, AccessFlags.Write); + if (m_BindDepthStencilAttachment) + CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle, cameraData.renderer.cameraDepthTargetHandle); + else + CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle); - builder.SetRenderFunc((CopyPassData data, RasterGraphContext rgContext) => - { - ExecuteCopyColorPass(rgContext.cmd, data.inputTexture); - }); + ExecuteMainPass(rasterCmd, m_FetchActiveColor ? m_CopiedColor : null, m_Material, m_PassIndex); } - - //Swap for next pass; - source = destination; } - else + + public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { - source = TextureHandle.nullHandle; - } + UniversalResourceData resourcesData = frameData.Get(); + UniversalCameraData cameraData = frameData.Get(); - destination = resourcesData.activeColorTexture; + TextureHandle source, destination; + Debug.Assert(resourcesData.cameraColor.IsValid()); - using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData, profilingSampler)) - { - passData.material = m_Material; - passData.passIndex = m_PassIndex; + if (m_FetchActiveColor) + { + var targetDesc = renderGraph.GetTextureDesc(resourcesData.cameraColor); + targetDesc.name = "_CameraColorFullScreenPass"; + targetDesc.clearBuffer = false; - passData.inputTexture = source; + source = resourcesData.activeColorTexture; + destination = renderGraph.CreateTexture(targetDesc); + + using (var builder = renderGraph.AddRasterRenderPass("Copy Color Full Screen", out var passData, profilingSampler)) + { + passData.inputTexture = source; + builder.UseTexture(passData.inputTexture, AccessFlags.Read); - if(passData.inputTexture.IsValid()) - builder.UseTexture(passData.inputTexture, AccessFlags.Read); + builder.SetRenderAttachment(destination, 0, AccessFlags.Write); - bool needsColor = (input & ScriptableRenderPassInput.Color) != ScriptableRenderPassInput.None; - bool needsDepth = (input & ScriptableRenderPassInput.Depth) != ScriptableRenderPassInput.None; - bool needsMotion = (input & ScriptableRenderPassInput.Motion) != ScriptableRenderPassInput.None; - bool needsNormal = (input & ScriptableRenderPassInput.Normal) != ScriptableRenderPassInput.None; + builder.SetRenderFunc((CopyPassData data, RasterGraphContext rgContext) => + { + ExecuteCopyColorPass(rgContext.cmd, data.inputTexture); + }); + } - if (needsColor) - { - Debug.Assert(resourcesData.cameraOpaqueTexture.IsValid()); - builder.UseTexture(resourcesData.cameraOpaqueTexture); + //Swap for next pass; + source = destination; } - - if (needsDepth) + else { - Debug.Assert(resourcesData.cameraDepthTexture.IsValid()); - builder.UseTexture(resourcesData.cameraDepthTexture); + source = TextureHandle.nullHandle; } - if (needsMotion) - { - Debug.Assert(resourcesData.motionVectorColor.IsValid()); - builder.UseTexture(resourcesData.motionVectorColor); - Debug.Assert(resourcesData.motionVectorDepth.IsValid()); - builder.UseTexture(resourcesData.motionVectorDepth); - } + destination = resourcesData.activeColorTexture; - if (needsNormal) + + using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData, profilingSampler)) { - Debug.Assert(resourcesData.cameraNormalsTexture.IsValid()); - builder.UseTexture(resourcesData.cameraNormalsTexture); - } + passData.material = m_Material; + passData.passIndex = m_PassIndex; + + passData.inputTexture = source; + + if(passData.inputTexture.IsValid()) + builder.UseTexture(passData.inputTexture, AccessFlags.Read); + + bool needsColor = (input & ScriptableRenderPassInput.Color) != ScriptableRenderPassInput.None; + bool needsDepth = (input & ScriptableRenderPassInput.Depth) != ScriptableRenderPassInput.None; + bool needsMotion = (input & ScriptableRenderPassInput.Motion) != ScriptableRenderPassInput.None; + bool needsNormal = (input & ScriptableRenderPassInput.Normal) != ScriptableRenderPassInput.None; + + if (needsColor) + { + Debug.Assert(resourcesData.cameraOpaqueTexture.IsValid()); + builder.UseTexture(resourcesData.cameraOpaqueTexture); + } + + if (needsDepth) + { + Debug.Assert(resourcesData.cameraDepthTexture.IsValid()); + builder.UseTexture(resourcesData.cameraDepthTexture); + } + + if (needsMotion) + { + Debug.Assert(resourcesData.motionVectorColor.IsValid()); + builder.UseTexture(resourcesData.motionVectorColor); + Debug.Assert(resourcesData.motionVectorDepth.IsValid()); + builder.UseTexture(resourcesData.motionVectorDepth); + } + + if (needsNormal) + { + Debug.Assert(resourcesData.cameraNormalsTexture.IsValid()); + builder.UseTexture(resourcesData.cameraNormalsTexture); + } - builder.SetRenderAttachment(destination, 0, AccessFlags.Write); + builder.SetRenderAttachment(destination, 0, AccessFlags.Write); - if (m_BindDepthStencilAttachment) - builder.SetRenderAttachmentDepth(resourcesData.activeDepthTexture, AccessFlags.Write); + if (m_BindDepthStencilAttachment) + builder.SetRenderAttachmentDepth(resourcesData.activeDepthTexture, AccessFlags.Write); - builder.SetRenderFunc((MainPassData data, RasterGraphContext rgContext) => - { - ExecuteMainPass(rgContext.cmd, data.inputTexture, data.material, data.passIndex); - }); + builder.SetRenderFunc((MainPassData data, RasterGraphContext rgContext) => + { + ExecuteMainPass(rgContext.cmd, data.inputTexture, data.material, data.passIndex); + }); + } } - } - private class CopyPassData - { - internal TextureHandle inputTexture; - } + private class CopyPassData + { + internal TextureHandle inputTexture; + } - private class MainPassData - { - internal Material material; - internal int passIndex; - internal TextureHandle inputTexture; + private class MainPassData + { + internal Material material; + internal int passIndex; + internal TextureHandle inputTexture; + } } } } diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature.migration.cs b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature.migration.cs index 28431a3126c..c0fa826ffbc 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature.migration.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature.migration.cs @@ -1,79 +1,82 @@ -using UnityEngine; using UnityEditor; -using UnityEngine.Rendering.Universal; +using UnityEngine.Scripting.APIUpdating; -public partial class FullScreenPassRendererFeature : ISerializationCallbackReceiver +namespace UnityEngine.Rendering.Universal { - private enum Version + [MovedFrom("")] + public partial class FullScreenPassRendererFeature : ISerializationCallbackReceiver { - // * Uninitialised is a special last entry that will only ever be set on newly created objects or objects - // which were previously serialised with no Version member at all. - // * We distinguish between new objects and the unversioned objects based on if we first see this value during - // serialization or during deserialization respectively. - Uninitialised = -1, - - Initial, - AddFetchColorBufferCheckbox, + private enum Version + { + // * Uninitialised is a special last entry that will only ever be set on newly created objects or objects + // which were previously serialised with no Version member at all. + // * We distinguish between new objects and the unversioned objects based on if we first see this value during + // serialization or during deserialization respectively. + Uninitialised = -1, - // These two entries should remain at the end of the enum and new version should be added before Count - Count, - Latest = Count - 1, - } + Initial, + AddFetchColorBufferCheckbox, - [SerializeField] - [HideInInspector] - private Version m_Version = Version.Uninitialised; + // These two entries should remain at the end of the enum and new version should be added before Count + Count, + Latest = Count - 1, + } - private void UpgradeIfNeeded() - { - // As we rely on serialization/deserialization order to initialize the version as player might have restricions - // on when and if serialization is done skipping any upgrading at runtime to avoid accidentally doing the - // upgrade on the latest version. Upgrading at runtime does not really have much utility as it would mean - // that the asset would need to have been produced in an editor which is an earlier build version than the player -#if UNITY_EDITOR - if (m_Version == Version.Latest) - return; + [SerializeField] + [HideInInspector] + private Version m_Version = Version.Uninitialised; - if(m_Version == Version.Initial) + private void UpgradeIfNeeded() { - // * Previously the ScriptableRenderPassInput.Color requirement was repurposed to mean "copy the active - // color target" even though it is typically used to request '_CameraOpaqueTexture' and the copy color pass. - // * From now on, the "Fetch Color Buffer" choice will be a separate checkbox to remove the inconsistent - // meaning and to allow using the '_CameraOpaqueTexture' if one wants to as well. - fetchColorBuffer = requirements.HasFlag(ScriptableRenderPassInput.Color); + // As we rely on serialization/deserialization order to initialize the version as player might have restricions + // on when and if serialization is done skipping any upgrading at runtime to avoid accidentally doing the + // upgrade on the latest version. Upgrading at runtime does not really have much utility as it would mean + // that the asset would need to have been produced in an editor which is an earlier build version than the player + #if UNITY_EDITOR + if (m_Version == Version.Latest) + return; + + if(m_Version == Version.Initial) + { + // * Previously the ScriptableRenderPassInput.Color requirement was repurposed to mean "copy the active + // color target" even though it is typically used to request '_CameraOpaqueTexture' and the copy color pass. + // * From now on, the "Fetch Color Buffer" choice will be a separate checkbox to remove the inconsistent + // meaning and to allow using the '_CameraOpaqueTexture' if one wants to as well. + fetchColorBuffer = requirements.HasFlag(ScriptableRenderPassInput.Color); - // As the Color flag was being masked out during actual rendering we can safely disable it. - requirements &= ~ScriptableRenderPassInput.Color; + // As the Color flag was being masked out during actual rendering we can safely disable it. + requirements &= ~ScriptableRenderPassInput.Color; - m_Version++; + m_Version++; + } + // Put the next upgrader in an "if" here (not "else if" as they migh all need to run) + + // Making sure SetDirty is called once after deserialization + EditorApplication.delayCall += () => + { + if (this) + EditorUtility.SetDirty(this); + }; + #endif } - // Put the next upgrader in an "if" here (not "else if" as they migh all need to run) - // Making sure SetDirty is called once after deserialization - EditorApplication.delayCall += () => + /// + void ISerializationCallbackReceiver.OnBeforeSerialize() { - if (this) - EditorUtility.SetDirty(this); - }; -#endif - } - - /// - void ISerializationCallbackReceiver.OnBeforeSerialize() - { - // This should only ever be true the first time we're serializing a newly created object - if (m_Version == Version.Uninitialised) - m_Version = Version.Latest; - } + // This should only ever be true the first time we're serializing a newly created object + if (m_Version == Version.Uninitialised) + m_Version = Version.Latest; + } - /// - void ISerializationCallbackReceiver.OnAfterDeserialize() - { - // The 'Uninitialised' version is expected to only occur during deserialization for objects that were previously - // serialized before we added the m_Version field - if (m_Version == Version.Uninitialised) - m_Version = Version.Initial; + /// + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + // The 'Uninitialised' version is expected to only occur during deserialization for objects that were previously + // serialized before we added the m_Version field + if (m_Version == Version.Uninitialised) + m_Version = Version.Initial; - UpgradeIfNeeded(); + UpgradeIfNeeded(); + } } } diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature_OldGUID.cs b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature_OldGUID.cs new file mode 100644 index 00000000000..52759072bba --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature_OldGUID.cs @@ -0,0 +1,44 @@ +// UUM-92491: This solve an issue where in 2022.3 FullScreenPassRendererFeature got introduced with another +// guid than in the 6000.0 version. To update the GUID, we are bound to this strange inheritance and migration. +// See also FullScreenPassRendererFeature_OldGUIDEditor, for the in editor downcasting. + +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; + + +[System.Obsolete("Kept for migration purpose only. Do not use (see script for more info) #from(6000.0) (UnityUpgradable) -> FullScreenPassRendererFeature", true)] +class FullScreenPassRendererFeature_OldGUID : UnityEngine.Rendering.Universal.FullScreenPassRendererFeature, ISerializationCallbackReceiver +{ + void ISerializationCallbackReceiver.OnAfterDeserialize() + { +#if UNITY_EDITOR + // InternalCreate cannot be called in serialization callback... Delaying + EditorApplication.delayCall += DownCast; +#endif + } + +#if UNITY_EDITOR + void DownCast() + { + if (this == null || this.Equals(null)) return; + + const string newGUID = "b00045f12942b46c698459096c89274e"; + const string oldGUID = "6d613f08f173d4dd895bb07b3230baa9"; + + // Check current GUID to be extra sure it is the old one to update + var serializedObject = new SerializedObject(this); + var scriptProperty = serializedObject.FindProperty("m_Script"); + MonoScript currentScript = scriptProperty.objectReferenceValue as MonoScript; + AssetDatabase.TryGetGUIDAndLocalFileIdentifier(currentScript.GetInstanceID(), out var currentGUID, out var _); + if (currentGUID != oldGUID) + return; + + // Mutate to base FullScreenPassRendererFeature script + var newScript = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(newGUID)); + scriptProperty.objectReferenceValue = newScript; + serializedObject.ApplyModifiedProperties(); + } +#endif +} diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature_OldGUID.cs.meta b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature_OldGUID.cs.meta new file mode 100644 index 00000000000..8028956fc52 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal/Runtime/RendererFeatures/FullScreenPassRendererFeature_OldGUID.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6d613f08f173d4dd895bb07b3230baa9 \ No newline at end of file diff --git a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs index b90c808824a..826c21d4c86 100644 --- a/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs +++ b/Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs @@ -174,6 +174,7 @@ protected internal override bool SupportsMotionVectors() internal DeferredLights deferredLights { get => m_DeferredLights; } internal LayerMask opaqueLayerMask { get; set; } internal LayerMask transparentLayerMask { get; set; } + internal bool shadowTransparentReceive { get; set; } internal GraphicsFormat cameraDepthTextureFormat { get => (m_CameraDepthTextureFormat != DepthFormat.Default) ? (GraphicsFormat)m_CameraDepthTextureFormat : k_DepthStencilFormatDefault; } internal GraphicsFormat cameraDepthAttachmentFormat { get => (m_CameraDepthAttachmentFormat != DepthFormat.Default) ? (GraphicsFormat)m_CameraDepthAttachmentFormat : k_DepthStencilFormatDefault; } @@ -222,6 +223,7 @@ public UniversalRenderer(UniversalRendererData data) : base(data) m_IntermediateTextureMode = data.intermediateTextureMode; opaqueLayerMask = data.opaqueLayerMask; transparentLayerMask = data.transparentLayerMask; + shadowTransparentReceive = data.shadowTransparentReceive; if (UniversalRenderPipeline.asset?.supportsLightCookies ?? false) { diff --git a/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/ScalingSetup.shader b/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/ScalingSetup.shader index 338f8624602..5d215ecf42d 100644 --- a/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/ScalingSetup.shader +++ b/Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/ScalingSetup.shader @@ -45,7 +45,7 @@ Shader "Hidden/Universal Render Pipeline/Scaling Setup" // In HDR output mode, the colors are expressed in nits, which can go up to 10k nits. // We divide by the display max nits to get a max value closer to 1.0 but it could still be > 1.0. // Finally, use FastTonemap() to squash everything < 1.0. - color = FastTonemap(color * OneOverPaperWhite); + color = half4(FastTonemap(color.rgb * OneOverPaperWhite), color.a); #endif // EASU expects perceptually encoded color data so either encode to gamma 2.0 here if the input // data is linear, or let it pass through unchanged if it's already gamma encoded. diff --git a/Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainDetailLitPasses.hlsl b/Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainDetailLitPasses.hlsl index 4a7ce2f0d57..659709ca500 100644 --- a/Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainDetailLitPasses.hlsl +++ b/Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainDetailLitPasses.hlsl @@ -159,7 +159,8 @@ Varyings TerrainLitVertex(Attributes input) diffuseColor += LightingLambert(attenuatedLightColor, mainLight.direction, NormalWS); } - #if defined(_ADDITIONAL_LIGHTS) || defined(_ADDITIONAL_LIGHTS_VERTEX) + // Adding !defined(USE_CLUSTER_LIGHT_LOOP): in Forward+ we can't possibly get the light list in a vertex shader. + #if (defined(_ADDITIONAL_LIGHTS) || defined(_ADDITIONAL_LIGHTS_VERTEX)) && !USE_FORWARD_PLUS if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_ADDITIONAL_LIGHTS)) { int pixelLightCount = GetAdditionalLightsCount(); diff --git a/Packages/com.unity.shadergraph/Editor/Generation/ShaderGraphVfxAsset.cs b/Packages/com.unity.shadergraph/Editor/Generation/ShaderGraphVfxAsset.cs index 4b37554f1b1..d283c23fec8 100644 --- a/Packages/com.unity.shadergraph/Editor/Generation/ShaderGraphVfxAsset.cs +++ b/Packages/com.unity.shadergraph/Editor/Generation/ShaderGraphVfxAsset.cs @@ -133,6 +133,11 @@ public string outputStructName internal set { m_OutputStructName = value; } } + internal void SetGUID(string guid) + { + m_Data.OverrideObjectId(guid, "SerializedVfxAssetData"); + } + public List properties { get diff --git a/Packages/com.unity.shadergraph/Editor/Importers/ShaderGraphImporter.cs b/Packages/com.unity.shadergraph/Editor/Importers/ShaderGraphImporter.cs index a27eb52a309..902978d272e 100644 --- a/Packages/com.unity.shadergraph/Editor/Importers/ShaderGraphImporter.cs +++ b/Packages/com.unity.shadergraph/Editor/Importers/ShaderGraphImporter.cs @@ -986,6 +986,7 @@ void AddCoordinateSpaceSnippets(InterpolatorType interpolatorType, Func Sampling > Sample Buffer** +**Menu Path : Operator > Sampling > Sample Graphics Buffer** -The Sample Buffer Operator enables you to fetch and sample a structured buffer. A structured buffer is a [GraphicsBuffer](https://docs.unity3d.com/ScriptReference/GraphicsBuffer.html) created using the [Structured](https://docs.unity3d.com/ScriptReference/GraphicsBuffer.Target.Structured.html) target. +The Sample Graphics Buffer Operator enables you to fetch and sample a structured buffer. A structured buffer is a [GraphicsBuffer](https://docs.unity3d.com/ScriptReference/GraphicsBuffer.html) created using the [Structured](https://docs.unity3d.com/ScriptReference/GraphicsBuffer.Target.Structured.html) target. ## Operator settings @@ -17,7 +17,7 @@ The Sample Buffer Operator enables you to fetch and sample a structured buffer. | **Input** | **Type** | **Description** | | ---------- | --------------------------------------- | ------------------------------------------------------------ | | **Input** | [Configurable](#operator-configuration) | The structure type. | -| **Buffer** | GraphicsBuffer | The structured buffer to fetch. You can only connect an exposed property to this input port. | +| **Buffer** | Graphics Buffer [property](Properties.md)| The structured buffer to fetch. You can only connect an exposed property to this input port. | | **Index** | uint | The index of the element to fetch. | | **Output** | **Type** | **Description** | @@ -26,32 +26,34 @@ The Sample Buffer Operator enables you to fetch and sample a structured buffer. ## Operator configuration -To view the Operator's configuration, click the **cog** icon in the Operator's header. +To set the struct type, select the cog icon. The available types are: -### Available types -This Operator supports sampling structured buffers that use blittable types. The list of built-in blittable types is: - - float - - int - - uint - - Vector2 - - Vector3 - - Vector4 - - Matrix4x4 +- float +- int +- uint +- Vector2 +- Vector3 +- Vector4 +- Matrix4x4 -You can also declare custom types. To do this, add the `[VFXType]` attribute to a struct, and use the `VFXTypeAttribute.Usage.GraphicsBuffer` type. For example: +### Add a custom type + +To add a custom type to the list, add the `[VFXType(VFXTypeAttribute.Usage.GraphicsBuffer)]` attribute to a struct. For example, the following script adds a **MyCustomData** type: ```c# using UnityEngine; using UnityEngine.VFX; [VFXType(VFXTypeAttribute.Usage.GraphicsBuffer)] -struct CustomData +struct MyCustomData { - public Vector3 color; - public Vector3 position; + public Vector3 myColor; + public Vector3 myPosition; } ``` +After you set a custom type, open the **s** dropdown to display the properties of the struct and connect them to other Operators and [Contexts](Contexts.md). + ## Limitations The Operator has the following limitations: diff --git a/Packages/com.unity.visualeffectgraph/Editor/Controls/VFXSliderField.cs b/Packages/com.unity.visualeffectgraph/Editor/Controls/VFXSliderField.cs index 23f003d87df..8d90de871cc 100644 --- a/Packages/com.unity.visualeffectgraph/Editor/Controls/VFXSliderField.cs +++ b/Packages/com.unity.visualeffectgraph/Editor/Controls/VFXSliderField.cs @@ -76,7 +76,7 @@ public float ToScaled(float linearValue) } } - abstract class VFXBaseSliderField : VisualElement, INotifyValueChanged + abstract class VFXBaseSliderField : VisualElement, IVFXNotifyValueChanged { protected readonly Slider m_Slider; protected readonly TextValueField m_Field; @@ -160,6 +160,11 @@ public void SetValueWithoutNotify(T newValue) SetValueWithoutNotify(ValueToFloat(newValue), newValue); } + public void SetValueWithoutNotify(T newValue, bool force) + { + SetValueWithoutNotify(ValueToFloat(newValue), newValue, force); + } + public T value { get => m_Value; diff --git a/Packages/com.unity.visualeffectgraph/Editor/GraphView/Views/Properties/PropertyRM.cs b/Packages/com.unity.visualeffectgraph/Editor/GraphView/Views/Properties/PropertyRM.cs index 33c133ac44b..5564ff69ccb 100644 --- a/Packages/com.unity.visualeffectgraph/Editor/GraphView/Views/Properties/PropertyRM.cs +++ b/Packages/com.unity.visualeffectgraph/Editor/GraphView/Views/Properties/PropertyRM.cs @@ -36,6 +36,10 @@ interface IPropertyRMProvider void EndLiveModification(); } + interface IVFXNotifyValueChanged : INotifyValueChanged + { + void SetValueWithoutNotify(T typedNewValue, bool force = false); + } class SimplePropertyRMProvider : IPropertyRMProvider { @@ -149,7 +153,7 @@ public virtual bool IsCompatible(IPropertyRMProvider provider) public float GetPreferredLabelWidth() { - if (hasLabel && this.Q