From 6283bae8adc6ba59a26ae0fc5ae8812bf2fc0575 Mon Sep 17 00:00:00 2001 From: Andy Adshead Date: Fri, 15 Feb 2019 11:05:10 +0000 Subject: [PATCH] Inital seperated config support --- Ryujinx.Profiler/Profile.cs | 26 ++++++--- Ryujinx.Profiler/ProfilerConfig.jsonc | 18 ++++++ Ryujinx.Profiler/ProfilerConfiguration.cs | 70 +++++++++++++++++++++++ Ryujinx.Profiler/Ryujinx.Profiler.csproj | 6 ++ Ryujinx/Program.cs | 2 + 5 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 Ryujinx.Profiler/ProfilerConfig.jsonc create mode 100644 Ryujinx.Profiler/ProfilerConfiguration.cs diff --git a/Ryujinx.Profiler/Profile.cs b/Ryujinx.Profiler/Profile.cs index 8869865e51..ac980789c2 100644 --- a/Ryujinx.Profiler/Profile.cs +++ b/Ryujinx.Profiler/Profile.cs @@ -1,4 +1,5 @@ -using System; +using Ryujinx.Common; +using System; using System.Collections.Generic; using System.Diagnostics; @@ -12,6 +13,23 @@ namespace Ryujinx.Profiler private static InternalProfile _profileInstance; private static ProfilerSettings _settings; + + [Conditional("USE_PROFILING")] + public static void Initalize() + { + var config = ProfilerConfiguration.Load("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, + }; + } + public static bool ProfilingEnabled() { #if USE_PROFILING @@ -27,12 +45,6 @@ namespace Ryujinx.Profiler #endif } - [Conditional("USE_PROFILING")] - public static void Configure(ProfilerSettings settings) - { - _settings = settings; - } - [Conditional("USE_PROFILING")] public static void FinishProfiling() { diff --git a/Ryujinx.Profiler/ProfilerConfig.jsonc b/Ryujinx.Profiler/ProfilerConfig.jsonc new file mode 100644 index 0000000000..e716aebd4b --- /dev/null +++ b/Ryujinx.Profiler/ProfilerConfig.jsonc @@ -0,0 +1,18 @@ +{ + "$schema": "./_schema.json", + + // Enable profiling (Only available on a profiling enabled build) + "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, + + // Set how long to keep profiling data in seconds, reduce if profiling is taking too much RAM + "history": 5, + + // 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 +} \ No newline at end of file diff --git a/Ryujinx.Profiler/ProfilerConfiguration.cs b/Ryujinx.Profiler/ProfilerConfiguration.cs new file mode 100644 index 0000000000..411bcd3843 --- /dev/null +++ b/Ryujinx.Profiler/ProfilerConfiguration.cs @@ -0,0 +1,70 @@ +using OpenTK.Input; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Utf8Json; +using Utf8Json.Resolvers; + +namespace Ryujinx.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 float History { get; private set; } + + /// + /// Loads a configuration file from disk + /// + /// The path to the JSON configuration file + public static ProfilerConfiguration Load(string path) + { + var resolver = CompositeResolver.Create( + new[] { new ConfigurationEnumFormatter() }, + new[] { StandardResolver.AllowPrivateSnakeCase } + ); + + if (!File.Exists(path)) + { + throw new FileNotFoundException($"Profiler configuration file {path} not found"); + } + + using (Stream stream = File.OpenRead(path)) + { + return JsonSerializer.Deserialize(stream, resolver); + } + } + + private class ConfigurationEnumFormatter : IJsonFormatter + where T : struct + { + public void Serialize(ref JsonWriter writer, T value, IJsonFormatterResolver formatterResolver) + { + formatterResolver.GetFormatterWithVerify() + .Serialize(ref writer, value.ToString(), formatterResolver); + } + + public T Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) + { + if (reader.ReadIsNull()) + { + return default(T); + } + + var enumName = formatterResolver.GetFormatterWithVerify() + .Deserialize(ref reader, formatterResolver); + + if (Enum.TryParse(enumName, out T result)) + { + return result; + } + + return default(T); + } + } + } +} diff --git a/Ryujinx.Profiler/Ryujinx.Profiler.csproj b/Ryujinx.Profiler/Ryujinx.Profiler.csproj index 2115f6d7d2..5a4c8f4f92 100644 --- a/Ryujinx.Profiler/Ryujinx.Profiler.csproj +++ b/Ryujinx.Profiler/Ryujinx.Profiler.csproj @@ -30,4 +30,10 @@ + + + PreserveNewest + + + diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs index c14db0e765..3b65ea7774 100644 --- a/Ryujinx/Program.cs +++ b/Ryujinx/Program.cs @@ -26,6 +26,8 @@ namespace Ryujinx Configuration.Load(Path.Combine(ApplicationDirectory, "Config.jsonc")); Configuration.Configure(device); + Profile.Initalize(); + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;