Guest User

Untitled

a guest
Oct 24th, 2025
28
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.29 KB | None | 0 0
  1. using UnityEditor;
  2. using UnityEngine;
  3. using UnityEngine.Profiling;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using UnityEngine.Rendering;
  7.  
  8. public class GpuTimingWindow : EditorWindow
  9. {
  10. private const int SampleCount = 1;
  11. private FrameTiming[] frameTimings = new FrameTiming[SampleCount];
  12. private double gpuFrameTime;
  13. private double cpuFrameTime;
  14.  
  15. private const int HistorySize = 50;
  16. private Queue<float> cpuHistory = new Queue<float>(HistorySize);
  17. private Queue<float> gpuHistory = new Queue<float>(HistorySize);
  18.  
  19. private Shader shaderToProfile;
  20. private CustomSampler shaderSampler;
  21.  
  22. [MenuItem("Window/Analysis/GPU Timing Viewer")]
  23. public static void ShowWindow()
  24. {
  25. var window = GetWindow<GpuTimingWindow>("GPU Timing");
  26. window.Show();
  27. }
  28.  
  29. private void OnEnable()
  30. {
  31. EditorApplication.update += UpdateTimings;
  32. }
  33.  
  34. private void OnDisable()
  35. {
  36. EditorApplication.update -= UpdateTimings;
  37. }
  38.  
  39. private void UpdateTimings()
  40. {
  41. // Capture frame timings from the last frame
  42. FrameTimingManager.CaptureFrameTimings();
  43. uint count = FrameTimingManager.GetLatestTimings((uint)frameTimings.Length, frameTimings);
  44.  
  45. if (count > 0)
  46. {
  47. var timing = frameTimings[0];
  48. gpuFrameTime = timing.gpuFrameTime;
  49. cpuFrameTime = timing.cpuFrameTime;
  50.  
  51. AddToHistory(cpuHistory, (float)cpuFrameTime);
  52. AddToHistory(gpuHistory, (float)gpuFrameTime);
  53.  
  54. Repaint();
  55. }
  56. }
  57.  
  58. private void AddToHistory(Queue<float> queue, float value)
  59. {
  60. if (queue.Count >= HistorySize)
  61. queue.Dequeue();
  62. queue.Enqueue(value);
  63. }
  64.  
  65. private float GetAverage(Queue<float> queue)
  66. {
  67. if (queue.Count == 0) return 0f;
  68. return queue.Average();
  69. }
  70.  
  71. private void OnGUI()
  72. {
  73. GUILayout.Label("GPU & CPU Frame Timing", EditorStyles.boldLabel);
  74.  
  75. EditorGUILayout.LabelField("CPU Frame Time (ms):", cpuFrameTime.ToString("F2"));
  76. EditorGUILayout.LabelField("GPU Frame Time (ms):", gpuFrameTime.ToString("F2"));
  77.  
  78. float avgCpu = GetAverage(cpuHistory);
  79. float avgGpu = GetAverage(gpuHistory);
  80.  
  81. EditorGUILayout.Space();
  82. EditorGUILayout.LabelField("CPU Avg (200 frames, ms):", avgCpu.ToString("F2"));
  83. EditorGUILayout.LabelField("GPU Avg (200 frames, ms):", avgGpu.ToString("F2"));
  84.  
  85. float targetFrameRate = 1000f / Mathf.Max(0.0001f, avgGpu);
  86. EditorGUILayout.LabelField("Approx. Avg GPU FPS:", targetFrameRate.ToString("F1"));
  87.  
  88. GUILayout.Space(10);
  89. Rect rect = GUILayoutUtility.GetRect(100, 30);
  90. DrawTimingBar(rect, (float)cpuFrameTime, (float)gpuFrameTime);
  91.  
  92. GUILayout.Space(20);
  93. GUILayout.Label("Frame Timing History (last 200 frames)", EditorStyles.boldLabel);
  94. Rect graphRect = GUILayoutUtility.GetRect(position.width - 20, 100);
  95. DrawGraph(graphRect, cpuHistory, gpuHistory);
  96. }
  97.  
  98. private void DrawTimingBar(Rect rect, float cpuMs, float gpuMs)
  99. {
  100. float maxMs = Mathf.Max(cpuMs, gpuMs, 16.67f); // baseline at ~60 FPS
  101. float cpuWidth = Mathf.Clamp01(cpuMs / maxMs) * rect.width;
  102. float gpuWidth = Mathf.Clamp01(gpuMs / maxMs) * rect.width;
  103.  
  104. EditorGUI.DrawRect(new Rect(rect.x, rect.y, cpuWidth, rect.height / 2), new Color(0.3f, 0.6f, 1f));
  105. EditorGUI.DrawRect(new Rect(rect.x, rect.y + rect.height / 2, gpuWidth, rect.height / 2), new Color(1f, 0.4f, 0.4f));
  106.  
  107. EditorGUI.DropShadowLabel(rect, $"CPU {cpuMs:F2} ms | GPU {gpuMs:F2} ms");
  108. }
  109.  
  110. private void DrawGraph(Rect rect, Queue<float> cpuData, Queue<float> gpuData)
  111. {
  112. Handles.BeginGUI();
  113. GUI.Box(rect, GUIContent.none);
  114.  
  115. if (cpuData.Count > 1 && gpuData.Count > 1)
  116. {
  117. float[] cpuArray = cpuData.ToArray();
  118. float[] gpuArray = gpuData.ToArray();
  119. int count = Mathf.Min(cpuArray.Length, gpuArray.Length);
  120.  
  121. float maxVal = 0f;
  122. for (int i = 0; i < count; i++)
  123. maxVal = Mathf.Max(maxVal, Mathf.Max(cpuArray[i], gpuArray[i]));
  124.  
  125. if (maxVal < 16.67f)
  126. maxVal = 16.67f; // ensure ~60 fps baseline is visible
  127.  
  128. Vector3 prevCpu = Vector3.zero;
  129. Vector3 prevGpu = Vector3.zero;
  130. for (int i = 0; i < count; i++)
  131. {
  132. float x = Mathf.Lerp(rect.x, rect.xMax, i / (float)(count - 1));
  133. float cpuY = Mathf.Lerp(rect.yMax, rect.y, cpuArray[i] / maxVal);
  134. float gpuY = Mathf.Lerp(rect.yMax, rect.y, gpuArray[i] / maxVal);
  135.  
  136. Vector3 cpuPoint = new Vector3(x, cpuY, 0);
  137. Vector3 gpuPoint = new Vector3(x, gpuY, 0);
  138.  
  139. if (i > 0)
  140. {
  141. Handles.color = new Color(0.3f, 0.6f, 1f);
  142. Handles.DrawLine(prevCpu, cpuPoint);
  143.  
  144. Handles.color = new Color(1f, 0.4f, 0.4f);
  145. Handles.DrawLine(prevGpu, gpuPoint);
  146. }
  147.  
  148. prevCpu = cpuPoint;
  149. prevGpu = gpuPoint;
  150. }
  151. }
  152.  
  153. Handles.EndGUI();
  154. }
  155. }
  156.  
Advertisement
Add Comment
Please, Sign In to add comment