Skip to content

Commit d2b609a

Browse files
committed
1.0.8
1 parent d4f5983 commit d2b609a

10 files changed

Lines changed: 400 additions & 148 deletions

File tree

Packages/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44
# Change this to match your new package name
55
!blueamulet.udonsharpoptimizer
66
!USOPatch.csproj
7-
!USOPatch.sln
7+
!USOPatch.sln
8+
OptimizerSettings.asset
9+
OptimizerSettings.asset.meta

Packages/blueamulet.udonsharpoptimizer/Editor/Optimizer.cs

Lines changed: 172 additions & 142 deletions
Large diffs are not rendered by default.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using UnityEditor;
2+
using UnityEngine;
3+
4+
namespace UdonSharpOptimizer
5+
{
6+
internal class OptimizerEditorWindow : EditorWindow
7+
{
8+
OptimizerSettings _settings;
9+
SerializedObject _settingsSO;
10+
SerializedProperty _optimizerEnabled;
11+
SerializedProperty _optimization1;
12+
SerializedProperty _optimization2;
13+
SerializedProperty _optimization3;
14+
SerializedProperty _optimization4;
15+
SerializedProperty _optimizationVar;
16+
SerializedProperty _optimizationThis;
17+
18+
[MenuItem("Tools/UdonSharp Optimizer")]
19+
public static void ShowWindow()
20+
{
21+
EditorWindow.GetWindow<OptimizerEditorWindow>("UdonSharp Optimizer");
22+
}
23+
24+
public void OnEnable()
25+
{
26+
_settings = OptimizerSettings.Instance;
27+
_settingsSO = new SerializedObject(_settings);
28+
_optimizerEnabled = _settingsSO.FindProperty(nameof(OptimizerSettings.EnableOptimizer));
29+
_optimization1 = _settingsSO.FindProperty(nameof(OptimizerSettings.EnableOPT01));
30+
_optimization2 = _settingsSO.FindProperty(nameof(OptimizerSettings.EnableOPT02));
31+
_optimization3 = _settingsSO.FindProperty(nameof(OptimizerSettings.EnableOPT03));
32+
_optimization4 = _settingsSO.FindProperty(nameof(OptimizerSettings.EnableOPT04));
33+
_optimizationVar = _settingsSO.FindProperty(nameof(OptimizerSettings.EnableVariableReduction));
34+
_optimizationThis = _settingsSO.FindProperty(nameof(OptimizerSettings.EnableThisBugFix));
35+
}
36+
37+
public void OnGUI()
38+
{
39+
// TODO: How to properly do this?
40+
if (_settingsSO == null)
41+
{
42+
OnEnable();
43+
}
44+
45+
GUIStyle richStyle = new GUIStyle(EditorStyles.label);
46+
richStyle.richText = true;
47+
48+
// Optimizer status
49+
EditorGUILayout.LabelField("Status:", EditorStyles.boldLabel);
50+
AlignedText("Optimizer:", $"<color={(OptimizerInject.PatchSuccess ? "lime>Activated" : "orange><b>Failed to inject</b>")}</color>", richStyle);
51+
int patchFailures = Optimizer.PatchFailures;
52+
EditorGUILayout.BeginHorizontal();
53+
EditorGUILayout.PrefixLabel("Patches:");
54+
if (patchFailures == 0)
55+
{
56+
EditorGUILayout.LabelField($"<color=lime>{patchFailures} patch failures</color>", richStyle);
57+
}
58+
else
59+
{
60+
EditorGUILayout.LabelField($"<color=orange><b>{patchFailures} patch failures</b></color>", richStyle);
61+
}
62+
EditorGUILayout.EndHorizontal();
63+
EditorGUILayout.Space();
64+
65+
// Settings
66+
EditorGUILayout.LabelField("Settings:", EditorStyles.boldLabel);
67+
EditorGUI.BeginChangeCheck();
68+
EditorGUILayout.PropertyField(_optimizerEnabled, false);
69+
EditorGUILayout.Space();
70+
using (new EditorGUI.DisabledScope(!_settings.EnableOptimizer))
71+
{
72+
EditorGUILayout.PropertyField(_optimization1, false);
73+
EditorGUILayout.PropertyField(_optimization2, false);
74+
EditorGUILayout.PropertyField(_optimization3, false);
75+
EditorGUILayout.PropertyField(_optimization4, false);
76+
EditorGUILayout.PropertyField(_optimizationVar, false);
77+
using (new EditorGUI.DisabledScope(!_settings.EnableVariableReduction))
78+
{
79+
EditorGUILayout.PropertyField(_optimizationThis, false);
80+
}
81+
}
82+
if (EditorGUI.EndChangeCheck())
83+
{
84+
_settingsSO.ApplyModifiedProperties();
85+
}
86+
87+
// Last Build information
88+
EditorGUILayout.Space();
89+
EditorGUILayout.LabelField("Last Build:", EditorStyles.boldLabel);
90+
AlignedText("Instructions:", $"{Optimizer.RemovedInstructions} removed", EditorStyles.label);
91+
AlignedText("Variables:", $"{Optimizer.RemovedVariables} removed", EditorStyles.label);
92+
AlignedText("Extra __this:", $"{Optimizer.RemovedThisTotal} removed", EditorStyles.label);
93+
}
94+
95+
private static void AlignedText(string prefix, string text, GUIStyle style)
96+
{
97+
EditorGUILayout.BeginHorizontal();
98+
EditorGUILayout.PrefixLabel(prefix);
99+
EditorGUILayout.LabelField(text, style);
100+
EditorGUILayout.EndHorizontal();
101+
}
102+
}
103+
}

