From f177d9c73594d5e84eeceacc1579acf054c50448 Mon Sep 17 00:00:00 2001 From: Andy Adshead Date: Mon, 28 Jan 2019 17:25:12 +0000 Subject: [PATCH] Profile window was getting too long so I added regions and split bar rendering out into partial class --- Ryujinx.Profiler/UI/ProfileWindow.cs | 190 ++++++++--------------- Ryujinx.Profiler/UI/ProfileWindowBars.cs | 84 ++++++++++ 2 files changed, 152 insertions(+), 122 deletions(-) create mode 100644 Ryujinx.Profiler/UI/ProfileWindowBars.cs diff --git a/Ryujinx.Profiler/UI/ProfileWindow.cs b/Ryujinx.Profiler/UI/ProfileWindow.cs index 0555c8be60..5b36e377c5 100644 --- a/Ryujinx.Profiler/UI/ProfileWindow.cs +++ b/Ryujinx.Profiler/UI/ProfileWindow.cs @@ -1,18 +1,16 @@ -using OpenTK; -using OpenTK.Graphics.OpenGL; -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text.RegularExpressions; +using OpenTK; +using OpenTK.Graphics.OpenGL; using OpenTK.Input; -using Ryujinx.Profiler; -using Ryujinx.Profiler.UI; using Ryujinx.Profiler.UI.SharpFontHelpers; -namespace Ryujinx +namespace Ryujinx.Profiler.UI { - public class ProfileWindow : GameWindow + public partial class ProfileWindow : GameWindow { // List all buttons for index in button array private enum ButtonIndex @@ -45,6 +43,14 @@ namespace Ryujinx private bool _showInactive = true; private bool _paused = false; + // Layout + private const int LineHeight = 16; + private const int TitleHeight = 24; + private const int TitleFontHeight = 16; + private const int LinePadding = 2; + private const int ColumnSpacing = 30; + private const int FilterHeight = 24; + // Sorting private List> _unsortedProfileData; private IComparer> _sortAction = new ProfileSorters.TagAscending(); @@ -301,27 +307,22 @@ namespace Ryujinx _fontService.fontColor = Color.White; int verticalIndex = 0; - int lineHeight = 16; - int titleHeight = 24; - int titleFontHeight = 16; - int linePadding = 2; - int columnSpacing = 30; - int filterHeight = 24; float width; float maxWidth = 0; - float yOffset = _scrollPos - titleHeight; + float yOffset = _scrollPos - TitleHeight; float xOffset = 10; // Background lines to make reading easier + #region Background Lines GL.Enable(EnableCap.ScissorTest); - GL.Scissor(0, filterHeight, Width, Height - titleHeight - filterHeight); + GL.Scissor(0, FilterHeight, Width, Height - TitleHeight - FilterHeight); GL.Begin(PrimitiveType.Triangles); GL.Color3(0.2f, 0.2f, 0.2f); for (int i = 0; i < _sortedProfileData.Count; i += 2) { - float top = GetLineY(yOffset, lineHeight, linePadding, false, i - 1); - float bottom = GetLineY(yOffset, lineHeight, linePadding, false, i); + float top = GetLineY(yOffset, LineHeight, LinePadding, false, i - 1); + float bottom = GetLineY(yOffset, LineHeight, LinePadding, false, i); // Skip rendering out of bounds bars if (top < 0 || bottom > Height) @@ -336,14 +337,16 @@ namespace Ryujinx GL.Vertex2(0, bottom); } GL.End(); - _maxScroll = (lineHeight + linePadding) * (_sortedProfileData.Count - 1); + _maxScroll = (LineHeight + LinePadding) * (_sortedProfileData.Count - 1); + #endregion // Display category + #region Category verticalIndex = 0; foreach (var entry in _sortedProfileData) { - float y = GetLineY(yOffset, lineHeight, linePadding, true, verticalIndex++); - width = _fontService.DrawText(entry.Key.Category, xOffset, y, lineHeight); + float y = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex++); + width = _fontService.DrawText(entry.Key.Category, xOffset, y, LineHeight); if (width > maxWidth) { maxWidth = width; @@ -351,21 +354,23 @@ namespace Ryujinx } GL.Disable(EnableCap.ScissorTest); - width = _fontService.DrawText("Category", xOffset, Height - titleFontHeight, titleFontHeight); + width = _fontService.DrawText("Category", xOffset, Height - TitleFontHeight, TitleFontHeight); if (width > maxWidth) maxWidth = width; - xOffset += maxWidth + columnSpacing; + xOffset += maxWidth + ColumnSpacing; + #endregion // Display session group + #region Session Group maxWidth = 0; verticalIndex = 0; GL.Enable(EnableCap.ScissorTest); foreach (var entry in _sortedProfileData) { - float y = GetLineY(yOffset, lineHeight, linePadding, true, verticalIndex++); - width = _fontService.DrawText(entry.Key.SessionGroup, xOffset, y, lineHeight); + float y = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex++); + width = _fontService.DrawText(entry.Key.SessionGroup, xOffset, y, LineHeight); if (width > maxWidth) { maxWidth = width; @@ -373,20 +378,23 @@ namespace Ryujinx } GL.Disable(EnableCap.ScissorTest); - width = _fontService.DrawText("Group", xOffset, Height - titleFontHeight, titleFontHeight); + width = _fontService.DrawText("Group", xOffset, Height - TitleFontHeight, TitleFontHeight); if (width > maxWidth) maxWidth = width; - xOffset += maxWidth + columnSpacing; + xOffset += maxWidth + ColumnSpacing; + #endregion // Display session item + + #region Session Item maxWidth = 0; verticalIndex = 0; GL.Enable(EnableCap.ScissorTest); foreach (var entry in _sortedProfileData) { - float y = GetLineY(yOffset, lineHeight, linePadding, true, verticalIndex++); - width = _fontService.DrawText(entry.Key.SessionItem, xOffset, y, lineHeight); + float y = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex++); + width = _fontService.DrawText(entry.Key.SessionItem, xOffset, y, LineHeight); if (width > maxWidth) { maxWidth = width; @@ -394,112 +402,47 @@ namespace Ryujinx } GL.Disable(EnableCap.ScissorTest); - width = _fontService.DrawText("Item", xOffset, Height - titleFontHeight, titleFontHeight); + width = _fontService.DrawText("Item", xOffset, Height - TitleFontHeight, TitleFontHeight); if (width > maxWidth) maxWidth = width; - xOffset += maxWidth + columnSpacing; - _buttons[(int)ButtonIndex.TagTitle].UpdateSize(0, Height - titleFontHeight, 0, (int)xOffset, titleFontHeight); + xOffset += maxWidth + ColumnSpacing; + _buttons[(int)ButtonIndex.TagTitle].UpdateSize(0, Height - TitleFontHeight, 0, (int)xOffset, TitleFontHeight); + #endregion // Time bars - if (_sortedProfileData.Count != 0) - { - long maxAverage; - long maxTotal; + DrawBars(xOffset, yOffset); - float barHeight = (lineHeight - linePadding) / 3.0f; - - width = Width - xOffset - 370; - verticalIndex = 0; - - // Get max values - var maxInstant = maxAverage = maxTotal = 0; - foreach (KeyValuePair kvp in _sortedProfileData) - { - maxInstant = Math.Max(maxInstant, kvp.Value.Instant); - maxAverage = Math.Max(maxAverage, kvp.Value.AverageTime); - maxTotal = Math.Max(maxTotal, kvp.Value.TotalTime); - } - - GL.Enable(EnableCap.ScissorTest); - GL.Begin(PrimitiveType.Triangles); - foreach (var entry in _sortedProfileData) - { - // Instant - GL.Color3(Color.Blue); - float bottom = GetLineY(yOffset, lineHeight, linePadding, true, verticalIndex++); - float top = bottom + barHeight; - float right = (float) entry.Value.Instant / maxInstant * width + xOffset; - - // Skip rendering out of bounds bars - if (top < 0 || bottom > Height) - continue; - - GL.Vertex2(xOffset, bottom); - GL.Vertex2(xOffset, top); - GL.Vertex2(right, top); - - GL.Vertex2(right, top); - GL.Vertex2(right, bottom); - GL.Vertex2(xOffset, bottom); - - // Average - GL.Color3(Color.Green); - top += barHeight; - bottom += barHeight; - right = (float) entry.Value.AverageTime / maxAverage * width + xOffset; - GL.Vertex2(xOffset, bottom); - GL.Vertex2(xOffset, top); - GL.Vertex2(right, top); - - GL.Vertex2(right, top); - GL.Vertex2(right, bottom); - GL.Vertex2(xOffset, bottom); - - // Total - GL.Color3(Color.Red); - top += barHeight; - bottom += barHeight; - right = (float) entry.Value.TotalTime / maxTotal * width + xOffset; - GL.Vertex2(xOffset, bottom); - GL.Vertex2(xOffset, top); - GL.Vertex2(right, top); - - GL.Vertex2(right, top); - GL.Vertex2(right, bottom); - GL.Vertex2(xOffset, bottom); - } - - GL.End(); - GL.Disable(EnableCap.ScissorTest); - } - - _fontService.DrawText("Blue: Instant, Green: Avg, Red: Total", xOffset, Height - titleFontHeight, titleFontHeight); + _fontService.DrawText("Blue: Instant, Green: Avg, Red: Total", xOffset, Height - TitleFontHeight, TitleFontHeight); xOffset = Width - 360; // Display timestamps + + #region Timestamps verticalIndex = 0; GL.Enable(EnableCap.ScissorTest); foreach (var entry in _sortedProfileData) { - float y = GetLineY(yOffset, lineHeight, linePadding, true, verticalIndex++); - _fontService.DrawText($"{Profile.ConvertTicksToMS(entry.Value.Instant):F3} ({entry.Value.InstantCount})", xOffset, y, lineHeight); - _fontService.DrawText($"{Profile.ConvertTicksToMS(entry.Value.AverageTime):F3}", columnSpacing + 120 + xOffset, y, lineHeight); - _fontService.DrawText($"{Profile.ConvertTicksToMS(entry.Value.TotalTime):F3}", columnSpacing + columnSpacing + 200 + xOffset, y, lineHeight); + float y = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex++); + _fontService.DrawText($"{Profile.ConvertTicksToMS(entry.Value.Instant):F3} ({entry.Value.InstantCount})", xOffset, y, LineHeight); + _fontService.DrawText($"{Profile.ConvertTicksToMS(entry.Value.AverageTime):F3}", ColumnSpacing + 120 + xOffset, y, LineHeight); + _fontService.DrawText($"{Profile.ConvertTicksToMS(entry.Value.TotalTime):F3}", ColumnSpacing + ColumnSpacing + 200 + xOffset, y, LineHeight); } GL.Disable(EnableCap.ScissorTest); - float yHeight = Height - titleFontHeight; + float yHeight = Height - TitleFontHeight; - _fontService.DrawText("Instant (ms, count)", xOffset, yHeight, titleFontHeight); - _buttons[(int)ButtonIndex.InstantTitle].UpdateSize((int)xOffset, (int)yHeight, 0, (int)(columnSpacing + 100), titleFontHeight); + _fontService.DrawText("Instant (ms, count)", xOffset, yHeight, TitleFontHeight); + _buttons[(int)ButtonIndex.InstantTitle].UpdateSize((int)xOffset, (int)yHeight, 0, (int)(ColumnSpacing + 100), TitleFontHeight); - _fontService.DrawText("Average (ms)", columnSpacing + 120 + xOffset, yHeight, titleFontHeight); - _buttons[(int)ButtonIndex.AverageTitle].UpdateSize((int)(columnSpacing + 120 + xOffset), (int)yHeight, 0, (int)(columnSpacing + 100), titleFontHeight); + _fontService.DrawText("Average (ms)", ColumnSpacing + 120 + xOffset, yHeight, TitleFontHeight); + _buttons[(int)ButtonIndex.AverageTitle].UpdateSize((int)(ColumnSpacing + 120 + xOffset), (int)yHeight, 0, (int)(ColumnSpacing + 100), TitleFontHeight); - _fontService.DrawText("Total (ms)", columnSpacing + columnSpacing + 200 + xOffset, yHeight, titleFontHeight); - _buttons[(int)ButtonIndex.TotalTitle].UpdateSize((int)(columnSpacing + columnSpacing + 200 + xOffset), (int)yHeight, 0, Width, titleFontHeight); + _fontService.DrawText("Total (ms)", ColumnSpacing + ColumnSpacing + 200 + xOffset, yHeight, TitleFontHeight); + _buttons[(int)ButtonIndex.TotalTitle].UpdateSize((int)(ColumnSpacing + ColumnSpacing + 200 + xOffset), (int)yHeight, 0, Width, TitleFontHeight); + #endregion + #region Bottom bar // Show/Hide Inactive float widthShowHideButton = _buttons[(int)ButtonIndex.ShowHideInactive].UpdateSize($"{(_showInactive ? "Hide" : "Show")} Inactive", 5, 5, 4, 16); @@ -508,32 +451,35 @@ namespace Ryujinx // Filter bar _fontService.DrawText($"{(_regexEnabled ? "Regex " : "Filter")}: {_filterText}", 25 + width, 7, 16); - _buttons[(int) ButtonIndex.FilterBar].UpdateSize((int)(25 + width), 0, 0, Width, filterHeight); + _buttons[(int) ButtonIndex.FilterBar].UpdateSize((int)(25 + width), 0, 0, Width, FilterHeight); + #endregion // Draw buttons foreach (ProfileButton button in _buttons) { button.Draw(); } - + // Dividing lines + #region Dividing lines GL.Color3(Color.White); GL.Begin(PrimitiveType.Lines); // Top divider - GL.Vertex2(0, Height -titleHeight); - GL.Vertex2(Width, Height - titleHeight); + GL.Vertex2(0, Height -TitleHeight); + GL.Vertex2(Width, Height - TitleHeight); // Bottom divider - GL.Vertex2(0, filterHeight); - GL.Vertex2(Width, filterHeight); + GL.Vertex2(0, FilterHeight); + GL.Vertex2(Width, FilterHeight); // Bottom vertical divider GL.Vertex2(widthShowHideButton + 10, 0); - GL.Vertex2(widthShowHideButton + 10, filterHeight); + GL.Vertex2(widthShowHideButton + 10, FilterHeight); GL.Vertex2(width + 20, 0); - GL.Vertex2(width + 20, filterHeight); + GL.Vertex2(width + 20, FilterHeight); GL.End(); + #endregion _redrawPending = false; SwapBuffers(); diff --git a/Ryujinx.Profiler/UI/ProfileWindowBars.cs b/Ryujinx.Profiler/UI/ProfileWindowBars.cs new file mode 100644 index 0000000000..fee9b17b9c --- /dev/null +++ b/Ryujinx.Profiler/UI/ProfileWindowBars.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using OpenTK; +using OpenTK.Graphics.OpenGL; + +namespace Ryujinx.Profiler.UI +{ + public partial class ProfileWindow + { + private void DrawBars(float xOffset, float yOffset) + { + if (_sortedProfileData.Count != 0) + { + long maxAverage; + long maxTotal; + + int verticalIndex = 0; + float barHeight = (LineHeight - LinePadding) / 3.0f; + float width = Width - xOffset - 370; + + // Get max values + var maxInstant = maxAverage = maxTotal = 0; + foreach (KeyValuePair kvp in _sortedProfileData) + { + maxInstant = Math.Max(maxInstant, kvp.Value.Instant); + maxAverage = Math.Max(maxAverage, kvp.Value.AverageTime); + maxTotal = Math.Max(maxTotal, kvp.Value.TotalTime); + } + + GL.Enable(EnableCap.ScissorTest); + GL.Begin(PrimitiveType.Triangles); + foreach (var entry in _sortedProfileData) + { + // Instant + GL.Color3(Color.Blue); + float bottom = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex++); + float top = bottom + barHeight; + float right = (float)entry.Value.Instant / maxInstant * width + xOffset; + + // Skip rendering out of bounds bars + if (top < 0 || bottom > Height) + continue; + + GL.Vertex2(xOffset, bottom); + GL.Vertex2(xOffset, top); + GL.Vertex2(right, top); + + GL.Vertex2(right, top); + GL.Vertex2(right, bottom); + GL.Vertex2(xOffset, bottom); + + // Average + GL.Color3(Color.Green); + top += barHeight; + bottom += barHeight; + right = (float)entry.Value.AverageTime / maxAverage * width + xOffset; + GL.Vertex2(xOffset, bottom); + GL.Vertex2(xOffset, top); + GL.Vertex2(right, top); + + GL.Vertex2(right, top); + GL.Vertex2(right, bottom); + GL.Vertex2(xOffset, bottom); + + // Total + GL.Color3(Color.Red); + top += barHeight; + bottom += barHeight; + right = (float)entry.Value.TotalTime / maxTotal * width + xOffset; + GL.Vertex2(xOffset, bottom); + GL.Vertex2(xOffset, top); + GL.Vertex2(right, top); + + GL.Vertex2(right, top); + GL.Vertex2(right, bottom); + GL.Vertex2(xOffset, bottom); + } + + GL.End(); + GL.Disable(EnableCap.ScissorTest); + } + } + } +}