From bed25230518ca382966eceda4877cf82227f875f Mon Sep 17 00:00:00 2001 From: KLCLAU Date: Mon, 31 Aug 2026 20:09:48 -0400 Subject: [PATCH] fix(android): fall back to stock Vulkan driver on Adreno 8xx The bundled Turnip driver (vulkan.ad07xx.so) only supports Adreno 6xx/7xx and enumerates zero physical devices on an Adreno 840 (Snapdragon 8 Elite Gen 5, Galaxy S25/S26). DXVK then throws DxvkInstance::enumAdapters: Failed to enumerate adapters and the app dies at TheDisplay->init(). The stock Qualcomm driver on Adreno 8xx already exposes Vulkan 1.3 and textureCompressionBC, so Turnip is neither needed nor usable there (this is the 'rung 1' path from the renderer-research doc). Parse the Adreno model number from /sys/class/kgsl/kgsl-3d0/gpu_model and, for series >= 8, skip staging the Turnip driver and setting the adrenotools env vars so the DXVK loader (vulkan_loader.cpp) falls through to the stock libvulkan.so. GENERALSX_NO_TURNIP=1 forces the same path on any device (useful for debugging or for a8xx parts the sysfs parse doesn't recognise). Tested on Galaxy S26+ (Adreno 840): boots to the main menu and plays a skirmish at ~30 FPS where the stock build crashed on launch. Co-Authored-By: Claude Sonnet 5 --- GeneralsMD/Code/Main/SDL3Main.cpp | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/GeneralsMD/Code/Main/SDL3Main.cpp b/GeneralsMD/Code/Main/SDL3Main.cpp index 8441ebc9a..ab0381342 100644 --- a/GeneralsMD/Code/Main/SDL3Main.cpp +++ b/GeneralsMD/Code/Main/SDL3Main.cpp @@ -272,6 +272,39 @@ static bool gxCopyFile(const char *src, const char *dst) return ok; } +// GeneralsX @patch KLCLAU 08/31/2026 — Adreno 8xx (Snapdragon 8 Elite / +// 8 Elite Gen 5, Galaxy S25/S26) stock-driver fallback. The bundled Turnip is +// built for Adreno 6xx/7xx only (vulkan.ad07xx.so) and enumerates ZERO physical +// devices on an Adreno 840 -> DXVK throws "DxvkInstance::enumAdapters: Failed to +// enumerate adapters" and the app dies. The stock Qualcomm driver on 8xx already +// exposes Vulkan 1.3 + textureCompressionBC, so Turnip is neither needed nor +// usable there (renderer-research doc "rung 1"). Parse the Adreno model number +// from kgsl sysfs and skip Turnip for series >= 8. GENERALSX_NO_TURNIP forces it. +static int gxAdrenoSeries() +{ + FILE *f = fopen("/sys/class/kgsl/kgsl-3d0/gpu_model", "r"); + if (!f) + return 0; + char buf[64] = {0}; + size_t n = fread(buf, 1, sizeof(buf) - 1, f); + fclose(f); + if (n == 0) + return 0; + // e.g. "Adreno840v2acd" -> 840 -> series 8 + const char *p = strstr(buf, "Adreno"); + if (!p) + return 0; + p += 6; + int num = 0; + while (*p >= '0' && *p <= '9') { + num = num * 10 + (*p - '0'); + p++; + } + if (num >= 100) + return num / 100; // 840 -> 8, 750 -> 7, 660 -> 6 + return num; // already a bare series digit +} + static void gxSetupTurnipDriver() { // Driver soname as it ships in the adrenotools package meta.json. adrenotools @@ -280,6 +313,17 @@ static void gxSetupTurnipDriver() // The jniLib we ship the Turnip .so as (Android only extracts lib*.so names). static const char *BUNDLED_SONAME = "libvulkan_freedreno.so"; + if (getenv("GENERALSX_NO_TURNIP")) { + fprintf(stderr, "INFO: Turnip: GENERALSX_NO_TURNIP set — using stock Vulkan driver\n"); + return; + } + const int adrenoSeries = gxAdrenoSeries(); + if (adrenoSeries >= 8) { + fprintf(stderr, "INFO: Turnip: Adreno %dxx detected — bundled Turnip (ad07xx) does not " + "support it; using stock Vulkan driver (Vulkan 1.3 + BCn native)\n", adrenoSeries); + return; + } + // 1) nativeLibraryDir: the directory containing this very .so (libmain.so). Dl_info info; if (dladdr(reinterpret_cast(&gxSetupTurnipDriver), &info) == 0 || info.dli_fname == nullptr) {