Compare commits

...
Author SHA1 Message Date
xXJsonDeruloXx 77738827a8 Select system Vulkan on Mali devices 2026-09-27 10:02:32 -04:00
5 changed files with 26 additions and 23 deletions

No files matched your search

+1 -1
View File
@@ -32,7 +32,7 @@ int vk_loader_open(const char *driver_path, const char *library_name,
g_handle = dlopen("libvulkan.so", RTLD_LOCAL | RTLD_NOW);
__android_log_print(ANDROID_LOG_WARN, TAG,
"no adrenotools driver -> system libvulkan handle=%p "
"(dmabuf import likely unsupported)", g_handle);
"(dma-buf import depends on system driver)", g_handle);
}
if (!g_handle) return -1;
g_gip = (PFN_vkGetInstanceProcAddr)dlsym(g_handle, "vkGetInstanceProcAddr");
@@ -433,7 +433,7 @@ class MainActivity : ComponentActivity() {
showNonAdreno?.let { release ->
ConfirmDialog(
title = "Not an Adreno GPU",
text = "Turnip supports Adreno GPUs. On ${com.droiddeck.launcher.core.DeviceSupport.gpuName()}, Steam may show a black screen. Download: ${"%.0f".format(release.size / 1e6)} MB.",
text = "The Linux runtime's bundled Vulkan driver targets Adreno GPUs. On ${com.droiddeck.launcher.core.DeviceSupport.gpuName()}, Steam may show a black screen. Download: ${"%.0f".format(release.size / 1e6)} MB.",
confirm = "Install anyway",
onConfirm = { showNonAdreno = null; install(release) },
onDismiss = { showNonAdreno = null },
@@ -1113,14 +1113,14 @@ class MainActivity : ComponentActivity() {
Thread({ checkCatalog() }, "catalog").start()
return
}
// The runtime draws with Turnip, an Adreno driver: on Mali, Xclipse or PowerVR the
// compositor gets no usable Vulkan device and a session is sound over a black screen.
// Said before the download, not after it; the user may still go ahead.
// The bundled Linux runtime Vulkan ICD is Freedreno, which targets Adreno. The Android
// compositor can use a non-Adreno system driver, but Steam may still have no guest Vulkan
// device. Warn before the download; the user may still go ahead.
if (installed == null && !com.droiddeck.launcher.core.DeviceSupport.adreno()) { showNonAdreno = release; return }
install(release)
}
/** Starts a session; with no runtime on a non-Adreno, the same warning Setup gives comes first, before any download. */
/** Starts a session; with no runtime on a non-Adreno, show the guest Vulkan warning before download. */
private fun startSession(intent: Intent, steamSession: Boolean = false) {
refreshPhantomStatus()
if (steamSession && PhantomProcessLimit.blocksSteam(phantomProcessStatus)) {
@@ -4,13 +4,12 @@ import android.os.Build
import java.io.File
/**
* Whether this device can draw a Linux session at all.
* Whether the bundled Linux runtime's Vulkan renderer is likely to work.
*
* The runtime draws with Turnip, an Adreno driver. On Mali, Xclipse and PowerVR the compositor
* gets no usable Vulkan device and a session comes up as sound over a black screen - a failure
* with nothing in it to read. The app cannot fix that, so it says so before the download rather
* than after it. Adreno is recognised by what only Qualcomm's stack has: the KGSL node, or the
* vendor's own Vulkan driver at its usual path.
* The runtime currently ships the Freedreno Vulkan ICD, which targets Adreno. The Android
* compositor uses a separate driver and can use a non-Adreno system Vulkan implementation. This
* check gates the guest-driver warning. Adreno is recognised by what only Qualcomm's stack has:
* the KGSL node, or the vendor's own Vulkan driver at its usual path.
*/
object DeviceSupport {
fun adreno(): Boolean =
@@ -5,6 +5,7 @@ import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import com.droiddeck.launcher.core.DeviceSupport;
import com.droiddeck.launcher.core.FileUtils;
import com.droiddeck.launcher.core.TarZst;
import com.droiddeck.launcher.session.SessionPrefs;
@@ -24,11 +25,11 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* The Vulkan driver the in-app compositor runs on. It has to be Turnip: the system Adreno driver
* does not implement VK_EXT_image_drm_format_modifier, so importing the dma-bufs gamescope hands
* over fails and the session renders nothing. Two builds ship in the apk, one per Adreno
* generation, and the GPU decides which is unpacked - unless the user has imported an AdrenoTools
* zip of their own and chosen it, which then wins.
* The Vulkan driver the in-app compositor runs on. On Adreno it needs Turnip: the system Adreno
* driver does not implement VK_EXT_image_drm_format_modifier, so importing the dma-bufs gamescope
* hands over fails and the session renders nothing. The bundled builds are Adreno-only; on other
* GPUs, use the system driver. The GPU decides which Turnip build is unpacked - unless the user
* has imported an AdrenoTools zip of their own and chosen it, which then wins.
*
* <p>The guest's own Turnip is a different copy entirely - a glibc build inside the rootfs, or an
* imported one ({@link LinuxVulkanDriverManager}). This one is the bionic build the app process
@@ -39,8 +40,8 @@ import java.util.zip.ZipInputStream;
* {@code meta.json} whose {@code libraryName} names the .so beside it - the AdrenoTools layout.
* The import path is ported from Bannerlator's {@code AdrenotoolsManager} (GPL-3.0), including
* the refusal of zips that belong in the Linux runtime list: a "-Linux" (glibc) Turnip names no
* library on purpose, and installed here it would put the compositor on the system Vulkan - a
* black screen wearing a driver's name.
* library on purpose, and installed here it would put the compositor on the system Vulkan while
* appearing to select a driver.
*/
public final class TurnipDriver {
private static final String TAG = "TurnipDriver";
@@ -267,8 +268,7 @@ public final class TurnipDriver {
/**
* Unpacks the driver this device needs and returns its id, or null to fall back to the system
* Vulkan loader (which means a black session on Adreno, but is better than refusing to start
* on a GPU neither build covers).
* Vulkan loader. The system driver must provide the compositor's Vulkan and dma-buf extensions.
*/
public String install() {
String id = choose();
@@ -322,6 +322,10 @@ public final class TurnipDriver {
if (forced.startsWith("a8")) return DRIVER_A8XX;
if (forced.startsWith("a7")) return DRIVER_A7XX;
}
if (!DeviceSupport.INSTANCE.adreno()) {
Log.i(TAG, "no bundled driver for this GPU; using system Vulkan");
return null;
}
String model = gpuModel();
Log.i(TAG, "gpu model: " + (model == null ? "unknown" : model));
if (model != null) {
@@ -156,8 +156,8 @@ public final class WaylandCompositor {
/** Start the compositor rendering to {@code surface}. XDG_RUNTIME_DIR = an
* app-writable dir for the wayland socket (e.g. context.getFilesDir()).
* driverPath/libraryName/nativeLibDir select the Turnip driver via adrenotools
* (all null -> system libvulkan, which can't do dmabuf import). */
* driverPath/libraryName/nativeLibDir select a bundled or imported driver via adrenotools
* (all null -> system libvulkan; dma-buf import support depends on that device's driver). */
public static native void nativeStartWithSurface(Surface surface, String xdgRuntimeDir,
String driverPath, String libraryName,
String nativeLibDir);