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. diff --git a/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs b/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs index 597d582a07a..288a0f652f4 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. @@ -451,8 +453,36 @@ 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(bool requestShaders = true) + public void RenderPreviews(EditorWindow editorWindow, bool requestShaders = true) { using (RenderPreviewsMarker.Auto()) using (var renderList2D = PooledList.Get()) @@ -486,10 +516,11 @@ 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 (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..) - m_PreviewsToDraw.UnionWith(m_TimedPreviews); + if (TimedNodesShouldUpdate(editorWindow)) + m_PreviewsToDraw.UnionWith(m_TimedPreviews); 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();