You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge ppy/osu master and refresh README with fork 2026.421.1 adoption + ANGLE doc
- Merged ppy/osu master (ranked-play fixesppy#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>
@@ -129,6 +129,42 @@ When Vulkan is available, it's used as the **primary renderer** (with OpenGL ES
129
129
130
130
---
131
131
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. |
|**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
+
132
168
### 📱 Android quality-of-life
133
169
134
170
| Feature | What it does |
@@ -163,7 +199,7 @@ This fork includes several crash fixes on top of upstream:
163
199
|||
164
200
|---|---|
165
201
|**.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|
167
203
|**Profiled AOT**| Startup-critical methods are ahead-of-time compiled for faster app launch |
168
204
|**IL trimming**| Unused code is stripped from the APK for smaller size |
169
205
|**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:
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.
- 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.
178
229
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.
180
233
181
234
**Audio engine tuning:**
182
235
- BASS device buffer: 10 ms → 5 ms
183
236
- Playback buffer: 100 ms → 25 ms (Android) / 30 ms (iOS)
184
237
- Update period: 5 ms → 2 ms (Android) / 3 ms (iOS)
- 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`).
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.
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:
0 commit comments