highly experimental runtime model decimation + file cache adjustment to clean up processed file copies
This commit is contained in:
@@ -944,6 +944,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
VisiblePairSortMode.VramUsage => SortVisibleByMetric(entryList, e => e.LastAppliedApproximateVramBytes),
|
||||
VisiblePairSortMode.EffectiveVramUsage => SortVisibleByMetric(entryList, e => e.LastAppliedApproximateEffectiveVramBytes),
|
||||
VisiblePairSortMode.TriangleCount => SortVisibleByMetric(entryList, e => e.LastAppliedDataTris),
|
||||
VisiblePairSortMode.EffectiveTriangleCount => SortVisibleByMetric(entryList, e => e.LastAppliedApproximateEffectiveTris),
|
||||
VisiblePairSortMode.Alphabetical => [.. entryList.OrderBy(e => AlphabeticalSortKey(e), StringComparer.OrdinalIgnoreCase)],
|
||||
VisiblePairSortMode.PreferredDirectPairs => SortVisibleByPreferred(entryList),
|
||||
_ => SortEntries(entryList),
|
||||
|
||||
@@ -326,6 +326,7 @@ public class DrawFolderTag : DrawFolderBase
|
||||
VisiblePairSortMode.VramUsage => "VRAM usage (descending)",
|
||||
VisiblePairSortMode.EffectiveVramUsage => "Effective VRAM usage (descending)",
|
||||
VisiblePairSortMode.TriangleCount => "Triangle count (descending)",
|
||||
VisiblePairSortMode.EffectiveTriangleCount => "Effective triangle count (descending)",
|
||||
VisiblePairSortMode.PreferredDirectPairs => "Preferred permissions & Direct pairs",
|
||||
_ => "Default",
|
||||
};
|
||||
|
||||
@@ -429,6 +429,7 @@ public class DrawUserPair
|
||||
_pair.LastAppliedApproximateVRAMBytes,
|
||||
_pair.LastAppliedApproximateEffectiveVRAMBytes,
|
||||
_pair.LastAppliedDataTris,
|
||||
_pair.LastAppliedApproximateEffectiveTris,
|
||||
_pair.IsPaired,
|
||||
groupDisplays is null ? ImmutableArray<string>.Empty : ImmutableArray.CreateRange(groupDisplays));
|
||||
|
||||
@@ -444,6 +445,8 @@ public class DrawUserPair
|
||||
private static string BuildTooltip(in TooltipSnapshot snapshot)
|
||||
{
|
||||
var builder = new StringBuilder(256);
|
||||
static string FormatTriangles(long count) =>
|
||||
count > 1000 ? (count / 1000d).ToString("0.0'k'") : count.ToString();
|
||||
|
||||
if (snapshot.IsPaused)
|
||||
{
|
||||
@@ -510,9 +513,13 @@ public class DrawUserPair
|
||||
{
|
||||
builder.Append(Environment.NewLine);
|
||||
builder.Append("Approx. Triangle Count (excl. Vanilla): ");
|
||||
builder.Append(snapshot.LastAppliedDataTris > 1000
|
||||
? (snapshot.LastAppliedDataTris / 1000d).ToString("0.0'k'")
|
||||
: snapshot.LastAppliedDataTris);
|
||||
builder.Append(FormatTriangles(snapshot.LastAppliedDataTris));
|
||||
if (snapshot.LastAppliedApproximateEffectiveTris >= 0)
|
||||
{
|
||||
builder.Append(" (Effective: ");
|
||||
builder.Append(FormatTriangles(snapshot.LastAppliedApproximateEffectiveTris));
|
||||
builder.Append(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,11 +551,12 @@ public class DrawUserPair
|
||||
long LastAppliedApproximateVRAMBytes,
|
||||
long LastAppliedApproximateEffectiveVRAMBytes,
|
||||
long LastAppliedDataTris,
|
||||
long LastAppliedApproximateEffectiveTris,
|
||||
bool IsPaired,
|
||||
ImmutableArray<string> GroupDisplays)
|
||||
{
|
||||
public static TooltipSnapshot Empty { get; } =
|
||||
new(false, false, false, IndividualPairStatus.None, string.Empty, string.Empty, -1, -1, -1, -1, false, ImmutableArray<string>.Empty);
|
||||
new(false, false, false, IndividualPairStatus.None, string.Empty, string.Empty, -1, -1, -1, -1, -1, false, ImmutableArray<string>.Empty);
|
||||
}
|
||||
|
||||
private void DrawPairedClientMenu()
|
||||
|
||||
@@ -217,6 +217,7 @@ public class DrawEntityFactory
|
||||
entry.PairStatus,
|
||||
handler?.LastAppliedDataBytes ?? -1,
|
||||
handler?.LastAppliedDataTris ?? -1,
|
||||
handler?.LastAppliedApproximateEffectiveTris ?? -1,
|
||||
handler?.LastAppliedApproximateVRAMBytes ?? -1,
|
||||
handler?.LastAppliedApproximateEffectiveVRAMBytes ?? -1,
|
||||
handler);
|
||||
|
||||
@@ -415,7 +415,9 @@ public class IdDisplayHandler
|
||||
var vramBytes = pair.LastAppliedApproximateEffectiveVRAMBytes >= 0
|
||||
? pair.LastAppliedApproximateEffectiveVRAMBytes
|
||||
: pair.LastAppliedApproximateVRAMBytes;
|
||||
var triangleCount = pair.LastAppliedDataTris;
|
||||
var triangleCount = pair.LastAppliedApproximateEffectiveTris >= 0
|
||||
? pair.LastAppliedApproximateEffectiveTris
|
||||
: pair.LastAppliedDataTris;
|
||||
if (vramBytes < 0 && triangleCount < 0)
|
||||
{
|
||||
return null;
|
||||
|
||||
@@ -21,6 +21,7 @@ public sealed record PairUiEntry(
|
||||
IndividualPairStatus? PairStatus,
|
||||
long LastAppliedDataBytes,
|
||||
long LastAppliedDataTris,
|
||||
long LastAppliedApproximateEffectiveTris,
|
||||
long LastAppliedApproximateVramBytes,
|
||||
long LastAppliedApproximateEffectiveVramBytes,
|
||||
IPairHandlerAdapter? Handler)
|
||||
|
||||
@@ -7,4 +7,5 @@ public enum VisiblePairSortMode
|
||||
EffectiveVramUsage = 2,
|
||||
TriangleCount = 3,
|
||||
PreferredDirectPairs = 4,
|
||||
EffectiveTriangleCount = 5,
|
||||
}
|
||||
|
||||
@@ -574,6 +574,94 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTriangleDecimationCounters()
|
||||
{
|
||||
HashSet<Pair> trackedPairs = new();
|
||||
|
||||
var snapshot = _pairUiService.GetSnapshot();
|
||||
|
||||
foreach (var pair in snapshot.DirectPairs)
|
||||
{
|
||||
trackedPairs.Add(pair);
|
||||
}
|
||||
|
||||
foreach (var group in snapshot.GroupPairs.Values)
|
||||
{
|
||||
foreach (var pair in group)
|
||||
{
|
||||
trackedPairs.Add(pair);
|
||||
}
|
||||
}
|
||||
|
||||
long totalOriginalTris = 0;
|
||||
long totalEffectiveTris = 0;
|
||||
var hasData = false;
|
||||
|
||||
foreach (var pair in trackedPairs)
|
||||
{
|
||||
if (!pair.IsVisible)
|
||||
continue;
|
||||
|
||||
var original = pair.LastAppliedDataTris;
|
||||
var effective = pair.LastAppliedApproximateEffectiveTris;
|
||||
|
||||
if (original >= 0)
|
||||
{
|
||||
hasData = true;
|
||||
totalOriginalTris += original;
|
||||
}
|
||||
|
||||
if (effective >= 0)
|
||||
{
|
||||
hasData = true;
|
||||
totalEffectiveTris += effective;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasData)
|
||||
{
|
||||
ImGui.TextDisabled("Triangle usage has not been calculated yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
var savedTris = Math.Max(0L, totalOriginalTris - totalEffectiveTris);
|
||||
var originalText = FormatTriangleCount(totalOriginalTris);
|
||||
var effectiveText = FormatTriangleCount(totalEffectiveTris);
|
||||
var savedText = FormatTriangleCount(savedTris);
|
||||
|
||||
ImGui.TextUnformatted($"Total triangle usage (original): {originalText}");
|
||||
ImGui.TextUnformatted($"Total triangle usage (effective): {effectiveText}");
|
||||
|
||||
if (savedTris > 0)
|
||||
{
|
||||
UiSharedService.ColorText($"Triangles saved by decimation: {savedText}", UIColors.Get("LightlessGreen"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextUnformatted($"Triangles saved by decimation: {savedText}");
|
||||
}
|
||||
|
||||
static string FormatTriangleCount(long triangleCount)
|
||||
{
|
||||
if (triangleCount < 0)
|
||||
{
|
||||
return "n/a";
|
||||
}
|
||||
|
||||
if (triangleCount >= 1_000_000)
|
||||
{
|
||||
return FormattableString.Invariant($"{triangleCount / 1_000_000d:0.#}m tris");
|
||||
}
|
||||
|
||||
if (triangleCount >= 1_000)
|
||||
{
|
||||
return FormattableString.Invariant($"{triangleCount / 1_000d:0.#}k tris");
|
||||
}
|
||||
|
||||
return $"{triangleCount} tris";
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawThemeVectorRow(MainStyle.StyleVector2Option option)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
@@ -1495,6 +1583,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
DrawPairPropertyRow("Approx. VRAM", FormatBytes(pair.LastAppliedApproximateVRAMBytes));
|
||||
DrawPairPropertyRow("Effective VRAM", FormatBytes(pair.LastAppliedApproximateEffectiveVRAMBytes));
|
||||
DrawPairPropertyRow("Last Triangles", pair.LastAppliedDataTris < 0 ? "n/a" : pair.LastAppliedDataTris.ToString(CultureInfo.InvariantCulture));
|
||||
DrawPairPropertyRow("Effective Triangles", pair.LastAppliedApproximateEffectiveTris < 0 ? "n/a" : pair.LastAppliedApproximateEffectiveTris.ToString(CultureInfo.InvariantCulture));
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
@@ -3528,6 +3617,102 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
if (_uiShared.MediumTreeNode("Model Optimization", UIColors.Get("DimRed")))
|
||||
{
|
||||
_uiShared.MediumText("Warning", UIColors.Get("DimRed"));
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||
new SeStringUtils.RichTextEntry("Model decimation is a "),
|
||||
new SeStringUtils.RichTextEntry("destructive", UIColors.Get("DimRed"), true),
|
||||
new SeStringUtils.RichTextEntry(" process and may cause broken or incorrect character appearances."));
|
||||
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||
new SeStringUtils.RichTextEntry("this shit is placeholder still owo"));
|
||||
|
||||
var performanceConfig = _playerPerformanceConfigService.Current;
|
||||
var enableDecimation = performanceConfig.EnableModelDecimation;
|
||||
if (ImGui.Checkbox("Enable model decimation", ref enableDecimation))
|
||||
{
|
||||
performanceConfig.EnableModelDecimation = enableDecimation;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When enabled, Lightless generates a decimated copy of given model after download.");
|
||||
|
||||
var triangleThreshold = performanceConfig.ModelDecimationTriangleThreshold;
|
||||
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.SliderInt("Decimate models above", ref triangleThreshold, 10_000, 100_000))
|
||||
{
|
||||
performanceConfig.ModelDecimationTriangleThreshold = Math.Clamp(triangleThreshold, 10_000, 100_000);
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
ImGui.Text("triangles");
|
||||
_uiShared.DrawHelpText($"Models below this triangle count are left untouched.{UiSharedService.TooltipSeparator}Default: 50,000");
|
||||
|
||||
var targetPercent = (float)(performanceConfig.ModelDecimationTargetRatio * 100.0);
|
||||
var clampedPercent = Math.Clamp(targetPercent, 70f, 99f);
|
||||
if (Math.Abs(clampedPercent - targetPercent) > float.Epsilon)
|
||||
{
|
||||
performanceConfig.ModelDecimationTargetRatio = clampedPercent / 100.0;
|
||||
_playerPerformanceConfigService.Save();
|
||||
targetPercent = clampedPercent;
|
||||
}
|
||||
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.SliderFloat("Target triangle ratio", ref targetPercent, 70f, 99f, "%.0f%%"))
|
||||
{
|
||||
performanceConfig.ModelDecimationTargetRatio = Math.Clamp(targetPercent / 100f, 0.7f, 0.99f);
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText($"Target ratio relative to original triangle count (70% keeps 70% of triangles).{UiSharedService.TooltipSeparator}Default: 70%");
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
ImGui.TextUnformatted("Decimation targets");
|
||||
_uiShared.DrawHelpText("Hair mods are always excluded from decimation.");
|
||||
|
||||
var allowBody = performanceConfig.ModelDecimationAllowBody;
|
||||
if (ImGui.Checkbox("Body", ref allowBody))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowBody = allowBody;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
var allowFaceHead = performanceConfig.ModelDecimationAllowFaceHead;
|
||||
if (ImGui.Checkbox("Face/head", ref allowFaceHead))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowFaceHead = allowFaceHead;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
var allowTail = performanceConfig.ModelDecimationAllowTail;
|
||||
if (ImGui.Checkbox("Tails/Ears", ref allowTail))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowTail = allowTail;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
var allowClothing = performanceConfig.ModelDecimationAllowClothing;
|
||||
if (ImGui.Checkbox("Clothing (body/legs/shoes/gloves/hats)", ref allowClothing))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowClothing = allowClothing;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
var allowAccessories = performanceConfig.ModelDecimationAllowAccessories;
|
||||
if (ImGui.Checkbox("Accessories (earring/rings/bracelet/necklace)", ref allowAccessories))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowAccessories = allowAccessories;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
DrawTriangleDecimationCounters();
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
ImGui.Dummy(new Vector2(10));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user