216 lines
5.8 KiB
C#
216 lines
5.8 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
namespace Obi
|
|
{
|
|
[DisallowMultipleComponent]
|
|
public class ObiProfiler : MonoBehaviour
|
|
{
|
|
[Header("Appearance")]
|
|
public GUISkin skin;
|
|
public Color threadColor = Color.white;
|
|
public Color taskColor = new Color(0.1f, 1, 0.2f);
|
|
public Color parallelTaskColor = new Color(1,0.8f,0.2f);
|
|
//public Color idleColor = new Color(0.7f,0.7f,0.7f);
|
|
public Color renderTaskColor = new Color(0.2f, 0.7f, 1.0f);
|
|
public Color defaultTaskColor = new Color(1, 0.5f, 0.2f);
|
|
|
|
[Header("Visualization")]
|
|
public bool showPercentages = false;
|
|
public int profileThrottle = 30;
|
|
|
|
private Oni.ProfileInfo[] info;
|
|
private double frameStart;
|
|
private double frameEnd;
|
|
private int frameCounter = 0;
|
|
private int yPos = 25;
|
|
private bool profiling = false;
|
|
|
|
private float zoom = 1;
|
|
private Vector2 scrollPosition = Vector2.zero;
|
|
|
|
private static ObiProfiler _instance;
|
|
|
|
private void Awake()
|
|
{
|
|
if (_instance != null && _instance != this)
|
|
DestroyImmediate(this);
|
|
else{
|
|
_instance = this;
|
|
}
|
|
}
|
|
|
|
public void OnDestroy(){
|
|
#if (OBI_ONI_SUPPORTED)
|
|
_instance = null;
|
|
Oni.EnableProfiler(false);
|
|
#endif
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
#if (OBI_ONI_SUPPORTED)
|
|
if (_instance != null && _instance.profiling)
|
|
Oni.EnableProfiler(true);
|
|
#endif
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
#if (OBI_ONI_SUPPORTED)
|
|
if (_instance != null)
|
|
Oni.EnableProfiler(false);
|
|
#endif
|
|
}
|
|
|
|
public static void EnableProfiler()
|
|
{
|
|
#if (OBI_ONI_SUPPORTED)
|
|
if (_instance != null)
|
|
{
|
|
_instance.profiling = true;
|
|
if (_instance.isActiveAndEnabled)
|
|
Oni.EnableProfiler(true);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public static void DisableProfiler()
|
|
{
|
|
#if (OBI_ONI_SUPPORTED)
|
|
if (_instance != null)
|
|
{
|
|
_instance.profiling = false;
|
|
Oni.EnableProfiler(false);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public static void BeginSample(string name, byte type)
|
|
{
|
|
#if (OBI_ONI_SUPPORTED)
|
|
if (_instance != null)
|
|
Oni.BeginSample(name, type);
|
|
#endif
|
|
}
|
|
|
|
public static void EndSample()
|
|
{
|
|
#if (OBI_ONI_SUPPORTED)
|
|
if (_instance != null)
|
|
Oni.EndSample();
|
|
#endif
|
|
}
|
|
|
|
private void UpdateProfilerInfo(){
|
|
#if (OBI_ONI_SUPPORTED)
|
|
frameCounter--;
|
|
if (frameCounter <= 0)
|
|
{
|
|
int count = Oni.GetProfilingInfoCount();
|
|
info = new Oni.ProfileInfo[count];
|
|
Oni.GetProfilingInfo(info,count);
|
|
|
|
frameCounter = profileThrottle;
|
|
|
|
// Calculate frame duration:
|
|
frameStart = double.MaxValue;
|
|
frameEnd = double.MinValue;
|
|
foreach (Oni.ProfileInfo i in info){
|
|
frameStart = Math.Min(frameStart,i.start);
|
|
frameEnd = Math.Max(frameEnd,i.end);
|
|
}
|
|
}
|
|
|
|
Oni.ClearProfiler();
|
|
#endif
|
|
}
|
|
|
|
public void OnGUI()
|
|
{
|
|
#if (OBI_ONI_SUPPORTED)
|
|
if (Event.current.type == EventType.Layout)
|
|
UpdateProfilerInfo();
|
|
|
|
if (info == null)
|
|
return;
|
|
|
|
GUI.skin = skin;
|
|
int toolbarHeight = 20;
|
|
int threadHeight = 20;
|
|
int scrollViewWidth = (int)(Screen.width / zoom);
|
|
|
|
double frameDuration = frameEnd - frameStart;
|
|
|
|
// Toolbar:
|
|
GUI.BeginGroup(new Rect(0,0,Screen.width,toolbarHeight),"","Box");
|
|
|
|
GUI.Label(new Rect(5,0,50,toolbarHeight),"Zoom:");
|
|
zoom = GUI.HorizontalSlider(new Rect(50,5,100,toolbarHeight),zoom,0.005f,1);
|
|
GUI.Label(new Rect(Screen.width - 100,0,100,toolbarHeight),(frameDuration/1000.0f).ToString("0.###") + " ms/frame");
|
|
|
|
GUI.EndGroup();
|
|
|
|
// Timeline view:
|
|
scrollPosition = GUI.BeginScrollView(new Rect(0, toolbarHeight, Screen.width, Screen.height-20), scrollPosition,
|
|
new Rect(0, 0, scrollViewWidth, yPos+30)); // height depends on amount of threads.
|
|
|
|
GUI.color = threadColor;
|
|
GUI.Label(new Rect(5,0,200,20),"Thread 1");
|
|
GUI.Box(new Rect(0, 0, scrollViewWidth, 40),"","Thread");
|
|
|
|
yPos = 25;
|
|
uint currentThreadId = 0;
|
|
uint currentLevel = 0;
|
|
foreach (Oni.ProfileInfo i in info)
|
|
{
|
|
uint threadId = (i.info & (uint)Oni.ProfileMask.ThreadIdMask) >> 16;
|
|
uint level = (i.info & (uint)Oni.ProfileMask.StackLevelMask) >> 8;
|
|
uint type = i.info & (uint)Oni.ProfileMask.TypeMask;
|
|
|
|
if (currentThreadId != threadId){
|
|
yPos += threadHeight+1;
|
|
GUI.color = threadColor;
|
|
GUI.Label(new Rect(5,yPos+5,200,20),"Thread "+(threadId+1));
|
|
GUI.Box(new Rect(0, yPos+5, scrollViewWidth, 40),"","Thread");
|
|
yPos += 30;
|
|
}else if (currentLevel != level){
|
|
yPos += threadHeight+1;
|
|
}
|
|
|
|
currentLevel = level;
|
|
currentThreadId = threadId;
|
|
|
|
switch(type){
|
|
case 0: GUI.color = taskColor; break;
|
|
//case 1: GUI.color = idleColor; break;
|
|
case 2: GUI.color = parallelTaskColor; break;
|
|
case 3: GUI.color = renderTaskColor; break;
|
|
default: GUI.color = defaultTaskColor; break;
|
|
}
|
|
|
|
// task duration:
|
|
int taskStart = (int) ((i.start - frameStart) / frameDuration * (Screen.width-10) / zoom);
|
|
int taskEnd = (int) ((i.end - frameStart) / frameDuration * (Screen.width-10) / zoom);
|
|
int taskDuration = taskEnd-taskStart;
|
|
|
|
string name;
|
|
if (showPercentages)
|
|
{
|
|
double pctg = (i.end-i.start)/frameDuration*100;
|
|
name = i.name + " ("+pctg.ToString("0.#")+"%)";
|
|
}
|
|
else{
|
|
double ms = (i.end-i.start)/1000.0f;
|
|
name = i.name + " ("+ms.ToString("0.###")+"ms)";
|
|
}
|
|
|
|
GUI.Box(new Rect(taskStart, yPos, taskDuration-1, threadHeight),name,"Task");
|
|
}
|
|
GUI.EndScrollView();
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|