using UnityEngine ;
using UnityEngine.Profiling ;
using UnityEngine.Rendering ;
public class MiniProfiler : MonoBehaviour {
namespace UnityEngine.Experimental.Rendering
{
public class MiniProfiler : MonoBehaviour
{
private bool m_Enable = true ;
private bool m_CurrentBatcherEnable = false ;
private const float kAverageStatDuration = 1.0f ; // stats refresh each second
private int m_frameCount ;
private float m_AccDeltaTime ;
private string m_statsLabel ;
private GUIStyle m_style ;
public bool m_Enable = false ;
internal class RecorderEntry
{
public string name ;
public int callCount ;
public float accTime ;
public Recorder recorder ;
} ;
enum SRPBMarkers
{
kStdRenderDraw ,
kStdShadowDraw ,
kSRPBRenderDraw ,
kSRPBShadowDraw ,
kRenderThreadIdle ,
kStdFlush ,
kSRPBFlush ,
} ;
RecorderEntry [ ] recordersList =
{
// Warning: Keep that list in the exact same order than SRPBMarkers enum
new RecorderEntry ( ) { name = "RenderLoop.Draw" } ,
new RecorderEntry ( ) { name = "Shadows.Draw" } ,
new RecorderEntry ( ) { name = "RenderLoopNewBatcher.Draw" } ,
new RecorderEntry ( ) { name = "ShadowLoopNewBatcher.Draw" } ,
new RecorderEntry ( ) { name = "RenderLoopDevice.Idle" } ,
new RecorderEntry ( ) { name = "BatchRenderer.Flush" } ,
new RecorderEntry ( ) { name = "SRPBatcher.Flush" } ,
} ;
void Awake ( )
{
for ( int i = 0 ; i < recordersList . Length ; i + + )
{
var sampler = Sampler . Get ( recordersList [ i ] . name ) ;
if ( sampler . isValid )
recordersList [ i ] . recorder = sampler . GetRecorder ( ) ;
}
private int frameCount = 0 ;
private const int kAverageFrameCount = 6 4 ;
private float m_AccDeltaTime ;
private float m_AvgDeltaTime ;
m_style = new GUIStyle ( ) ;
m_style . fontSize = 3 0 ;
m_style . normal . textColor = Color . white ;
internal class RecorderEntry
{
public string name ;
public float time ;
public int count ;
public float avgTime ;
public float avgCount ;
public float accTime ;
public int accCount ;
public Recorder recorder ;
} ;
ResetStats ( ) ;
RecorderEntry [ ] recordersList =
{
new RecorderEntry ( ) { name = "RenderLoop.Draw" } ,
new RecorderEntry ( ) { name = "CullScriptable" } ,
new RecorderEntry ( ) { name = "Gfx.WaitForPresent" }
} ;
}
void Awake ( )
{
for ( int i = 0 ; i < recordersList . Length ; i + + )
void RazCounters ( )
var sampler = Sampler . Get ( recordersList [ i ] . name ) ;
if ( sampler ! = null )
m_AccDeltaTime = 0.0f ;
m_frameCount = 0 ;
for ( int i = 0 ; i < recordersList . Length ; i + + )
recordersList [ i ] . recorder = sampler . GetRecorder ( ) ;
recordersList [ i ] . accTime = 0.0f ;
recordersList [ i ] . callCount = 0 ;
}
void ResetStats ( )
{
m_statsLabel = "Gathering data..." ;
RazCounters ( ) ;
}
void Update ( )
{
void Update ( )
{
if ( m_Enable )
{
if ( Input . GetKeyDown ( KeyCode . F9 ) )
{
GraphicsSettings . useScriptableRenderPipelineBatching = ! GraphicsSettings . useScriptableRenderPipelineBatching ;
}
// get timing & update average accumulators
for ( int i = 0 ; i < recordersList . Length ; i + + )
if ( Input . GetKeyDown ( KeyCode . F8 ) )
recordersList [ i ] . time = recordersList [ i ] . recorder . elapsedNanoseconds / 1 0 0 0 0 0 0.0f ;
recordersList [ i ] . count = recordersList [ i ] . recorder . sampleBlockCount ;
recordersList [ i ] . accTime + = recordersList [ i ] . time ;
recordersList [ i ] . accCount + = recordersList [ i ] . count ;
m_Enable = ! m_Enable ;
ResetStats ( ) ;
m_AccDeltaTime + = Time . deltaTime ;
if ( m_CurrentBatcherEnable ! = GraphicsSettings . useScriptableRenderPipelineBatching )
{
ResetStats ( ) ;
m_CurrentBatcherEnable = GraphicsSettings . useScriptableRenderPipelineBatching ;
}
frameCount + + ;
// time to time, update average values & reset accumulators
if ( frameCount > = kAverageFrameCount )
if ( m_Enable )
bool SRPBatcher = GraphicsSettings . useScriptableRenderPipelineBatching ;
m_AccDeltaTime + = Time . unscaledDeltaTime ;
m_frameCount + + ;
// get timing & update average accumulators
recordersList [ i ] . avgTime = recordersList [ i ] . accTime * ( 1.0f / kAverageFrameCount ) ;
recordersList [ i ] . avgCount = recordersList [ i ] . accCount * ( 1.0f / kAverageFrameCount ) ;
recordersList [ i ] . accTime = 0.0f ;
recordersList [ i ] . accCount = 0 ;
if ( recordersList [ i ] . recorder ! = null )
{
recordersList [ i ] . accTime + = recordersList [ i ] . recorder . elapsedNanoseconds / 1 0 0 0 0 0 0.0f ; // acc time in ms
recordersList [ i ] . callCount + = recordersList [ i ] . recorder . sampleBlockCount ;
}
m_AvgDeltaTime = m_AccDeltaTime / kAverageFrameCount ;
m_AccDeltaTime = 0.0f ;
frameCount = 0 ;
}
}
if ( m_AccDeltaTime > = kAverageStatDuration )
{
}
float ooFrameCount = 1.0f / ( float ) m_frameCount ;
float avgStdRender = recordersList [ ( int ) SRPBMarkers . kStdRenderDraw ] . accTime * ooFrameCount ;
float avgStdShadow = recordersList [ ( int ) SRPBMarkers . kStdShadowDraw ] . accTime * ooFrameCount ;
float avgSRPBRender = recordersList [ ( int ) SRPBMarkers . kSRPBRenderDraw ] . accTime * ooFrameCount ;
float avgSRPBShadow = recordersList [ ( int ) SRPBMarkers . kSRPBShadowDraw ] . accTime * ooFrameCount ;
float RTIdleTime = recordersList [ ( int ) SRPBMarkers . kRenderThreadIdle ] . accTime * ooFrameCount ;
void OnGUI ( )
{
m_statsLabel = string . Format ( "Accumulated time for RenderLoop.Draw and ShadowLoop.Draw (all threads)\n{0:F2}ms CPU Rendering time ( incl {1:F2}ms RT idle )\n" , avgStdRender + avgStdShadow + avgSRPBRender + avgSRPBShadow , RTIdleTime ) ;
if ( SRPBatcher )
{
m_statsLabel + = string . Format ( " {0:F2}ms SRP Batcher code path ({1} flush(s))\n" , avgSRPBRender + avgSRPBShadow , recordersList [ ( int ) SRPBMarkers . kSRPBFlush ] . callCount / ( int ) m_frameCount ) ;
m_statsLabel + = string . Format ( " {0:F2}ms All objects\n" , avgSRPBRender ) ;
m_statsLabel + = string . Format ( " {0:F2}ms Shadows\n" , avgSRPBShadow ) ;
}
m_statsLabel + = string . Format ( " {0:F2}ms Standard code path ({1} flush(s))\n" , avgStdRender + avgStdShadow , recordersList [ ( int ) SRPBMarkers . kStdFlush ] . callCount / ( int ) m_frameCount ) ;
m_statsLabel + = string . Format ( " {0:F2}ms All objects\n" , avgStdRender ) ;
m_statsLabel + = string . Format ( " {0:F2}ms Shadows\n" , avgStdShadow ) ;
m_statsLabel + = string . Format ( "Global Main Loop: {0:F2}ms ({1} FPS)\n" , m_AccDeltaTime * 1 0 0 0.0f * ooFrameCount , ( int ) ( ( ( float ) m_frameCount ) / m_AccDeltaTime ) ) ;
if ( m_Enable )
RazCounters ( ) ;
}
}
}
void OnGUI ( )
GUI . color = new Color ( 0 , 0.54f , 1 , 0.8f ) ;
float w = 5 0 0 , h = 1 4 0 ;
if ( m_Enable )
{
bool SRPBatcher = GraphicsSettings . useScriptableRenderPipelineBatching ;
// GUI.skin.label.fontSize = 15;
GUI . color = new Color ( 1 , 1 , 1 , 1 ) ;
float w = 1 0 0 0 , h = 3 5 6 ;
GUILayout . BeginArea ( new Rect ( 1 0 , 1 0 , w , h ) , "Mini Profiler" , GUI . skin . window ) ;
GUI . color = new Color ( 1 , 0.9f , 0.3f , 1f ) ;
if ( SRPBatcher )
GUILayout . BeginArea ( new Rect ( 3 2 , 5 0 , w , h ) , "(SRP batcher ON)" , GUI . skin . window ) ;
else
GUILayout . BeginArea ( new Rect ( 3 2 , 5 0 , w , h ) , "(SRP batcher OFF)" , GUI . skin . window ) ;
float avgMs = m_AvgDeltaTime * 1 0 0 0.0f ;
float avgWait = recordersList [ 2 ] . avgTime ;
GUILayout . Label ( m_statsLabel , m_style ) ;
string sLabel = System . String . Format ( "<b>Total {0:F2} FPS ({1:F2}ms)</b>\n" , 1.0f / m_AvgDeltaTime , avgMs ) ;
sLabel + = System . String . Format ( "<b>CPU {0:F2}ms</b>\n" , avgMs - avgWait ) ;
sLabel + = System . String . Format ( "<b>GPU(guess) {0:F2}ms</b>\n" , avgWait ) ;
for ( int i = 0 ; i < recordersList . Length ; i + + )
{
sLabel + = string . Format ( "{0:F2}ms (*{1:F2})\t({2:F2}ms *{3:F2})\t<b>{4}</b>\n" , recordersList [ i ] . avgTime , recordersList [ i ] . avgCount , recordersList [ i ] . time , recordersList [ i ] . count , recordersList [ i ] . name ) ;
GUILayout . EndArea ( ) ;
GUILayout . Label ( sLabel ) ;
GUILayout . EndArea ( ) ;
}