Skip to content

Commit 74e657b

Browse files
Merge ppy/osu master and refresh README with fork 2026.421.1 adoption + ANGLE doc
- Merged ppy/osu master (ranked-play fixes ppy#37439 disable-discord-invites and ppy#37444 hide-beatmap-download-notification). - Overhauled the "osu-framework fork changes" and "Veldrid fork changes" sections of README.md to reflect v2026.421.1 reality: D3D12 backend, public BackendInfo* APIs, ILowLatencyProvider + LatencyMode, FrameSync UVSync/Custom + CustomDrawLimit slider, raw keyboard + async keys, API 33 min, 16 KB page alignment, Android stability guards. - Replaced the stale "Framework as submodule" docs with the current NuGet consumption flow and updated the Clone/Build instructions accordingly. - Added a new "Rendering tuning" table covering all fork-added Settings → Graphics → Renderer options exposed to users. - Added an "ANGLE on Android (advanced / experimental)" section with step -by-step Developer-Options and ADB instructions, noting why a first-class renderer-dropdown entry belongs upstream in osu-framework (new RendererType + bundled ANGLE libs). Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/b4d1b445-45fd-4076-9286-bc15ad8d0886 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
1 parent 798709e commit 74e657b

2 files changed

Lines changed: 120 additions & 42 deletions

File tree

README.md

Lines changed: 110 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,42 @@ When Vulkan is available, it's used as the **primary renderer** (with OpenGL ES
129129
130130
---
131131

132+
### 🧪 ANGLE on Android (advanced / experimental)
133+
134+
[ANGLE](https://chromium.googlesource.com/angle/angle/) is Google's OpenGL-ES-on-Vulkan translator. On devices with a sketchy native GL ES driver, forcing ANGLE can work around driver bugs or even improve performance. Android 10+ supports enabling ANGLE **per app** — no APK changes required on our side:
135+
136+
**Option 1 — Developer Options (no PC needed):**
137+
1. Enable Developer Options (`Settings → About phone → tap Build number 7 times`).
138+
2. `Settings → System → Developer options → ANGLE preferences` *(name varies: "OpenGL renderer", "GLES driver" on some OEMs)*.
139+
3. Select **osu!** and choose **`angle`** (default is `native`/`default`).
140+
4. Force-stop and relaunch osu!.
141+
142+
**Option 2 — ADB (one-liner):**
143+
```shell
144+
adb shell settings put global angle_gl_driver_selection_pkgs sh.ppy.osulazer
145+
adb shell settings put global angle_gl_driver_selection_values angle
146+
adb shell am force-stop sh.ppy.osulazer
147+
```
148+
To revert, set the value back to `native` (or `default`).
149+
150+
> **Note:** This affects only the OpenGL ES path — Vulkan rendering (the default on this fork) already runs natively. Use ANGLE only if you've explicitly switched the renderer to OpenGL ES in Settings → Graphics → Renderer. A first-class "ANGLE" entry in the renderer dropdown would need framework-level work (new `RendererType` value + bundling ANGLE's native libs into the APK) and is intentionally left out until the upstream [`winnerspiros/osu-framework`](https://github.com/winnerspiros/osu-framework) fork grows it.
151+
152+
---
153+
154+
### ⚡ Rendering tuning (desktop + Android)
155+
156+
Settings → Graphics → Renderer now exposes the full set of fork-added options:
157+
158+
| Option | What it does |
159+
|---|---|
160+
| **Renderer** | Picks the GPU backend. On Windows you get Metal / Vulkan / D3D11 / **D3D12 (new)** / OpenGL plus their `Deferred_*` experimental variants. On Android you get Vulkan (if supported) and OpenGL ES. |
161+
| **Frame limiter** | VSync, **VSync Unbuffered (new)** — ideal for G-Sync / FreeSync / VRR displays, 2×/4×/8× refresh, Unlimited, or **Custom (new)**. |
162+
| **Custom draw rate limit** | Slider 0–1000 Hz, only visible when the frame limiter is set to Custom. `0` = unlimited draw thread. Useful for benchmarking or VRR-specific tuning. |
163+
| **Threading mode** | Single / MultiThreaded / MultiThreadedDrawing. |
164+
| **Low latency** | `Off` / `On` / `Boost` — drives the fork's generic `ILowLatencyProvider` (NVIDIA Reflex / LatencyFlex-ready on D3D11 & D3D12; no-op on other backends until a provider plugin is supplied). `Boost` also sleeps at the start of each update frame for lower input-to-photon latency. |
165+
166+
---
167+
132168
### 📱 Android quality-of-life
133169

134170
| Feature | What it does |
@@ -163,7 +199,7 @@ This fork includes several crash fixes on top of upstream:
163199
| | |
164200
|---|---|
165201
| **.NET 10** | Upgraded from .NET 8 (upstream) to .NET 10 for the latest runtime and language improvements |
166-
| **Framework as submodule** | Uses a [custom osu-framework fork](https://github.com/winnerspiros/osu-framework) as a git submodule instead of the NuGet package — enables deep platform changes |
202+
| **Framework as NuGet (fork)** | Consumes the [`winnerspiros/osu-framework`](https://github.com/winnerspiros/osu-framework) fork as `ppy.osu.Framework` / `ppy.osu.Framework.Android` / `ppy.osu.Framework.iOS` **v2026.421.1** from the winnerspiros GitHub Packages feed — enables deep platform changes without carrying a submodule |
167203
| **Profiled AOT** | Startup-critical methods are ahead-of-time compiled for faster app launch |
168204
| **IL trimming** | Unused code is stripped from the APK for smaller size |
169205
| **LZ4 compression** | Assembly compression saves ~20 MB in the final APK |
@@ -174,55 +210,89 @@ This fork includes several crash fixes on top of upstream:
174210
</details>
175211

176212
<details>
177-
<summary><strong>osu-framework fork changes</strong></summary>
213+
<summary><strong>osu-framework fork changes (v2026.421.1)</strong></summary>
214+
215+
The [winnerspiros/osu-framework](https://github.com/winnerspiros/osu-framework) fork (published as NuGet v2026.421.1) layers the following on top of upstream `ppy/osu-framework`:
216+
217+
**Rendering backends:**
218+
- Full **Direct3D 12** backend powered by the [winnerspiros/veldrid](https://github.com/winnerspiros/veldrid) fork — exposed as `RendererType.Direct3D12` / `Deferred_Direct3D12` in the renderer dropdown (Windows only; auto-hidden on other platforms).
219+
- Android renderer order: Vulkan (primary) → OpenGL ES (fallback). Vulkan 1.3 requirement check with diagnostic logging.
220+
- New public **`BackendInfoD3D11/D3D12/Metal/OpenGL/Vulkan`** APIs consumed by `VeldridExtensions.LogD3D11/LogD3D12/LogMetal/LogOpenGL/LogVulkan` — avoids re-issuing native capability queries and exposes richer diagnostics (driver name/info, fragment shading rate, mesh shaders, raytracing, enhanced barriers, etc.).
221+
222+
**Low-latency infrastructure (GPU + input):**
223+
- Generic `ILowLatencyProvider` interface (with D3D11-specific `IDirect3D11LowLatencyProvider`) and default no-op implementations — ready for NVIDIA Reflex / LatencyFlex implementations on D3D11 or D3D12.
224+
- Latency markers inserted into `GameHost.UpdateFrame()` / `DrawFrame()` (`SimulationStart/End`, `RenderSubmitStart/End`, `PresentStart/End`, `InputSample`, `TriggerFlash`).
225+
- Provider auto-initialises on the draw thread using the native device handle from Veldrid's `BackendInfoD3D11` / `BackendInfoD3D12`.
226+
- **New `LatencyMode` setting** (`Off` / `On` / `Boost`) — surfaced as "Low latency" in Settings → Graphics → Renderer.
227+
- **Raw keyboard input** on Windows (`SDL_HINT_WINDOWS_RAW_KEYBOARD` enabled by default) — bypasses Windows message translation.
228+
- **Async keyboard event handling** — when text input (IME) is inactive, `KEY_DOWN` / `KEY_UP` are handled directly in SDL's event filter, bypassing the SDL event queue for reduced input-to-render latency.
178229

179-
The [winnerspiros/osu-framework](https://github.com/winnerspiros/osu-framework) fork includes:
230+
**Frame-rate limiter enhancements:**
231+
- **Unbuffered VSync (`FrameSync.UVSync`)** — limits both draw and update threads to the exact display refresh rate. Useful for VRR / G-Sync / FreeSync displays where regular VSync adds buffering.
232+
- **Custom FPS limiter (`FrameSync.Custom` + `CustomDrawLimit` 0–1000 Hz)** — surfaced as a "Custom draw rate limit" slider in Settings → Graphics → Renderer that appears only when Custom is selected. `0` = unlimited draw thread.
180233

181234
**Audio engine tuning:**
182235
- BASS device buffer: 10 ms → 5 ms
183236
- Playback buffer: 100 ms → 25 ms (Android) / 30 ms (iOS)
184237
- Update period: 5 ms → 2 ms (Android) / 3 ms (iOS)
185-
- AAudio backend enabled for BASS
186-
- Native 48 kHz sample rate (matches Android/iOS hardware)
238+
- AAudio backend enabled for BASS, native 48 kHz sample rate (matches Android/iOS hardware)
187239
- Mixer handle made public for Oboe bridge access
188240

189-
**Rendering:**
190-
- Android renderer order changed to Vulkan (primary) → OpenGL (fallback)
191-
- Vulkan 1.3 requirement check with diagnostic logging
192-
193-
**Platform layers:**
194-
- Full `osu.Framework.Android` project (activity lifecycle, storage, file picker)
195-
- Full `osu.Framework.iOS` project (Metal window, AOT, native frameworks)
196-
197-
**Performance:**
198-
- LINQ eliminated from hot paths (Dropdown, FlowContainer, shader pipelines)
199-
- Modern `System.Threading.Lock` type replaces `lock(object)` in renderers
200-
- Reduced redundant OpenGL state changes
201-
- Faster texture uploads on mobile
202-
203-
**Dependencies updated:** SDL3-CS, ImageSharp, Newtonsoft.Json, JetBrains.Annotations, StbiSharp, AndroidX.Window
241+
**Performance (all transparent to consumers):**
242+
- Hot-path LINQ allocations eliminated across the framework (for-loops, spans, cached collections).
243+
- `object`-based locks migrated to `System.Threading.Lock` for lower overhead on .NET 10.
244+
- GridContainer cell sizing uses `RequiredParentSizeToFit` instead of `BoundingBox` — avoids redundant matrix-to-parent-space transforms each layout pass.
245+
- `VeldridExtensions.LogOpenGL` hoists cached Version / ShadingLanguageVersion out of the GL-thread execution scope (fewer unsafe `glGetString` + `Marshal.PtrToStringUTF8` calls per init).
246+
- GL state-change, shader warm-up, texture upload, and mobile vertex-batching improvements.
247+
248+
**Platform targeting:**
249+
- Full `osu.Framework.Android` / `osu.Framework.iOS` implementations.
250+
- Android minimum bumped to **API 33** (matches app manifest), target API 36.
251+
- Android release config: profiled AOT (`AndroidEnableProfiledAot`), partial trimming, `AndroidStripILAfterAOT=false` (avoids `plt_entry` crashes), no LLVM (incompatible with profiled AOT).
252+
- iOS: `SupportedOSPlatformVersion` 13.4, trim-analysis warnings suppressed with `[DynamicallyAccessedMembers]` and `[UnconditionalSuppressMessage]`.
253+
254+
**Stability fixes consumed by the Android build:**
255+
- Null `ANativeWindow` guard in `VkSurfaceUtil` prevents SIGSEGV at `pc=0x0` from invalid Vulkan function pointers.
256+
- `VeldridDevice` polls `SurfaceHandle` for up to 5 s when the Android surface is not yet ready.
257+
- `DrawThread.OnInitialize()` wraps the initial `BeginFrame` in try-catch for graceful handling before surface readiness.
258+
- NRE fix in `GraphicsPipeline.cs` (null-conditional `ResourceLayouts?.Length`).
204259

205260
</details>
206261

207262
<details>
208263
<summary><strong>Veldrid fork changes</strong></summary>
209264

210-
The [winnerspiros/veldrid](https://github.com/winnerspiros/veldrid) fork adds:
265+
The [winnerspiros/veldrid](https://github.com/winnerspiros/veldrid) fork (net10.0, C# 14, `System.Threading.Lock`) powers the framework above. It adds:
266+
267+
**Direct3D 12 backend:**
268+
- Full D3D12 renderer with swapchain creation (`VeldridDevice.CreateD3D12`) and `PersistentStagingBuffer`.
269+
- `BackendInfoD3D12`: `SupportsEnhancedBarriers`, `SupportsMeshShaders`, `SupportsVariableRateShading`, `SupportsRaytracing`, device handle for low-latency providers.
270+
- D3D12 redundant-state caching, staging-pool swap-remove.
211271

212272
**Android Vulkan rendering:**
213-
- Vulkan surface creation from `ANativeWindow` via `VK_KHR_android_surface`
214-
- Android-specific extension detection and enablement
215-
- Native window P/Invoke bindings
273+
- Vulkan surface creation from `ANativeWindow` via `VK_KHR_android_surface`.
274+
- Android-specific extension detection and enablement.
275+
- `VK_EXT_host_image_copy`, push descriptors, dynamic rendering, pipeline-cache optimisations.
216276

217277
**OpenGL ES fallback:**
218-
- Complete EGL 1.4 bindings for GLES 2.0/3.0 context creation
219-
- Proper stencil buffer initialisation (critical for osu!'s UI)
278+
- Complete EGL 1.4 bindings for GLES 2.0/3.0 context creation.
279+
- Proper stencil buffer initialisation (critical for osu!'s UI).
280+
- OpenGL pipeline state caching; `BackendInfoOpenGL` caches `Version` / `ShadingLanguageVersion` off-thread.
281+
282+
**Metal / D3D11 / general:**
283+
- `BackendInfoMetal` with `MaxFeatureSet` / `FeatureSet`, merged layout-offset loops.
284+
- `BackendInfoD3D11` exposing `FeatureLevel`, `DeviceId`, native `Device` handle (no redundant COM RCW).
285+
- D3D11/D3D12 staging-pool swap-remove for faster buffer recycling.
220286

221-
**Performance:**
222-
- `System.Threading.Lock` migration across all GPU backends
223-
- UTF-8 string literals for zero-allocation Vulkan lookups
224-
- Vulkan fence early-out to avoid blocking waits
225-
- Screen tearing support for lowest-latency present modes
287+
**Performance, all backends:**
288+
- `System.Threading.Lock` migration across every GPU backend.
289+
- UTF-8 string literals for zero-allocation Vulkan lookups.
290+
- Vulkan fence early-out to avoid blocking waits.
291+
- Screen-tearing support for lowest-latency present modes.
292+
- `Vortice.Windows` bumped to 3.8.3.
293+
294+
**Android packaging:**
295+
- `veldrid-spirv` built with 16 KB ELF page alignment (Android 15+ / API 36 compliance).
226296

227297
</details>
228298

@@ -251,10 +321,18 @@ The [winnerspiros/veldrid](https://github.com/winnerspiros/veldrid) fork adds:
251321
### Clone
252322

253323
```shell
254-
git clone --recurse-submodules https://github.com/winnerspiros/osu
324+
git clone https://github.com/winnerspiros/osu
255325
cd osu
256326
```
257327

328+
The fork's framework + Veldrid are consumed as NuGet packages from the `winnerspiros` GitHub Packages feed (configured in `NuGet.Config`), so there are no git submodules to initialise. You'll need a GitHub Personal Access Token with `read:packages` scope to restore — the CI workflows pass `GITHUB_TOKEN` automatically:
329+
330+
```shell
331+
dotnet nuget update source winnerspiros-github \
332+
--username <your-gh-username> --password <your-PAT> \
333+
--store-password-in-clear-text
334+
```
335+
258336
### Debug build (quick iteration)
259337

260338
```shell

osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,15 @@ private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, IDi
4949

5050
var frameSync = config.GetBindable<FrameSync>(FrameworkSetting.FrameSync);
5151

52-
SettingsItemV2 customDrawLimitItem;
52+
var customDrawLimitItem = new SettingsItemV2(new FormSliderBar<int>
53+
{
54+
Caption = GraphicsSettingsStrings.CustomDrawLimit,
55+
Current = config.GetBindable<int>(FrameworkSetting.CustomDrawLimit),
56+
TransferValueOnCommit = true,
57+
})
58+
{
59+
Keywords = new[] { @"fps", @"framerate", @"custom", @"hz" },
60+
};
5361

5462
Children = new Drawable[]
5563
{
@@ -74,15 +82,7 @@ private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, IDi
7482
{
7583
Keywords = new[] { @"fps", @"framerate" },
7684
},
77-
customDrawLimitItem = new SettingsItemV2(new FormSliderBar<int>
78-
{
79-
Caption = GraphicsSettingsStrings.CustomDrawLimit,
80-
Current = config.GetBindable<int>(FrameworkSetting.CustomDrawLimit),
81-
TransferValueOnCommit = true,
82-
})
83-
{
84-
Keywords = new[] { @"fps", @"framerate", @"custom", @"hz" },
85-
},
85+
customDrawLimitItem,
8686
new SettingsItemV2(new FormEnumDropdown<ExecutionMode>
8787
{
8888
Caption = GraphicsSettingsStrings.ThreadingMode,

0 commit comments

Comments
 (0)