Skip to content

Commit ba2588d

Browse files
committed
Added ProfilerModule and detailed view as well as custom profile counters.
1 parent 94afade commit ba2588d

File tree

4 files changed

+180
-0
lines changed

4 files changed

+180
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#if UNITY_EDITOR // Input System currently do not have proper asmdef for editor code.
2+
3+
using Unity.Profiling.Editor;
4+
using UnityEditor;
5+
using UnityEditorInternal;
6+
using UnityEngine.UIElements;
7+
8+
namespace UnityEngine.InputSystem.Editor
9+
{
10+
/// <summary>
11+
/// A profiler module that integrates Input System with the Profiler editor window.
12+
/// </summary>
13+
[ProfilerModuleMetadata("Input System")]
14+
internal sealed class InputSystemProfilerModule : ProfilerModule
15+
{
16+
/// <summary>
17+
/// A profiler module detail view that extends the Profiler window and shows details for the selected frame.
18+
/// </summary>
19+
private sealed class InputSystemDetailsViewController : ProfilerModuleViewController
20+
{
21+
public InputSystemDetailsViewController(ProfilerWindow profilerWindow)
22+
: base(profilerWindow)
23+
{ }
24+
25+
private Label m_EventCountLabel;
26+
private Label m_EventSizeLabel;
27+
private Label m_AverageLatencyLabel;
28+
private Label m_MaxLatencyLabel;
29+
private Label m_EventProcessingTimeLabel;
30+
31+
private Label CreateLabel()
32+
{
33+
return new Label() { style = { paddingTop = 8, paddingLeft = 8 } };
34+
}
35+
36+
protected override VisualElement CreateView()
37+
{
38+
var view = new VisualElement();
39+
40+
m_EventCountLabel = CreateLabel();
41+
m_EventSizeLabel = CreateLabel();
42+
m_AverageLatencyLabel = CreateLabel();
43+
m_MaxLatencyLabel = CreateLabel();
44+
m_EventProcessingTimeLabel = CreateLabel();
45+
46+
view.Add(m_EventCountLabel);
47+
view.Add(m_EventSizeLabel);
48+
view.Add(m_AverageLatencyLabel);
49+
view.Add(m_MaxLatencyLabel);
50+
view.Add(m_EventProcessingTimeLabel);
51+
52+
// Populate the label with the current data for the selected frame.
53+
ReloadData();
54+
55+
// Be notified when the selected frame index in the Profiler Window changes, so we can update the label.
56+
ProfilerWindow.SelectedFrameIndexChanged += OnSelectedFrameIndexChanged;
57+
58+
return view;
59+
}
60+
61+
protected override void Dispose(bool disposing)
62+
{
63+
if (disposing)
64+
{
65+
// Unsubscribe from the Profiler window event that we previously subscribed to.
66+
ProfilerWindow.SelectedFrameIndexChanged -= OnSelectedFrameIndexChanged;
67+
}
68+
69+
base.Dispose(disposing);
70+
}
71+
72+
void ReloadData()
73+
{
74+
var selectedFrameIndex = System.Convert.ToInt32(ProfilerWindow.selectedFrameIndex);
75+
76+
var eventCount = ProfilerDriver.GetFormattedCounterValue(selectedFrameIndex,
77+
InputStatistics.Category.Name, InputStatistics.kEventCountName);
78+
var eventSizeBytes = ProfilerDriver.GetFormattedCounterValue(selectedFrameIndex,
79+
InputStatistics.Category.Name, InputStatistics.kEventSizeName);
80+
var averageLatency = ProfilerDriver.GetFormattedCounterValue(selectedFrameIndex,
81+
InputStatistics.Category.Name, InputStatistics.kAverageLatencyName);
82+
var maxLatency = ProfilerDriver.GetFormattedCounterValue(selectedFrameIndex,
83+
InputStatistics.Category.Name, InputStatistics.kMaxLatencyName);
84+
var eventProcessingTime = ProfilerDriver.GetFormattedCounterValue(selectedFrameIndex,
85+
InputStatistics.Category.Name, InputStatistics.kEventProcessingTimeName);
86+
87+
m_EventCountLabel.text = $"{InputStatistics.kEventCountName}: {eventCount}";
88+
m_EventSizeLabel.text = $"{InputStatistics.kEventSizeName}: {eventSizeBytes}";
89+
m_AverageLatencyLabel.text = $"{InputStatistics.kAverageLatencyName}: {averageLatency}";
90+
m_MaxLatencyLabel.text = $"{InputStatistics.kMaxLatencyName}: {maxLatency}";
91+
m_EventProcessingTimeLabel.text = $"{InputStatistics.kEventProcessingTimeName}: {eventProcessingTime}";
92+
}
93+
94+
void OnSelectedFrameIndexChanged(long selectedFrameIndex)
95+
{
96+
ReloadData();
97+
}
98+
}
99+
100+
private static readonly ProfilerCounterDescriptor[] Counters = new ProfilerCounterDescriptor[]
101+
{
102+
new (InputStatistics.kEventCountName, InputStatistics.Category),
103+
new (InputStatistics.kEventSizeName, InputStatistics.Category),
104+
new (InputStatistics.kAverageLatencyName, InputStatistics.Category),
105+
new (InputStatistics.kMaxLatencyName, InputStatistics.Category),
106+
new (InputStatistics.kEventProcessingTimeName, InputStatistics.Category),
107+
};
108+
109+
public InputSystemProfilerModule()
110+
: base(Counters)
111+
{ }
112+
113+
public override ProfilerModuleViewController CreateDetailsViewController()
114+
{
115+
return new InputSystemDetailsViewController(ProfilerWindow);
116+
}
117+
}
118+
}
119+
120+
#endif // UNITY_EDITOR

