1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-14 04:52:55 +08:00

Merge pull request #23034 from peppy/fix-ruleset-shader-caching

Fix stutters during gameplay due to shaders not correctly using cache
This commit is contained in:
Dean Herbert 2023-04-03 00:20:48 +09:00 committed by GitHub
commit ea42e7f3fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 43 additions and 33 deletions

View File

@ -11,7 +11,7 @@
<AndroidManifestMerger>manifestmerger.jar</AndroidManifestMerger> <AndroidManifestMerger>manifestmerger.jar</AndroidManifestMerger>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Framework.Android" Version="2023.327.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2023.402.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidManifestOverlay Include="$(MSBuildThisFileDirectory)osu.Android\Properties\AndroidManifestOverlay.xml" /> <AndroidManifestOverlay Include="$(MSBuildThisFileDirectory)osu.Android\Properties\AndroidManifestOverlay.xml" />

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
@ -51,9 +49,11 @@ namespace osu.Game.Tests.Testing
[Test] [Test]
public void TestRetrieveShader() public void TestRetrieveShader()
{ {
AddAssert("ruleset shaders retrieved", () => AddStep("ruleset shaders retrieved without error", () =>
Dependencies.Get<ShaderManager>().LoadRaw(@"sh_TestVertex.vs") != null && {
Dependencies.Get<ShaderManager>().LoadRaw(@"sh_TestFragment.fs") != null); Dependencies.Get<ShaderManager>().LoadRaw(@"sh_TestVertex.vs");
Dependencies.Get<ShaderManager>().LoadRaw(@"sh_TestFragment.fs");
});
} }
[Test] [Test]
@ -76,12 +76,12 @@ namespace osu.Game.Tests.Testing
} }
public override IResourceStore<byte[]> CreateResourceStore() => new NamespacedResourceStore<byte[]>(TestResources.GetStore(), @"Resources"); public override IResourceStore<byte[]> CreateResourceStore() => new NamespacedResourceStore<byte[]>(TestResources.GetStore(), @"Resources");
public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new TestRulesetConfigManager(); public override IRulesetConfigManager CreateConfig(SettingsStore? settings) => new TestRulesetConfigManager();
public override IEnumerable<Mod> GetModsFor(ModType type) => Array.Empty<Mod>(); public override IEnumerable<Mod> GetModsFor(ModType type) => Array.Empty<Mod>();
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => null; public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod>? mods = null) => null!;
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null!;
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null!;
} }
private class TestRulesetConfigManager : IRulesetConfigManager private class TestRulesetConfigManager : IRulesetConfigManager

View File

@ -55,7 +55,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu
set => valueText.Text = value.ToLocalisableString("N0"); set => valueText.Text = value.ToLocalisableString("N0");
} }
public CountSection(LocalisableString header) protected CountSection(LocalisableString header)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;

View File

@ -75,7 +75,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
if (window != null) if (window != null)
{ {
currentDisplay.BindTo(window.CurrentDisplayBindable); currentDisplay.BindTo(window.CurrentDisplayBindable);
windowModes.BindTo(window.SupportedWindowModes);
window.DisplaysChanged += onDisplaysChanged; window.DisplaysChanged += onDisplaysChanged;
} }
@ -87,7 +86,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
windowModeDropdown = new SettingsDropdown<WindowMode> windowModeDropdown = new SettingsDropdown<WindowMode>
{ {
LabelText = GraphicsSettingsStrings.ScreenMode, LabelText = GraphicsSettingsStrings.ScreenMode,
ItemSource = windowModes, Items = window?.SupportedWindowModes,
Current = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode), Current = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
}, },
displayDropdown = new DisplaySettingsDropdown displayDropdown = new DisplaySettingsDropdown

View File

