From 159aeaad5bfb50350969a8c72feef1cb4b62176d Mon Sep 17 00:00:00 2001 From: Chris Tchou Date: Mon, 19 Jul 2021 14:13:34 -0700 Subject: [PATCH 1/3] Adding animated preview throttle, removing old dead code --- .../Editor/Drawing/PreviewManager.cs | 27 ++++++++++++++++--- .../Editor/Drawing/PreviewRate.cs | 9 ------- .../Editor/Drawing/PreviewRate.cs.meta | 3 --- .../Editor/Drawing/Views/GraphEditorView.cs | 4 +-- 4 files changed, 26 insertions(+), 17 deletions(-) delete mode 100644 com.unity.shadergraph/Editor/Drawing/PreviewRate.cs delete mode 100644 com.unity.shadergraph/Editor/Drawing/PreviewRate.cs.meta diff --git a/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs b/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs index 597d582a07a..39573ed3ef2 100644 --- a/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs +++ b/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs @@ -37,6 +37,8 @@ class PreviewManager : IDisposable HashSet m_PreviewsToDraw = new HashSet(); // previews to re-render the texture (either because shader compile changed or property changed) HashSet m_TimedPreviews = new HashSet(); // previews that are dependent on a time node -- i.e. animated / need to redraw every frame + double m_LastTimedUpdateTime = 0.0f; + bool m_TopologyDirty; // indicates topology changed, used to rebuild timed node list and preview type (2D/3D) inheritance. HashSet m_MasterNodeTempBlocks = new HashSet(); // temp blocks used by the most recent master node preview generation. @@ -452,7 +454,7 @@ void AssignPerMaterialPreviewProperties(Material mat, List perM } private static readonly ProfilerMarker RenderPreviewsMarker = new ProfilerMarker("RenderPreviews"); - public void RenderPreviews(bool requestShaders = true) + public void RenderPreviews(EditorWindow editorWindow, bool requestShaders = true) { using (RenderPreviewsMarker.Auto()) using (var renderList2D = PooledList.Get()) @@ -486,10 +488,29 @@ public void RenderPreviews(bool requestShaders = true) CollectPreviewProperties(m_NodesPropertyChanged, perMaterialPreviewProperties); m_NodesPropertyChanged.Clear(); - // timed nodes change every frame, so must be drawn + // timed nodes are animated, so they should be updated regularly // (m_TimedPreviews has been pre-propagated downstream) // HOWEVER they do not need to collect properties. (the only property changing is time..) - m_PreviewsToDraw.UnionWith(m_TimedPreviews); + + // get current window FPS, clamp to what we consider a valid range + // this is probably not accurate for multi-monitor.. but should be relevant to at least one of the monitors + double windowFPS = Screen.currentResolution.refreshRate + 1.0; // +1 to round up, since it is an integer and rounded down + windowFPS = Math.Min(windowFPS, 120.0); + windowFPS = Math.Max(windowFPS, 30.0); + + var curTime = EditorApplication.timeSinceStartup; + var deltaTime = curTime - m_LastTimedUpdateTime; + bool isFocusedWindow = (EditorWindow.focusedWindow == editorWindow); + + // we throttle the update rate, based on whether the window is focused and if unity is active + double k_NonFocusedFPS = 10.0; + double k_InactiveFPS = 2.0; + double maxAnimatedFPS = (UnityEditorInternal.InternalEditorUtility.isApplicationActive ? (isFocusedWindow ? windowFPS : k_NonFocusedFPS) : k_InactiveFPS); + if (deltaTime > (1.0 / maxAnimatedFPS)) + { + m_PreviewsToDraw.UnionWith(m_TimedPreviews); + m_LastTimedUpdateTime = curTime; + } ForEachNodesPreview(nodesToDraw, p => m_PreviewsToDraw.Add(p)); diff --git a/com.unity.shadergraph/Editor/Drawing/PreviewRate.cs b/com.unity.shadergraph/Editor/Drawing/PreviewRate.cs deleted file mode 100644 index 6ffcb3e0a69..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/PreviewRate.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UnityEditor.ShaderGraph.Drawing -{ - enum PreviewRate - { - Full, - Throttled, - Off - } -} diff --git a/com.unity.shadergraph/Editor/Drawing/PreviewRate.cs.meta b/com.unity.shadergraph/Editor/Drawing/PreviewRate.cs.meta deleted file mode 100644 index d91be546579..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/PreviewRate.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: fa070520993a4b839e705dcd7f22e4d6 -timeCreated: 1506421104 \ No newline at end of file diff --git a/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs b/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs index 5ec8868b257..63e7d97f304 100644 --- a/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs +++ b/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs @@ -131,7 +131,7 @@ public GraphEditorView(EditorWindow editorWindow, GraphData graph, MessageManage m_AssetName = graphName; m_MessageManager = messageManager; previewManager = new PreviewManager(graph, messageManager); - previewManager.RenderPreviews(false); + previewManager.RenderPreviews(m_EditorWindow, false); styleSheets.Add(Resources.Load("Styles/GraphEditorView")); var serializedSettings = EditorUserSettings.GetConfigValue(k_UserViewSettings); @@ -669,7 +669,7 @@ public void HandleGraphChanges(bool wasUndoRedoPerformed) m_ColorManager.UpdateNodeViews(nodeList); } - previewManager.RenderPreviews(); + previewManager.RenderPreviews(m_EditorWindow); if (wasUndoRedoPerformed || m_InspectorView.doesInspectorNeedUpdate) m_InspectorView.Update(); From 5105cc5675666d3882ba122fa66b0063ada02f38 Mon Sep 17 00:00:00 2001 From: Chris Tchou Date: Mon, 19 Jul 2021 14:19:35 -0700 Subject: [PATCH 2/3] Added changelog --- com.unity.shadergraph/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.shadergraph/CHANGELOG.md b/com.unity.shadergraph/CHANGELOG.md index 80a8a8da23f..16ac800a197 100644 --- a/com.unity.shadergraph/CHANGELOG.md +++ b/com.unity.shadergraph/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added toggle "Disable Global Mip Bias" in Sample Texture 2D and Sample Texture 2D array node. This checkbox disables the runtimes automatic Mip Bias, which for instance can be activated during dynamic resolution scaling. - Added `Sprite` option to Main Preview, which is similar to `Quad` but does not allow rotation. `Sprite` is used as the default preview for URP Sprite shaders. - Added visible errors for invalid stage capability connections to shader graph. + - Added a ShaderGraph animated preview framerate throttle. ### Changed - Properties and Keywords are no longer separated by type on the blackboard. Categories allow for any combination of properties and keywords to be grouped together as the user defines. From 612085ff9d00748237bb67e5dc289cbcfe641203 Mon Sep 17 00:00:00 2001 From: Chris Tchou Date: Tue, 20 Jul 2021 09:52:27 -0700 Subject: [PATCH 3/3] Moving ShouldUpdate logic to it's own function --- .../Editor/Drawing/PreviewManager.cs | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs b/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs index 39573ed3ef2..288a0f652f4 100644 --- a/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs +++ b/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs @@ -453,6 +453,34 @@ void AssignPerMaterialPreviewProperties(Material mat, List perM } } + bool TimedNodesShouldUpdate(EditorWindow editorWindow) + { + // get current screen FPS, clamp to what we consider a valid range + // this is probably not accurate for multi-monitor.. but should be relevant to at least one of the monitors + double monitorFPS = Screen.currentResolution.refreshRate + 1.0; // +1 to round up, since it is an integer and rounded down + if (Double.IsInfinity(monitorFPS) || Double.IsNaN(monitorFPS)) + monitorFPS = 60.0f; + monitorFPS = Math.Min(monitorFPS, 144.0); + monitorFPS = Math.Max(monitorFPS, 30.0); + + var curTime = EditorApplication.timeSinceStartup; + var deltaTime = curTime - m_LastTimedUpdateTime; + bool isFocusedWindow = (EditorWindow.focusedWindow == editorWindow); + + // we throttle the update rate, based on whether the window is focused and if unity is active + const double k_AnimatedFPS_WhenNotFocused = 10.0; + const double k_AnimatedFPS_WhenInactive = 2.0; + double maxAnimatedFPS = + (UnityEditorInternal.InternalEditorUtility.isApplicationActive ? + (isFocusedWindow ? monitorFPS : k_AnimatedFPS_WhenNotFocused) : + k_AnimatedFPS_WhenInactive); + + bool update = (deltaTime > (1.0 / maxAnimatedFPS)); + if (update) + m_LastTimedUpdateTime = curTime; + return update; + } + private static readonly ProfilerMarker RenderPreviewsMarker = new ProfilerMarker("RenderPreviews"); public void RenderPreviews(EditorWindow editorWindow, bool requestShaders = true) { @@ -488,29 +516,11 @@ public void RenderPreviews(EditorWindow editorWindow, bool requestShaders = true CollectPreviewProperties(m_NodesPropertyChanged, perMaterialPreviewProperties); m_NodesPropertyChanged.Clear(); - // timed nodes are animated, so they should be updated regularly + // timed nodes are animated, so they should be updated regularly (but not necessarily on every update) // (m_TimedPreviews has been pre-propagated downstream) // HOWEVER they do not need to collect properties. (the only property changing is time..) - - // get current window FPS, clamp to what we consider a valid range - // this is probably not accurate for multi-monitor.. but should be relevant to at least one of the monitors - double windowFPS = Screen.currentResolution.refreshRate + 1.0; // +1 to round up, since it is an integer and rounded down - windowFPS = Math.Min(windowFPS, 120.0); - windowFPS = Math.Max(windowFPS, 30.0); - - var curTime = EditorApplication.timeSinceStartup; - var deltaTime = curTime - m_LastTimedUpdateTime; - bool isFocusedWindow = (EditorWindow.focusedWindow == editorWindow); - - // we throttle the update rate, based on whether the window is focused and if unity is active - double k_NonFocusedFPS = 10.0; - double k_InactiveFPS = 2.0; - double maxAnimatedFPS = (UnityEditorInternal.InternalEditorUtility.isApplicationActive ? (isFocusedWindow ? windowFPS : k_NonFocusedFPS) : k_InactiveFPS); - if (deltaTime > (1.0 / maxAnimatedFPS)) - { + if (TimedNodesShouldUpdate(editorWindow)) m_PreviewsToDraw.UnionWith(m_TimedPreviews); - m_LastTimedUpdateTime = curTime; - } ForEachNodesPreview(nodesToDraw, p => m_PreviewsToDraw.Add(p));