123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903 |
- using UnityEditorInternal;
- using System.Reflection;
- using System;
- using System.Collections;
- using UnityEngine;
- using System.Collections.Generic;
- using System.IO;
- using UnityEngine.Profiling;
- #if UNITY_2020_1_OR_NEWER
- using UnityEditor.Profiling;
- #endif
- #if UNITY_2021_2_OR_NEWER
- using Unity.Profiling.Editor;
- // stub so that ProfilerWindow can be moved to this namespace in trunk without a need to change PA
- namespace Unity.Profiling.Editor {}
- #endif
- namespace UnityEditor.Performance.ProfileAnalyzer
- {
- internal class ProfilerWindowInterface
- {
- bool m_ProfilerWindowInitialized = false;
- const float k_NsToMs = 1000000;
- #if UNITY_2020_1_OR_NEWER
- bool s_UseRawIterator = true;
- #endif
- ProgressBarDisplay m_progressBar;
- [NonSerialized] bool m_SendingSelectionEventToProfilerWindowInProgress = false;
- [NonSerialized] int m_LastSelectedFrameInProfilerWindow = 0;
- #if UNITY_2021_1_OR_NEWER
- [NonSerialized] ProfilerWindow m_ProfilerWindow;
- [NonSerialized] IProfilerFrameTimeViewSampleSelectionController m_CpuProfilerModule;
- #else
- Type m_ProfilerWindowType;
- EditorWindow m_ProfilerWindow;
- FieldInfo m_CurrentFrameFieldInfo;
- FieldInfo m_TimeLineGUIFieldInfo;
- FieldInfo m_SelectedEntryFieldInfo;
- FieldInfo m_SelectedNameFieldInfo;
- FieldInfo m_SelectedTimeFieldInfo;
- FieldInfo m_SelectedDurationFieldInfo;
- FieldInfo m_SelectedInstanceIdFieldInfo;
- FieldInfo m_SelectedFrameIdFieldInfo;
- FieldInfo m_SelectedThreadIndexFieldInfo;
- FieldInfo m_SelectedNativeIndexFieldInfo;
- FieldInfo m_SelectedInstanceCountFieldInfo;
- FieldInfo m_SelectedInstanceCountForThreadFieldInfo;
- FieldInfo m_SelectedInstanceCountForFrameFieldInfo;
- FieldInfo m_SelectedMetaDataFieldInfo;
- FieldInfo m_SelectedThreadCountFieldInfo;
- FieldInfo m_SelectedCallstackInfoFieldInfo;
- MethodInfo m_GetProfilerModuleInfo;
- Type m_CPUProfilerModuleType;
- #endif
- public ProfilerWindowInterface(ProgressBarDisplay progressBar)
- {
- m_progressBar = progressBar;
- #if !UNITY_2021_1_OR_NEWER
- Assembly assem = typeof(Editor).Assembly;
- m_ProfilerWindowType = assem.GetType("UnityEditor.ProfilerWindow");
- m_CurrentFrameFieldInfo = m_ProfilerWindowType.GetField("m_CurrentFrame", BindingFlags.NonPublic | BindingFlags.Instance);
- m_TimeLineGUIFieldInfo = m_ProfilerWindowType.GetField("m_CPUTimelineGUI", BindingFlags.NonPublic | BindingFlags.Instance);
- if (m_TimeLineGUIFieldInfo == null)
- {
- // m_CPUTimelineGUI isn't present in 2019.3.0a8 onward
- m_GetProfilerModuleInfo = m_ProfilerWindowType.GetMethod("GetProfilerModule", BindingFlags.NonPublic | BindingFlags.Instance);
- if (m_GetProfilerModuleInfo == null)
- {
- Debug.Log("Unable to initialise link to Profiler Timeline, no GetProfilerModule found");
- }
- m_CPUProfilerModuleType = assem.GetType("UnityEditorInternal.Profiling.CPUProfilerModule");
- m_TimeLineGUIFieldInfo = m_CPUProfilerModuleType.GetField("m_TimelineGUI", BindingFlags.NonPublic | BindingFlags.Instance);
- if (m_TimeLineGUIFieldInfo == null)
- {
- Debug.Log("Unable to initialise link to Profiler Timeline");
- }
- }
- if (m_TimeLineGUIFieldInfo != null)
- m_SelectedEntryFieldInfo = m_TimeLineGUIFieldInfo.FieldType.GetField("m_SelectedEntry", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- if (m_SelectedEntryFieldInfo != null)
- {
- m_SelectedNameFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("name", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedTimeFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("time", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedDurationFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("duration", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedInstanceIdFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("instanceId", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedFrameIdFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("frameId", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- // confusingly this is called threadId but is the thread _index_
- m_SelectedThreadIndexFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("threadId", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedNativeIndexFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("nativeIndex", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedInstanceCountFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("instanceCount", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedInstanceCountForThreadFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("instanceCountForThread", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedInstanceCountForFrameFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("instanceCountForFrame", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedThreadCountFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("threadCount", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedMetaDataFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("metaData", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- m_SelectedCallstackInfoFieldInfo = m_SelectedEntryFieldInfo.FieldType.GetField("callstackInfo", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- }
- #endif
- }
- public bool IsReady()
- {
- return m_ProfilerWindow != null && m_ProfilerWindowInitialized;
- }
- public void GetProfilerWindowHandle()
- {
- Profiler.BeginSample("GetProfilerWindowHandle");
- #if UNITY_2021_1_OR_NEWER
- if (m_CpuProfilerModule != null)
- {
- m_CpuProfilerModule.selectionChanged -= OnSelectionChangedInCpuProfilerModule;
- m_CpuProfilerModule = null;
- }
- var windows = Resources.FindObjectsOfTypeAll<ProfilerWindow>();
- if (windows != null && windows.Length > 0)
- m_ProfilerWindow = windows[0];
- if (m_ProfilerWindow != null)
- {
- #if UNITY_2021_2_OR_NEWER
- var cpuModuleIdentifier = ProfilerWindow.cpuModuleIdentifier;
- #else
- var cpuModuleIdentifier = ProfilerWindow.cpuModuleName;
- #endif
- m_CpuProfilerModule =
- m_ProfilerWindow.GetFrameTimeViewSampleSelectionController(cpuModuleIdentifier);
- m_CpuProfilerModule.selectionChanged -= OnSelectionChangedInCpuProfilerModule;
- m_CpuProfilerModule.selectionChanged += OnSelectionChangedInCpuProfilerModule;
- m_ProfilerWindow.Repaint();
- m_ProfilerWindowInitialized = false;
- // wait a frame for the Profiler to get Repainted
- EditorApplication.delayCall += () => m_ProfilerWindowInitialized = true;
- }
- #else
- UnityEngine.Object[] windows = Resources.FindObjectsOfTypeAll(m_ProfilerWindowType);
- if (windows != null && windows.Length > 0)
- m_ProfilerWindow = (EditorWindow)windows[0];
- m_ProfilerWindowInitialized = true;
- #endif
- Profiler.EndSample();
- }
- public void OpenProfilerOrUseExisting()
- {
- // Note we use existing if possible to fix a bug after domain reload
- // Where calling EditorWindow.GetWindow directly causes a second window to open
- if (m_ProfilerWindow == null)
- {
- #if UNITY_2021_1_OR_NEWER
- m_ProfilerWindow = EditorWindow.GetWindow<ProfilerWindow>();
- #if UNITY_2021_2_OR_NEWER
- var cpuModuleIdentifier = ProfilerWindow.cpuModuleIdentifier;
- #else
- var cpuModuleIdentifier = ProfilerWindow.cpuModuleName;
- #endif
- m_CpuProfilerModule = m_ProfilerWindow.GetFrameTimeViewSampleSelectionController(cpuModuleIdentifier);
- m_CpuProfilerModule.selectionChanged -= OnSelectionChangedInCpuProfilerModule;
- m_CpuProfilerModule.selectionChanged += OnSelectionChangedInCpuProfilerModule;
- #else
- // Create new
- m_ProfilerWindow = EditorWindow.GetWindow(m_ProfilerWindowType);
- #endif
- }
- }
- public bool GetFrameRangeFromProfiler(out int first, out int last)
- {
- if (m_ProfilerWindow != null)
- {
- first = 1 + ProfilerDriver.firstFrameIndex;
- last = 1 + ProfilerDriver.lastFrameIndex;
- #if !UNITY_2018_4_OR_NEWER
- //Prior to 18.4 we need to clip to the visible frames in the profile which indents 1 in from end
- //as the last frame is not visible and sometimes still being processed
- if (first < last)
- last--;
- #endif
- return true;
- }
- first = 1;
- last = 1;
- return false;
- }
- public void CloseProfiler()
- {
- if (m_ProfilerWindow != null)
- m_ProfilerWindow.Close();
- }
- #if !UNITY_2021_1_OR_NEWER
- object GetTimeLineGUI()
- {
- object timeLineGUI = null;
- if (m_CPUProfilerModuleType != null)
- {
- object[] parametersArray = new object[] { ProfilerArea.CPU };
- var getCPUProfilerModuleInfo = m_GetProfilerModuleInfo.MakeGenericMethod(m_CPUProfilerModuleType);
- var cpuModule = getCPUProfilerModuleInfo.Invoke(m_ProfilerWindow, parametersArray);
- timeLineGUI = m_TimeLineGUIFieldInfo.GetValue(cpuModule);
- }
- else if (m_TimeLineGUIFieldInfo != null)
- {
- timeLineGUI = m_TimeLineGUIFieldInfo.GetValue(m_ProfilerWindow);
- }
- return timeLineGUI;
- }
- #endif
- #if UNITY_2021_1_OR_NEWER
- private void OnSelectionChangedInCpuProfilerModule(IProfilerFrameTimeViewSampleSelectionController controller, ProfilerTimeSampleSelection selection)
- {
- if (controller == m_CpuProfilerModule && !m_SendingSelectionEventToProfilerWindowInProgress)
- {
- if (selection != null && selection.markerNamePath != null && selection.markerNamePath.Count > 0)
- {
- selectedMarkerChanged(selection.markerNamePath[selection.markerNamePath.Count - 1], selection.threadGroupName, selection.threadName);
- }
- }
- }
- #endif
- public event Action<string, string, string> selectedMarkerChanged = delegate {};
- public void PollProfilerWindowMarkerName()
- {
- #if !UNITY_2021_1_OR_NEWER
- if (m_ProfilerWindow != null)
- {
- var timeLineGUI = GetTimeLineGUI();
- if (timeLineGUI != null && m_SelectedEntryFieldInfo != null)
- {
- var selectedEntry = m_SelectedEntryFieldInfo.GetValue(timeLineGUI);
- if (selectedEntry != null && m_SelectedNameFieldInfo != null)
- {
- string threadGroupName = null;
- string threadName = null;
- #if UNITY_2020_1_OR_NEWER
- if (m_SelectedFrameIdFieldInfo != null && m_SelectedThreadIndexFieldInfo != null)
- {
- using (RawFrameDataView frameData = ProfilerDriver.GetRawFrameDataView((int)m_SelectedFrameIdFieldInfo.GetValue(selectedEntry), (int)m_SelectedThreadIndexFieldInfo.GetValue(selectedEntry)))
- {
- if (frameData != null && frameData.valid)
- {
- threadGroupName = frameData.threadGroupName;
- threadName = frameData.threadName;
- }
- }
- }
- #endif
- selectedMarkerChanged(m_SelectedNameFieldInfo.GetValue(selectedEntry).ToString(), threadGroupName, threadName);
- }
- }
- }
- #endif
- }
- public ProfileData PullFromProfiler(int firstFrameDisplayIndex, int lastFrameDisplayIndex)
- {
- Profiler.BeginSample("ProfilerWindowInterface.PullFromProfiler");
- bool recording = IsRecording();
- if (recording)
- StopRecording();
- int firstFrameIndex = Mathf.Max(firstFrameDisplayIndex - 1, 0);
- int lastFrameIndex = lastFrameDisplayIndex - 1;
- ProfileData profileData = GetData(firstFrameIndex, lastFrameIndex);
- if (recording)
- StartRecording();
- Profiler.EndSample();
- return profileData;
- }
- public int GetThreadCountForFrame(int frameIndex)
- {
- if (!IsReady())
- return 0;
- ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
- frameData.SetRoot(frameIndex, 0);
- return frameData.GetThreadCount(frameIndex);
- }
- public ProfileFrame GetProfileFrameForThread(int frameIndex, int threadIndex)
- {
- if (!IsReady())
- return null;
- var frame = new ProfileFrame();
- #if UNITY_2020_1_OR_NEWER
- using (RawFrameDataView frameData = ProfilerDriver.GetRawFrameDataView(frameIndex, threadIndex))
- {
- frame.msStartTime = frameData.frameStartTimeMs;
- frame.msFrame = frameData.frameTimeMs;
- }
- #else
- ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
- frameData.SetRoot(frameIndex, threadIndex);
- frame.msStartTime = 1000.0 * frameData.GetFrameStartS(frameIndex);
- frame.msFrame = frameData.frameTimeMS;
- #endif
- return frame;
- }
- #if UNITY_2020_1_OR_NEWER
- ProfileData GetDataRaw(ProfileData data, int firstFrameIndex, int lastFrameIndex)
- {
- bool firstError = true;
- data.SetFrameIndexOffset(firstFrameIndex);
- var depthStack = new Stack<int>();
- var threadNameCount = new Dictionary<string, int>();
- var markerIdToNameIndex = new Dictionary<int, int>();
- for (int frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; ++frameIndex)
- {
- m_progressBar.AdvanceProgressBar();
- int threadIndex = 0;
- threadNameCount.Clear();
- ProfileFrame frame = null;
- while (true)
- {
- using (RawFrameDataView frameData = ProfilerDriver.GetRawFrameDataView(frameIndex, threadIndex))
- {
- if (threadIndex == 0)
- {
- if ((frameIndex == firstFrameIndex || frameIndex == lastFrameIndex)
- && firstFrameIndex != lastFrameIndex && (!frameData.valid || frameData.frameTimeNs == 0))
- {
- // skip incomplete frames when they are at the beginning or end of the capture
- if (++frameIndex <= lastFrameIndex)
- {
- data.FirstFrameIncomplete = true;
- data.SetFrameIndexOffset(frameIndex);
- continue;
- }
- else
- {
- // break out entirely if this is the last frame
- data.LastFrameIncomplete = true;
- break;
- }
- }
- frame = new ProfileFrame();
- if (frameData.valid)
- {
- frame.msStartTime = frameData.frameStartTimeMs;
- frame.msFrame = frameData.frameTimeMs;
- }
- data.Add(frame);
- }
- if (!frameData.valid)
- break;
- string threadNameWithIndex = null;
- string threadName = frameData.threadName;
- if (threadName.Trim() == "")
- {
- Debug.Log(string.Format("Warning: Unnamed thread found on frame {0}. Corrupted data suspected, ignoring frame", frameIndex));
- threadIndex++;
- continue;
- }
- var groupName = frameData.threadGroupName;
- threadName = ProfileData.GetThreadNameWithGroup(threadName, groupName);
- int nameCount = 0;
- threadNameCount.TryGetValue(threadName, out nameCount);
- threadNameCount[threadName] = nameCount + 1;
- threadNameWithIndex = ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName);
- var thread = new ProfileThread();
- data.AddThreadName(threadNameWithIndex, thread);
- frame.Add(thread);
- // The markers are in depth first order
- depthStack.Clear();
- // first sample is the thread name
- for (int i = 1; i < frameData.sampleCount; i++)
- {
- float durationMS = frameData.GetSampleTimeMs(i);
- int markerId = frameData.GetSampleMarkerId(i);
- if (durationMS < 0)
- {
- if (firstError)
- {
- int displayIndex = data.OffsetToDisplayFrame(frameIndex);
- string name = frameData.GetSampleName(i);
- Debug.LogFormat("Ignoring Invalid marker time found for {0} on frame {1} on thread {2} ({3} < 0)",
- name, displayIndex, threadName, durationMS);
- firstError = false;
- }
- }
- else
- {
- int depth = 1 + depthStack.Count;
- var markerData = ProfileMarker.Create(durationMS, depth);
- // Use name index directly if we have already stored this named marker before
- int nameIndex;
- if (markerIdToNameIndex.TryGetValue(markerId, out nameIndex))
- {
- markerData.nameIndex = nameIndex;
- }
- else
- {
- string name = frameData.GetSampleName(i);
- data.AddMarkerName(name, markerData);
- markerIdToNameIndex[markerId] = markerData.nameIndex;
- }
- thread.AddMarker(markerData);
- }
- int childrenCount = frameData.GetSampleChildrenCount(i);
- if (childrenCount > 0)
- {
- depthStack.Push(childrenCount);
- }
- else
- {
- while (depthStack.Count > 0)
- {
- int remainingChildren = depthStack.Pop();
- if (remainingChildren > 1)
- {
- depthStack.Push(remainingChildren - 1);
- break;
- }
- }
- }
- }
- }
- threadIndex++;
- }
- }
- data.Finalise();
- return data;
- }
- #endif
- ProfileData GetDataOriginal(ProfileData data, int firstFrameIndex, int lastFrameIndex)
- {
- ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
- bool firstError = true;
- data.SetFrameIndexOffset(firstFrameIndex);
- Dictionary<string, int> threadNameCount = new Dictionary<string, int>();
- for (int frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; ++frameIndex)
- {
- m_progressBar.AdvanceProgressBar();
- int threadCount = frameData.GetThreadCount(frameIndex);
- frameData.SetRoot(frameIndex, 0);
- var msFrame = frameData.frameTimeMS;
- if ((frameIndex == firstFrameIndex || frameIndex == lastFrameIndex)
- && firstFrameIndex != lastFrameIndex && msFrame == 0)
- {
- var nextFrame = frameIndex + 1;
- // skip incomplete frames when they are at the beginning or end of the capture
- if (nextFrame <= lastFrameIndex)
- {
- data.FirstFrameIncomplete = true;
- data.SetFrameIndexOffset(nextFrame);
- continue;
- }
- else
- {
- // break out entirely if this is the last frame
- data.LastFrameIncomplete = true;
- break;
- }
- }
- /*
- if (frameIndex == lastFrameIndex)
- {
- // Check if last frame appears to be invalid data
- float median;
- float mean;
- float standardDeviation;
- CalculateFrameTimeStats(data, out median, out mean, out standardDeviation);
- float execessiveDeviation = (3f * standardDeviation);
- if (msFrame > (median + execessiveDeviation))
- {
- Debug.LogFormat("Dropping last frame as it is significantly larger than the median of the rest of the data set {0} > {1} (median {2} + 3 * standard deviation {3})", msFrame, median + execessiveDeviation, median, standardDeviation);
- break;
- }
- if (msFrame < (median - execessiveDeviation))
- {
- Debug.LogFormat("Dropping last frame as it is significantly smaller than the median of the rest of the data set {0} < {1} (median {2} - 3 * standard deviation {3})", msFrame, median - execessiveDeviation, median, standardDeviation);
- break;
- }
- }
- */
- ProfileFrame frame = new ProfileFrame();
- frame.msStartTime = 1000.0 * frameData.GetFrameStartS(frameIndex);
- frame.msFrame = msFrame;
- data.Add(frame);
- threadNameCount.Clear();
- for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
- {
- frameData.SetRoot(frameIndex, threadIndex);
- var threadName = frameData.GetThreadName();
- if (threadName.Trim() == "")
- {
- Debug.Log(string.Format("Warning: Unnamed thread found on frame {0}. Corrupted data suspected, ignoring frame", frameIndex));
- continue;
- }
- var groupName = frameData.GetGroupName();
- threadName = ProfileData.GetThreadNameWithGroup(threadName, groupName);
- ProfileThread thread = new ProfileThread();
- frame.Add(thread);
- int nameCount = 0;
- threadNameCount.TryGetValue(threadName, out nameCount);
- threadNameCount[threadName] = nameCount + 1;
- data.AddThreadName(ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName), thread);
- const bool enterChildren = true;
- // The markers are in depth first order and the depth is known
- // So we can infer a parent child relationship
- while (frameData.Next(enterChildren))
- {
- if (frameData.durationMS < 0)
- {
- if (firstError)
- {
- int displayIndex = data.OffsetToDisplayFrame(frameIndex);
- Debug.LogFormat("Ignoring Invalid marker time found for {0} on frame {1} on thread {2} ({3} < 0) : Instance id : {4}",
- frameData.name, displayIndex, threadName, frameData.durationMS, frameData.instanceId);
- firstError = false;
- }
- continue;
- }
- var markerData = ProfileMarker.Create(frameData);
- data.AddMarkerName(frameData.name, markerData);
- thread.AddMarker(markerData);
- }
- }
- }
- data.Finalise();
- frameData.Dispose();
- return data;
- }
- ProfileData GetData(int firstFrameIndex, int lastFrameIndex)
- {
- ProfileData data = new ProfileData(ProfileAnalyzerWindow.TmpPath);
- #if UNITY_2020_1_OR_NEWER
- GetDataRaw(data, firstFrameIndex, lastFrameIndex);
- #else
- GetDataOriginal(data, firstFrameIndex, lastFrameIndex);
- #endif
- data.Write();
- return data;
- }
- #if UNITY_2020_1_OR_NEWER
- public float GetFrameTimeRaw(int frameIndex)
- {
- using (RawFrameDataView frameData = ProfilerDriver.GetRawFrameDataView(frameIndex, 0))
- {
- if (!frameData.valid)
- return 0f;
- return frameData.frameTimeMs;
- }
- }
- #endif
- public float GetFrameTime(int frameIndex)
- {
- #if UNITY_2020_1_OR_NEWER
- if (s_UseRawIterator)
- return GetFrameTimeRaw(frameIndex);
- #endif
- ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
- frameData.SetRoot(frameIndex, 0);
- float ms = frameData.frameTimeMS;
- frameData.Dispose();
- return ms;
- }
- struct ThreadIndexIterator
- {
- public ProfilerFrameDataIterator frameData;
- public int threadIndex;
- }
- IEnumerator<ThreadIndexIterator> GetNextThreadIndexFittingThreadFilters(int frameIndex, List<string> threadFilters)
- {
- ProfilerFrameDataIterator frameData = new ProfilerFrameDataIterator();
- int threadCount = frameData.GetThreadCount(frameIndex);
- Dictionary<string, int> threadNameCount = new Dictionary<string, int>();
- for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex)
- {
- frameData.SetRoot(frameIndex, threadIndex);
- var threadName = frameData.GetThreadName();
- // Name here could be "Worker Thread 1"
- var groupName = frameData.GetGroupName();
- threadName = ProfileData.GetThreadNameWithGroup(threadName, groupName);
- int nameCount = 0;
- threadNameCount.TryGetValue(threadName, out nameCount);
- threadNameCount[threadName] = nameCount + 1;
- var threadNameWithIndex = ProfileData.ThreadNameWithIndex(threadNameCount[threadName], threadName);
- // To compare on the filter we need to remove the postfix on the thread name
- // "3:Worker Thread 0" -> "1:Worker Thread"
- // The index of the thread (0) is used +1 as a prefix
- // The preceding number (3) is the count of number of threads with this name
- // Unfortunately multiple threads can have the same name
- threadNameWithIndex = ProfileData.CorrectThreadName(threadNameWithIndex);
- if (threadFilters.Contains(threadNameWithIndex))
- {
- yield return new ThreadIndexIterator {frameData = frameData, threadIndex = threadIndex};
- }
- }
- frameData.Dispose();
- }
- bool GetMarkerInfo(string markerName, int frameIndex, List<string> threadFilters, out int outThreadIndex, out int outNativeIndex, out float time, out float duration, out int instanceId)
- {
- outThreadIndex = 0;
- outNativeIndex = 0;
- time = 0.0f;
- duration = 0.0f;
- instanceId = 0;
- bool found = false;
- var iterator = GetNextThreadIndexFittingThreadFilters(frameIndex, threadFilters);
- while (iterator.MoveNext())
- {
- const bool enterChildren = true;
- while (iterator.Current.frameData.Next(enterChildren))
- {
- if (iterator.Current.frameData.name == markerName)
- {
- time = iterator.Current.frameData.startTimeMS;
- duration = iterator.Current.frameData.durationMS;
- instanceId = iterator.Current.frameData.instanceId;
- outNativeIndex = iterator.Current.frameData.sampleId;
- outThreadIndex = iterator.Current.threadIndex;
- found = true;
- break;
- }
- }
- if (found)
- break;
- }
- return found;
- }
- public bool SetProfilerWindowMarkerName(string markerName, List<string> threadFilters)
- {
- m_SendingSelectionEventToProfilerWindowInProgress = true;
- if (m_ProfilerWindow == null)
- return false;
- #if UNITY_2021_1_OR_NEWER
- #if UNITY_2021_2_OR_NEWER
- var cpuModuleIdentifier = ProfilerWindow.cpuModuleIdentifier;
- var selectedModuleIdentifier = m_ProfilerWindow.selectedModuleIdentifier;
- #else
- var cpuModuleIdentifier = ProfilerWindow.cpuModuleName;
- var selectedModuleIdentifier = m_ProfilerWindow.selectedModuleName;
- #endif
- m_CpuProfilerModule = m_ProfilerWindow.GetFrameTimeViewSampleSelectionController(cpuModuleIdentifier);
- if (m_CpuProfilerModule != null && selectedModuleIdentifier == cpuModuleIdentifier
- && m_ProfilerWindow.firstAvailableFrameIndex >= 0)
- {
- // Read profiler data direct from profile to find time/duration
- int currentFrameIndex = (int)m_ProfilerWindow.selectedFrameIndex;
- var iterator = GetNextThreadIndexFittingThreadFilters(currentFrameIndex, threadFilters);
- while (iterator.MoveNext())
- {
- using (var rawFrameDataView = ProfilerDriver.GetRawFrameDataView(currentFrameIndex, iterator.Current.threadIndex))
- {
- if (m_CpuProfilerModule.SetSelection(currentFrameIndex,
- rawFrameDataView.threadGroupName, rawFrameDataView.threadName, markerName,
- threadId: rawFrameDataView.threadId))
- {
- m_ProfilerWindow.Repaint();
- m_SendingSelectionEventToProfilerWindowInProgress = false;
- return true; // setting the selection was successful, nothing more to do here.
- }
- }
- }
- // selection couldn't be found, so clear the current one to avoid confusion
- m_CpuProfilerModule.ClearSelection();
- m_ProfilerWindow.Repaint();
- }
- #else
- var timeLineGUI = GetTimeLineGUI();
- if (timeLineGUI == null)
- {
- m_SendingSelectionEventToProfilerWindowInProgress = false;
- return false;
- }
- if (m_SelectedEntryFieldInfo != null)
- {
- var selectedEntry = m_SelectedEntryFieldInfo.GetValue(timeLineGUI);
- if (selectedEntry != null)
- {
- // Read profiler data direct from profile to find time/duration
- int currentFrameIndex = (int)m_CurrentFrameFieldInfo.GetValue(m_ProfilerWindow);
- float time;
- float duration;
- int instanceId;
- int nativeIndex;
- int threadIndex;
- if (GetMarkerInfo(markerName, currentFrameIndex, threadFilters, out threadIndex, out nativeIndex, out time, out duration, out instanceId))
- {
- /*
- Debug.Log(string.Format("Setting profiler to {0} on {1} at frame {2} at {3}ms for {4}ms ({5})",
- markerName, currentFrameIndex, threadFilter, time, duration, instanceId));
- */
- if (m_SelectedNameFieldInfo != null)
- m_SelectedNameFieldInfo.SetValue(selectedEntry, markerName);
- if (m_SelectedTimeFieldInfo != null)
- m_SelectedTimeFieldInfo.SetValue(selectedEntry, time);
- if (m_SelectedDurationFieldInfo != null)
- m_SelectedDurationFieldInfo.SetValue(selectedEntry, duration);
- if (m_SelectedInstanceIdFieldInfo != null)
- m_SelectedInstanceIdFieldInfo.SetValue(selectedEntry, instanceId);
- if (m_SelectedFrameIdFieldInfo != null)
- m_SelectedFrameIdFieldInfo.SetValue(selectedEntry, currentFrameIndex);
- if (m_SelectedNativeIndexFieldInfo != null)
- m_SelectedNativeIndexFieldInfo.SetValue(selectedEntry, nativeIndex);
- if (m_SelectedThreadIndexFieldInfo != null)
- m_SelectedThreadIndexFieldInfo.SetValue(selectedEntry, threadIndex);
- // TODO : Update to fill in the total and number of instances.
- // For now we force Instance count to 1 to avoid the incorrect info showing.
- if (m_SelectedInstanceCountFieldInfo != null)
- m_SelectedInstanceCountFieldInfo.SetValue(selectedEntry, 1);
- if (m_SelectedInstanceCountForThreadFieldInfo != null)
- m_SelectedInstanceCountForThreadFieldInfo.SetValue(selectedEntry, 1);
- if (m_SelectedInstanceCountForFrameFieldInfo != null)
- m_SelectedInstanceCountForFrameFieldInfo.SetValue(selectedEntry, 1);
- if (m_SelectedThreadCountFieldInfo != null)
- m_SelectedThreadCountFieldInfo.SetValue(selectedEntry, 1);
- if (m_SelectedMetaDataFieldInfo != null)
- m_SelectedMetaDataFieldInfo.SetValue(selectedEntry, "");
- if (m_SelectedCallstackInfoFieldInfo != null)
- m_SelectedCallstackInfoFieldInfo.SetValue(selectedEntry, "");
- m_ProfilerWindow.Repaint();
- m_SendingSelectionEventToProfilerWindowInProgress = false;
- return true;
- }
- }
- }
- #endif
- m_SendingSelectionEventToProfilerWindowInProgress = false;
- return false;
- }
- public bool JumpToFrame(int index)
- {
- if (m_ProfilerWindow == null)
- return false;
- if (index - 1 < ProfilerDriver.firstFrameIndex)
- return false;
- if (index - 1 > ProfilerDriver.lastFrameIndex)
- return false;
- #if UNITY_2021_1_OR_NEWER
- m_ProfilerWindow.selectedFrameIndex = index - 1;
- #else
- m_CurrentFrameFieldInfo.SetValue(m_ProfilerWindow, index - 1);
- #endif
- m_ProfilerWindow.Repaint();
- return true;
- }
- public int selectedFrame
- {
- get
- {
- if (m_ProfilerWindow == null)
- return 0;
- #if UNITY_2021_1_OR_NEWER
- return (int)m_ProfilerWindow.selectedFrameIndex + 1;
- #else
- return (int)m_CurrentFrameFieldInfo.GetValue(m_ProfilerWindow) + 1;
- #endif
- }
- }
- public event Action<int> selectedFrameChanged = delegate {};
- public void PollSelectedFrameChanges()
- {
- var currentlySelectedFrame = selectedFrame;
- if (m_LastSelectedFrameInProfilerWindow != currentlySelectedFrame && !m_SendingSelectionEventToProfilerWindowInProgress)
- {
- m_LastSelectedFrameInProfilerWindow = currentlySelectedFrame;
- selectedFrameChanged(currentlySelectedFrame);
- }
- }
- public bool IsRecording()
- {
- #if UNITY_2017_4_OR_NEWER
- return ProfilerDriver.enabled;
- #else
- return false;
- #endif
- }
- public void StopRecording()
- {
- #if UNITY_2017_4_OR_NEWER
- // Stop recording first
- ProfilerDriver.enabled = false;
- #endif
- }
- public void StartRecording()
- {
- #if UNITY_2017_4_OR_NEWER
- // Stop recording first
- ProfilerDriver.enabled = true;
- #endif
- }
- public void OnDisable()
- {
- if (m_ProfilerWindow != null)
- {
- m_ProfilerWindow = null;
- }
- #if UNITY_2021_1_OR_NEWER
- if (m_CpuProfilerModule != null)
- {
- m_CpuProfilerModule.selectionChanged -= OnSelectionChangedInCpuProfilerModule;
- m_CpuProfilerModule = null;
- }
- #endif
- }
- }
- }
|