@ -25,21 +25,28 @@ namespace osu.Game.Rulesets.UI
/// <summary> /// <summary>
/// The texture store to be used for the ruleset. /// The texture store to be used for the ruleset.
/// </summary> /// </summary>
/// <remarks>
/// Reads textures from the "Textures" folder in ruleset resources.
/// If not available locally, lookups will fallback to the global texture store.
/// </remarks>
public TextureStore TextureStore { get; } public TextureStore TextureStore { get; }
/// <summary> /// <summary>
/// The sample store to be used for the ruleset. /// The sample store to be used for the ruleset.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This is the local sample store pointing to the ruleset sample resources, /// Reads samples from the "Samples" folder in ruleset resources.
/// the cached sample store (<see cref="FallbackSampleStore"/>) retrieves from /// If not available locally, lookups will fallback to the global sample store.
/// this store and falls back to the parent store if this store doesn't have the requested sample.
/// </remarks> /// </remarks>
public ISampleStore SampleStore { get; } public ISampleStore SampleStore { get; }
/// <summary> /// <summary>
/// The shader manager to be used for the ruleset. /// The shader manager to be used for the ruleset.
/// </summary> /// </summary>
/// <remarks>
/// Reads shaders from the "Shaders" folder in ruleset resources.
/// If not available locally, lookups will fallback to the global shader manager.
/// </remarks>
public ShaderManager ShaderManager { get; } public ShaderManager ShaderManager { get; }
/// <summary> /// <summary>
@ -61,8 +68,7 @@ namespace osu.Game.Rulesets.UI
SampleStore.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; SampleStore.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY;
CacheAs(SampleStore = new FallbackSampleStore(SampleStore, parent.Get<ISampleStore>())); CacheAs(SampleStore = new FallbackSampleStore(SampleStore, parent.Get<ISampleStore>()));
ShaderManager = new ShaderManager(host.Renderer, new NamespacedResourceStore<byte[]>(resources, @"Shaders")); CacheAs(ShaderManager = new RulesetShaderManager(host.Renderer, new NamespacedResourceStore<byte[]>(resources, @"Shaders"), parent.Get<ShaderManager>()));
CacheAs(ShaderManager = new FallbackShaderManager(host.Renderer, ShaderManager, parent.Get<ShaderManager>()));
RulesetConfigManager = parent.Get<IRulesetConfigCache>().GetConfigFor(ruleset); RulesetConfigManager = parent.Get<IRulesetConfigCache>().GetConfigFor(ruleset);
if (RulesetConfigManager != null) if (RulesetConfigManager != null)
@ -190,24 +196,27 @@ namespace osu.Game.Rulesets.UI
} }
} }
private class FallbackShaderManager : ShaderManager private class RulesetShaderManager : ShaderManager
{ {
private readonly ShaderManager primary; private readonly ShaderManager parent;
private readonly ShaderManager fallback;
public FallbackShaderManager(IRenderer renderer, ShaderManager primary, ShaderManager fallback) public RulesetShaderManager(IRenderer renderer, NamespacedResourceStore<byte[]> rulesetResources, ShaderManager parent)
: base(renderer, new ResourceStore<byte[]>()) : base(renderer, rulesetResources)
{ {
this.primary = primary; this.parent = parent;
this.fallback = fallback;
} }
public override byte[]? LoadRaw(string name) => primary.LoadRaw(name) ?? fallback.LoadRaw(name); public override IShader Load(string vertex, string fragment)
protected override void Dispose(bool disposing)
{ {
base.Dispose(disposing); try
if (primary.IsNotNull()) primary.Dispose(); {
return base.Load(vertex, fragment);
}
catch
{
// Shader lookup is very non-standard. Rather than returning null on missing shaders, exceptions are thrown.
return parent.Load(vertex, fragment);
}
} }
} }
} }

View File

@ -130,6 +130,8 @@ namespace osu.Game.Screens
loadTargets.Add(manager.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE)); loadTargets.Add(manager.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE));
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_2, "TriangleBorder"));
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE)); loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE));
} }

View File

@ -36,8 +36,8 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Realm" Version="10.20.0" /> <PackageReference Include="Realm" Version="10.20.0" />
<PackageReference Include="ppy.osu.Framework" Version="2023.327.0" /> <PackageReference Include="ppy.osu.Framework" Version="2023.402.1" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2023.320.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2023.402.0" />
<PackageReference Include="Sentry" Version="3.28.1" /> <PackageReference Include="Sentry" Version="3.28.1" />
<PackageReference Include="SharpCompress" Version="0.32.2" /> <PackageReference Include="SharpCompress" Version="0.32.2" />
<PackageReference Include="NUnit" Version="3.13.3" /> <PackageReference Include="NUnit" Version="3.13.3" />

View File

@ -16,6 +16,6 @@
<RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier> <RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Framework.iOS" Version="2023.327.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2023.402.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>