forked from Mirror/Ryujinx
Remove the Ryujinx.Debugger project (#1506)
This project wasn't really used by anyone and isn't worth mantaining. This commit remove the profiler entirely from Ryujinx and remove the associated CI tasks.
This commit is contained in:
parent
b9398f1f3a
commit
4f3ae6f62c
33 changed files with 10 additions and 2468 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -13,7 +13,7 @@ jobs:
|
|||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
dotnet: ['3.1.100']
|
||||
environment: ['Debug', 'Release', 'Profile Debug', 'Profile Release']
|
||||
environment: ['Debug', 'Release']
|
||||
name: ${{ matrix.environment }} build (Dotnet ${{ matrix.dotnet }}, OS ${{ matrix.os }})
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
|
|
@ -14,15 +14,6 @@
|
|||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -3,29 +3,17 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;USE_PROFILING</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;USE_PROFILING</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.6.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -4,29 +4,17 @@
|
|||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -4,29 +4,17 @@
|
|||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageReference Include="System.Management" Version="4.7.0" />
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
using System;
|
||||
using Ryujinx.Debugger.UI;
|
||||
|
||||
namespace Ryujinx.Debugger
|
||||
{
|
||||
public class Debugger : IDisposable
|
||||
{
|
||||
public DebuggerWidget Widget { get; set; }
|
||||
|
||||
public Debugger()
|
||||
{
|
||||
Widget = new DebuggerWidget();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
Widget.Enable();
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
Widget.Disable();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
|
||||
Widget.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
using Ryujinx.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public static class DumpProfile
|
||||
{
|
||||
public static void ToFile(string path, InternalProfile profile)
|
||||
{
|
||||
String fileData = "Category,Session Group,Session Item,Count,Average(ms),Total(ms)\r\n";
|
||||
|
||||
foreach (KeyValuePair<ProfileConfig, TimingInfo> time in profile.Timers.OrderBy(key => key.Key.Tag))
|
||||
{
|
||||
fileData += $"{time.Key.Category}," +
|
||||
$"{time.Key.SessionGroup}," +
|
||||
$"{time.Key.SessionItem}," +
|
||||
$"{time.Value.Count}," +
|
||||
$"{time.Value.AverageTime / PerformanceCounter.TicksPerMillisecond}," +
|
||||
$"{time.Value.TotalTime / PerformanceCounter.TicksPerMillisecond}\r\n";
|
||||
}
|
||||
|
||||
// Ensure file directory exists before write
|
||||
FileInfo fileInfo = new FileInfo(path);
|
||||
if (fileInfo == null)
|
||||
throw new Exception("Unknown logging error, probably a bad file path");
|
||||
if (fileInfo.Directory != null && !fileInfo.Directory.Exists)
|
||||
Directory.CreateDirectory(fileInfo.Directory.FullName);
|
||||
|
||||
File.WriteAllText(fileInfo.FullName, fileData);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
using Ryujinx.Common;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public class InternalProfile
|
||||
{
|
||||
private struct TimerQueueValue
|
||||
{
|
||||
public ProfileConfig Config;
|
||||
public long Time;
|
||||
public bool IsBegin;
|
||||
}
|
||||
|
||||
internal Dictionary<ProfileConfig, TimingInfo> Timers { get; set; }
|
||||
|
||||
private readonly object _timerQueueClearLock = new object();
|
||||
private ConcurrentQueue<TimerQueueValue> _timerQueue;
|
||||
|
||||
private int _sessionCounter = 0;
|
||||
|
||||
// Cleanup thread
|
||||
private readonly Thread _cleanupThread;
|
||||
private bool _cleanupRunning;
|
||||
private readonly long _history;
|
||||
private long _preserve;
|
||||
|
||||
// Timing flags
|
||||
private TimingFlag[] _timingFlags;
|
||||
private long[] _timingFlagAverages;
|
||||
private long[] _timingFlagLast;
|
||||
private long[] _timingFlagLastDelta;
|
||||
private int _timingFlagCount;
|
||||
private int _timingFlagIndex;
|
||||
|
||||
private int _maxFlags;
|
||||
|
||||
private Action<TimingFlag> _timingFlagCallback;
|
||||
|
||||
public InternalProfile(long history, int maxFlags)
|
||||
{
|
||||
_maxFlags = maxFlags;
|
||||
Timers = new Dictionary<ProfileConfig, TimingInfo>();
|
||||
_timingFlags = new TimingFlag[_maxFlags];
|
||||
_timingFlagAverages = new long[(int)TimingFlagType.Count];
|
||||
_timingFlagLast = new long[(int)TimingFlagType.Count];
|
||||
_timingFlagLastDelta = new long[(int)TimingFlagType.Count];
|
||||
_timerQueue = new ConcurrentQueue<TimerQueueValue>();
|
||||
_history = history;
|
||||
_cleanupRunning = true;
|
||||
|
||||
// Create cleanup thread.
|
||||
_cleanupThread = new Thread(CleanupLoop)
|
||||
{
|
||||
Name = "Profiler.CleanupThread"
|
||||
};
|
||||
_cleanupThread.Start();
|
||||
}
|
||||
|
||||
private void CleanupLoop()
|
||||
{
|
||||
bool queueCleared = false;
|
||||
|
||||
while (_cleanupRunning)
|
||||
{
|
||||
// Ensure we only ever have 1 instance modifying timers or timerQueue
|
||||
if (Monitor.TryEnter(_timerQueueClearLock))
|
||||
{
|
||||
queueCleared = ClearTimerQueue();
|
||||
|
||||
// Calculate before foreach to mitigate redundant calculations
|
||||
long cleanupBefore = PerformanceCounter.ElapsedTicks - _history;
|
||||
long preserveStart = _preserve - _history;
|
||||
|
||||
// Each cleanup is self contained so run in parallel for maximum efficiency
|
||||
Parallel.ForEach(Timers, (t) => t.Value.Cleanup(cleanupBefore, preserveStart, _preserve));
|
||||
|
||||
Monitor.Exit(_timerQueueClearLock);
|
||||
}
|
||||
|
||||
// Only sleep if queue was successfully cleared
|
||||
if (queueCleared)
|
||||
{
|
||||
Thread.Sleep(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ClearTimerQueue()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while (_timerQueue.TryDequeue(out TimerQueueValue item))
|
||||
{
|
||||
if (!Timers.TryGetValue(item.Config, out TimingInfo value))
|
||||
{
|
||||
value = new TimingInfo();
|
||||
Timers.Add(item.Config, value);
|
||||
}
|
||||
|
||||
if (item.IsBegin)
|
||||
{
|
||||
value.Begin(item.Time);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.End(item.Time);
|
||||
}
|
||||
|
||||
// Don't block for too long as memory disposal is blocked while this function runs
|
||||
if (count++ > 10000)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void FlagTime(TimingFlagType flagType)
|
||||
{
|
||||
int flagId = (int)flagType;
|
||||
|
||||
_timingFlags[_timingFlagIndex] = new TimingFlag()
|
||||
{
|
||||
FlagType = flagType,
|
||||
Timestamp = PerformanceCounter.ElapsedTicks
|
||||
};
|
||||
|
||||
_timingFlagCount = Math.Max(_timingFlagCount + 1, _maxFlags);
|
||||
|
||||
// Work out average
|
||||
if (_timingFlagLast[flagId] != 0)
|
||||
{
|
||||
_timingFlagLastDelta[flagId] = _timingFlags[_timingFlagIndex].Timestamp - _timingFlagLast[flagId];
|
||||
_timingFlagAverages[flagId] = (_timingFlagAverages[flagId] == 0) ? _timingFlagLastDelta[flagId] :
|
||||
(_timingFlagLastDelta[flagId] + _timingFlagAverages[flagId]) >> 1;
|
||||
}
|
||||
_timingFlagLast[flagId] = _timingFlags[_timingFlagIndex].Timestamp;
|
||||
|
||||
// Notify subscribers
|
||||
_timingFlagCallback?.Invoke(_timingFlags[_timingFlagIndex]);
|
||||
|
||||
if (++_timingFlagIndex >= _maxFlags)
|
||||
{
|
||||
_timingFlagIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void BeginProfile(ProfileConfig config)
|
||||
{
|
||||
_timerQueue.Enqueue(new TimerQueueValue()
|
||||
{
|
||||
Config = config,
|
||||
IsBegin = true,
|
||||
Time = PerformanceCounter.ElapsedTicks,
|
||||
});
|
||||
}
|
||||
|
||||
public void EndProfile(ProfileConfig config)
|
||||
{
|
||||
_timerQueue.Enqueue(new TimerQueueValue()
|
||||
{
|
||||
Config = config,
|
||||
IsBegin = false,
|
||||
Time = PerformanceCounter.ElapsedTicks,
|
||||
});
|
||||
}
|
||||
|
||||
public string GetSession()
|
||||
{
|
||||
// Can be called from multiple threads so we need to ensure no duplicate sessions are generated
|
||||
return Interlocked.Increment(ref _sessionCounter).ToString();
|
||||
}
|
||||
|
||||
public List<KeyValuePair<ProfileConfig, TimingInfo>> GetProfilingData()
|
||||
{
|
||||
_preserve = PerformanceCounter.ElapsedTicks;
|
||||
|
||||
lock (_timerQueueClearLock)
|
||||
{
|
||||
ClearTimerQueue();
|
||||
return Timers.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public TimingFlag[] GetTimingFlags()
|
||||
{
|
||||
int count = Math.Max(_timingFlagCount, _maxFlags);
|
||||
TimingFlag[] outFlags = new TimingFlag[count];
|
||||
|
||||
for (int i = 0, sourceIndex = _timingFlagIndex; i < count; i++, sourceIndex++)
|
||||
{
|
||||
if (sourceIndex >= _maxFlags)
|
||||
sourceIndex = 0;
|
||||
outFlags[i] = _timingFlags[sourceIndex];
|
||||
}
|
||||
|
||||
return outFlags;
|
||||
}
|
||||
|
||||
public (long[], long[]) GetTimingAveragesAndLast()
|
||||
{
|
||||
return (_timingFlagAverages, _timingFlagLastDelta);
|
||||
}
|
||||
|
||||
public void RegisterFlagReceiver(Action<TimingFlag> receiver)
|
||||
{
|
||||
_timingFlagCallback = receiver;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cleanupRunning = false;
|
||||
_cleanupThread.Join();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
using Ryujinx.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public static class Profile
|
||||
{
|
||||
public static float UpdateRate => _settings.UpdateRate;
|
||||
public static long HistoryLength => _settings.History;
|
||||
|
||||
#pragma warning disable CS0649
|
||||
private static InternalProfile _profileInstance;
|
||||
#pragma warning restore CS0649
|
||||
private static ProfilerSettings _settings;
|
||||
|
||||
[Conditional("USE_DEBUGGING")]
|
||||
public static void Initialize()
|
||||
{
|
||||
var config = ProfilerConfiguration.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ProfilerConfig.jsonc"));
|
||||
|
||||
_settings = new ProfilerSettings()
|
||||
{
|
||||
Enabled = config.Enabled,
|
||||
FileDumpEnabled = config.DumpPath != "",
|
||||
DumpLocation = config.DumpPath,
|
||||
UpdateRate = (config.UpdateRate <= 0) ? -1 : 1.0f / config.UpdateRate,
|
||||
History = (long)(config.History * PerformanceCounter.TicksPerSecond),
|
||||
MaxLevel = config.MaxLevel,
|
||||
MaxFlags = config.MaxFlags,
|
||||
};
|
||||
}
|
||||
|
||||
public static bool ProfilingEnabled()
|
||||
{
|
||||
#if USE_DEBUGGING
|
||||
if (!_settings.Enabled)
|
||||
return false;
|
||||
|
||||
if (_profileInstance == null)
|
||||
_profileInstance = new InternalProfile(_settings.History, _settings.MaxFlags);
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
[Conditional("USE_DEBUGGING")]
|
||||
public static void FinishProfiling()
|
||||
{
|
||||
if (!ProfilingEnabled())
|
||||
return;
|
||||
|
||||
if (_settings.FileDumpEnabled)
|
||||
DumpProfile.ToFile(_settings.DumpLocation, _profileInstance);
|
||||
|
||||
_profileInstance.Dispose();
|
||||
}
|
||||
|
||||
[Conditional("USE_DEBUGGING")]
|
||||
public static void FlagTime(TimingFlagType flagType)
|
||||
{
|
||||
if (!ProfilingEnabled())
|
||||
return;
|
||||
_profileInstance.FlagTime(flagType);
|
||||
}
|
||||
|
||||
[Conditional("USE_DEBUGGING")]
|
||||
public static void RegisterFlagReceiver(Action<TimingFlag> receiver)
|
||||
{
|
||||
if (!ProfilingEnabled())
|
||||
return;
|
||||
_profileInstance.RegisterFlagReceiver(receiver);
|
||||
}
|
||||
|
||||
[Conditional("USE_DEBUGGING")]
|
||||
public static void Begin(ProfileConfig config)
|
||||
{
|
||||
if (!ProfilingEnabled())
|
||||
return;
|
||||
if (config.Level > _settings.MaxLevel)
|
||||
return;
|
||||
_profileInstance.BeginProfile(config);
|
||||
}
|
||||
|
||||
[Conditional("USE_DEBUGGING")]
|
||||
public static void End(ProfileConfig config)
|
||||
{
|
||||
if (!ProfilingEnabled())
|
||||
return;
|
||||
if (config.Level > _settings.MaxLevel)
|
||||
return;
|
||||
_profileInstance.EndProfile(config);
|
||||
}
|
||||
|
||||
public static string GetSession()
|
||||
{
|
||||
#if USE_DEBUGGING
|
||||
if (!ProfilingEnabled())
|
||||
return null;
|
||||
return _profileInstance.GetSession();
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
public static List<KeyValuePair<ProfileConfig, TimingInfo>> GetProfilingData()
|
||||
{
|
||||
#if USE_DEBUGGING
|
||||
if (!ProfilingEnabled())
|
||||
return new List<KeyValuePair<ProfileConfig, TimingInfo>>();
|
||||
return _profileInstance.GetProfilingData();
|
||||
#else
|
||||
return new List<KeyValuePair<ProfileConfig, TimingInfo>>();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static TimingFlag[] GetTimingFlags()
|
||||
{
|
||||
#if USE_DEBUGGING
|
||||
if (!ProfilingEnabled())
|
||||
return new TimingFlag[0];
|
||||
return _profileInstance.GetTimingFlags();
|
||||
#else
|
||||
return new TimingFlag[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
public static (long[], long[]) GetTimingAveragesAndLast()
|
||||
{
|
||||
#if USE_DEBUGGING
|
||||
if (!ProfilingEnabled())
|
||||
return (new long[0], new long[0]);
|
||||
return _profileInstance.GetTimingAveragesAndLast();
|
||||
#else
|
||||
return (new long[0], new long[0]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,254 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public struct ProfileConfig : IEquatable<ProfileConfig>
|
||||
{
|
||||
public string Category;
|
||||
public string SessionGroup;
|
||||
public string SessionItem;
|
||||
|
||||
public int Level;
|
||||
|
||||
// Private cached variables
|
||||
private string _cachedTag;
|
||||
private string _cachedSession;
|
||||
private string _cachedSearch;
|
||||
|
||||
// Public helpers to get config in more user friendly format,
|
||||
// Cached because they never change and are called often
|
||||
public string Search
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_cachedSearch == null)
|
||||
{
|
||||
_cachedSearch = $"{Category}.{SessionGroup}.{SessionItem}";
|
||||
}
|
||||
|
||||
return _cachedSearch;
|
||||
}
|
||||
}
|
||||
|
||||
public string Tag
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_cachedTag == null)
|
||||
_cachedTag = $"{Category}{(Session == "" ? "" : $" ({Session})")}";
|
||||
return _cachedTag;
|
||||
}
|
||||
}
|
||||
|
||||
public string Session
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_cachedSession == null)
|
||||
{
|
||||
if (SessionGroup != null && SessionItem != null)
|
||||
{
|
||||
_cachedSession = $"{SessionGroup}: {SessionItem}";
|
||||
}
|
||||
else if (SessionGroup != null)
|
||||
{
|
||||
_cachedSession = $"{SessionGroup}";
|
||||
}
|
||||
else if (SessionItem != null)
|
||||
{
|
||||
_cachedSession = $"---: {SessionItem}";
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedSession = "";
|
||||
}
|
||||
}
|
||||
|
||||
return _cachedSession;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The default comparison is far too slow for the number of comparisons needed because it doesn't know what's important to compare
|
||||
/// </summary>
|
||||
/// <param name="obj">Object to compare to</param>
|
||||
/// <returns></returns>
|
||||
public bool Equals(ProfileConfig cmpObj)
|
||||
{
|
||||
// Order here is important.
|
||||
// Multiple entries with the same item is considerable less likely that multiple items with the same group.
|
||||
// Likewise for group and category.
|
||||
return (cmpObj.SessionItem == SessionItem &&
|
||||
cmpObj.SessionGroup == SessionGroup &&
|
||||
cmpObj.Category == Category);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Predefined configs to make profiling easier,
|
||||
/// nested so you can reference as Profiles.Category.Group.Item where item and group may be optional
|
||||
/// </summary>
|
||||
public static class Profiles
|
||||
{
|
||||
public static class CPU
|
||||
{
|
||||
public static ProfileConfig TranslateTier0 = new ProfileConfig()
|
||||
{
|
||||
Category = "CPU",
|
||||
SessionGroup = "TranslateTier0"
|
||||
};
|
||||
|
||||
public static ProfileConfig TranslateTier1 = new ProfileConfig()
|
||||
{
|
||||
Category = "CPU",
|
||||
SessionGroup = "TranslateTier1"
|
||||
};
|
||||
}
|
||||
|
||||
public static class Input
|
||||
{
|
||||
public static ProfileConfig ControllerInput = new ProfileConfig
|
||||
{
|
||||
Category = "Input",
|
||||
SessionGroup = "ControllerInput"
|
||||
};
|
||||
|
||||
public static ProfileConfig TouchInput = new ProfileConfig
|
||||
{
|
||||
Category = "Input",
|
||||
SessionGroup = "TouchInput"
|
||||
};
|
||||
}
|
||||
|
||||
public static class GPU
|
||||
{
|
||||
public static class Engine2d
|
||||
{
|
||||
public static ProfileConfig TextureCopy = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine2D",
|
||||
SessionGroup = "TextureCopy"
|
||||
};
|
||||
}
|
||||
|
||||
public static class Engine3d
|
||||
{
|
||||
public static ProfileConfig CallMethod = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "CallMethod",
|
||||
};
|
||||
|
||||
public static ProfileConfig VertexEnd = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "VertexEnd"
|
||||
};
|
||||
|
||||
public static ProfileConfig ClearBuffers = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "ClearBuffers"
|
||||
};
|
||||
|
||||
public static ProfileConfig SetFrameBuffer = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "SetFrameBuffer",
|
||||
};
|
||||
|
||||
public static ProfileConfig SetZeta = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "SetZeta"
|
||||
};
|
||||
|
||||
public static ProfileConfig UploadShaders = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "UploadShaders"
|
||||
};
|
||||
|
||||
public static ProfileConfig UploadTextures = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "UploadTextures"
|
||||
};
|
||||
|
||||
public static ProfileConfig UploadTexture = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "UploadTexture"
|
||||
};
|
||||
|
||||
public static ProfileConfig UploadConstBuffers = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "UploadConstBuffers"
|
||||
};
|
||||
|
||||
public static ProfileConfig UploadVertexArrays = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "UploadVertexArrays"
|
||||
};
|
||||
|
||||
public static ProfileConfig ConfigureState = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Engine3D",
|
||||
SessionGroup = "ConfigureState"
|
||||
};
|
||||
}
|
||||
|
||||
public static class EngineM2mf
|
||||
{
|
||||
public static ProfileConfig CallMethod = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.EngineM2mf",
|
||||
SessionGroup = "CallMethod",
|
||||
};
|
||||
|
||||
public static ProfileConfig Execute = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.EngineM2mf",
|
||||
SessionGroup = "Execute",
|
||||
};
|
||||
}
|
||||
|
||||
public static class EngineP2mf
|
||||
{
|
||||
public static ProfileConfig CallMethod = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.EngineP2mf",
|
||||
SessionGroup = "CallMethod",
|
||||
};
|
||||
|
||||
public static ProfileConfig Execute = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.EngineP2mf",
|
||||
SessionGroup = "Execute",
|
||||
};
|
||||
|
||||
public static ProfileConfig PushData = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.EngineP2mf",
|
||||
SessionGroup = "PushData",
|
||||
};
|
||||
}
|
||||
|
||||
public static class Shader
|
||||
{
|
||||
public static ProfileConfig Decompile = new ProfileConfig()
|
||||
{
|
||||
Category = "GPU.Shader",
|
||||
SessionGroup = "Decompile",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static ProfileConfig ServiceCall = new ProfileConfig()
|
||||
{
|
||||
Category = "ServiceCall",
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public static class ProfileSorters
|
||||
{
|
||||
public class InstantAscending : IComparer<KeyValuePair<ProfileConfig, TimingInfo>>
|
||||
{
|
||||
public int Compare(KeyValuePair<ProfileConfig, TimingInfo> pair1, KeyValuePair<ProfileConfig, TimingInfo> pair2)
|
||||
=> pair2.Value.Instant.CompareTo(pair1.Value.Instant);
|
||||
}
|
||||
|
||||
public class AverageAscending : IComparer<KeyValuePair<ProfileConfig, TimingInfo>>
|
||||
{
|
||||
public int Compare(KeyValuePair<ProfileConfig, TimingInfo> pair1, KeyValuePair<ProfileConfig, TimingInfo> pair2)
|
||||
=> pair2.Value.AverageTime.CompareTo(pair1.Value.AverageTime);
|
||||
}
|
||||
|
||||
public class TotalAscending : IComparer<KeyValuePair<ProfileConfig, TimingInfo>>
|
||||
{
|
||||
public int Compare(KeyValuePair<ProfileConfig, TimingInfo> pair1, KeyValuePair<ProfileConfig, TimingInfo> pair2)
|
||||
=> pair2.Value.TotalTime.CompareTo(pair1.Value.TotalTime);
|
||||
}
|
||||
|
||||
public class TagAscending : IComparer<KeyValuePair<ProfileConfig, TimingInfo>>
|
||||
{
|
||||
public int Compare(KeyValuePair<ProfileConfig, TimingInfo> pair1, KeyValuePair<ProfileConfig, TimingInfo> pair2)
|
||||
=> StringComparer.CurrentCulture.Compare(pair1.Key.Search, pair2.Key.Search);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
using Ryujinx.Common.Utilities;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public class ProfilerConfiguration
|
||||
{
|
||||
public bool Enabled { get; private set; }
|
||||
public string DumpPath { get; private set; }
|
||||
public float UpdateRate { get; private set; }
|
||||
public int MaxLevel { get; private set; }
|
||||
public int MaxFlags { get; private set; }
|
||||
public float History { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Loads a configuration file from disk
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the JSON configuration file</param>
|
||||
public static ProfilerConfiguration Load(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new FileNotFoundException($"Profiler configuration file {path} not found");
|
||||
}
|
||||
|
||||
return JsonHelper.DeserializeFromFile<ProfilerConfiguration>(path);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public class ProfilerSettings
|
||||
{
|
||||
// Default settings for profiler
|
||||
public bool Enabled { get; set; } = false;
|
||||
public bool FileDumpEnabled { get; set; } = false;
|
||||
public string DumpLocation { get; set; } = "";
|
||||
public float UpdateRate { get; set; } = 0.1f;
|
||||
public int MaxLevel { get; set; } = 0;
|
||||
public int MaxFlags { get; set; } = 1000;
|
||||
|
||||
// 19531225 = 5 seconds in ticks on most pc's.
|
||||
// It should get set on boot to the time specified in config
|
||||
public long History { get; set; } = 19531225;
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public enum TimingFlagType
|
||||
{
|
||||
FrameSwap = 0,
|
||||
SystemFrame = 1,
|
||||
|
||||
// Update this for new flags
|
||||
Count = 2,
|
||||
}
|
||||
|
||||
public struct TimingFlag
|
||||
{
|
||||
public TimingFlagType FlagType;
|
||||
public long Timestamp;
|
||||
}
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Debugger.Profiler
|
||||
{
|
||||
public struct Timestamp
|
||||
{
|
||||
public long BeginTime;
|
||||
public long EndTime;
|
||||
}
|
||||
|
||||
public class TimingInfo
|
||||
{
|
||||
// Timestamps
|
||||
public long TotalTime { get; set; }
|
||||
public long Instant { get; set; }
|
||||
|
||||
// Measurement counts
|
||||
public int Count { get; set; }
|
||||
public int InstantCount { get; set; }
|
||||
|
||||
// Work out average
|
||||
public long AverageTime => (Count == 0) ? -1 : TotalTime / Count;
|
||||
|
||||
// Intentionally not locked as it's only a get count
|
||||
public bool IsActive => _timestamps.Count > 0;
|
||||
|
||||
public long BeginTime
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_timestampLock)
|
||||
{
|
||||
if (_depth > 0)
|
||||
{
|
||||
return _currentTimestamp.BeginTime;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Timestamp collection
|
||||
private List<Timestamp> _timestamps;
|
||||
private readonly object _timestampLock = new object();
|
||||
private readonly object _timestampListLock = new object();
|
||||
private Timestamp _currentTimestamp;
|
||||
|
||||
// Depth of current timer,
|
||||
// each begin call increments and each end call decrements
|
||||
private int _depth;
|
||||
|
||||
public TimingInfo()
|
||||
{
|
||||
_timestamps = new List<Timestamp>();
|
||||
_depth = 0;
|
||||
}
|
||||
|
||||
public void Begin(long beginTime)
|
||||
{
|
||||
lock (_timestampLock)
|
||||
{
|
||||
// Finish current timestamp if already running
|
||||
if (_depth > 0)
|
||||
{
|
||||
EndUnsafe(beginTime);
|
||||
}
|
||||
|
||||
BeginUnsafe(beginTime);
|
||||
_depth++;
|
||||
}
|
||||
}
|
||||
|
||||
private void BeginUnsafe(long beginTime)
|
||||
{
|
||||
_currentTimestamp.BeginTime = beginTime;
|
||||
_currentTimestamp.EndTime = -1;
|
||||
}
|
||||
|
||||
public void End(long endTime)
|
||||
{
|
||||
lock (_timestampLock)
|
||||
{
|
||||
_depth--;
|
||||
|
||||
if (_depth < 0)
|
||||
{
|
||||
throw new Exception("Timing info end called without corresponding begin");
|
||||
}
|
||||
|
||||
EndUnsafe(endTime);
|
||||
|
||||
// Still have others using this timing info so recreate start for them
|
||||
if (_depth > 0)
|
||||
{
|
||||
BeginUnsafe(endTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EndUnsafe(long endTime)
|
||||
{
|
||||
_currentTimestamp.EndTime = endTime;
|
||||
lock (_timestampListLock)
|
||||
{
|
||||
_timestamps.Add(_currentTimestamp);
|
||||
}
|
||||
|
||||
long delta = _currentTimestamp.EndTime - _currentTimestamp.BeginTime;
|
||||
TotalTime += delta;
|
||||
Instant += delta;
|
||||
|
||||
Count++;
|
||||
InstantCount++;
|
||||
}
|
||||
|
||||
// Remove any timestamps before given timestamp to free memory
|
||||
public void Cleanup(long before, long preserveStart, long preserveEnd)
|
||||
{
|
||||
lock (_timestampListLock)
|
||||
{
|
||||
int toRemove = 0;
|
||||
int toPreserveStart = 0;
|
||||
int toPreserveLen = 0;
|
||||
|
||||
for (int i = 0; i < _timestamps.Count; i++)
|
||||
{
|
||||
if (_timestamps[i].EndTime < preserveStart)
|
||||
{
|
||||
toPreserveStart++;
|
||||
InstantCount--;
|
||||
Instant -= _timestamps[i].EndTime - _timestamps[i].BeginTime;
|
||||
}
|
||||
else if (_timestamps[i].EndTime < preserveEnd)
|
||||
{
|
||||
toPreserveLen++;
|
||||
}
|
||||
else if (_timestamps[i].EndTime < before)
|
||||
{
|
||||
toRemove++;
|
||||
InstantCount--;
|
||||
Instant -= _timestamps[i].EndTime - _timestamps[i].BeginTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume timestamps are in chronological order so no more need to be removed
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (toPreserveStart > 0)
|
||||
{
|
||||
_timestamps.RemoveRange(0, toPreserveStart);
|
||||
}
|
||||
|
||||
if (toRemove > 0)
|
||||
{
|
||||
_timestamps.RemoveRange(toPreserveLen, toRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Timestamp[] GetAllTimestamps()
|
||||
{
|
||||
lock (_timestampListLock)
|
||||
{
|
||||
Timestamp[] returnTimestamps = new Timestamp[_timestamps.Count];
|
||||
_timestamps.CopyTo(returnTimestamps);
|
||||
return returnTimestamps;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
// Enable profiling (Only available on a profiling enabled builds)
|
||||
"enabled": true,
|
||||
|
||||
// Set profile file dump location, if blank file dumping disabled. (e.g. `ProfileDump.csv`)
|
||||
"dump_path": "",
|
||||
|
||||
// Update rate for profiler UI, in hertz. -1 updates every time a frame is issued
|
||||
"update_rate": 4.0,
|
||||
|
||||
// Set how long to keep profiling data in seconds, reduce if profiling is taking too much RAM
|
||||
"history": 5.0,
|
||||
|
||||
// Set the maximum profiling level. Higher values may cause a heavy load on your system but will allow you to profile in more detail
|
||||
"max_level": 0,
|
||||
|
||||
// Sets the maximum number of flags to keep
|
||||
"max_flags": 1000,
|
||||
|
||||
// Keyboard Controls
|
||||
// https://github.com/opentk/opentk/blob/master/src/OpenTK/Input/Key.cs
|
||||
"controls": {
|
||||
"buttons": {
|
||||
// Show/Hide the profiler
|
||||
"toggle_profiler": "F2"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Configurations>Debug;Release;Profile Release;Profile Debug</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="UI\DebuggerWidget.glade" />
|
||||
<None Remove="UI\ProfilerWidget.glade" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="UI\DebuggerWidget.glade" />
|
||||
<EmbeddedResource Include="UI\ProfilerWidget.glade" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GtkSharp" Version="3.22.25.56" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="1.68.1.1" />
|
||||
<PackageReference Include="SkiaSharp.Views.Gtk3" Version="1.68.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="ProfilerConfig.jsonc">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,44 +0,0 @@
|
|||
using Gtk;
|
||||
using System;
|
||||
using GUI = Gtk.Builder.ObjectAttribute;
|
||||
|
||||
namespace Ryujinx.Debugger.UI
|
||||
{
|
||||
public class DebuggerWidget : Box
|
||||
{
|
||||
public event EventHandler DebuggerEnabled;
|
||||
public event EventHandler DebuggerDisabled;
|
||||
|
||||
#pragma warning disable CS0649
|
||||
[GUI] Notebook _widgetNotebook;
|
||||
#pragma warning restore CS0649
|
||||
|
||||
public DebuggerWidget() : this(new Builder("Ryujinx.Debugger.UI.DebuggerWidget.glade")) { }
|
||||
|
||||
public DebuggerWidget(Builder builder) : base(builder.GetObject("_debuggerBox").Handle)
|
||||
{
|
||||
builder.Autoconnect(this);
|
||||
|
||||
LoadProfiler();
|
||||
}
|
||||
|
||||
public void LoadProfiler()
|
||||
{
|
||||
ProfilerWidget widget = new ProfilerWidget();
|
||||
|
||||
widget.RegisterParentDebugger(this);
|
||||
|
||||
_widgetNotebook.AppendPage(widget, new Label("Profiler"));
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
DebuggerEnabled.Invoke(this, null);
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
DebuggerDisabled.Invoke(this, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.21.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkBox" id="_debuggerBox">
|
||||
<property name="name">DebuggerBox</property>
|
||||
<property name="width_request">1024</property>
|
||||
<property name="height_request">720</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkNotebook" id="_widgetNotebook">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -1,803 +0,0 @@
|
|||
using Gtk;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Debugger.Profiler;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.Views.Desktop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
using GUI = Gtk.Builder.ObjectAttribute;
|
||||
|
||||
namespace Ryujinx.Debugger.UI
|
||||
{
|
||||
public class ProfilerWidget : Box
|
||||
{
|
||||
private Thread _profilerThread;
|
||||
private double _prevTime;
|
||||
private bool _profilerRunning;
|
||||
|
||||
private TimingFlag[] _timingFlags;
|
||||
|
||||
private bool _initComplete = false;
|
||||
private bool _redrawPending = true;
|
||||
private bool _doStep = false;
|
||||
|
||||
// Layout
|
||||
private const int LineHeight = 16;
|
||||
private const int MinimumColumnWidth = 200;
|
||||
private const int TitleHeight = 24;
|
||||
private const int TitleFontHeight = 16;
|
||||
private const int LinePadding = 2;
|
||||
private const int ColumnSpacing = 15;
|
||||
private const int FilterHeight = 24;
|
||||
private const int BottomBarHeight = FilterHeight + LineHeight;
|
||||
|
||||
// Sorting
|
||||
private List<KeyValuePair<ProfileConfig, TimingInfo>> _unsortedProfileData;
|
||||
private IComparer<KeyValuePair<ProfileConfig, TimingInfo>> _sortAction = new ProfileSorters.TagAscending();
|
||||
|
||||
// Flag data
|
||||
private long[] _timingFlagsAverages;
|
||||
private long[] _timingFlagsLast;
|
||||
|
||||
// Filtering
|
||||
private string _filterText = "";
|
||||
private bool _regexEnabled = false;
|
||||
|
||||
// Scrolling
|
||||
private float _scrollPos = 0;
|
||||
|
||||
// Profile data storage
|
||||
private List<KeyValuePair<ProfileConfig, TimingInfo>> _sortedProfileData;
|
||||
private long _captureTime;
|
||||
|
||||
// Graph
|
||||
private SKColor[] _timingFlagColors = new[]
|
||||
{
|
||||
new SKColor(150, 25, 25, 50), // FrameSwap = 0
|
||||
new SKColor(25, 25, 150, 50), // SystemFrame = 1
|
||||
};
|
||||
|
||||
private const float GraphMoveSpeed = 40000;
|
||||
private const float GraphZoomSpeed = 50;
|
||||
|
||||
private float _graphZoom = 1;
|
||||
private float _graphPosition = 0;
|
||||
private int _rendererHeight => _renderer.AllocatedHeight;
|
||||
private int _rendererWidth => _renderer.AllocatedWidth;
|
||||
|
||||
// Event management
|
||||
private long _lastOutputUpdate;
|
||||
private long _lastOutputDraw;
|
||||
private long _lastOutputUpdateDuration;
|
||||
private long _lastOutputDrawDuration;
|
||||
private double _lastFrameTimeMs;
|
||||
private double _updateTimer;
|
||||
private bool _profileUpdated = false;
|
||||
private readonly object _profileDataLock = new object();
|
||||
|
||||
private SkRenderer _renderer;
|
||||
|
||||
#pragma warning disable CS0649
|
||||
[GUI] ScrolledWindow _scrollview;
|
||||
[GUI] CheckButton _enableCheckbutton;
|
||||
[GUI] Scrollbar _outputScrollbar;
|
||||
[GUI] Entry _filterBox;
|
||||
[GUI] ComboBox _modeBox;
|
||||
[GUI] CheckButton _showFlags;
|
||||
[GUI] CheckButton _showInactive;
|
||||
[GUI] Button _stepButton;
|
||||
[GUI] CheckButton _pauseCheckbutton;
|
||||
#pragma warning restore CS0649
|
||||
|
||||
public ProfilerWidget() : this(new Builder("Ryujinx.Debugger.UI.ProfilerWidget.glade")) { }
|
||||
|
||||
public ProfilerWidget(Builder builder) : base(builder.GetObject("_profilerBox").Handle)
|
||||
{
|
||||
builder.Autoconnect(this);
|
||||
|
||||
this.KeyPressEvent += ProfilerWidget_KeyPressEvent;
|
||||
|
||||
this.Expand = true;
|
||||
|
||||
_renderer = new SkRenderer();
|
||||
_renderer.Expand = true;
|
||||
|
||||
_outputScrollbar.ValueChanged += _outputScrollbar_ValueChanged;
|
||||
|
||||
_renderer.DrawGraphs += _renderer_DrawGraphs;
|
||||
|
||||
_filterBox.Changed += _filterBox_Changed;
|
||||
|
||||
_stepButton.Clicked += _stepButton_Clicked;
|
||||
|
||||
_scrollview.Add(_renderer);
|
||||
|
||||
if (Profile.UpdateRate <= 0)
|
||||
{
|
||||
// Perform step regardless of flag type
|
||||
Profile.RegisterFlagReceiver((t) =>
|
||||
{
|
||||
if (_pauseCheckbutton.Active)
|
||||
{
|
||||
_doStep = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void _stepButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (_pauseCheckbutton.Active)
|
||||
{
|
||||
_doStep = true;
|
||||
}
|
||||
|
||||
_profileUpdated = true;
|
||||
}
|
||||
|
||||
private void _filterBox_Changed(object sender, EventArgs e)
|
||||
{
|
||||
_filterText = _filterBox.Text;
|
||||
_profileUpdated = true;
|
||||
}
|
||||
|
||||
private void _outputScrollbar_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
_scrollPos = -(float)Math.Max(0, _outputScrollbar.Value);
|
||||
_profileUpdated = true;
|
||||
}
|
||||
|
||||
private void _renderer_DrawGraphs(object sender, EventArgs e)
|
||||
{
|
||||
if (e is SKPaintSurfaceEventArgs se)
|
||||
{
|
||||
Draw(se.Surface.Canvas);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterParentDebugger(DebuggerWidget debugger)
|
||||
{
|
||||
debugger.DebuggerEnabled += Debugger_DebuggerAttached;
|
||||
debugger.DebuggerDisabled += Debugger_DebuggerDettached;
|
||||
}
|
||||
|
||||
private void Debugger_DebuggerDettached(object sender, EventArgs e)
|
||||
{
|
||||
_profilerRunning = false;
|
||||
|
||||
if (_profilerThread != null)
|
||||
{
|
||||
_profilerThread.Join();
|
||||
}
|
||||
}
|
||||
|
||||
private void Debugger_DebuggerAttached(object sender, EventArgs e)
|
||||
{
|
||||
_profilerRunning = false;
|
||||
|
||||
if (_profilerThread != null)
|
||||
{
|
||||
_profilerThread.Join();
|
||||
}
|
||||
|
||||
_profilerRunning = true;
|
||||
|
||||
_profilerThread = new Thread(UpdateLoop)
|
||||
{
|
||||
Name = "Profiler.UpdateThread"
|
||||
};
|
||||
_profilerThread.Start();
|
||||
}
|
||||
|
||||
private void ProfilerWidget_KeyPressEvent(object o, Gtk.KeyPressEventArgs args)
|
||||
{
|
||||
switch (args.Event.Key)
|
||||
{
|
||||
case Gdk.Key.Left:
|
||||
_graphPosition += (long)(GraphMoveSpeed * _lastFrameTimeMs);
|
||||
break;
|
||||
|
||||
case Gdk.Key.Right:
|
||||
_graphPosition = Math.Max(_graphPosition - (long)(GraphMoveSpeed * _lastFrameTimeMs), 0);
|
||||
break;
|
||||
|
||||
case Gdk.Key.Up:
|
||||
_graphZoom = MathF.Min(_graphZoom + (float)(GraphZoomSpeed * _lastFrameTimeMs), 100.0f);
|
||||
break;
|
||||
|
||||
case Gdk.Key.Down:
|
||||
_graphZoom = MathF.Max(_graphZoom - (float)(GraphZoomSpeed * _lastFrameTimeMs), 1f);
|
||||
break;
|
||||
}
|
||||
_profileUpdated = true;
|
||||
}
|
||||
|
||||
public void UpdateLoop()
|
||||
{
|
||||
_lastOutputUpdate = PerformanceCounter.ElapsedTicks;
|
||||
_lastOutputDraw = PerformanceCounter.ElapsedTicks;
|
||||
|
||||
while (_profilerRunning)
|
||||
{
|
||||
_lastOutputUpdate = PerformanceCounter.ElapsedTicks;
|
||||
int timeToSleepMs = (_pauseCheckbutton.Active || !_enableCheckbutton.Active) ? 33 : 1;
|
||||
|
||||
if (Profile.ProfilingEnabled() && _enableCheckbutton.Active)
|
||||
{
|
||||
double time = (double)PerformanceCounter.ElapsedTicks / PerformanceCounter.TicksPerSecond;
|
||||
|
||||
Update(time - _prevTime);
|
||||
|
||||
_lastOutputUpdateDuration = PerformanceCounter.ElapsedTicks - _lastOutputUpdate;
|
||||
_prevTime = time;
|
||||
|
||||
Gdk.Threads.AddIdle(1000, ()=>
|
||||
{
|
||||
_renderer.QueueDraw();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
Thread.Sleep(timeToSleepMs);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(double frameTime)
|
||||
{
|
||||
_lastFrameTimeMs = frameTime;
|
||||
|
||||
// Get timing data if enough time has passed
|
||||
_updateTimer += frameTime;
|
||||
|
||||
if (_doStep || ((Profile.UpdateRate > 0) && (!_pauseCheckbutton.Active && (_updateTimer > Profile.UpdateRate))))
|
||||
{
|
||||
_updateTimer = 0;
|
||||
_captureTime = PerformanceCounter.ElapsedTicks;
|
||||
_timingFlags = Profile.GetTimingFlags();
|
||||
_doStep = false;
|
||||
_profileUpdated = true;
|
||||
|
||||
_unsortedProfileData = Profile.GetProfilingData();
|
||||
|
||||
(_timingFlagsAverages, _timingFlagsLast) = Profile.GetTimingAveragesAndLast();
|
||||
}
|
||||
|
||||
// Filtering
|
||||
if (_profileUpdated)
|
||||
{
|
||||
lock (_profileDataLock)
|
||||
{
|
||||
_sortedProfileData = _showInactive.Active ? _unsortedProfileData : _unsortedProfileData.FindAll(kvp => kvp.Value.IsActive);
|
||||
|
||||
if (_sortAction != null)
|
||||
{
|
||||
_sortedProfileData.Sort(_sortAction);
|
||||
}
|
||||
|
||||
if (_regexEnabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
Regex filterRegex = new Regex(_filterText, RegexOptions.IgnoreCase);
|
||||
if (_filterText != "")
|
||||
{
|
||||
_sortedProfileData = _sortedProfileData.Where((pair => filterRegex.IsMatch(pair.Key.Search))).ToList();
|
||||
}
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Skip filtering for invalid regex
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular filtering
|
||||
_sortedProfileData = _sortedProfileData.Where((pair => pair.Key.Search.ToLower().Contains(_filterText.ToLower()))).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
_profileUpdated = false;
|
||||
_redrawPending = true;
|
||||
_initComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTimeString(long timestamp)
|
||||
{
|
||||
float time = (float)timestamp / PerformanceCounter.TicksPerMillisecond;
|
||||
|
||||
return (time < 1) ? $"{time * 1000:F3}us" : $"{time:F3}ms";
|
||||
}
|
||||
|
||||
private void FilterBackspace()
|
||||
{
|
||||
if (_filterText.Length <= 1)
|
||||
{
|
||||
_filterText = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
_filterText = _filterText.Remove(_filterText.Length - 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private float GetLineY(float offset, float lineHeight, float padding, bool centre, int line)
|
||||
{
|
||||
return offset + lineHeight + padding + ((lineHeight + padding) * line) - ((centre) ? padding : 0);
|
||||
}
|
||||
|
||||
public void Draw(SKCanvas canvas)
|
||||
{
|
||||
_lastOutputDraw = PerformanceCounter.ElapsedTicks;
|
||||
if (!Visible ||
|
||||
!_initComplete ||
|
||||
!_enableCheckbutton.Active ||
|
||||
!_redrawPending)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float viewTop = TitleHeight + 5;
|
||||
float viewBottom = _rendererHeight - FilterHeight - LineHeight;
|
||||
|
||||
float columnWidth;
|
||||
float maxColumnWidth = MinimumColumnWidth;
|
||||
float yOffset = _scrollPos + viewTop;
|
||||
float xOffset = 10;
|
||||
float timingWidth;
|
||||
|
||||
float contentHeight = GetLineY(0, LineHeight, LinePadding, false, _sortedProfileData.Count - 1);
|
||||
|
||||
_outputScrollbar.Adjustment.Upper = contentHeight;
|
||||
_outputScrollbar.Adjustment.Lower = 0;
|
||||
_outputScrollbar.Adjustment.PageSize = viewBottom - viewTop;
|
||||
|
||||
|
||||
SKPaint textFont = new SKPaint()
|
||||
{
|
||||
Color = SKColors.White,
|
||||
TextSize = LineHeight
|
||||
};
|
||||
|
||||
SKPaint titleFont = new SKPaint()
|
||||
{
|
||||
Color = SKColors.White,
|
||||
TextSize = TitleFontHeight
|
||||
};
|
||||
|
||||
SKPaint evenItemBackground = new SKPaint()
|
||||
{
|
||||
Color = SKColors.Gray
|
||||
};
|
||||
|
||||
canvas.Save();
|
||||
canvas.ClipRect(new SKRect(0, viewTop, _rendererWidth, viewBottom), SKClipOperation.Intersect);
|
||||
|
||||
for (int i = 1; i < _sortedProfileData.Count; i += 2)
|
||||
{
|
||||
float top = GetLineY(yOffset, LineHeight, LinePadding, false, i - 1);
|
||||
float bottom = GetLineY(yOffset, LineHeight, LinePadding, false, i);
|
||||
|
||||
canvas.DrawRect(new SKRect(0, top, _rendererWidth, bottom), evenItemBackground);
|
||||
}
|
||||
|
||||
lock (_profileDataLock)
|
||||
{
|
||||
// Display category
|
||||
|
||||
for (int verticalIndex = 0; verticalIndex < _sortedProfileData.Count; verticalIndex++)
|
||||
{
|
||||
KeyValuePair<ProfileConfig, TimingInfo> entry = _sortedProfileData[verticalIndex];
|
||||
|
||||
if (entry.Key.Category == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float y = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex);
|
||||
|
||||
canvas.DrawText(entry.Key.Category, new SKPoint(xOffset, y), textFont);
|
||||
|
||||
columnWidth = textFont.MeasureText(entry.Key.Category);
|
||||
|
||||
if (columnWidth > maxColumnWidth)
|
||||
{
|
||||
maxColumnWidth = columnWidth;
|
||||
}
|
||||
}
|
||||
|
||||
canvas.Restore();
|
||||
canvas.DrawText("Category", new SKPoint(xOffset, TitleFontHeight + 2), titleFont);
|
||||
|
||||
columnWidth = titleFont.MeasureText("Category");
|
||||
|
||||
if (columnWidth > maxColumnWidth)
|
||||
{
|
||||
maxColumnWidth = columnWidth;
|
||||
}
|
||||
|
||||
xOffset += maxColumnWidth + ColumnSpacing;
|
||||
|
||||
canvas.DrawLine(new SKPoint(xOffset - ColumnSpacing / 2, 0), new SKPoint(xOffset - ColumnSpacing / 2, viewBottom), textFont);
|
||||
|
||||
// Display session group
|
||||
maxColumnWidth = MinimumColumnWidth;
|
||||
|
||||
canvas.Save();
|
||||
canvas.ClipRect(new SKRect(0, viewTop, _rendererWidth, viewBottom), SKClipOperation.Intersect);
|
||||
|
||||
for (int verticalIndex = 0; verticalIndex < _sortedProfileData.Count; verticalIndex++)
|
||||
{
|
||||
KeyValuePair<ProfileConfig, TimingInfo> entry = _sortedProfileData[verticalIndex];
|
||||
|
||||
if (entry.Key.SessionGroup == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float y = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex);
|
||||
|
||||
canvas.DrawText(entry.Key.SessionGroup, new SKPoint(xOffset, y), textFont);
|
||||
|
||||
columnWidth = textFont.MeasureText(entry.Key.SessionGroup);
|
||||
|
||||
if (columnWidth > maxColumnWidth)
|
||||
{
|
||||
maxColumnWidth = columnWidth;
|
||||
}
|
||||
}
|
||||
|
||||
canvas.Restore();
|
||||
canvas.DrawText("Group", new SKPoint(xOffset, TitleFontHeight + 2), titleFont);
|
||||
|
||||
columnWidth = titleFont.MeasureText("Group");
|
||||
|
||||
if (columnWidth > maxColumnWidth)
|
||||
{
|
||||
maxColumnWidth = columnWidth;
|
||||
}
|
||||
|
||||
xOffset += maxColumnWidth + ColumnSpacing;
|
||||
|
||||
canvas.DrawLine(new SKPoint(xOffset - ColumnSpacing / 2, 0), new SKPoint(xOffset - ColumnSpacing / 2, viewBottom), textFont);
|
||||
|
||||
// Display session item
|
||||
maxColumnWidth = MinimumColumnWidth;
|
||||
|
||||
canvas.Save();
|
||||
canvas.ClipRect(new SKRect(0, viewTop, _rendererWidth, viewBottom), SKClipOperation.Intersect);
|
||||
|
||||
for (int verticalIndex = 0; verticalIndex < _sortedProfileData.Count; verticalIndex++)
|
||||
{
|
||||
KeyValuePair<ProfileConfig, TimingInfo> entry = _sortedProfileData[verticalIndex];
|
||||
|
||||
if (entry.Key.SessionItem == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float y = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex);
|
||||
|
||||
canvas.DrawText(entry.Key.SessionItem, new SKPoint(xOffset, y), textFont);
|
||||
|
||||
columnWidth = textFont.MeasureText(entry.Key.SessionItem);
|
||||
|
||||
if (columnWidth > maxColumnWidth)
|
||||
{
|
||||
maxColumnWidth = columnWidth;
|
||||
}
|
||||
}
|
||||
|
||||
canvas.Restore();
|
||||
canvas.DrawText("Item", new SKPoint(xOffset, TitleFontHeight + 2), titleFont);
|
||||
|
||||
columnWidth = titleFont.MeasureText("Item");
|
||||
|
||||
if (columnWidth > maxColumnWidth)
|
||||
{
|
||||
maxColumnWidth = columnWidth;
|
||||
}
|
||||
|
||||
xOffset += maxColumnWidth + ColumnSpacing;
|
||||
|
||||
timingWidth = _rendererWidth - xOffset - 370;
|
||||
|
||||
canvas.Save();
|
||||
canvas.ClipRect(new SKRect(0, viewTop, _rendererWidth, viewBottom), SKClipOperation.Intersect);
|
||||
canvas.DrawLine(new SKPoint(xOffset, 0), new SKPoint(xOffset, _rendererHeight), textFont);
|
||||
|
||||
int mode = _modeBox.Active;
|
||||
|
||||
canvas.Save();
|
||||
canvas.ClipRect(new SKRect(xOffset, yOffset,xOffset + timingWidth,yOffset + contentHeight),
|
||||
SKClipOperation.Intersect);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
DrawGraph(xOffset, yOffset, timingWidth, canvas);
|
||||
break;
|
||||
case 1:
|
||||
DrawBars(xOffset, yOffset, timingWidth, canvas);
|
||||
|
||||
canvas.DrawText("Blue: Instant, Green: Avg, Red: Total",
|
||||
new SKPoint(xOffset, _rendererHeight - TitleFontHeight), titleFont);
|
||||
break;
|
||||
}
|
||||
|
||||
canvas.Restore();
|
||||
canvas.DrawLine(new SKPoint(xOffset + timingWidth, 0), new SKPoint(xOffset + timingWidth, _rendererHeight), textFont);
|
||||
|
||||
xOffset = _rendererWidth - 360;
|
||||
|
||||
// Display timestamps
|
||||
long totalInstant = 0;
|
||||
long totalAverage = 0;
|
||||
long totalTime = 0;
|
||||
long totalCount = 0;
|
||||
|
||||
for (int verticalIndex = 0; verticalIndex < _sortedProfileData.Count; verticalIndex++)
|
||||
{
|
||||
KeyValuePair<ProfileConfig, TimingInfo> entry = _sortedProfileData[verticalIndex];
|
||||
|
||||
float y = GetLineY(yOffset, LineHeight, LinePadding, true, verticalIndex);
|
||||
|
||||
canvas.DrawText($"{GetTimeString(entry.Value.Instant)} ({entry.Value.InstantCount})", new SKPoint(xOffset, y), textFont);
|
||||
canvas.DrawText(GetTimeString(entry.Value.AverageTime), new SKPoint(150 + xOffset, y), textFont);
|
||||
canvas.DrawText(GetTimeString(entry.Value.TotalTime), new SKPoint(260 + xOffset, y), textFont);
|
||||
|
||||
totalInstant += entry.Value.Instant;
|
||||
totalAverage += entry.Value.AverageTime;
|
||||
totalTime += entry.Value.TotalTime;
|
||||
totalCount += entry.Value.InstantCount;
|
||||
}
|
||||
|
||||
canvas.Restore();
|
||||
canvas.DrawLine(new SKPoint(0, viewTop), new SKPoint(_rendererWidth, viewTop), titleFont);
|
||||
|
||||
float yHeight = 0 + TitleFontHeight;
|
||||
|
||||
canvas.DrawText("Instant (Count)", new SKPoint(xOffset, yHeight), titleFont);
|
||||
canvas.DrawText("Average", new SKPoint(150 + xOffset, yHeight), titleFont);
|
||||
canvas.DrawText("Total (ms)", new SKPoint(260 + xOffset, yHeight), titleFont);
|
||||
|
||||
// Totals
|
||||
yHeight = _rendererHeight - FilterHeight + 3;
|
||||
|
||||
int textHeight = LineHeight - 2;
|
||||
|
||||
SKPaint detailFont = new SKPaint()
|
||||
{
|
||||
Color = new SKColor(100, 100, 255, 255),
|
||||
TextSize = textHeight
|
||||
};
|
||||
|
||||
canvas.DrawLine(new SkiaSharp.SKPoint(0, viewBottom), new SkiaSharp.SKPoint(_rendererWidth,viewBottom), textFont);
|
||||
|
||||
string hostTimeString = $"Host {GetTimeString(_timingFlagsLast[(int)TimingFlagType.SystemFrame])} " +
|
||||
$"({GetTimeString(_timingFlagsAverages[(int)TimingFlagType.SystemFrame])})";
|
||||
|
||||
canvas.DrawText(hostTimeString, new SKPoint(5, yHeight), detailFont);
|
||||
|
||||
float tempWidth = detailFont.MeasureText(hostTimeString);
|
||||
|
||||
detailFont.Color = SKColors.Red;
|
||||
|
||||
string gameTimeString = $"Game {GetTimeString(_timingFlagsLast[(int)TimingFlagType.FrameSwap])} " +
|
||||
$"({GetTimeString(_timingFlagsAverages[(int)TimingFlagType.FrameSwap])})";
|
||||
|
||||
canvas.DrawText(gameTimeString, new SKPoint(15 + tempWidth, yHeight), detailFont);
|
||||
|
||||
tempWidth += detailFont.MeasureText(gameTimeString);
|
||||
|
||||
detailFont.Color = SKColors.White;
|
||||
|
||||
canvas.DrawText($"Profiler: Update {GetTimeString(_lastOutputUpdateDuration)} Draw {GetTimeString(_lastOutputDrawDuration)}",
|
||||
new SKPoint(20 + tempWidth, yHeight), detailFont);
|
||||
|
||||
detailFont.Color = SKColors.White;
|
||||
|
||||
canvas.DrawText($"{GetTimeString(totalInstant)} ({totalCount})", new SKPoint(xOffset, yHeight), detailFont);
|
||||
canvas.DrawText(GetTimeString(totalAverage), new SKPoint(150 + xOffset, yHeight), detailFont);
|
||||
canvas.DrawText(GetTimeString(totalTime), new SKPoint(260 + xOffset, yHeight), detailFont);
|
||||
|
||||
_lastOutputDrawDuration = PerformanceCounter.ElapsedTicks - _lastOutputDraw;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGraph(float xOffset, float yOffset, float width, SKCanvas canvas)
|
||||
{
|
||||
if (_sortedProfileData.Count != 0)
|
||||
{
|
||||
int left, right;
|
||||
float top, bottom;
|
||||
|
||||
float graphRight = xOffset + width;
|
||||
float barHeight = (LineHeight - LinePadding);
|
||||
long history = Profile.HistoryLength;
|
||||
double timeWidthTicks = history / (double)_graphZoom;
|
||||
long graphPositionTicks = (long)(_graphPosition * PerformanceCounter.TicksPerMillisecond);
|
||||
long ticksPerPixel = (long)(timeWidthTicks / width);
|
||||
|
||||
// Reset start point if out of bounds
|
||||
if (timeWidthTicks + graphPositionTicks > history)
|
||||
{
|
||||
graphPositionTicks = history - (long)timeWidthTicks;
|
||||
_graphPosition = (float)graphPositionTicks / PerformanceCounter.TicksPerMillisecond;
|
||||
}
|
||||
|
||||
graphPositionTicks = _captureTime - graphPositionTicks;
|
||||
|
||||
// Draw timing flags
|
||||
if (_showFlags.Active)
|
||||
{
|
||||
TimingFlagType prevType = TimingFlagType.Count;
|
||||
|
||||
SKPaint timingPaint = new SKPaint
|
||||
{
|
||||
Color = _timingFlagColors.First()
|
||||
};
|
||||
|
||||
foreach (TimingFlag timingFlag in _timingFlags)
|
||||
{
|
||||
if (prevType != timingFlag.FlagType)
|
||||
{
|
||||
prevType = timingFlag.FlagType;
|
||||
timingPaint.Color = _timingFlagColors[(int)prevType];
|
||||
}
|
||||
|
||||
int x = (int)(graphRight - ((graphPositionTicks - timingFlag.Timestamp) / timeWidthTicks) * width);
|
||||
|
||||
if (x > xOffset)
|
||||
{
|
||||
canvas.DrawLine(new SKPoint(x, yOffset), new SKPoint(x, _rendererHeight), timingPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SKPaint barPaint = new SKPaint()
|
||||
{
|
||||
Color = SKColors.Green,
|
||||
};
|
||||
|
||||
// Draw bars
|
||||
for (int verticalIndex = 0; verticalIndex < _sortedProfileData.Count; verticalIndex++)
|
||||
{
|
||||
KeyValuePair<ProfileConfig, TimingInfo> entry = _sortedProfileData[verticalIndex];
|
||||
long furthest = 0;
|
||||
|
||||
bottom = GetLineY(yOffset, LineHeight, LinePadding, false, verticalIndex);
|
||||
top = bottom + barHeight;
|
||||
|
||||
// Skip rendering out of bounds bars
|
||||
if (top < 0 || bottom > _rendererHeight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
barPaint.Color = SKColors.Green;
|
||||
|
||||
foreach (Timestamp timestamp in entry.Value.GetAllTimestamps())
|
||||
{
|
||||
// Skip drawing multiple timestamps on same pixel
|
||||
if (timestamp.EndTime < furthest)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
furthest = timestamp.EndTime + ticksPerPixel;
|
||||
|
||||
left = (int)(graphRight - ((graphPositionTicks - timestamp.BeginTime) / timeWidthTicks) * width);
|
||||
right = (int)(graphRight - ((graphPositionTicks - timestamp.EndTime) / timeWidthTicks) * width);
|
||||
|
||||
left = (int)Math.Max(xOffset +1, left);
|
||||
|
||||
// Make sure width is at least 1px
|
||||
right = Math.Max(left + 1, right);
|
||||
|
||||
canvas.DrawRect(new SKRect(left, top, right, bottom), barPaint);
|
||||
}
|
||||
|
||||
// Currently capturing timestamp
|
||||
barPaint.Color = SKColors.Red;
|
||||
|
||||
long entryBegin = entry.Value.BeginTime;
|
||||
|
||||
if (entryBegin != -1)
|
||||
{
|
||||
left = (int)(graphRight - ((graphPositionTicks - entryBegin) / timeWidthTicks) * width);
|
||||
|
||||
// Make sure width is at least 1px
|
||||
left = Math.Min(left - 1, (int)graphRight);
|
||||
|
||||
left = (int)Math.Max(xOffset + 1, left);
|
||||
|
||||
canvas.DrawRect(new SKRect(left, top, graphRight, bottom), barPaint);
|
||||
}
|
||||
}
|
||||
|
||||
string label = $"-{MathF.Round(_graphPosition, 2)} ms";
|
||||
|
||||
SKPaint labelPaint = new SKPaint()
|
||||
{
|
||||
Color = SKColors.White,
|
||||
TextSize = LineHeight
|
||||
};
|
||||
|
||||
float labelWidth = labelPaint.MeasureText(label);
|
||||
|
||||
canvas.DrawText(label,new SKPoint(graphRight - labelWidth - LinePadding, FilterHeight + LinePadding) , labelPaint);
|
||||
|
||||
canvas.DrawText($"-{MathF.Round((float)((timeWidthTicks / PerformanceCounter.TicksPerMillisecond) + _graphPosition), 2)} ms",
|
||||
new SKPoint(xOffset + LinePadding, FilterHeight + LinePadding), labelPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBars(float xOffset, float yOffset, float width, SKCanvas canvas)
|
||||
{
|
||||
if (_sortedProfileData.Count != 0)
|
||||
{
|
||||
long maxAverage = 0;
|
||||
long maxTotal = 0;
|
||||
long maxInstant = 0;
|
||||
|
||||
float barHeight = (LineHeight - LinePadding) / 3.0f;
|
||||
|
||||
// Get max values
|
||||
foreach (KeyValuePair<ProfileConfig, TimingInfo> kvp in _sortedProfileData)
|
||||
{
|
||||
maxInstant = Math.Max(maxInstant, kvp.Value.Instant);
|
||||
maxAverage = Math.Max(maxAverage, kvp.Value.AverageTime);
|
||||
maxTotal = Math.Max(maxTotal, kvp.Value.TotalTime);
|
||||
}
|
||||
|
||||
SKPaint barPaint = new SKPaint()
|
||||
{
|
||||
Color = SKColors.Blue
|
||||
};
|
||||
|
||||
for (int verticalIndex = 0; verticalIndex < _sortedProfileData.Count; verticalIndex++)
|
||||
{
|
||||
KeyValuePair<ProfileConfig, TimingInfo> entry = _sortedProfileData[verticalIndex];
|
||||
// Instant
|
||||
barPaint.Color = SKColors.Blue;
|
||||
|
||||
float bottom = GetLineY(yOffset, LineHeight, LinePadding, false, verticalIndex);
|
||||
float top = bottom + barHeight;
|
||||
float right = (float)entry.Value.Instant / maxInstant * width + xOffset;
|
||||
|
||||
// Skip rendering out of bounds bars
|
||||
if (top < 0 || bottom > _rendererHeight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
canvas.DrawRect(new SKRect(xOffset, top, right, bottom), barPaint);
|
||||
|
||||
// Average
|
||||
barPaint.Color = SKColors.Green;
|
||||
|
||||
top += barHeight;
|
||||
bottom += barHeight;
|
||||
right = (float)entry.Value.AverageTime / maxAverage * width + xOffset;
|
||||
|
||||
canvas.DrawRect(new SKRect(xOffset, top, right, bottom), barPaint);
|
||||
|
||||
// Total
|
||||
barPaint.Color = SKColors.Red;
|
||||
|
||||
top += barHeight;
|
||||
bottom += barHeight;
|
||||
right = (float)entry.Value.TotalTime / maxTotal * width + xOffset;
|
||||
|
||||
canvas.DrawRect(new SKRect(xOffset, top, right, bottom), barPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.21.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkListStore" id="viewMode">
|
||||
<columns>
|
||||
<!-- column-name mode -->
|
||||
<column type="gint"/>
|
||||
<!-- column-name label -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0">0</col>
|
||||
<col id="1" translatable="yes">Graph</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0">1</col>
|
||||
<col id="1" translatable="yes">Bars</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkBox" id="_profilerBox">
|
||||
<property name="name">ProfilerBox</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="_enableCheckbutton">
|
||||
<property name="label" translatable="yes">Enable Profiler</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="_scrollview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="vscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrollbar" id="_outputScrollbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="_showInactive">
|
||||
<property name="label" translatable="yes">Show Inactive</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="_showFlags">
|
||||
<property name="label" translatable="yes">Show Flags</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="_pauseCheckbutton">
|
||||
<property name="label" translatable="yes">Paused</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">View Mode: </property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="_modeBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="model">viewMode</property>
|
||||
<property name="active">0</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="modeTextRenderer"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Filter: </property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="_filterBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="_stepButton">
|
||||
<property name="label" translatable="yes">Step</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -1,23 +0,0 @@
|
|||
using SkiaSharp;
|
||||
using SkiaSharp.Views.Gtk;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Debugger.UI
|
||||
{
|
||||
public class SkRenderer : SKDrawingArea
|
||||
{
|
||||
public event EventHandler DrawGraphs;
|
||||
|
||||
public SkRenderer()
|
||||
{
|
||||
this.PaintSurface += SkRenderer_PaintSurface;
|
||||
}
|
||||
|
||||
private void SkRenderer_PaintSurface(object sender, SkiaSharp.Views.Desktop.SKPaintSurfaceEventArgs e)
|
||||
{
|
||||
e.Surface.Canvas.Clear(SKColors.Black);
|
||||
|
||||
DrawGraphs.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ using Ryujinx.HLE.HOS.Kernel.Ipc;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Ryujinx.Debugger.Profiler;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -111,16 +110,7 @@ namespace Ryujinx.HLE.HOS.Services
|
|||
{
|
||||
Logger.Debug?.Print(LogClass.KernelIpc, $"{service.GetType().Name}: {processRequest.Name}");
|
||||
|
||||
ProfileConfig profile = Profiles.ServiceCall;
|
||||
|
||||
profile.SessionGroup = service.GetType().Name;
|
||||
profile.SessionItem = processRequest.Name;
|
||||
|
||||
Profile.Begin(profile);
|
||||
|
||||
result = (ResultCode)processRequest.Invoke(service, new object[] { context });
|
||||
|
||||
Profile.End(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using Ryujinx.Debugger.Profiler;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
using System.Timers;
|
||||
|
||||
namespace Ryujinx.HLE
|
||||
|
@ -83,13 +82,11 @@ namespace Ryujinx.HLE
|
|||
public void RecordSystemFrameTime()
|
||||
{
|
||||
RecordFrameTime(FrameTypeSystem);
|
||||
Profile.FlagTime(TimingFlagType.SystemFrame);
|
||||
}
|
||||
|
||||
public void RecordGameFrameTime()
|
||||
{
|
||||
RecordFrameTime(FrameTypeGame);
|
||||
Profile.FlagTime(TimingFlagType.FrameSwap);
|
||||
}
|
||||
|
||||
private void RecordFrameTime(int frameType)
|
||||
|
|
|
@ -4,29 +4,17 @@
|
|||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Due to Concentus. -->
|
||||
<PropertyGroup>
|
||||
<NoWarn>NU1605</NoWarn>
|
||||
|
@ -47,7 +35,6 @@
|
|||
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Cpu\Ryujinx.Cpu.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Debugger\Ryujinx.Debugger.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj" />
|
||||
|
|
|
@ -9,17 +9,7 @@
|
|||
<LangVersion>8.0</LangVersion>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -5,21 +5,11 @@
|
|||
<LangVersion>8.0</LangVersion>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -10,23 +10,13 @@
|
|||
<TargetOS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">windows</TargetOS>
|
||||
<TargetOS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">osx</TargetOS>
|
||||
<TargetOS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">linux</TargetOS>
|
||||
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
|
|
108
Ryujinx.sln
108
Ryujinx.sln
|
@ -33,8 +33,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec", "R
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Renderer", "Ryujinx.Audio.Renderer\Ryujinx.Audio.Renderer.csproj", "{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Debugger", "Ryujinx.Debugger\Ryujinx.Debugger.csproj", "{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
|
@ -61,209 +59,103 @@ EndProject
|
|||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Profile Debug|Any CPU = Profile Debug|Any CPU
|
||||
Profile Release|Any CPU = Profile Release|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5C1D818E-682A-46A5-9D54-30006E26C270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5C1D818E-682A-46A5-9D54-30006E26C270}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5C1D818E-682A-46A5-9D54-30006E26C270}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU
|
||||
{5C1D818E-682A-46A5-9D54-30006E26C270}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU
|
||||
{5C1D818E-682A-46A5-9D54-30006E26C270}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU
|
||||
{5C1D818E-682A-46A5-9D54-30006E26C270}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
|
||||
{5C1D818E-682A-46A5-9D54-30006E26C270}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5C1D818E-682A-46A5-9D54-30006E26C270}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Profile Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Profile Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Profile Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Profile Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Profile Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Profile Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Profile Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Profile Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Profile Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Profile Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}.Profile Debug|Any CPU.ActiveCfg = Profile Debug|Any CPU
|
||||
{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}.Profile Debug|Any CPU.Build.0 = Profile Debug|Any CPU
|
||||
{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}.Profile Release|Any CPU.ActiveCfg = Profile Release|Any CPU
|
||||
{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
|
||||
{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{79E4EE34-9C5F-4BE6-8529-A49D32B5B0CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{990F9601-343E-46CB-8529-B498FA761A92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{990F9601-343E-46CB-8529-B498FA761A92}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{990F9601-343E-46CB-8529-B498FA761A92}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{990F9601-343E-46CB-8529-B498FA761A92}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{990F9601-343E-46CB-8529-B498FA761A92}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{990F9601-343E-46CB-8529-B498FA761A92}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{990F9601-343E-46CB-8529-B498FA761A92}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{990F9601-343E-46CB-8529-B498FA761A92}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Profile Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
|
|
|
@ -4,7 +4,6 @@ using Ryujinx.Common.Configuration;
|
|||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.SystemInfo;
|
||||
using Ryujinx.Configuration;
|
||||
using Ryujinx.Debugger.Profiler;
|
||||
using Ryujinx.Ui;
|
||||
using OpenTK;
|
||||
using System;
|
||||
|
@ -105,8 +104,6 @@ namespace Ryujinx
|
|||
|
||||
PrintSystemInfo();
|
||||
|
||||
Profile.Initialize();
|
||||
|
||||
Application.Init();
|
||||
|
||||
bool hasGlobalProdKeys = File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys"));
|
||||
|
|
|
@ -6,20 +6,10 @@
|
|||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>1.0.0-dirty</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Release|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;USE_DEBUGGING</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Due to .net core 3.1 embedded resource loading -->
|
||||
<PropertyGroup>
|
||||
<EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
|
||||
|
@ -90,7 +80,6 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Debugger\Ryujinx.Debugger.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
|
||||
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
|
||||
|
|
|
@ -7,17 +7,13 @@ using Ryujinx.Common.Configuration;
|
|||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.System;
|
||||
using Ryujinx.Configuration;
|
||||
using Ryujinx.Configuration.System;
|
||||
using Ryujinx.Debugger.Profiler;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.FileSystem.Content;
|
||||
using Ryujinx.HLE.HOS.Services.Hid;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -45,12 +41,6 @@ namespace Ryujinx.Ui
|
|||
private static bool _gameLoaded;
|
||||
private static bool _ending;
|
||||
|
||||
#pragma warning disable CS0169
|
||||
private static bool _debuggerOpened;
|
||||
|
||||
private static Debugger.Debugger _debugger;
|
||||
#pragma warning restore CS0169
|
||||
|
||||
#pragma warning disable CS0169, CS0649, IDE0044
|
||||
|
||||
[GUI] MenuBar _menuBar;
|
||||
|
@ -62,7 +52,6 @@ namespace Ryujinx.Ui
|
|||
[GUI] MenuItem _firmwareInstallDirectory;
|
||||
[GUI] MenuItem _firmwareInstallFile;
|
||||
[GUI] Label _hostStatus;
|
||||
[GUI] MenuItem _openDebugger;
|
||||
[GUI] CheckMenuItem _iconToggle;
|
||||
[GUI] CheckMenuItem _developerToggle;
|
||||
[GUI] CheckMenuItem _appToggle;
|
||||
|
@ -150,13 +139,6 @@ namespace Ryujinx.Ui
|
|||
if (ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn) _fileSizeToggle.Active = true;
|
||||
if (ConfigurationState.Instance.Ui.GuiColumns.PathColumn) _pathToggle.Active = true;
|
||||
|
||||
#if USE_DEBUGGING
|
||||
_debugger = new Debugger.Debugger();
|
||||
_openDebugger.Activated += _openDebugger_Opened;
|
||||
#else
|
||||
_openDebugger.Hide();
|
||||
#endif
|
||||
|
||||
_gameTable.Model = _tableStore = new ListStore(
|
||||
typeof(bool),
|
||||
typeof(Gdk.Pixbuf),
|
||||
|
@ -205,36 +187,6 @@ namespace Ryujinx.Ui
|
|||
_fullScreen.Label = args.Event.NewWindowState.HasFlag(Gdk.WindowState.Fullscreen) ? "Exit Fullscreen" : "Enter Fullscreen";
|
||||
}
|
||||
|
||||
#if USE_DEBUGGING
|
||||
private void _openDebugger_Opened(object sender, EventArgs e)
|
||||
{
|
||||
if (_debuggerOpened)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Window debugWindow = new Window("Debugger");
|
||||
|
||||
debugWindow.SetSizeRequest(1280, 640);
|
||||
debugWindow.Child = _debugger.Widget;
|
||||
debugWindow.DeleteEvent += DebugWindow_DeleteEvent;
|
||||
debugWindow.ShowAll();
|
||||
|
||||
_debugger.Enable();
|
||||
|
||||
_debuggerOpened = true;
|
||||
}
|
||||
|
||||
private void DebugWindow_DeleteEvent(object o, DeleteEventArgs args)
|
||||
{
|
||||
_debuggerOpened = false;
|
||||
|
||||
_debugger.Disable();
|
||||
|
||||
(_debugger.Widget.Parent as Window)?.Remove(_debugger.Widget);
|
||||
}
|
||||
#endif
|
||||
|
||||
internal static void ApplyTheme()
|
||||
{
|
||||
if (!ConfigurationState.Instance.Ui.EnableCustomTheme)
|
||||
|
@ -640,11 +592,6 @@ namespace Ryujinx.Ui
|
|||
|
||||
private void End(HLE.Switch device)
|
||||
{
|
||||
|
||||
#if USE_DEBUGGING
|
||||
_debugger.Dispose();
|
||||
#endif
|
||||
|
||||
if (_ending)
|
||||
{
|
||||
return;
|
||||
|
@ -668,7 +615,6 @@ namespace Ryujinx.Ui
|
|||
|
||||
Dispose();
|
||||
|
||||
Profile.FinishProfiling();
|
||||
DiscordIntegrationModule.Exit();
|
||||
|
||||
Ptc.Dispose();
|
||||
|
|
|
@ -295,14 +295,6 @@
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="_openDebugger">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Open Debugger</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
Reference in a new issue