Packages/blueamulet.udonsharpoptimizer/Editor/OptimizerEditorWindow.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Packages/blueamulet.udonsharpoptimizer/Editor/OptimizerInject.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,20 @@
1313
using UnityEditor;
1414
using UnityEngine;
1515

16+
#pragma warning disable IDE0090 // Use 'new(...)'
17+
1618
namespace UdonSharpOptimizer
1719
{
1820
[InitializeOnLoad]
19-
public static class OptimizerInject
21+
internal static class OptimizerInject
2022
{
2123
private const string HARMONY_ID = "BlueAmulet.USOptimizer.Injector";
22-
private static Harmony harmony;
24+
private static readonly Harmony harmony;
2325
private static readonly MethodInfo optimizerInject = AccessTools.Method(typeof(Optimizer), nameof(Optimizer.OptimizeProgram));
2426

27+
private static bool patchSuccess;
28+
public static bool PatchSuccess { get => patchSuccess; }
29+
2530
static OptimizerInject()
2631
{
2732
harmony = new Harmony(HARMONY_ID);
@@ -100,6 +105,7 @@ private static IEnumerable<CodeInstruction> TranspilerDump(IEnumerable<CodeInstr
100105
}
101106
}
102107

108+
patchSuccess = patched || already;
103109
if (patched)
104110
{
105111
Debug.Log("[Optimizer] Activated");
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using System.IO;
3+
using System.Runtime.CompilerServices;
4+
using UnityEditor;
5+
using UnityEngine;
6+
7+
#pragma warning disable IDE0029 // Use coalesce expression
8+
#pragma warning disable RCS1084 // Use coalesce expression instead of conditional expression
9+
10+
namespace UdonSharpOptimizer
11+
{
12+
internal class OptimizerSettings : ScriptableObject
13+
{
14+
[Tooltip("Enable or disable the optimizer entirely")]
15+
public bool EnableOptimizer = true;
16+
17+
[Tooltip("Targets COPY+JUMP_IF_FALSE")]
18+
public bool EnableOPT01 = true;
19+
[Tooltip("Targets EXTERN+COPY")]
20+
public bool EnableOPT02 = true;
21+
[Tooltip("Targets Unread COPY (Cow dirty)")]
22+
public bool EnableOPT03 = true;
23+
[Tooltip("Performs Tail Call Optimization")]
24+
public bool EnableOPT04 = true;
25+
[Tooltip("Reduce amount of temporary variables")]
26+
public bool EnableVariableReduction = true;
27+
[Tooltip("Fix extra __this_ variables")]
28+
public bool EnableThisBugFix = true;
29+
30+
private static OptimizerSettings _instance;
31+
32+
public static OptimizerSettings Instance => _instance != null ? _instance : (_instance = LoadAsset());
33+
34+
private static OptimizerSettings LoadAsset()
35+
{
36+
string path = GetAssetPath();
37+
OptimizerSettings asset = AssetDatabase.LoadAssetAtPath<OptimizerSettings>(path);
38+
39+
if (asset == null)
40+
{
41+
asset = CreateInstance<OptimizerSettings>();
42+
AssetDatabase.CreateAsset(asset, path);
43+
AssetDatabase.SaveAssets();
44+
}
45+
46+
return asset;
47+
}
48+
49+
private static string GetAssetPath([CallerFilePath] string callerFilePath = null)
50+
{
51+
// TODO: This cannot be the correct way to do this ...
52+
string path = Path.GetDirectoryName(callerFilePath);
53+
path = Path.Combine(path, "OptimizerSettings.asset");
54+
#if NET_UNITY_4_8
55+
path = Path.GetRelativePath(Path.GetDirectoryName(Application.dataPath), path);
56+
#else
57+
path = GetRelativePath(Path.GetDirectoryName(Application.dataPath), path);
58+
#endif
59+
return path.Replace("\\", "/");
60+
}
61+
62+
#if !NET_UNITY_4_8
63+
private static string GetRelativePath(string fromPath, string toPath)
64+
{
65+
if (!fromPath.EndsWith(Path.DirectorySeparatorChar.ToString()) && !fromPath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
66+
{
67+
fromPath += Path.DirectorySeparatorChar;
68+
}
69+
Uri fromUri = new Uri(fromPath);
70+
Uri toUri = new Uri(toPath);
71+
if (fromUri.Scheme != toUri.Scheme)
72+
{
73+
return toPath;
74+
}
75+
return Uri.UnescapeDataString(fromUri.MakeRelativeUri(toUri).ToString());
76+
}
77+
#endif
78+
}
79+
}

Packages/blueamulet.udonsharpoptimizer/Editor/OptimizerSettings.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Packages/blueamulet.udonsharpoptimizer/README.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
This is an experimental optimizer for UdonSharp to remove unnecessary instructions and variables, resulting in smaller and faster code.
22

3-
No permanent changes are made to the VRCSDK, all changes are made in memory and can be easily removed by removing this UdonSharpOptimizer folder.
3+
After any UdonSharp compile, a line will appear in the console similar to the following:
4+
[Optimizer] Removed # instructions, # variables, and # extra __this total
5+
6+
No permanent changes are made to the VRCSDK, all changes are made in memory and can be easily removed by removing this package.
47

58
The USOPatch.dll included is part of the non permanent change system, allowing the optimizer access to UdonSharp's internals. The source code for this dll is included in the USOPatch folder
69

@@ -12,4 +15,5 @@ Changelog:
1215
1.0.4 - __this_ fix for even less variables
1316
1.0.5 - Added ExternWrite+Copy check for variables, added missing jump checks
1417
1.0.6 - Added tail call optimization
15-
1.0.7 - Single .unitypackage installation
18+
1.0.7 - Single .unitypackage installation
19+
1.0.8 - Added basic Settings panel

Packages/blueamulet.udonsharpoptimizer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "blueamulet.udonsharpoptimizer",
33
"displayName": "UdonSharpOptimizer",
4-
"version": "1.0.7",
4+
"version": "1.0.8",
55
"description": "UdonSharp postprocessor to reduce instruction and variable counts",
66
"gitDependencies": {},
77
"vpmDependencies": {

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
[VCC Listing](https://blueamulet.github.io/UdonSharpOptimizer/)
33
Adds a hook to UdonSharp to process the generated Udon, reducing the number of instructions and making better use of temporary variables, as well as fixing a bug resulting in unnecessary variables. This results in udon programs that are faster and smaller.
44

5+
After any UdonSharp compile, a line will appear in the console similar to the following:
6+
`[Optimizer] Removed # instructions, # variables, and # extra __this total`
7+
8+
No permanent changes are made to the VRCSDK, all changes are made in memory and can be easily removed by removing this package.
9+
510
## Optimizations
611
There are currently 3 class of optimizations:
712
### COPY Removal:
@@ -20,3 +25,4 @@ UdonSharp makes a *LOT* of temporary variables. We detect places where we can re
2025
1.0.5 - Added ExternWrite+Copy check for variables, added missing jump checks
2126
1.0.6 - Added tail call optimization
2227
1.0.7 - Single .unitypackage installation
28+
1.0.8 - Added basic Settings panel

0 commit comments

Comments
 (0)