Merge branch '1.5' into dotnet7
This commit is contained in:
293
Source/Editor/Windows/Profiler/Assets.cs
Normal file
293
Source/Editor/Windows/Profiler/Assets.cs
Normal file
@@ -0,0 +1,293 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Json;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
|
||||
namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
/// <summary>
|
||||
/// The Assets profiling mode.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Windows.Profiler.ProfilerMode" />
|
||||
internal sealed class Assets : ProfilerMode
|
||||
{
|
||||
private struct Resource
|
||||
{
|
||||
public string Name;
|
||||
public string TypeName;
|
||||
public int ReferencesCount;
|
||||
public ulong MemoryUsage;
|
||||
public Guid AssetId;
|
||||
}
|
||||
|
||||
private readonly SingleChart _memoryUsageChart;
|
||||
private readonly Table _table;
|
||||
private SamplesBuffer<Resource[]> _resources;
|
||||
private List<ClickableRow> _tableRowsCache;
|
||||
private Dictionary<Guid, Resource> _resourceCache;
|
||||
private StringBuilder _stringBuilder;
|
||||
|
||||
public Assets()
|
||||
: base("Assets")
|
||||
{
|
||||
// Layout
|
||||
var panel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
Parent = this,
|
||||
};
|
||||
var layout = new VerticalPanel
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
Offsets = Margin.Zero,
|
||||
IsScrollable = true,
|
||||
Parent = panel,
|
||||
};
|
||||
|
||||
// Chart
|
||||
_memoryUsageChart = new SingleChart
|
||||
{
|
||||
Title = "Assets Memory Usage (CPU)",
|
||||
FormatSample = v => Utilities.Utils.FormatBytesCount((int)v),
|
||||
Parent = layout,
|
||||
};
|
||||
_memoryUsageChart.SelectedSampleChanged += OnSelectedSampleChanged;
|
||||
|
||||
// Table
|
||||
var headerColor = Style.Current.LightBackground;
|
||||
_table = new Table
|
||||
{
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
{
|
||||
UseExpandCollapseMode = true,
|
||||
CellAlignment = TextAlignment.Near,
|
||||
Title = "Resource",
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "Type",
|
||||
CellAlignment = TextAlignment.Center,
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "References",
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "Memory Usage",
|
||||
TitleBackgroundColor = headerColor,
|
||||
FormatValue = v => Utilities.Utils.FormatBytesCount((ulong)v),
|
||||
},
|
||||
},
|
||||
Parent = layout,
|
||||
};
|
||||
_table.Splits = new[]
|
||||
{
|
||||
0.6f,
|
||||
0.2f,
|
||||
0.08f,
|
||||
0.12f,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Clear()
|
||||
{
|
||||
_memoryUsageChart.Clear();
|
||||
_resources?.Clear();
|
||||
_resourceCache?.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(ref SharedUpdateData sharedData)
|
||||
{
|
||||
if (_resourceCache == null)
|
||||
_resourceCache = new Dictionary<Guid, Resource>();
|
||||
if (_stringBuilder == null)
|
||||
_stringBuilder = new StringBuilder();
|
||||
|
||||
// Capture current assets usage info
|
||||
var assets = FlaxEngine.Content.Assets;
|
||||
var sb = _stringBuilder;
|
||||
var resources = new Resource[assets.Length];
|
||||
var contentDatabase = Editor.Instance.ContentDatabase;
|
||||
ulong totalMemoryUsage = 0;
|
||||
for (int i = 0; i < resources.Length; i++)
|
||||
{
|
||||
var asset = assets[i];
|
||||
if (!asset)
|
||||
continue;
|
||||
|
||||
// Try to reuse cached resource info
|
||||
var assetId = asset.ID;
|
||||
if (!_resourceCache.TryGetValue(assetId, out var resource))
|
||||
{
|
||||
resource = new Resource
|
||||
{
|
||||
Name = asset.Path,
|
||||
TypeName = asset.TypeName,
|
||||
AssetId = assetId,
|
||||
};
|
||||
var typeNameEnding = asset.TypeName.LastIndexOf('.');
|
||||
if (typeNameEnding != -1)
|
||||
resource.TypeName = resource.TypeName.Substring(typeNameEnding + 1);
|
||||
var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId);
|
||||
if (assetItem != null)
|
||||
{
|
||||
resource.Name = assetItem.NamePath;
|
||||
}
|
||||
if (string.IsNullOrEmpty(resource.Name) && asset.IsVirtual)
|
||||
resource.Name = "<virtual>";
|
||||
_resourceCache.Add(assetId, resource);
|
||||
}
|
||||
|
||||
resource.MemoryUsage = asset.MemoryUsage;
|
||||
totalMemoryUsage += resource.MemoryUsage;
|
||||
resource.ReferencesCount = asset.ReferencesCount;
|
||||
resources[i] = resource;
|
||||
}
|
||||
_memoryUsageChart.AddSample((float)totalMemoryUsage);
|
||||
Array.Sort(resources, SortResources);
|
||||
if (_resources == null)
|
||||
_resources = new SamplesBuffer<Resource[]>();
|
||||
_resources.Add(resources);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents)
|
||||
{
|
||||
_memoryUsageChart.SelectedSampleIndex = selectedFrame;
|
||||
|
||||
if (_resources == null)
|
||||
return;
|
||||
if (_tableRowsCache == null)
|
||||
_tableRowsCache = new List<ClickableRow>();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
_resources?.Clear();
|
||||
_resourceCache?.Clear();
|
||||
_tableRowsCache?.Clear();
|
||||
_stringBuilder?.Clear();
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
private static int SortResources(Resource a, Resource b)
|
||||
{
|
||||
return (int)(b.MemoryUsage - a.MemoryUsage);
|
||||
}
|
||||
|
||||
private void UpdateTable()
|
||||
{
|
||||
_table.IsLayoutLocked = true;
|
||||
int idx = 0;
|
||||
while (_table.Children.Count > idx)
|
||||
{
|
||||
var child = _table.Children[idx];
|
||||
if (child is ClickableRow row)
|
||||
{
|
||||
_tableRowsCache.Add(row);
|
||||
child.Parent = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
_table.LockChildrenRecursive();
|
||||
|
||||
UpdateTableInner();
|
||||
|
||||
_table.UnlockChildrenRecursive();
|
||||
_table.PerformLayout();
|
||||
}
|
||||
|
||||
private void UpdateTableInner()
|
||||
{
|
||||
if (_resources.Count == 0)
|
||||
return;
|
||||
var resources = _resources.Get(_memoryUsageChart.SelectedSampleIndex);
|
||||
if (resources == null || resources.Length == 0)
|
||||
return;
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
for (int i = 0; i < resources.Length; i++)
|
||||
{
|
||||
ref var e = ref resources[i];
|
||||
|
||||
ClickableRow row;
|
||||
if (_tableRowsCache.Count != 0)
|
||||
{
|
||||
// Reuse row
|
||||
var last = _tableRowsCache.Count - 1;
|
||||
row = _tableRowsCache[last];
|
||||
_tableRowsCache.RemoveAt(last);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate new row
|
||||
row = new ClickableRow { Values = new object[4] };
|
||||
row.RowDoubleClick = OnRowDoubleClick;
|
||||
row.RowRightClick = OnRowRightClick;
|
||||
}
|
||||
|
||||
// Setup row data
|
||||
row.Tag = e.AssetId;
|
||||
row.Values[0] = e.Name;
|
||||
row.Values[1] = e.TypeName;
|
||||
row.Values[2] = e.ReferencesCount;
|
||||
row.Values[3] = e.MemoryUsage;
|
||||
|
||||
// Add row to the table
|
||||
row.Width = _table.Width;
|
||||
row.BackgroundColor = i % 2 == 0 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRowDoubleClick(ClickableRow row)
|
||||
{
|
||||
var assetId = (Guid)row.Tag;
|
||||
var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId);
|
||||
if (assetItem != null)
|
||||
Editor.Instance.ContentEditing.Open(assetItem);
|
||||
}
|
||||
|
||||
private void OnRowRightClick(ClickableRow row)
|
||||
{
|
||||
var assetId = (Guid)row.Tag;
|
||||
var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId);
|
||||
if (assetItem != null)
|
||||
{
|
||||
var cm = new ContextMenu();
|
||||
ContextMenuButton b;
|
||||
b = cm.AddButton("Open", () => Editor.Instance.ContentEditing.Open(assetItem));
|
||||
cm.AddButton("Show in content window", () => Editor.Instance.Windows.ContentWin.Select(assetItem));
|
||||
cm.AddButton("Show in explorer", () => FileSystem.ShowFileExplorer(System.IO.Path.GetDirectoryName(assetItem.Path)));
|
||||
cm.AddButton("Select actors using this asset", () => Editor.Instance.SceneEditing.SelectActorsUsingAsset(assetItem.ID));
|
||||
cm.AddButton("Show asset references graph", () => Editor.Instance.Windows.Open(new AssetReferencesGraphWindow(Editor.Instance, assetItem)));
|
||||
cm.AddButton("Copy name", () => Clipboard.Text = assetItem.NamePath);
|
||||
cm.AddButton("Copy path", () => Clipboard.Text = assetItem.Path);
|
||||
cm.AddButton("Copy asset ID", () => Clipboard.Text = JsonSerializer.GetStringID(assetItem.ID));
|
||||
cm.Show(row, row.PointFromScreen(Input.MouseScreenPosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
_timelineLabelsCache?.Clear();
|
||||
_timelineEventsCache?.Clear();
|
||||
_tableRowsCache?.Clear();
|
||||
|
||||
@@ -166,7 +166,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
_timelineEventsCache?.Clear();
|
||||
_tableRowsCache?.Clear();
|
||||
|
||||
|
||||
327
Source/Editor/Windows/Profiler/MemoryGPU.cs
Normal file
327
Source/Editor/Windows/Profiler/MemoryGPU.cs
Normal file
@@ -0,0 +1,327 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
/// <summary>
|
||||
/// The GPU Memory profiling mode.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Windows.Profiler.ProfilerMode" />
|
||||
internal sealed class MemoryGPU : ProfilerMode
|
||||
{
|
||||
private struct Resource
|
||||
{
|
||||
public string Name;
|
||||
public string Tooltip;
|
||||
public GPUResourceType Type;
|
||||
public ulong MemoryUsage;
|
||||
public Guid AssetId;
|
||||
public bool IsAssetItem;
|
||||
}
|
||||
|
||||
private readonly SingleChart _memoryUsageChart;
|
||||
private readonly Table _table;
|
||||
private SamplesBuffer<Resource[]> _resources;
|
||||
private List<ClickableRow> _tableRowsCache;
|
||||
private string[] _resourceTypesNames;
|
||||
private Dictionary<string, Guid> _assetPathToId;
|
||||
private Dictionary<Guid, Resource> _resourceCache;
|
||||
private StringBuilder _stringBuilder;
|
||||
|
||||
public MemoryGPU()
|
||||
: base("GPU Memory")
|
||||
{
|
||||
// Layout
|
||||
var panel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
Parent = this,
|
||||
};
|
||||
var layout = new VerticalPanel
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
Offsets = Margin.Zero,
|
||||
IsScrollable = true,
|
||||
Parent = panel,
|
||||
};
|
||||
|
||||
// Chart
|
||||
_memoryUsageChart = new SingleChart
|
||||
{
|
||||
Title = "GPU Memory Usage",
|
||||
FormatSample = v => Utilities.Utils.FormatBytesCount((int)v),
|
||||
Parent = layout,
|
||||
};
|
||||
_memoryUsageChart.SelectedSampleChanged += OnSelectedSampleChanged;
|
||||
|
||||
// Table
|
||||
var headerColor = Style.Current.LightBackground;
|
||||
_table = new Table
|
||||
{
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
{
|
||||
UseExpandCollapseMode = true,
|
||||
CellAlignment = TextAlignment.Near,
|
||||
Title = "Resource",
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "Type",
|
||||
CellAlignment = TextAlignment.Center,
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "Memory Usage",
|
||||
TitleBackgroundColor = headerColor,
|
||||
FormatValue = v => Utilities.Utils.FormatBytesCount((ulong)v),
|
||||
},
|
||||
},
|
||||
Parent = layout,
|
||||
};
|
||||
_table.Splits = new[]
|
||||
{
|
||||
0.6f,
|
||||
0.2f,
|
||||
0.2f,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Clear()
|
||||
{
|
||||
_memoryUsageChart.Clear();
|
||||
_resources?.Clear();
|
||||
_assetPathToId?.Clear();
|
||||
_resourceCache?.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(ref SharedUpdateData sharedData)
|
||||
{
|
||||
_memoryUsageChart.AddSample(sharedData.Stats.MemoryGPU.Used);
|
||||
|
||||
if (_resourceCache == null)
|
||||
_resourceCache = new Dictionary<Guid, Resource>();
|
||||
if (_assetPathToId == null)
|
||||
_assetPathToId = new Dictionary<string, Guid>();
|
||||
if (_stringBuilder == null)
|
||||
_stringBuilder = new StringBuilder();
|
||||
|
||||
// Capture current GPU resources usage info
|
||||
var contentDatabase = Editor.Instance.ContentDatabase;
|
||||
var gpuResources = GPUDevice.Instance.Resources;
|
||||
var resources = new Resource[gpuResources.Length];
|
||||
var sb = _stringBuilder;
|
||||
for (int i = 0; i < resources.Length; i++)
|
||||
{
|
||||
var gpuResource = gpuResources[i];
|
||||
|
||||
// Try to reuse cached resource info
|
||||
var gpuResourceId = gpuResource.ID;
|
||||
if (!_resourceCache.TryGetValue(gpuResourceId, out var resource))
|
||||
{
|
||||
resource = new Resource
|
||||
{
|
||||
Name = gpuResource.Name,
|
||||
Type = gpuResource.ResourceType,
|
||||
};
|
||||
|
||||
// Create tooltip
|
||||
sb.Clear();
|
||||
if (gpuResource is GPUTexture gpuTexture)
|
||||
{
|
||||
var desc = gpuTexture.Description;
|
||||
sb.Append("Format: ").Append(desc.Format).AppendLine();
|
||||
sb.Append("Size: ").Append(desc.Width).Append('x').Append(desc.Height);
|
||||
if (desc.Depth != 1)
|
||||
sb.Append('x').Append(desc.Depth);
|
||||
if (desc.ArraySize != 1)
|
||||
sb.Append('[').Append(desc.ArraySize).Append(']');
|
||||
sb.AppendLine();
|
||||
sb.Append("Mip Levels: ").Append(desc.MipLevels).AppendLine();
|
||||
if (desc.IsMultiSample)
|
||||
sb.Append("MSAA: ").Append('x').Append((int)desc.MultiSampleLevel).AppendLine();
|
||||
sb.Append("Flags: ").Append(desc.Flags).AppendLine();
|
||||
sb.Append("Usage: ").Append(desc.Usage);
|
||||
}
|
||||
else if (gpuResource is GPUBuffer gpuBuffer)
|
||||
{
|
||||
var desc = gpuBuffer.Description;
|
||||
sb.Append("Format: ").Append(desc.Format).AppendLine();
|
||||
sb.Append("Stride: ").Append(desc.Stride).AppendLine();
|
||||
sb.Append("Elements: ").Append(desc.ElementsCount).AppendLine();
|
||||
sb.Append("Flags: ").Append(desc.Flags).AppendLine();
|
||||
sb.Append("Usage: ").Append(desc.Usage);
|
||||
}
|
||||
resource.Tooltip = _stringBuilder.ToString();
|
||||
|
||||
// Detect asset path in the resource name
|
||||
int ext = resource.Name.LastIndexOf(".flax", StringComparison.OrdinalIgnoreCase);
|
||||
if (ext != -1)
|
||||
{
|
||||
var assetPath = resource.Name.Substring(0, ext + 5);
|
||||
if (!_assetPathToId.TryGetValue(assetPath, out resource.AssetId))
|
||||
{
|
||||
var asset = FlaxEngine.Content.GetAsset(assetPath);
|
||||
if (asset != null)
|
||||
resource.AssetId = asset.ID;
|
||||
_assetPathToId.Add(assetPath, resource.AssetId);
|
||||
}
|
||||
var assetItem = contentDatabase.FindAsset(resource.AssetId);
|
||||
if (assetItem != null)
|
||||
{
|
||||
resource.IsAssetItem = true;
|
||||
resource.Name = assetItem.NamePath + resource.Name.Substring(ext + 5); // Use text after asset path to display (eg. subobject)
|
||||
}
|
||||
}
|
||||
|
||||
_resourceCache.Add(gpuResourceId, resource);
|
||||
}
|
||||
|
||||
resource.MemoryUsage = gpuResource.MemoryUsage;
|
||||
if (resource.MemoryUsage == 1)
|
||||
resource.MemoryUsage = 0; // Sometimes GPU backend fakes memory usage as 1 to mark as allocated but not resided in actual GPU memory
|
||||
resources[i] = resource;
|
||||
}
|
||||
Array.Sort(resources, SortResources);
|
||||
if (_resources == null)
|
||||
_resources = new SamplesBuffer<Resource[]>();
|
||||
_resources.Add(resources);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents)
|
||||
{
|
||||
_memoryUsageChart.SelectedSampleIndex = selectedFrame;
|
||||
|
||||
if (_resources == null)
|
||||
return;
|
||||
if (_tableRowsCache == null)
|
||||
_tableRowsCache = new List<ClickableRow>();
|
||||
if (_resourceTypesNames == null)
|
||||
_resourceTypesNames = new string[(int)GPUResourceType.MAX]
|
||||
{
|
||||
"Render Target",
|
||||
"Texture",
|
||||
"Cube Texture",
|
||||
"Volume Texture",
|
||||
"Buffer",
|
||||
"Shader",
|
||||
"Pipeline State",
|
||||
"Descriptor",
|
||||
"Query",
|
||||
"Sampler",
|
||||
};
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
_resources?.Clear();
|
||||
_resourceCache?.Clear();
|
||||
_assetPathToId?.Clear();
|
||||
_tableRowsCache?.Clear();
|
||||
_stringBuilder?.Clear();
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
private static int SortResources(Resource a, Resource b)
|
||||
{
|
||||
return (int)(b.MemoryUsage - a.MemoryUsage);
|
||||
}
|
||||
|
||||
private void UpdateTable()
|
||||
{
|
||||
_table.IsLayoutLocked = true;
|
||||
int idx = 0;
|
||||
while (_table.Children.Count > idx)
|
||||
{
|
||||
var child = _table.Children[idx];
|
||||
if (child is ClickableRow row)
|
||||
{
|
||||
_tableRowsCache.Add(row);
|
||||
child.Parent = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
_table.LockChildrenRecursive();
|
||||
|
||||
UpdateTableInner();
|
||||
|
||||
_table.UnlockChildrenRecursive();
|
||||
_table.PerformLayout();
|
||||
}
|
||||
|
||||
private void UpdateTableInner()
|
||||
{
|
||||
if (_resources.Count == 0)
|
||||
return;
|
||||
var resources = _resources.Get(_memoryUsageChart.SelectedSampleIndex);
|
||||
if (resources == null || resources.Length == 0)
|
||||
return;
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
for (int i = 0; i < resources.Length; i++)
|
||||
{
|
||||
ref var e = ref resources[i];
|
||||
|
||||
ClickableRow row;
|
||||
if (_tableRowsCache.Count != 0)
|
||||
{
|
||||
// Reuse row
|
||||
var last = _tableRowsCache.Count - 1;
|
||||
row = _tableRowsCache[last];
|
||||
_tableRowsCache.RemoveAt(last);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate new row
|
||||
row = new ClickableRow { Values = new object[3] };
|
||||
}
|
||||
|
||||
// Setup row data
|
||||
row.Values[0] = e.Name;
|
||||
row.Values[1] = _resourceTypesNames[(int)e.Type];
|
||||
row.Values[2] = e.MemoryUsage;
|
||||
|
||||
// Setup row interactions
|
||||
row.Tag = e;
|
||||
row.TooltipText = e.Tooltip;
|
||||
row.RowDoubleClick = null;
|
||||
if (e.IsAssetItem)
|
||||
{
|
||||
row.RowDoubleClick = OnRowDoubleClickAsset;
|
||||
}
|
||||
|
||||
// Add row to the table
|
||||
row.Width = _table.Width;
|
||||
row.BackgroundColor = i % 2 == 0 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRowDoubleClickAsset(ClickableRow row)
|
||||
{
|
||||
var e = (Resource)row.Tag;
|
||||
var assetItem = Editor.Instance.ContentDatabase.FindAsset(e.AssetId);
|
||||
Editor.Instance.ContentEditing.Open(assetItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
87
Source/Editor/Windows/Profiler/Network.cs
Normal file
87
Source/Editor/Windows/Profiler/Network.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
/// <summary>
|
||||
/// The network profiling mode.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Windows.Profiler.ProfilerMode" />
|
||||
internal sealed class Network : ProfilerMode
|
||||
{
|
||||
private readonly SingleChart _dataSentChart;
|
||||
private readonly SingleChart _dataReceivedChart;
|
||||
private FlaxEngine.Networking.NetworkDriverStats _prevStats;
|
||||
|
||||
public Network()
|
||||
: base("Network")
|
||||
{
|
||||
// Layout
|
||||
var panel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
Parent = this,
|
||||
};
|
||||
var layout = new VerticalPanel
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
Offsets = Margin.Zero,
|
||||
IsScrollable = true,
|
||||
Parent = panel,
|
||||
};
|
||||
|
||||
// Charts
|
||||
_dataSentChart = new SingleChart
|
||||
{
|
||||
Title = "Data Sent",
|
||||
FormatSample = FormatSampleBytes,
|
||||
Parent = layout,
|
||||
};
|
||||
_dataSentChart.SelectedSampleChanged += OnSelectedSampleChanged;
|
||||
_dataReceivedChart = new SingleChart
|
||||
{
|
||||
Title = "Data Received",
|
||||
FormatSample = FormatSampleBytes,
|
||||
Parent = layout,
|
||||
};
|
||||
_dataReceivedChart.SelectedSampleChanged += OnSelectedSampleChanged;
|
||||
}
|
||||
|
||||
private static string FormatSampleBytes(float v)
|
||||
{
|
||||
return (uint)v + " bytes";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Clear()
|
||||
{
|
||||
_dataSentChart.Clear();
|
||||
_dataReceivedChart.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(ref SharedUpdateData sharedData)
|
||||
{
|
||||
var peer = FlaxEngine.Networking.NetworkManager.Peer;
|
||||
if (peer == null)
|
||||
{
|
||||
_prevStats = new FlaxEngine.Networking.NetworkDriverStats();
|
||||
return;
|
||||
}
|
||||
var stats = peer.NetworkDriver.GetStats();
|
||||
_dataSentChart.AddSample(Mathf.Max((long)stats.TotalDataSent - (long)_prevStats.TotalDataSent, 0));
|
||||
_dataReceivedChart.AddSample(Mathf.Max((long)stats.TotalDataReceived - (long)_prevStats.TotalDataReceived, 0));
|
||||
_prevStats = stats;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents)
|
||||
{
|
||||
_dataSentChart.SelectedSampleIndex = selectedFrame;
|
||||
_dataReceivedChart.SelectedSampleIndex = selectedFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,14 @@ namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this instance.
|
||||
/// </summary>
|
||||
|
||||
@@ -52,10 +52,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
if (_frameIndex != value)
|
||||
{
|
||||
_frameIndex = value;
|
||||
|
||||
UpdateButtons();
|
||||
if (_tabs.SelectedTab is ProfilerMode mode)
|
||||
mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents);
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,10 +69,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
if (_showOnlyLastUpdateEvents != value)
|
||||
{
|
||||
_showOnlyLastUpdateEvents = value;
|
||||
|
||||
UpdateButtons();
|
||||
if (_tabs.SelectedTab is ProfilerMode mode)
|
||||
mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents);
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,7 +148,9 @@ namespace FlaxEditor.Windows.Profiler
|
||||
if (_tabs.Children[i] is ProfilerMode mode)
|
||||
{
|
||||
mode.Clear();
|
||||
FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView");
|
||||
mode.UpdateView(ViewFrameIndex, _showOnlyLastUpdateEvents);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +160,11 @@ namespace FlaxEditor.Windows.Profiler
|
||||
private void OnSelectedTabChanged(Tabs tabs)
|
||||
{
|
||||
if (tabs.SelectedTab is ProfilerMode mode)
|
||||
{
|
||||
FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView");
|
||||
mode.UpdateView(ViewFrameIndex, _showOnlyLastUpdateEvents);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateButtons()
|
||||
@@ -174,6 +176,16 @@ namespace FlaxEditor.Windows.Profiler
|
||||
_showOnlyLastUpdateEventsButton.Checked = _showOnlyLastUpdateEvents;
|
||||
}
|
||||
|
||||
private void UpdateView()
|
||||
{
|
||||
if (_tabs.SelectedTab is ProfilerMode mode)
|
||||
{
|
||||
FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView");
|
||||
mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnInit()
|
||||
{
|
||||
@@ -181,7 +193,10 @@ namespace FlaxEditor.Windows.Profiler
|
||||
AddMode(new Overall());
|
||||
AddMode(new CPU());
|
||||
AddMode(new GPU());
|
||||
AddMode(new MemoryGPU());
|
||||
AddMode(new Memory());
|
||||
AddMode(new Assets());
|
||||
AddMode(new Network());
|
||||
|
||||
// Init view
|
||||
_frameIndex = -1;
|
||||
@@ -192,6 +207,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
}
|
||||
|
||||
UpdateButtons();
|
||||
|
||||
ScriptsBuilder.ScriptsReloadEnd += Clear; // Prevent crashes if any of the profiler tabs has some scripting types cached (eg. asset type info)
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -206,11 +223,19 @@ namespace FlaxEditor.Windows.Profiler
|
||||
for (int i = 0; i < _tabs.ChildrenCount; i++)
|
||||
{
|
||||
if (_tabs.Children[i] is ProfilerMode mode)
|
||||
{
|
||||
FlaxEngine.Profiler.BeginEvent(mode.GetType().FullName);
|
||||
mode.Update(ref sharedData);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
{
|
||||
if (_tabs.SelectedTab is ProfilerMode mode)
|
||||
{
|
||||
FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView");
|
||||
mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
sharedData.End();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user