Packages/com.unity.inputsystem/InputSystem/Editor/Internal/ProfilerModule.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using Unity.Profiling;
2+
3+
namespace UnityEngine.InputSystem
4+
{
5+
/// <summary>
6+
/// Input Statistics for Unity Profiler integration.
7+
/// </summary>
8+
internal class InputStatistics
9+
{
10+
public static readonly ProfilerCategory Category = ProfilerCategory.Input;
11+
12+
public const string kEventCountName = "Input Event Count";
13+
public const string kEventSizeName = "Input Event Size";
14+
public const string kAverageLatencyName = "Average Latency";
15+
public const string kMaxLatencyName = "Max Latency";
16+
public const string kEventProcessingTimeName = "Event Processing Time";
17+
18+
/// <summary>
19+
/// Counter reflecting the number of input events.
20+
/// </summary>
21+
public static readonly ProfilerCounterValue<int> EventCount = new ProfilerCounterValue<int>(
22+
Category, kEventCountName, ProfilerMarkerDataUnit.Count,
23+
ProfilerCounterOptions.FlushOnEndOfFrame | ProfilerCounterOptions.ResetToZeroOnFlush);
24+
25+
/// <summary>
26+
/// Counter reflecting the accumulated input event size in bytes.
27+
/// </summary>
28+
public static readonly ProfilerCounterValue<int> EventSize = new ProfilerCounterValue<int>(
29+
Category, kEventSizeName, ProfilerMarkerDataUnit.Bytes,
30+
ProfilerCounterOptions.FlushOnEndOfFrame | ProfilerCounterOptions.ResetToZeroOnFlush);
31+
32+
/// <summary>
33+
/// Counter value reflecting the average input latency.
34+
/// </summary>
35+
public static readonly ProfilerCounterValue<float> AverageLatency = new ProfilerCounterValue<float>(
36+
Category, kAverageLatencyName, ProfilerMarkerDataUnit.TimeNanoseconds,
37+
ProfilerCounterOptions.FlushOnEndOfFrame | ProfilerCounterOptions.ResetToZeroOnFlush);
38+
39+
/// <summary>
40+
/// Counter value reflecting the maximum input latency.
41+
/// </summary>
42+
public static readonly ProfilerCounterValue<float> MaxLatency = new ProfilerCounterValue<float>(
43+
Category, kMaxLatencyName, ProfilerMarkerDataUnit.TimeNanoseconds,
44+
ProfilerCounterOptions.FlushOnEndOfFrame | ProfilerCounterOptions.ResetToZeroOnFlush);
45+
46+
/// <summary>
47+
/// Counter value reflecting the accumulated event processing time (Update) during a rendering frame.
48+
/// </summary>
49+
public static readonly ProfilerCounterValue<double> EventProcessingTime = new ProfilerCounterValue<double>(
50+
Category, kEventProcessingTimeName, ProfilerMarkerDataUnit.TimeNanoseconds,
51+
ProfilerCounterOptions.FlushOnEndOfFrame | ProfilerCounterOptions.ResetToZeroOnFlush
52+
);
53+
}
54+
}

Packages/com.unity.inputsystem/InputSystem/Utilities/InputStatistics.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)