No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AutoPerfControl.cs 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.AdaptivePerformance;
  5. using System.Diagnostics;
  6. using Debug = UnityEngine.Debug;
  7. public class AutoPerfControl : MonoBehaviour
  8. {
  9. class Marker
  10. {
  11. public float time;
  12. public string label;
  13. public float avgFrameTime, avgCPUTime, avgGPUTime;
  14. public int CPULevel, GPULevel;
  15. public float tempLevel, tempTrend;
  16. public string warningLevel;
  17. public Marker(float Time, string Label, float AvgFrameTime, float AvgCPUTime, float AvgGPUTime, int _CPULevel, int _GPULevel, float TempLevel, float TempTrend, string WarningLevel)
  18. {
  19. time = Time;
  20. label = Label;
  21. avgFrameTime = AvgFrameTime;
  22. avgCPUTime = AvgCPUTime;
  23. avgGPUTime = AvgGPUTime;
  24. CPULevel = _CPULevel;
  25. GPULevel = _GPULevel;
  26. tempLevel = TempLevel;
  27. tempTrend = TempTrend;
  28. warningLevel = WarningLevel;
  29. }
  30. }
  31. public GameObject HighLevelLoad, MidLevelLoad, NoLoad;
  32. IAdaptivePerformance ap;
  33. TestSequence sequence;
  34. List<Marker> markers = new List<Marker>();
  35. Stopwatch watch = new Stopwatch();
  36. bool loop = false;
  37. bool autoMode = false;
  38. int loopCycles = 2;
  39. float timer = 0, timerMax = 3;
  40. int activeID = -1;
  41. [Tooltip("Time in seconds after which test will stop with a Timeout log")]
  42. public float testTimeout = 600;
  43. [Tooltip("Enable the Adaptive Performance Auto control mode which controls CPU and GPU levels based on current load")]
  44. public bool AutoControlMode = true;
  45. void Start()
  46. {
  47. ap = Holder.Instance;
  48. if (ap == null || !ap.Active)
  49. {
  50. Debug.Log("[AP APC] AP is not Active");
  51. enabled = false;
  52. return;
  53. }
  54. var seq = GameObject.Find("TestSequencer");
  55. sequence = seq.GetComponent<TestSequence>();
  56. loop = sequence.loop;
  57. autoMode = sequence.autoMode;
  58. ap.DevicePerformanceControl.AutomaticPerformanceControl = AutoControlMode;
  59. ap.DevelopmentSettings.Logging = true;
  60. ap.DevelopmentSettings.LoggingFrequencyInFrames = 200;
  61. Debug.Log($"Auto Performance Control overrides settings automatic performance mode to {ap.DevicePerformanceControl.AutomaticPerformanceControl},logging to {ap.DevelopmentSettings.Logging}.");
  62. // The base cycle amount for one test sequence
  63. loopCycles = 1;
  64. // If Auto mode is enabled, we're not using the loopCycles
  65. if (autoMode)
  66. {
  67. loop = false;
  68. // Since loopCycles won't be decremented, a value of 2 means it will be running forever
  69. loopCycles = 2;
  70. }
  71. if (loop) loopCycles = sequence.loopCycles;
  72. watch.Start();
  73. LogResult("Test start");
  74. ap.ThermalStatus.ThermalEvent += OnThermalEvent;
  75. StartCoroutine(continuousLogging());
  76. }
  77. void OnThermalEvent(ThermalMetrics ev)
  78. {
  79. if (loop)
  80. return;
  81. switch (ev.WarningLevel)
  82. {
  83. case WarningLevel.NoWarning:
  84. break;
  85. case WarningLevel.ThrottlingImminent:
  86. ap.ThermalStatus.ThermalEvent -= OnThermalEvent;
  87. LogResult("ThrottlingImminent state reached");
  88. StartCoroutine(FinishAutoMode());
  89. break;
  90. case WarningLevel.Throttling:
  91. ap.ThermalStatus.ThermalEvent -= OnThermalEvent;
  92. LogResult("Throttling state reached");
  93. StartCoroutine(FinishAutoMode());
  94. break;
  95. }
  96. }
  97. void Update()
  98. {
  99. if (!AutoControlMode)
  100. {
  101. ap.DevicePerformanceControl.CpuLevel = ap.DevicePerformanceControl.MaxCpuPerformanceLevel;
  102. ap.DevicePerformanceControl.GpuLevel = ap.DevicePerformanceControl.MaxGpuPerformanceLevel;
  103. }
  104. if (watch.ElapsedMilliseconds > testTimeout * 1000)
  105. {
  106. LogResult("Timeout reached");
  107. FinishTest();
  108. }
  109. timer -= Time.deltaTime;
  110. if (timer < 0)
  111. {
  112. if (activeID >= 0)
  113. LogResult("Finished with state: " + sequence.orderedLoadLevels[activeID].Name.ToString());
  114. int count = sequence.orderedLoadLevels.Count;
  115. if (activeID < count - 1)
  116. {
  117. activeID++;
  118. }
  119. else
  120. {
  121. if (loopCycles - 1 <= 0)
  122. FinishTest();
  123. activeID = 0;
  124. // In auto mode the test cycles forever until thermal state is reached or timeout happens
  125. if (!autoMode) loopCycles--;
  126. LogResult("Finished one loop, starting a new one");
  127. }
  128. ActivateLoadLevel(count, activeID);
  129. LogResult("Beginning state: " + sequence.orderedLoadLevels[activeID].Name.ToString());
  130. timer = timerMax;
  131. }
  132. }
  133. void FinishTest()
  134. {
  135. Debug.Log("[AP APC] Test Finished, Outputting results:");
  136. LogResult("Test Finished");
  137. for (int i = 0; i < markers.Count; i++)
  138. {
  139. Debug.LogFormat("[AP APC] {0} , Timestamp: {1} , Average Frame time: {2} , " +
  140. "Avg CPU Time: {3}, Avg GPU Time: {4}, CPULevel: {5}/{6} , GPULevel: {7}/{8}, " +
  141. "Temp level: {9}, Temp trend: {10}, WarningLevel: {11}",
  142. markers[i].label, markers[i].time, markers[i].avgFrameTime,
  143. markers[i].avgCPUTime, markers[i].avgGPUTime, markers[i].CPULevel, ap.DevicePerformanceControl.MaxCpuPerformanceLevel,
  144. markers[i].GPULevel, ap.DevicePerformanceControl.MaxGpuPerformanceLevel, markers[i].tempLevel,
  145. markers[i].tempTrend, markers[i].warningLevel);
  146. }
  147. watch.Stop();
  148. #if UNITY_EDITOR
  149. UnityEditor.EditorApplication.isPlaying = false;
  150. #else
  151. Application.Quit();
  152. #endif
  153. }
  154. IEnumerator FinishAutoMode()
  155. {
  156. LogResult("'ThrottlingImminent' reached");
  157. if (AutoControlMode)
  158. {
  159. LogResult("Setting TargetFrameRate to 45 and waiting for test to finish");
  160. Application.targetFrameRate = 45;
  161. }
  162. else
  163. {
  164. LogResult("Waiting for test to finish");
  165. }
  166. yield return null;
  167. }
  168. void LogResult(string Label)
  169. {
  170. Marker marker = new Marker(
  171. watch.ElapsedMilliseconds,
  172. "[AP APC] " + Label,
  173. ap.PerformanceStatus.FrameTiming.AverageFrameTime,
  174. ap.PerformanceStatus.FrameTiming.AverageCpuFrameTime,
  175. ap.PerformanceStatus.FrameTiming.AverageGpuFrameTime,
  176. ap.PerformanceStatus.PerformanceMetrics.CurrentCpuLevel,
  177. ap.PerformanceStatus.PerformanceMetrics.CurrentGpuLevel,
  178. ap.ThermalStatus.ThermalMetrics.TemperatureLevel,
  179. ap.ThermalStatus.ThermalMetrics.TemperatureTrend,
  180. ap.ThermalStatus.ThermalMetrics.WarningLevel.ToString()
  181. );
  182. markers.Add(marker);
  183. if (loggingActive)
  184. Debug.LogFormat("{0} | " +
  185. "Timestamp: {1} | " +
  186. "Average frame time: {2} | " +
  187. "Average CPU time: {3} | " +
  188. "Average GPU time: {4} | " +
  189. "Current CPU level: {5}/{6} | " +
  190. "Current GPU level: {7}/{8} | " +
  191. "Current Temp level: {9} | " +
  192. "Temp trend: {10} | " +
  193. "Temp Warning Level: {11} ",
  194. marker.label, marker.time, marker.avgFrameTime, marker.avgCPUTime, marker.avgGPUTime, marker.CPULevel, ap.DevicePerformanceControl.MaxCpuPerformanceLevel,
  195. marker.GPULevel, ap.DevicePerformanceControl.MaxGpuPerformanceLevel, marker.tempLevel, marker.tempTrend, marker.warningLevel);
  196. }
  197. void ActivateLoadLevel(int count, int ID)
  198. {
  199. for (int i = 0; i < count; i++)
  200. {
  201. sequence.orderedLoadLevels[i].isActive = false;
  202. }
  203. sequence.orderedLoadLevels[ID].isActive = true;
  204. timerMax = sequence.orderedLoadLevels[ID].Duration;
  205. switch (sequence.orderedLoadLevels[ID].Name)
  206. {
  207. case LoadLevel.loadlevels.High:
  208. EnableGameObject(HighLevelLoad);
  209. HighLevelLoadManager Hmanager = FindObjectOfType<HighLevelLoadManager>();
  210. Hmanager.SetLoad(Hmanager.startingLoadAmount);
  211. break;
  212. case LoadLevel.loadlevels.Mid:
  213. EnableGameObject(MidLevelLoad);
  214. MidLevelLoadManager Mmanager = FindObjectOfType<MidLevelLoadManager>();
  215. Mmanager.SetLoad(Mmanager.startingLoadAmount);
  216. break;
  217. case LoadLevel.loadlevels.No:
  218. EnableGameObject(NoLoad);
  219. break;
  220. default:
  221. Debug.Log("Unrecognized Load level");
  222. break;
  223. }
  224. }
  225. void EnableGameObject(GameObject level)
  226. {
  227. HighLevelLoad.transform.GetChild(0).gameObject.SetActive(false);
  228. MidLevelLoad.transform.GetChild(0).gameObject.SetActive(false);
  229. NoLoad.transform.GetChild(0).gameObject.SetActive(false);
  230. level.transform.GetChild(0).gameObject.SetActive(true);
  231. }
  232. [Tooltip("If checked, logs will be taken at the LoggingFrequency interval ")]
  233. public bool loggingActive = true;
  234. [Tooltip("Interval for logging data continuously, measured in seconds")]
  235. [Range(0.5f, 10)]
  236. public float loggingFrequency = 1.0f;
  237. IEnumerator continuousLogging()
  238. {
  239. while (true)
  240. {
  241. if (loggingActive) LogResult("Continuous Log");
  242. yield return new WaitForSeconds(loggingFrequency);
  243. }
  244. }
  245. }