171 lines
4.2 KiB
C#
171 lines
4.2 KiB
C#
using System.Diagnostics;
|
|
using CircularBuffer;
|
|
using SRDebugger.Services;
|
|
using SRF;
|
|
using SRF.Service;
|
|
using UnityEngine;
|
|
|
|
namespace SRDebugger.Profiler
|
|
{
|
|
[Service(typeof(IProfilerService))]
|
|
public class ProfilerServiceImpl : SRServiceBase<IProfilerService>, IProfilerService
|
|
{
|
|
private const int FrameBufferSize = 400;
|
|
|
|
private readonly SRList<ProfilerCameraListener> _cameraListeners = new SRList<ProfilerCameraListener>();
|
|
|
|
private readonly CircularBuffer<ProfilerFrame> _frameBuffer = new CircularBuffer<ProfilerFrame>(400);
|
|
|
|
private Camera[] _cameraCache = new Camera[6];
|
|
|
|
private ProfilerLateUpdateListener _lateUpdateListener;
|
|
|
|
private double _renderDuration;
|
|
|
|
private int _reportedCameras;
|
|
|
|
private int _expectedCameraCount;
|
|
|
|
private Stopwatch _stopwatch = new Stopwatch();
|
|
|
|
private double _updateDuration;
|
|
|
|
private double _updateToRenderDuration;
|
|
|
|
public float AverageFrameTime { get; private set; }
|
|
|
|
public float LastFrameTime { get; private set; }
|
|
|
|
public CircularBuffer<ProfilerFrame> FrameBuffer
|
|
{
|
|
get
|
|
{
|
|
return _frameBuffer;
|
|
}
|
|
}
|
|
|
|
protected void PushFrame(double totalTime, double updateTime, double renderTime)
|
|
{
|
|
_frameBuffer.PushBack(new ProfilerFrame
|
|
{
|
|
OtherTime = totalTime - updateTime - renderTime,
|
|
UpdateTime = updateTime,
|
|
RenderTime = renderTime
|
|
});
|
|
}
|
|
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
_lateUpdateListener = base.gameObject.AddComponent<ProfilerLateUpdateListener>();
|
|
_lateUpdateListener.OnLateUpdate = OnLateUpdate;
|
|
base.CachedGameObject.hideFlags = HideFlags.NotEditable;
|
|
base.CachedTransform.SetParent(Hierarchy.Get("SRDebugger"), true);
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
base.Update();
|
|
if (FrameBuffer.Size > 0)
|
|
{
|
|
ProfilerFrame value = FrameBuffer.Back();
|
|
value.FrameTime = Time.deltaTime;
|
|
FrameBuffer[FrameBuffer.Size - 1] = value;
|
|
}
|
|
LastFrameTime = Time.deltaTime;
|
|
int num = Mathf.Min(20, FrameBuffer.Size);
|
|
double num2 = 0.0;
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
num2 += FrameBuffer[i].FrameTime;
|
|
}
|
|
AverageFrameTime = (float)num2 / (float)num;
|
|
if (_reportedCameras != _cameraListeners.Count)
|
|
{
|
|
}
|
|
if (_stopwatch.IsRunning)
|
|
{
|
|
_stopwatch.Stop();
|
|
_stopwatch.Reset();
|
|
}
|
|
_updateDuration = (_renderDuration = (_updateToRenderDuration = 0.0));
|
|
_reportedCameras = 0;
|
|
CameraCheck();
|
|
_expectedCameraCount = 0;
|
|
for (int j = 0; j < _cameraListeners.Count; j++)
|
|
{
|
|
if (_cameraListeners[j].isActiveAndEnabled && _cameraListeners[j].Camera.isActiveAndEnabled)
|
|
{
|
|
_expectedCameraCount++;
|
|
}
|
|
}
|
|
_stopwatch.Start();
|
|
}
|
|
|
|
private void OnLateUpdate()
|
|
{
|
|
_updateDuration = _stopwatch.Elapsed.TotalSeconds;
|
|
}
|
|
|
|
private void EndFrame()
|
|
{
|
|
if (_stopwatch.IsRunning)
|
|
{
|
|
PushFrame(_stopwatch.Elapsed.TotalSeconds, _updateDuration, _renderDuration);
|
|
_stopwatch.Reset();
|
|
_stopwatch.Start();
|
|
}
|
|
}
|
|
|
|
private void CameraDurationCallback(ProfilerCameraListener listener, double duration)
|
|
{
|
|
_reportedCameras++;
|
|
_renderDuration = _stopwatch.Elapsed.TotalSeconds - _updateDuration - _updateToRenderDuration;
|
|
if (_reportedCameras >= _expectedCameraCount)
|
|
{
|
|
EndFrame();
|
|
}
|
|
}
|
|
|
|
private void CameraCheck()
|
|
{
|
|
for (int num = _cameraListeners.Count - 1; num >= 0; num--)
|
|
{
|
|
if (_cameraListeners[num] == null)
|
|
{
|
|
_cameraListeners.RemoveAt(num);
|
|
}
|
|
}
|
|
if (Camera.allCamerasCount == _cameraListeners.Count)
|
|
{
|
|
return;
|
|
}
|
|
if (Camera.allCamerasCount > _cameraCache.Length)
|
|
{
|
|
_cameraCache = new Camera[Camera.allCamerasCount];
|
|
}
|
|
int allCameras = Camera.GetAllCameras(_cameraCache);
|
|
for (int i = 0; i < allCameras; i++)
|
|
{
|
|
Camera camera = _cameraCache[i];
|
|
bool flag = false;
|
|
for (int j = 0; j < _cameraListeners.Count; j++)
|
|
{
|
|
if (_cameraListeners[j].Camera == camera)
|
|
{
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
ProfilerCameraListener profilerCameraListener = camera.gameObject.AddComponent<ProfilerCameraListener>();
|
|
profilerCameraListener.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
|
|
profilerCameraListener.RenderDurationCallback = CameraDurationCallback;
|
|
_cameraListeners.Add(profilerCameraListener);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|