Error with the METAL skiko.renderAPI
Hello,
Still with the idea of making a cross-platform application that is not incompatible with Intel GPUs, I use this main.kt :
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import fr.genie23.tools.SystemTool
fun main() = application {
// Détermine le système de rendu en fonction de l'OS
when(SystemTool.getOS()) {
SystemTool.OS.LINUX, SystemTool.OS.WINDOWS -> System.setProperty("skiko.renderApi", "OPENGL");
SystemTool.OS.MAC -> System.setProperty("skiko.renderApi", "METAL");
}
Window(onCloseRequest = ::exitApplication, title = "Test") {
Button(onClick = {
println("Debug")
}) {
Text("Test")
}
}
}
On Windows, everything is fine, my button is displayed and the action is executed.
However, on macOS, if the button displays well now and the action executes (a println is very fast to execute, but I also tested with a swing dialog box that took a huge amount of time to open), when launching the gradle runDistributable task, I have the following errors displayed in my terminal :
> Task :createDistributable
The distribution is written to /Users/cedric/pdf-assembler/build/compose/binaries/main/app
> Task :runDistributable
WARNING: GL pipe is running in software mode (Renderer ID=0x1020400)
Can't wrap nullptr
Failed to create Skia Metal context!
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Check failed.
at org.jetbrains.skiko.SkiaLayer.update$skiko(SkiaLayer.kt:297)
at org.jetbrains.skiko.redrawer.SoftwareRedrawer.redrawImmediately(SoftwareRedrawer.kt:32)
at org.jetbrains.skiko.SkiaLayer.findNextWorkingRenderApi(SkiaLayer.kt:125)
at org.jetbrains.skiko.SkiaLayer.prepareDrawContext$skiko(SkiaLayer.kt:333)
at org.jetbrains.skiko.redrawer.MetalRedrawer$draw$2.invokeSuspend(MetalRedrawer.kt:65)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
BUILD SUCCESSFUL in 45s
8 actionable tasks: 5 executed, 3 up-to-date
Apart from my main.kt, I have only one other Kotlin file, which I use to define a function to determine the current OS :
package fr.genie23.tools
import java.lang.System
import java.util.*
class SystemTool {
enum class OS {
WINDOWS, LINUX, MAC
}
companion object {
fun getOS(): OS? {
val os = System.getProperty("os.name").lowercase(Locale.getDefault())
return when {
os.contains("win") -> {
OS.WINDOWS
}
os.contains("nix") || os.contains("nux") || os.contains("aix") -> {
OS.LINUX
}
os.contains("mac") -> {
OS.MAC
}
else -> null
}
}
}
}
But since I removed all references to any graphical element outside of the application, Window, Button and Text classes and functions from Compose that I use in my Main, I had tested to use swing dialogs, I don't understand where these errors come from. I also disabled the 3D acceleration of my virtual machine (which was not supported by the guest system anyway, according to VMWare), thinking it was coming from there. But none of these actions brought any change, the error messages are still there.
The only conclusive test to remove this error was to change the renderAPI value from METAL to SOFTWARE. Now I don't have the error anymore, but I still have the warning message :
> Task :createDistributable
The distribution is written to /Users/cedric/pdf-assembler/build/compose/binaries/main/app
> Task :runDistributable
WARNING: GL pipe is running in software mode (Renderer ID=0x1020400)
BUILD SUCCESSFUL in 31s
8 actionable tasks: 5 executed, 3 up-to-date
Having no more ideas, I'll come back to you to see if you can help me like yesterday. I open a new issue because even if it is, for me, the continuation of the solution of yesterday, the problem is different (and can concern other people).
Thank you for the help you will give me.
What is your macOS version? Why do you need to control Skiko renderer?
I use macOS Big Sur, and I define skiko.renderApi because of the incompatibility between Intel and Compose graphics chipsets (on Windows, it causes an error during execution).
So at first I had set it to OPENGL for all OS, until yesterday when I was told (in a previous issue) that on macOS it was better to use SOFTWARE (impossible because of the incompatibility with at least some Intel GPUs) or METAL (which I tried). My initial problem #968 , the buttons not being displayed, was solved.
And so I came to this problem.
Do not think that it is related to chipset, but likely to virtual machine software acceleration logic. Can you run on the host machine without VM? With VM, I guess SOFTWARE would be the safest option.
We'll try to improve fallback logic in Skiko further down the road.
I don't have macOS outside my virtual machine. On Windows (the operating system of my computer), and on my other virtual machines (Debian and Fedora, two Linux), everything works correctly. But I can use the OpenGL engine, which is not the case on my macOS machine. Well, since one of the two projects I'm working on is an application I've been asked to develop for macOS, I can't really free myself from this system as I used to do before (by only developing for Windows)...
And I don't know if there are macOS computers that use Intel GPUs, that's why I was using METAL instead of SOFTWARE for this OS.
So, for Windows and Linux, I won't have any problem of compatibility with Intel GPUs (since OpenGL is available), but for macOS it won't be the case at least for the moment (since OpenGL is not available anymore in favor of Metal).
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.