Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEditor;
- using UnityEngine;
- using UnityEngine.Profiling;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine.Rendering;
- public class GpuTimingWindow : EditorWindow
- {
- private const int SampleCount = 1;
- private FrameTiming[] frameTimings = new FrameTiming[SampleCount];
- private double gpuFrameTime;
- private double cpuFrameTime;
- private const int HistorySize = 50;
- private Queue<float> cpuHistory = new Queue<float>(HistorySize);
- private Queue<float> gpuHistory = new Queue<float>(HistorySize);
- private Shader shaderToProfile;
- private CustomSampler shaderSampler;
- [MenuItem("Window/Analysis/GPU Timing Viewer")]
- public static void ShowWindow()
- {
- var window = GetWindow<GpuTimingWindow>("GPU Timing");
- window.Show();
- }
- private void OnEnable()
- {
- EditorApplication.update += UpdateTimings;
- }
- private void OnDisable()
- {
- EditorApplication.update -= UpdateTimings;
- }
- private void UpdateTimings()
- {
- // Capture frame timings from the last frame
- FrameTimingManager.CaptureFrameTimings();
- uint count = FrameTimingManager.GetLatestTimings((uint)frameTimings.Length, frameTimings);
- if (count > 0)
- {
- var timing = frameTimings[0];
- gpuFrameTime = timing.gpuFrameTime;
- cpuFrameTime = timing.cpuFrameTime;
- AddToHistory(cpuHistory, (float)cpuFrameTime);
- AddToHistory(gpuHistory, (float)gpuFrameTime);
- Repaint();
- }
- }
- private void AddToHistory(Queue<float> queue, float value)
- {
- if (queue.Count >= HistorySize)
- queue.Dequeue();
- queue.Enqueue(value);
- }
- private float GetAverage(Queue<float> queue)
- {
- if (queue.Count == 0) return 0f;
- return queue.Average();
- }
- private void OnGUI()
- {
- GUILayout.Label("GPU & CPU Frame Timing", EditorStyles.boldLabel);
- EditorGUILayout.LabelField("CPU Frame Time (ms):", cpuFrameTime.ToString("F2"));
- EditorGUILayout.LabelField("GPU Frame Time (ms):", gpuFrameTime.ToString("F2"));
- float avgCpu = GetAverage(cpuHistory);
- float avgGpu = GetAverage(gpuHistory);
- EditorGUILayout.Space();
- EditorGUILayout.LabelField("CPU Avg (200 frames, ms):", avgCpu.ToString("F2"));
- EditorGUILayout.LabelField("GPU Avg (200 frames, ms):", avgGpu.ToString("F2"));
- float targetFrameRate = 1000f / Mathf.Max(0.0001f, avgGpu);
- EditorGUILayout.LabelField("Approx. Avg GPU FPS:", targetFrameRate.ToString("F1"));
- GUILayout.Space(10);
- Rect rect = GUILayoutUtility.GetRect(100, 30);
- DrawTimingBar(rect, (float)cpuFrameTime, (float)gpuFrameTime);
- GUILayout.Space(20);
- GUILayout.Label("Frame Timing History (last 200 frames)", EditorStyles.boldLabel);
- Rect graphRect = GUILayoutUtility.GetRect(position.width - 20, 100);
- DrawGraph(graphRect, cpuHistory, gpuHistory);
- }
- private void DrawTimingBar(Rect rect, float cpuMs, float gpuMs)
- {
- float maxMs = Mathf.Max(cpuMs, gpuMs, 16.67f); // baseline at ~60 FPS
- float cpuWidth = Mathf.Clamp01(cpuMs / maxMs) * rect.width;
- float gpuWidth = Mathf.Clamp01(gpuMs / maxMs) * rect.width;
- EditorGUI.DrawRect(new Rect(rect.x, rect.y, cpuWidth, rect.height / 2), new Color(0.3f, 0.6f, 1f));
- EditorGUI.DrawRect(new Rect(rect.x, rect.y + rect.height / 2, gpuWidth, rect.height / 2), new Color(1f, 0.4f, 0.4f));
- EditorGUI.DropShadowLabel(rect, $"CPU {cpuMs:F2} ms | GPU {gpuMs:F2} ms");
- }
- private void DrawGraph(Rect rect, Queue<float> cpuData, Queue<float> gpuData)
- {
- Handles.BeginGUI();
- GUI.Box(rect, GUIContent.none);
- if (cpuData.Count > 1 && gpuData.Count > 1)
- {
- float[] cpuArray = cpuData.ToArray();
- float[] gpuArray = gpuData.ToArray();
- int count = Mathf.Min(cpuArray.Length, gpuArray.Length);
- float maxVal = 0f;
- for (int i = 0; i < count; i++)
- maxVal = Mathf.Max(maxVal, Mathf.Max(cpuArray[i], gpuArray[i]));
- if (maxVal < 16.67f)
- maxVal = 16.67f; // ensure ~60 fps baseline is visible
- Vector3 prevCpu = Vector3.zero;
- Vector3 prevGpu = Vector3.zero;
- for (int i = 0; i < count; i++)
- {
- float x = Mathf.Lerp(rect.x, rect.xMax, i / (float)(count - 1));
- float cpuY = Mathf.Lerp(rect.yMax, rect.y, cpuArray[i] / maxVal);
- float gpuY = Mathf.Lerp(rect.yMax, rect.y, gpuArray[i] / maxVal);
- Vector3 cpuPoint = new Vector3(x, cpuY, 0);
- Vector3 gpuPoint = new Vector3(x, gpuY, 0);
- if (i > 0)
- {
- Handles.color = new Color(0.3f, 0.6f, 1f);
- Handles.DrawLine(prevCpu, cpuPoint);
- Handles.color = new Color(1f, 0.4f, 0.4f);
- Handles.DrawLine(prevGpu, gpuPoint);
- }
- prevCpu = cpuPoint;
- prevGpu = gpuPoint;
- }
- }
- Handles.EndGUI();
- }
- }
Add Comment
Please, Sign In to add comment