Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
exit $exit_code

- name: InspectCode
uses: JetBrains/ReSharper-InspectCode@v0.11
uses: JetBrains/ReSharper-InspectCode@v0.12
with:
# this is WTF tier but if you don't specify *both* of these the defaults assume `build: true`
build: false
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,35 @@ This fork ([winnerspiros/osu-framework](https://github.com/winnerspiros/osu-fram
- Hot-path LINQ allocations eliminated across the framework (replaced with `for` loops, span-based code, and cached collections).
- `object`-based locks migrated to `System.Threading.Lock` for lower overhead on modern runtimes.
- BASS audio, GL state-change, shader warm-up, texture upload, and mobile vertex-batching improvements.
- **GridContainer cell sizing** uses `RequiredParentSizeToFit` instead of `BoundingBox`, avoiding redundant matrix-to-parent-space transforms on every layout pass ([upstream Issue #3215](https://github.com/ppy/osu-framework/issues/3215)).

### Direct3D 12 renderer support

- Added `RendererType.Direct3D12` / `RendererType.Deferred_Direct3D12` and `GraphicsSurfaceType.Direct3D12`.
- Full pipeline: `VeldridDevice.CreateD3D12` swapchain creation, `LogD3D12` diagnostics (adapter info, Enhanced Barriers, Mesh Shaders, VRS, Raytracing support), and `PersistentStagingBuffer` staging.
- D3D12 is included in the Windows renderer fallback order (after D3D11, before OpenGL).
- Leverages the [winnerspiros/veldrid](https://github.com/winnerspiros/veldrid) submodule which contains a full D3D12 backend.

### Low-latency rendering infrastructure

- Generic `ILowLatencyProvider` interface for GPU-side latency reduction (NVIDIA Reflex, LatencyFlex, or any future API).
- `IDirect3D11LowLatencyProvider` (D3D11-specific) extends `ILowLatencyProvider`.
- `NoOpLowLatencyProvider` (default no-op) and `NoOpDirect3D11LowLatencyProvider` included.
- Latency markers (`SimulationStart/End`, `RenderSubmitStart/End`, `PresentStart/End`, `InputSample`, `TriggerFlash`) inserted into `GameHost.UpdateFrame()` and `GameHost.DrawFrame()`.
- `FrameSleep()` called at the start of each update frame for provider-controlled sleep (Reflex Boost mode).
- Provider auto-initialises on the draw thread using the native D3D11 or D3D12 device handle from Veldrid's `BackendInfoD3D11` / `BackendInfoD3D12`.
- `LatencyMode` setting (`Off` / `On` / `Boost`) added to `FrameworkConfigManager`.
- Inspired by [upstream PR #6666](https://github.com/ppy/osu-framework/pull/6666).

### Frame rate limiter enhancements

- **Unbuffered VSync (`UVSync`)**: Limits both draw *and* update threads to the exact display refresh rate. Useful for VRR/G-Sync/FreeSync displays where regular VSync introduces unwanted buffering ([upstream PR #6696](https://github.com/ppy/osu-framework/pull/6696)).
- **Custom FPS limiter**: `FrameSync.Custom` mode with a `CustomDrawLimit` setting (0–1000 Hz). When set to 0, the draw thread is unlimited. Update thread runs at max Hz. Useful for benchmarking or VRR-specific tuning ([upstream PR #6725](https://github.com/ppy/osu-framework/pull/6725)).

### Input latency improvements

- **Raw keyboard input on Windows**: `SDL_HINT_WINDOWS_RAW_KEYBOARD` enabled by default, bypassing the Windows message translation layer for lower-latency key events ([upstream PR #6507](https://github.com/ppy/osu-framework/pull/6507)).
- **Async keyboard event handling**: When text input (IME) is not active, keyboard events (`KEY_DOWN`/`KEY_UP`) are handled directly in SDL's event filter (`HandleEventFromFilter`), bypassing the SDL event queue for reduced input-to-render latency ([upstream PR #6506](https://github.com/ppy/osu-framework/pull/6506)).

### Code quality

Expand Down
3 changes: 3 additions & 0 deletions osu.Framework.Android.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
<NullabilityInfoContextSupport>true</NullabilityInfoContextSupport>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<NoWarn>$(NoWarn);XA4218</NoWarn>
<!-- Suppress benign JAVAC warnings about Kotlin annotation enum constants
(AnnotationTarget.*, AnnotationRetention.BINARY) that Java doesn't recognise. -->
<AndroidJavacAdditionalArguments>-Xlint:-classfile</AndroidJavacAdditionalArguments>
</PropertyGroup>
<!-- Android release performance optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
Expand Down
18 changes: 18 additions & 0 deletions osu.Framework.Android/AndroidGameHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ protected override void SetupConfig(IDictionary<FrameworkSetting, object> defaul
base.SetupConfig(defaultOverrides);
}

protected override void SetupForRun()
{
base.SetupForRun();

// Set the main thread to THREAD_PRIORITY_DISPLAY (-4) for scheduler prioritisation.
// In SingleThread mode (the default on Android), the main thread handles all game threads
// including rendering. This gives the rendering work higher scheduler priority.
try
{
global::Android.OS.Process.SetThreadPriority(global::Android.OS.ThreadPriority.Display);
Logger.Log("Android thread priority set to THREAD_PRIORITY_DISPLAY.", LoggingTarget.Runtime, LogLevel.Important);
}
catch (Exception ex)
{
Logger.Log($"Failed to set Android thread priority: {ex.Message}", LoggingTarget.Runtime, LogLevel.Debug);
}
}

protected override IWindow CreateWindow(GraphicsSurfaceType preferredSurface) => new AndroidGameWindow(preferredSurface, Options.FriendlyGameName);

protected override void DrawFrame()
Expand Down
5 changes: 4 additions & 1 deletion osu.Framework.iOS.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
<!-- MT7091 occurs when referencing a .framework bundle that consists of a static library.
It only warns about not copying the library to the app bundle to save space,
so there's nothing to be worried about. -->
<NoWarn>$(NoWarn);MT7091</NoWarn>
<!-- IL2104: Suppress assembly-level trim warnings from third-party libraries we cannot annotate
(HidSharpCore, Microsoft.Diagnostics.Runtime, Newtonsoft.Json, nunit.framework,
OpenTabletDriver, osuTK, ppy.Veldrid.SPIRV, SharpGen.Runtime, System.Private.Xml, Commons.Music.Midi). -->
<NoWarn>$(NoWarn);MT7091;IL2104</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<!-- On debug configurations, we use Mono interpreter for faster compilation. -->
Expand Down
2 changes: 2 additions & 0 deletions osu.Framework/Allocation/ResolvedAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
Expand Down Expand Up @@ -74,6 +75,7 @@ public ResolvedAttribute(Type parent = null, string name = null, bool canBeNull
CanBeNull = canBeNull;
}

[UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "Types used with DI are preserved by the framework's dependency container.")]
internal static InjectDependencyDelegate CreateActivator(Type type)
{
count_reflection_attributes.Value++;
Expand Down
6 changes: 6 additions & 0 deletions osu.Framework/Configuration/FrameSync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ public enum FrameSync
{
VSync,

[Description("VSync Unbuffered")]
UVSync,

[Description("2x refresh rate")]
Limit2x,

Expand All @@ -23,5 +26,8 @@ public enum FrameSync

[Description("Basically unlimited")]
Unlimited,

[Description("Custom")]
Custom,
}
}
5 changes: 5 additions & 0 deletions osu.Framework/Configuration/FrameworkConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Drawing;
using osu.Framework.Configuration.Tracking;
using osu.Framework.Extensions;
using osu.Framework.Graphics.Rendering.LowLatency;
using osu.Framework.Graphics.Video;
using osu.Framework.Input;
using osu.Framework.Platform;
Expand Down Expand Up @@ -40,8 +41,10 @@ protected override void InitialiseDefaults()
SetDefault(FrameworkSetting.SizeFullscreen, new Size(9999, 9999), new Size(320, 240));
SetDefault(FrameworkSetting.MinimiseOnFocusLossInFullscreen, RuntimeInfo.IsDesktop);
SetDefault(FrameworkSetting.FrameSync, FrameSync.Limit2x);
SetDefault(FrameworkSetting.CustomDrawLimit, 0, 0, 1000);
SetDefault(FrameworkSetting.WindowMode, WindowMode.Windowed);
SetDefault(FrameworkSetting.Renderer, RendererType.Automatic);
SetDefault(FrameworkSetting.LatencyMode, LatencyMode.Off);
SetDefault(FrameworkSetting.ShowUnicode, false);
SetDefault(FrameworkSetting.Locale, string.Empty);

Expand Down Expand Up @@ -101,8 +104,10 @@ public enum FrameworkSetting

Renderer,
WindowMode,
LatencyMode,
ConfineMouseMode,
FrameSync,
CustomDrawLimit,
ExecutionMode,

ShowUnicode,
Expand Down
6 changes: 6 additions & 0 deletions osu.Framework/Configuration/RendererType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public enum RendererType
[Description("Direct3D 11")]
Direct3D11,

[Description("Direct3D 12")]
Direct3D12,

/// <summary>
/// Uses <see cref="GLRenderer"/>.
/// </summary>
Expand All @@ -44,6 +47,9 @@ public enum RendererType
[Description("Direct3D 11 (Experimental)")]
Deferred_Direct3D11,

[Description("Direct3D 12 (Experimental)")]
Deferred_Direct3D12,

[Description("OpenGL (Experimental)")]
Deferred_OpenGL
}
Expand Down
2 changes: 2 additions & 0 deletions osu.Framework/Configuration/TypedRepopulatingConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
Expand Down Expand Up @@ -39,6 +40,7 @@ public override IReadOnlyList<T> ReadJson(JsonReader reader, Type objectType, IR
return existingList;
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Configuration types are preserved by the framework.")]
public override void WriteJson(JsonWriter writer, IReadOnlyList<T> value, JsonSerializer serializer)
{
var objects = new List<JObject>();
Expand Down
3 changes: 2 additions & 1 deletion osu.Framework/Development/ReflectionUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using osu.Framework.Extensions.TypeExtensions;
Expand Down Expand Up @@ -46,7 +47,7 @@ internal static class ReflectionUtils
/// <param name="fixtureType">The type to examine.</param>
/// <param name="attributeType">Only methods to which this attribute is applied will be returned.</param>
/// <param name="inherit">Specifies whether to search the fixture type inheritance chain.</param>
internal static MethodInfo[] GetMethodsWithAttribute(Type fixtureType, Type attributeType, bool inherit)
internal static MethodInfo[] GetMethodsWithAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type fixtureType, Type attributeType, bool inherit)
{
if (!inherit)
{
Expand Down
2 changes: 2 additions & 0 deletions osu.Framework/Extensions/OSPlatformExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.Versioning;
Expand All @@ -19,6 +20,7 @@ public static class OSPlatformExtensions
/// <remarks>
/// This is only a naive check of attributes defined directly on this member, and doesn't account for the (un)supported platforms of the containing class or assembly.
/// </remarks>
[UnconditionalSuppressMessage("Trimming", "IL2045", Justification = "Platform attributes are always preserved by the runtime.")]
public static bool IsSupportedOnCurrentOSPlatform(this MemberInfo member)
{
var supported = member.GetCustomAttributes<SupportedOSPlatformAttribute>().ToArray();
Expand Down
4 changes: 2 additions & 2 deletions osu.Framework/Graphics/Containers/GridContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ private float[] getCellSizesAlongAxis(Axes axis, float spanLength)
}

private static bool shouldConsiderCell(Drawable cell) => cell != null && cell.IsAlive && cell.IsPresent;
private static float getCellWidth(Drawable cell) => shouldConsiderCell(cell) ? cell.BoundingBox.Width : 0;
private static float getCellHeight(Drawable cell) => shouldConsiderCell(cell) ? cell.BoundingBox.Height : 0;
private static float getCellWidth(Drawable cell) => shouldConsiderCell(cell) ? cell.RequiredParentSizeToFit.X : 0;
private static float getCellHeight(Drawable cell) => shouldConsiderCell(cell) ? cell.RequiredParentSizeToFit.Y : 0;

/// <summary>
/// Distributes any available length along all distributed dimensions, if required.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 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.

namespace osu.Framework.Graphics.Rendering.LowLatency
{
/// <summary>
/// Low-latency provider specifically for Direct3D 11 backends (e.g. NVIDIA Reflex via D3D11).
/// </summary>
public interface IDirect3D11LowLatencyProvider : ILowLatencyProvider
{
}
}
24 changes: 24 additions & 0 deletions osu.Framework/Graphics/Rendering/LowLatency/ILowLatencyProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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.

using System;

namespace osu.Framework.Graphics.Rendering.LowLatency
{
/// <summary>
/// Generic low-latency provider interface supporting any graphics backend.
/// Implementations may use NVIDIA Reflex, LatencyFlex, or other latency reduction APIs.
/// </summary>
public interface ILowLatencyProvider
{
bool IsAvailable { get; }

void Initialize(IntPtr nativeDeviceHandle);

void SetMode(LatencyMode mode);

void SetMarker(LatencyMarker marker, ulong frameId);

void FrameSleep();
}
}
17 changes: 17 additions & 0 deletions osu.Framework/Graphics/Rendering/LowLatency/LatencyMarker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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.

namespace osu.Framework.Graphics.Rendering.LowLatency
{
public enum LatencyMarker
{
SimulationStart,
SimulationEnd,
RenderSubmitStart,
RenderSubmitEnd,
PresentStart,
PresentEnd,
InputSample,
TriggerFlash
}
}
12 changes: 12 additions & 0 deletions osu.Framework/Graphics/Rendering/LowLatency/LatencyMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 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.

namespace osu.Framework.Graphics.Rendering.LowLatency
{
public enum LatencyMode
{
Off = 0,
On = 1,
Boost = 2
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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.

using System;

namespace osu.Framework.Graphics.Rendering.LowLatency
{
internal sealed class NoOpDirect3D11LowLatencyProvider : IDirect3D11LowLatencyProvider
{
public static readonly NoOpDirect3D11LowLatencyProvider INSTANCE = new NoOpDirect3D11LowLatencyProvider();

public bool IsAvailable => false;

public void Initialize(IntPtr deviceHandle) { }

public void SetMode(LatencyMode mode) { }

public void SetMarker(LatencyMarker marker, ulong frameId) { }

public void FrameSleep() { }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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.

using System;

namespace osu.Framework.Graphics.Rendering.LowLatency
{
internal sealed class NoOpLowLatencyProvider : ILowLatencyProvider
{
public static readonly NoOpLowLatencyProvider INSTANCE = new NoOpLowLatencyProvider();

public bool IsAvailable => false;

public void Initialize(IntPtr deviceHandle) { }

public void SetMode(LatencyMode mode) { }

public void SetMarker(LatencyMarker marker, ulong frameId) { }

public void FrameSleep() { }
}
}
2 changes: 2 additions & 0 deletions osu.Framework/Graphics/Rendering/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -1292,6 +1293,7 @@ IShaderStorageBufferObject<TData> IRenderer.CreateShaderStorageBufferObject<TDat
return CreateShaderStorageBufferObject<TData>(uboSize, ssboSize);
}

[UnconditionalSuppressMessage("Trimming", "IL2090", Justification = "Uniform layout types are compile-time constants and always preserved.")]
private void validateUniformLayout<TData>()
{
if (validUboTypes.Contains(typeof(TData)))
Expand Down
2 changes: 2 additions & 0 deletions osu.Framework/Graphics/Shaders/ShaderCompilationStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public ComputeProgramCompilation CompileCompute(string programText, CrossCompile
return compilation;
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Shader compilation types are known and preserved.")]
private bool tryGetCached<T>(string filename, [NotNullWhen(true)] out T? compilation)
where T : class
{
Expand Down Expand Up @@ -126,6 +127,7 @@ private bool tryGetCached<T>(string filename, [NotNullWhen(true)] out T? compila

private static readonly Lock save_lock = new();

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Shader compilation types are known and preserved.")]
private void saveToCache(string filename, object compilation)
{
// Multiple save operations could happen in parallel due to the asynchronous
Expand Down
2 changes: 2 additions & 0 deletions osu.Framework/Graphics/Transforms/TransformCustom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -81,6 +82,7 @@ private static WriteFunc createPropertySetter(MethodInfo setter)
return setter.CreateDelegate<WriteFunc>();
}

[UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "Transform target types are preserved by the framework.")]
private static Accessor findAccessor(Type type, string propertyOrFieldName)
{
PropertyInfo property = type.GetProperty(propertyOrFieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
Expand Down
Loading
Loading