125 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using UnityEditor; | ||
|  | using Unity.Collections; | ||
|  | using Unity.Collections.LowLevel.Unsafe; | ||
|  | using Unity.Jobs.LowLevel.Unsafe; | ||
|  | using UnityEngine; | ||
|  | 
 | ||
|  | // This menu is available from the editor directly on later versions | ||
|  | #if !UNITY_2022_2_14F1_OR_NEWER | ||
|  | class JobsMenu | ||
|  | { | ||
|  |     private static int savedJobWorkerCount = JobsUtility.JobWorkerCount; | ||
|  | 
 | ||
|  |     [SettingsProvider] | ||
|  |     private static SettingsProvider JobsPreferencesItem() | ||
|  |     { | ||
|  |         var provider = new SettingsProvider("Preferences/Jobs", SettingsScope.User) | ||
|  |         { | ||
|  |             label = "Jobs", | ||
|  |             keywords = new[]{"Jobs"}, | ||
|  |             guiHandler = (searchContext) => | ||
|  |             { | ||
|  |                 var originalWidth = EditorGUIUtility.labelWidth; | ||
|  |                 EditorGUIUtility.labelWidth = 200f; | ||
|  |                 EditorGUILayout.BeginVertical(); | ||
|  | 
 | ||
|  |                 GUILayout.BeginVertical(); | ||
|  |                 EditorGUILayout.LabelField("For safety, these values are reset on editor restart."); | ||
|  | 
 | ||
|  |                 bool madeChange = false; | ||
|  | 
 | ||
|  |                 bool oldWorkerCount = (JobsUtility.JobWorkerCount > 0); | ||
|  |                 bool newWorkerCount = EditorGUILayout.Toggle(new GUIContent("Use Job Threads:"), oldWorkerCount); | ||
|  |                 if (newWorkerCount != oldWorkerCount) | ||
|  |                 { | ||
|  |                     madeChange = true; | ||
|  |                     SwitchUseJobThreads(); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 bool oldUseJobsDebugger = JobsUtility.JobDebuggerEnabled; | ||
|  |                 var newUseJobsDebugger = EditorGUILayout.Toggle(new GUIContent("Enable Jobs Debugger"), JobsUtility.JobDebuggerEnabled); | ||
|  |                 if (newUseJobsDebugger != oldUseJobsDebugger) | ||
|  |                 { | ||
|  |                     madeChange = true; | ||
|  |                     SetUseJobsDebugger(newUseJobsDebugger); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 var oldLeakDetectionMode = NativeLeakDetection.Mode; | ||
|  |                 var newLeakDetectionMode = (NativeLeakDetectionMode) EditorGUILayout.EnumPopup(new GUIContent("Leak Detection Level"), oldLeakDetectionMode); | ||
|  |                 if (newLeakDetectionMode != oldLeakDetectionMode) | ||
|  |                 { | ||
|  |                     madeChange = true; | ||
|  |                     SetLeakDetection(newLeakDetectionMode); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if (madeChange) | ||
|  |                     Telemetry.LogMenuPreferences(new Telemetry.MenuPreferencesEvent { useJobsThreads = newUseJobsDebugger, enableJobsDebugger = newUseJobsDebugger, nativeLeakDetectionMode = newLeakDetectionMode }); | ||
|  | 
 | ||
|  |                 GUILayout.EndVertical(); | ||
|  |                 EditorGUILayout.EndVertical(); | ||
|  | 
 | ||
|  |                 EditorGUIUtility.labelWidth = originalWidth; | ||
|  |             } | ||
|  | 
 | ||
|  |         }; | ||
|  | 
 | ||
|  |         return provider; | ||
|  |     } | ||
|  | 
 | ||
|  |     static void SwitchUseJobThreads() | ||
|  |     { | ||
|  |         if (JobsUtility.JobWorkerCount > 0) | ||
|  |         { | ||
|  |             savedJobWorkerCount = JobsUtility.JobWorkerCount; | ||
|  |             JobsUtility.JobWorkerCount = 0; | ||
|  |         } | ||
|  |         else | ||
|  |         { | ||
|  |             JobsUtility.JobWorkerCount = savedJobWorkerCount; | ||
|  |             if (savedJobWorkerCount == 0) | ||
|  |             { | ||
|  |                 JobsUtility.ResetJobWorkerCount(); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     static void SetUseJobsDebugger(bool value) | ||
|  |     { | ||
|  |         JobsUtility.JobDebuggerEnabled = value; | ||
|  |     } | ||
|  | 
 | ||
|  |     static void SetLeakDetection(NativeLeakDetectionMode value) | ||
|  |     { | ||
|  |         switch(value) | ||
|  |         { | ||
|  |             case NativeLeakDetectionMode.Disabled: | ||
|  |             { | ||
|  |                 // In the case where someone enables, disables, then re-enables leak checking, we might miss some frees | ||
|  |                 // while disabled. So to avoid spurious leak warnings, just forgive the leaks every time someone disables | ||
|  |                 // leak checking through the menu. | ||
|  |                 UnsafeUtility.ForgiveLeaks(); | ||
|  |                 Debug.LogWarning("Leak detection has been disabled. Leak warnings will not be generated, and all leaks up to now are forgotten."); | ||
|  |                 break; | ||
|  |             } | ||
|  |             case NativeLeakDetectionMode.Enabled: | ||
|  |             { | ||
|  |                 Debug.Log("Leak detection has been enabled. Leak warnings will be generated upon exiting play mode."); | ||
|  |                 break; | ||
|  |             } | ||
|  |             case NativeLeakDetectionMode.EnabledWithStackTrace: | ||
|  |             { | ||
|  |                 Debug.Log("Leak detection with stack traces has been enabled. Leak warnings will be generated upon exiting play mode."); | ||
|  |                 break; | ||
|  |             } | ||
|  |             default: | ||
|  |             { | ||
|  |                 throw new Exception($"Unhandled {nameof(NativeLeakDetectionMode)}"); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         NativeLeakDetection.Mode = value; | ||
|  |     } | ||
|  | } | ||
|  | #endif |