123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- //#define RTPROFILER_DEBUG
-
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
-
- namespace UnityEngine.Rendering
- {
- /// <summary>
- /// Debug frame timings class
- /// </summary>
- public class DebugFrameTiming
- {
- const string k_FpsFormatString = "{0:F1}";
- const string k_MsFormatString = "{0:F2}ms";
- const float k_RefreshRate = 1f / 5f;
-
- internal FrameTimeSampleHistory m_FrameHistory;
- internal BottleneckHistory m_BottleneckHistory;
-
- /// <summary>
- /// Size of the Bottleneck History Window in number of samples.
- /// </summary>
- public int bottleneckHistorySize { get; set; } = 60;
-
- /// <summary>
- /// Size of the Sample History Window in number of samples.
- /// </summary>
- public int sampleHistorySize { get; set; } = 30;
-
- FrameTiming[] m_Timing = new FrameTiming[1];
- FrameTimeSample m_Sample = new FrameTimeSample();
-
- /// <summary>
- /// Constructs the debug frame timing
- /// </summary>
- public DebugFrameTiming()
- {
- m_FrameHistory = new FrameTimeSampleHistory(sampleHistorySize);
- m_BottleneckHistory = new BottleneckHistory(bottleneckHistorySize);
- }
-
- /// <summary>
- /// Update timing data from profiling counters.
- /// </summary>
- public void UpdateFrameTiming()
- {
- m_Timing[0] = default;
- m_Sample = default;
- FrameTimingManager.CaptureFrameTimings();
- FrameTimingManager.GetLatestTimings(1, m_Timing);
-
- if (m_Timing.Length > 0)
- {
- m_Sample.FullFrameTime = (float)m_Timing.First().cpuFrameTime;
- m_Sample.FramesPerSecond = m_Sample.FullFrameTime > 0f ? 1000f / m_Sample.FullFrameTime : 0f;
- m_Sample.MainThreadCPUFrameTime = (float)m_Timing.First().cpuMainThreadFrameTime;
- m_Sample.MainThreadCPUPresentWaitTime = (float)m_Timing.First().cpuMainThreadPresentWaitTime;
- m_Sample.RenderThreadCPUFrameTime = (float)m_Timing.First().cpuRenderThreadFrameTime;
- m_Sample.GPUFrameTime = (float)m_Timing.First().gpuFrameTime;
- }
-
- m_FrameHistory.DiscardOldSamples(sampleHistorySize);
- m_FrameHistory.Add(m_Sample);
- m_FrameHistory.ComputeAggregateValues();
-
- m_BottleneckHistory.DiscardOldSamples(bottleneckHistorySize);
- m_BottleneckHistory.AddBottleneckFromAveragedSample(m_FrameHistory.SampleAverage);
- m_BottleneckHistory.ComputeHistogram();
- }
-
- /// <summary>
- /// Add frame timing data widgets to debug UI.
- /// </summary>
- /// <param name="list">List of widgets to add the stats.</param>
- public void RegisterDebugUI(List<DebugUI.Widget> list)
- {
- list.Add(new DebugUI.Foldout()
- {
- displayName = "Frame Stats",
- isHeader = true,
- opened = true,
- columnLabels = new string[] { "Avg", "Min", "Max" },
- children =
- {
- new DebugUI.ValueTuple
- {
- displayName = "Frame Rate (FPS)",
- values = new[]
- {
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FpsFormatString, getter = () => m_FrameHistory.SampleAverage.FramesPerSecond },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FpsFormatString, getter = () => m_FrameHistory.SampleMin.FramesPerSecond },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FpsFormatString, getter = () => m_FrameHistory.SampleMax.FramesPerSecond },
- }
- },
- new DebugUI.ValueTuple
- {
- displayName = "Frame Time",
- values = new[]
- {
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleAverage.FullFrameTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMin.FullFrameTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMax.FullFrameTime },
- }
- },
- new DebugUI.ValueTuple
- {
- displayName = "CPU Main Thread Frame",
- values = new[]
- {
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleAverage.MainThreadCPUFrameTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMin.MainThreadCPUFrameTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMax.MainThreadCPUFrameTime },
- }
- },
- new DebugUI.ValueTuple
- {
- displayName = "CPU Render Thread Frame",
- values = new[]
- {
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleAverage.RenderThreadCPUFrameTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMin.RenderThreadCPUFrameTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMax.RenderThreadCPUFrameTime },
- }
- },
- new DebugUI.ValueTuple
- {
- displayName = "CPU Present Wait",
- values = new[]
- {
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleAverage.MainThreadCPUPresentWaitTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMin.MainThreadCPUPresentWaitTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMax.MainThreadCPUPresentWaitTime },
- }
- },
- new DebugUI.ValueTuple
- {
- displayName = "GPU Frame",
- values = new[]
- {
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleAverage.GPUFrameTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMin.GPUFrameTime },
- new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_MsFormatString, getter = () => m_FrameHistory.SampleMax.GPUFrameTime },
- }
- }
- }
- });
-
- list.Add(new DebugUI.Foldout
- {
- displayName = "Bottlenecks",
- isHeader = true,
- children =
- {
- #if UNITY_EDITOR
- new DebugUI.Container { displayName = "Not supported in Editor" }
- #else
- new DebugUI.ProgressBarValue { displayName = "CPU", getter = () => m_BottleneckHistory.Histogram.CPU },
- new DebugUI.ProgressBarValue { displayName = "GPU", getter = () => m_BottleneckHistory.Histogram.GPU },
- new DebugUI.ProgressBarValue { displayName = "Present limited", getter = () => m_BottleneckHistory.Histogram.PresentLimited },
- new DebugUI.ProgressBarValue { displayName = "Balanced", getter = () => m_BottleneckHistory.Histogram.Balanced },
- #endif
- }
- });
- #if RTPROFILER_DEBUG
- list.Add(new DebugUI.Foldout
- {
- displayName = "Realtime Profiler Debug",
- children =
- {
- new DebugUI.IntField
- {
- displayName = "Frame Time Sample History Size",
- getter = () => sampleHistorySize,
- setter = (value) => { sampleHistorySize = value; },
- min = () => 1,
- max = () => 100
- },
- new DebugUI.IntField
- {
- displayName = "Bottleneck History Size",
- getter = () => bottleneckHistorySize,
- setter = (value) => { bottleneckHistorySize = value; },
- min = () => 1,
- max = () => 100
- },
- new DebugUI.IntField
- {
- displayName = "Force VSyncCount",
- min = () => - 1,
- max = () => 4,
- getter = () => QualitySettings.vSyncCount,
- setter = (value) => { QualitySettings.vSyncCount = value; }
- },
- new DebugUI.IntField
- {
- displayName = "Force TargetFrameRate",
- min = () => - 1,
- max = () => 1000,
- getter = () => Application.targetFrameRate,
- setter = (value) => { Application.targetFrameRate = value; }
- },
- }
- });
- #endif
- }
-
- internal void Reset()
- {
- m_BottleneckHistory.Clear();
- m_FrameHistory.Clear();
- }
- }
- }
|