forked from BilalY/Rasagar
263 lines
8.2 KiB
C#
263 lines
8.2 KiB
C#
|
using System.Collections.Generic;
|
|||
|
using UnityEditor.Experimental.GraphView;
|
|||
|
using UnityEngine;
|
|||
|
using UnityEngine.UIElements;
|
|||
|
using UnityEngine.VFX;
|
|||
|
|
|||
|
namespace UnityEditor.VFX.UI
|
|||
|
{
|
|||
|
class VFXAnchoredProfilerUI : GraphElement
|
|||
|
{
|
|||
|
public VFXAnchoredProfilerUI()
|
|||
|
{
|
|||
|
capabilities |= Capabilities.Movable | Capabilities.Deletable | Capabilities.Collapsible;
|
|||
|
|
|||
|
string path = VisualEffectAssetEditorUtility.editorResourcesPath + "/uxml/VFXAnchoredProfiler.uxml";
|
|||
|
var tpl = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(path);
|
|||
|
tpl.CloneTree(this);
|
|||
|
|
|||
|
m_Foldout = this.Q<Foldout>();
|
|||
|
m_Foldout.Q<Toggle>().focusable = false;
|
|||
|
m_Foldout.RegisterCallback<ChangeEvent<bool>>(OnCollapseChanged);
|
|||
|
m_LockButton = this.Q("lock-button");
|
|||
|
m_LockButton.AddManipulator(new Clickable(ToggleLockState));
|
|||
|
|
|||
|
styleSheets.Add(VFXView.LoadStyleSheet("VFXAnchoredProfiler"));
|
|||
|
styleSheets.Add(VFXView.LoadStyleSheet("VFXPanelBadge"));
|
|||
|
AddToClassList("VFXAnchoredProfiler");
|
|||
|
RegisterCallback<MouseDownEvent>(OnMouseClick);
|
|||
|
m_SupportsGPURecorder = SystemInfo.supportsGpuRecorder;
|
|||
|
}
|
|||
|
|
|||
|
protected Foldout m_Foldout;
|
|||
|
protected string m_SystemName;
|
|||
|
protected bool m_SupportsGPURecorder;
|
|||
|
|
|||
|
protected List<VFXProfilingBoard.ProfilingItemLeaf> m_ProfilingGPUItemLeaves;
|
|||
|
protected List<VFXProfilingBoard.ProfilingItemLeaf> m_ProfilingCPUItemLeaves;
|
|||
|
|
|||
|
protected const string k_CollapsedStyleClass = "collapsed";
|
|||
|
protected const string k_HiddenStyleClass = "hidden";
|
|||
|
protected const string k_LockedStyleClass = "locked";
|
|||
|
protected const string k_HotStyleClass = "hot";
|
|||
|
protected const string k_MediumStyleClass = "medium";
|
|||
|
protected const string k_ColdStyleClass = "cold";
|
|||
|
|
|||
|
protected readonly VisualElement m_CollapseButtonExpanded;
|
|||
|
protected readonly VisualElement m_CollapseButtonCollapsed;
|
|||
|
protected readonly VisualElement m_LockButton;
|
|||
|
protected float m_HeatmapRefValue = 0.1f;
|
|||
|
|
|||
|
public const string kGpuRecorderNotSupportedMsg = "GPU Recorder is not supported on this platform";
|
|||
|
|
|||
|
|
|||
|
public void SetHeatmapRefValue(float value)
|
|||
|
{
|
|||
|
m_HeatmapRefValue = value;
|
|||
|
}
|
|||
|
protected VisualEffect m_AttachedComponent;
|
|||
|
public VisualEffect attachedComponent
|
|||
|
{
|
|||
|
get => m_AttachedComponent;
|
|||
|
set
|
|||
|
{
|
|||
|
m_AttachedComponent = value;
|
|||
|
SetupStatsLayout();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public virtual bool isCollapsed { get; }
|
|||
|
|
|||
|
protected bool m_Locked = false;
|
|||
|
protected const float kAnchorHorizontalOffset = 50.0f;
|
|||
|
protected float m_AnchorVerticalOffset = 0.0f;
|
|||
|
|
|||
|
protected internal void SetVerticalOffset(float offset)
|
|||
|
{
|
|||
|
m_AnchorVerticalOffset = offset;
|
|||
|
}
|
|||
|
|
|||
|
public override string title
|
|||
|
{
|
|||
|
set => m_Foldout.text = value;
|
|||
|
get => m_Foldout.text;
|
|||
|
}
|
|||
|
|
|||
|
protected void AnchorPositioning(Rect anchorRect)
|
|||
|
{
|
|||
|
style.left = anchorRect.xMax + kAnchorHorizontalOffset ;
|
|||
|
style.top = anchorRect.y + m_AnchorVerticalOffset;
|
|||
|
}
|
|||
|
|
|||
|
protected void ClearContent()
|
|||
|
{
|
|||
|
m_Foldout.Clear();
|
|||
|
}
|
|||
|
|
|||
|
protected void AddContent(VisualElement content)
|
|||
|
{
|
|||
|
m_Foldout.Add(content);
|
|||
|
}
|
|||
|
|
|||
|
protected void RepositionPanel(VFXContextUI target)
|
|||
|
{
|
|||
|
Rect targetRect = target.contentRect;
|
|||
|
var transformedRect = target.ChangeCoordinatesTo(hierarchy.parent, targetRect);
|
|||
|
style.position = UnityEngine.UIElements.Position.Absolute;
|
|||
|
AnchorPositioning(transformedRect);
|
|||
|
}
|
|||
|
|
|||
|
public virtual void AnchorTo(VFXContextUI target)
|
|||
|
{
|
|||
|
Detach();
|
|||
|
target.Add(this);
|
|||
|
RepositionPanel(target);
|
|||
|
}
|
|||
|
|
|||
|
void OnMouseClick(MouseDownEvent e)
|
|||
|
{
|
|||
|
if (hierarchy.parent == null)
|
|||
|
return;
|
|||
|
|
|||
|
hierarchy.parent.BringToFront();
|
|||
|
}
|
|||
|
|
|||
|
protected virtual void OnCollapseChanged(ChangeEvent<bool> evt)
|
|||
|
{
|
|||
|
if (evt.target == m_Foldout)
|
|||
|
{
|
|||
|
this.ToggleInClassList(k_CollapsedStyleClass);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public virtual void Detach()
|
|||
|
{
|
|||
|
RemoveFromHierarchy();
|
|||
|
}
|
|||
|
|
|||
|
public void ToggleLockState()
|
|||
|
{
|
|||
|
if (m_Foldout.value) //Lock/Unlock can only be done in expanded state
|
|||
|
{
|
|||
|
m_Locked = !m_Locked;
|
|||
|
ToggleInClassList(k_LockedStyleClass);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public virtual void ForceExpand()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public virtual void ForceClose()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
internal void UpdateStatsDisplay()
|
|||
|
{
|
|||
|
if (attachedComponent == null)
|
|||
|
{
|
|||
|
if(m_ProfilingGPUItemLeaves != null)
|
|||
|
m_ProfilingGPUItemLeaves.Clear();
|
|||
|
else
|
|||
|
m_ProfilingGPUItemLeaves = new List<VFXProfilingBoard.ProfilingItemLeaf>();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
UpdateDynamicValues();
|
|||
|
}
|
|||
|
|
|||
|
protected float NanoToMilli(long timeLong)
|
|||
|
{
|
|||
|
const float kNanoToMilli = 1e-6f;
|
|||
|
return timeLong * kNanoToMilli;
|
|||
|
}
|
|||
|
|
|||
|
protected string ComputeHeatmapClass(float currentValue, float maxValue)
|
|||
|
{
|
|||
|
if(currentValue < maxValue * 0.50f)
|
|||
|
return k_ColdStyleClass;
|
|||
|
if(currentValue < maxValue * 1.0f)
|
|||
|
return k_MediumStyleClass;
|
|||
|
return k_HotStyleClass;
|
|||
|
}
|
|||
|
|
|||
|
protected string ComputeEfficiencyColor(uint alive, uint capacity)
|
|||
|
{
|
|||
|
float efficiency = (float)alive / capacity;
|
|||
|
if (efficiency < 0.51f)
|
|||
|
return k_HotStyleClass;
|
|||
|
if (efficiency < 0.91f)
|
|||
|
return k_MediumStyleClass;
|
|||
|
return k_ColdStyleClass;
|
|||
|
}
|
|||
|
internal virtual void UpdateDynamicValues()
|
|||
|
{
|
|||
|
|
|||
|
if (m_ProfilingGPUItemLeaves != null && m_SupportsGPURecorder)
|
|||
|
{
|
|||
|
foreach (var leaf in m_ProfilingGPUItemLeaves)
|
|||
|
{
|
|||
|
var timingLabel = leaf.label;
|
|||
|
if (timingLabel != null)
|
|||
|
{
|
|||
|
int sampleCount = leaf.recorder.gpuSampleBlockCount;
|
|||
|
|
|||
|
float timeMs = NanoToMilli(leaf.average);
|
|||
|
timingLabel.text = $"{timeMs:F3} ms ({sampleCount.ToString()})";
|
|||
|
timingLabel.ClearClassList();
|
|||
|
timingLabel.AddToClassList(ComputeHeatmapClass(timeMs, m_HeatmapRefValue));
|
|||
|
}
|
|||
|
|
|||
|
leaf.ResetTimingStats();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (m_ProfilingCPUItemLeaves != null)
|
|||
|
{
|
|||
|
foreach (var leaf in m_ProfilingCPUItemLeaves)
|
|||
|
{
|
|||
|
var timingLabel = leaf.label;
|
|||
|
if (timingLabel != null)
|
|||
|
timingLabel.text = $"{NanoToMilli(leaf.average):F3} ms";
|
|||
|
|
|||
|
leaf.ResetTimingStats();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
protected Label CreateBadge(string text, string tip)
|
|||
|
{
|
|||
|
return new Label { name = "Badge", text = text, tooltip = tip};
|
|||
|
}
|
|||
|
|
|||
|
protected virtual void SetupStatsLayout()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
internal void CollectStats()
|
|||
|
{
|
|||
|
if (m_ProfilingGPUItemLeaves != null)
|
|||
|
{
|
|||
|
foreach (var leaf in m_ProfilingGPUItemLeaves)
|
|||
|
{
|
|||
|
leaf.UpdateTimingStats(leaf.recorder.gpuElapsedNanoseconds);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (m_ProfilingCPUItemLeaves != null)
|
|||
|
{
|
|||
|
foreach (var leaf in m_ProfilingCPUItemLeaves)
|
|||
|
{
|
|||
|
leaf.UpdateTimingStats(leaf.recorder.elapsedNanoseconds);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected Label AddLabelToFoldout(Foldout foldout)
|
|||
|
{
|
|||
|
var label = new Label { name = "toggleInfo" };
|
|||
|
foldout.Q<Toggle>().Add(label);
|
|||
|
return label;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|