LWJGL3 and Android Redux

Absolutely fantastic progress folks! I’ve still been tied up releasing TJSDoc (Javascript documentation tooling) and hope to get that finished this week then I’ll pick up and start testing and using the Android LWJGL port full time+ for the remaining time leading into GDC. Here’s hoping Vulkan comes online too! ;D Keep the info flowing and perhaps point out any pertinent details on where / how to get started with the current state of things. Got a wiki entry yet?

Everything is available in the android branch. Please note that we’re force pushing regularly to clean up the commit history and whenever we sync with master.

If you clone the branch and run “ant compile-templates arr”, it should produce a bin/android/lwjgl.aar file. Drop it in an Android project and it should just work. That’s all there is to it right now. Next steps are: adding Android extensions that might be missing (in EGL, GLES and Vulkan), testing Vulkan, adding non-JNI natives (OpenAL-Soft, jemalloc, etc) and doing performance testing/tuning.

Sterling stuff Spasi!

Cas :slight_smile:

Hello VKSurfaceView!

XAGi07iSbe8

Once again; this is huge! Amazing! Great work! I’ll get in contact with Khronos to see if they’ll let me do a quick ~3 minute announcement at GDC / Khronos tutorial day. I assume you can do the opengl.org blog announcement. Also I’ll print up ~2k color business card (mini-flyers) with info on LWJGL going cross-platform to Android to pass out. Let me know if you have any logo / branding ideas or other input on graphics involved; I’ll keep it classy. Any chance a permanent tutorial guide can be put up I can link to in addition to the main LWJGL web site; a Github wiki with screenshot walkthrough would be great! I’m still tied up for most of next week w/ the TJSDoc launch, but I’m going to get the word out at GDC. I’m sure I’ll run into a bunch of Android bloggers too, so if some articles aren’t up by GDC I’ll see if I can drum up some interest.

Hey Catharsis,

I’ll work on this a bit more, mainly to clean up the code. There are two issues:

We currently require Android N and platform 24+. Which corresponds to too low a percentage of Android users. Making it work on earlier versions should be possible, but I have neither the energy nor the incentive to do it myself. Not sure if it’s even worth doing, given the performance characteristics (I’ll write another post with the details).

There’s also the issue of better handling buffer/device lost events, which are fairly common with Vulkan on Android. You may notice it in the above video, when the orientation changes, there’s a full destroy and recreation of the whole thing. Moving out of the app and back in again also requires a “soft-reset”, but I think I’ve handled that one sufficiently.

The issue is complicated by the fact that I’ve written VKSurfaceView similarly to GLSurfaceView; everything runs on a separate thread and the UI events arrive asynchronously. If you’re familiar with GLSurfaceView’s implementation… it’s not trivial and I don’t have the necessary experience (or time) to make it robust. If I fail, I’ll probably make another version that runs on the UI thread and maybe Android engineers can help with properly fixing the concurrent version.

Once that’s done, I’ll update the lwjgl3 android branch and will create another repo with an Android Studio sample project and some instructions.

Other than that, I won’t have time for much else. I’m fairly busy at work and I’m also becoming a father for the 2nd time (today or tomorrow). I’m also not really comfortable with announcing what is essentially a work-in-progress. And it’s not like LWJGL needs that much branding/marketing. People that need to go low-level can easily find it, there aren’t many options out there. I certainly don’t want to give the illusion that it’s a library for the average developer. Especially wrt Vulkan.

I’ll pm you links to LWJGL’s logo in various formats.

From my perspective this is fine as Google constantly introduces new SDK APIs that aren’t available at lower platform levels. In the coming months I will try and see if things can be back-ported at least for GLES to platform 19 (4.4 / KitKat / GLES 3.0); I’m generally aware of the problems / efficiency though of pre-OpenJDK though. Vulkan itself has more or less a limitation of Android N regardless if going native or through LWJGL, so again not so much of an issue with platform 24.

The amazing part of LWJGL being on Android is that now there is an option for low level graphics that is separate of the SDK / firmware conundrum of how previous SDK graphics APIs are managed. IE As the Vulkan spec continues to be modified we don’t have to wait for platform 25, 26 … X to get these new features enabled like previous Java SDK efforts being locked to the firmware. Granted there are still firmware locked drivers, but if it’s an advancement of the Vulkan API itself that isn’t dependent on driver updates then these new features will always be available at platform 24.

When you get a chance this will be much appreciated and will provide initial metrics to compare for any back-porting.

That you got this mostly worked out initially is great work. However this is not an issue as since day 1 with GLES on Android 1.0 onward one simply locks the orientation for game / graphics apps. Very few intense graphics apps don’t lock the orientation and and leave the orientation restart process enabled.

I can perhaps see the difficulty of enabling various debug layers of Vulkan and getting all the necessary output perhaps if it’s not being logged per se, but that is a separate issue.

I wouldn’t hold my breath per se for any Android engineers being involved; I don’t think there are any more Java / graphics champions involved to a meaningful degree on the Android team. If there is collaboration though it will be embraced warmly!

I do have experience in creating an updated GLSurfaceView2, so I’ll take a look in time on any improvements there as well for VKSurfaceView, etc. If I recall correctly it was necessary at the time to expose GLES 3.1 since the Android SDK GLSurfaceView is based on the old EGL API (
javax.microedition.khronos.egl.EGL10) instead of 1.4 (android.opengl.EGL14).

If the repo can be created sooner than later along with a wiki entry where instructions will go then I can proceed with the mini-flyers.
I’ll also gladly contribute the screen shot walk through of setting things up similar to what I did for my GL demos / source code setup.

Congrats with your new child! I’m always amazed that you consistently move LWJGL and the larger community forward so deftly in your spare time!

It shows that any backpedaling on Google’s side is simply that; a lack of will to get things done. It’s kind of been that way for a while now as things go. Your effort with LWJGL on Android means that Java will remain a first class citizen for modern app development and this is huge.

I agree the average game developer for a long time now has moved away from engine development.

In this case though the Khronos tutorial day is filled with folks making up the right audience to send a message to and that is Java remaining a first class citizen for advanced graphics development on Android and LWJGL filling the need for a unified cross-platform SDK for low level access which fulfills the promise of Vulkan and is something Google would never do re: one Java API that runs on the desktop and Android.

[quote=“Catharsis,post:27,topic:58057”]
Yes, totally agree. But it would be nice if this decoupling benefit could be extended to developers that target OpenGL ES and earlier API levels.

[quote=“Catharsis,post:27,topic:58057”]
Good point.

[quote=“Catharsis,post:27,topic:58057”]
That’s actually very easy; the NDK includes precompiled layer libraries that you can simply drop in your project. Vulkan validation works just fine.

[quote=“Catharsis,post:27,topic:58057”]
It doesn’t have to be Java developers. Anyone that writes a Vulkan app, either in Java or C, will face the same issues.

Actually, I couldn’t find a Vulkan sample in the official repo that handles surface destruction properly. I could just as easily call this “not my problem” and actually I don’t plan adding VKSurfaceView to lwjgl3. But it’d be very nice if we could provide a sample project that handles some of the complexity and exposes an API that’s familiar to anyone that has used GLSurfaceView.

[quote=“Catharsis,post:27,topic:58057”]
Will try to get it ready asap.

Disclaimer: I’m an Android noob and it’s entirely possible that I missed something important.

Here are my performance findings on Android. All tests were done on a Nexus 6P running Android N 7.1.1. The app was deployed as a signed APK, release variant, minimum platform 25. Metrics were printed with Android’s Log and retrieved using logcat:

A general remark first. ART’s JIT compilation is underwhelming. I’d say roughly equivalent to a Java client VM from a decade ago. Which I have a hard time believing given how experienced Google is with VMs and JITs (V8 is more than impressive). My first instinct while doing tests was that the app was always running in 100% interpreter mode. But no matter what I tried, it didn’t get any better. I even left the app installed overnight, maybe the offline ART AOT would do some magic, but nothing improved. I really hope I’m missing something simple. The hardware feels pretty powerful and I don’t think doing basic optimizations would waste that much battery.

  • The first problem that affects LWJGL is that ART is not able to treat static final fields that are initialized at runtime as constants. This affects primitives (e.g. compiling away normal and debug mode checks that are behind static final booleans) and calls to interfaces with a single implementation instantiated at runtime (static final AnInterface FOO = new AnImpl()). Hotspot is easily able to de-virtualize such calls and fully inline them. This is critical for LWJGL performance in several cases.

  • The above issue can be mitigated using ProGuard optimization passes. Which, again, takes us back a decade or more. It cannot even be done once for LWJGL, it needs to run on every build of the user’s app, making builds horribly slow. The performance improvement is substantial though. ProGuard is able to inline and devirtualize a lot of code. The worse your JIT is, the more difference this makes.

  • ART does not perform escape analysis. This I was expecting, but think it’s worth mentioning. No EA means LWJGL users must be careful with allocations. The MemoryStack should not be used in tight loops, struct buffers should be accessed with the flyweight pattern, etc. This, again, means writing Java 1.4 era code, preallocating and reusing buffer instances etc.

  • LWJGL depends on Unsafe and intrinsics for many things. For Vulkan in particular, that is an API heavy on structs, LWJGL uses Unsafe to access all struct members. The good news is that Android 7 supports the full Java 8 Unsafe API and has proper intrinsics. Measuring simple reads/writes produces appropriate results for the underlying hardware. The first problem is inlining: properly encapsulating Unsafe sacrifices a lot of performance without ProGuard. The second problem is a bug on Aarch64: it’s impossible to access > 32bit memory addresses with Unsafe, the address is getting masked out at 32bits. This won’t affect most app allocations, but all libraries are mapped to a >32bit address and any memory provided by them will be in that range.

  • Android has another internal API similar to Unsafe, libcore.io.Memory. This class is also intrinsified and doesn’t suffer from the same bug. Unfortunately, it’s about 4x slower than Unsafe in my tests.

  • The java.nio buffer implementation on Android is bad. Too many allocations, too much overhead, they use libcore.io.Memory instead of Unsafe. Accessing anything via a buffer is 10x slower than the equivalent Unsafe access.

To sum up, it feels like Java on Android is meant to be used for client UI code only. Anything performance sensitive should be moved to JNI and native code. Making Java+LWJGL a decent alternative will take some work and I’m not sure if it can be done within the official repo or better moved to a fork. E.g. one solution to the last point is writing a custom buffer API, which means the entire LWJGL API needs to change. Actually, getting rid of NIO was something that I briefly consider doing when I started lwjgl3 (it would benefit desktop apps as well), but decided it was more important to keep compatibility with the lwjgl2 bindings.

What about OpenJDK (Zulu) on Android?

Cas :slight_smile:

or what about Java SE Embedded, they already have ARM builds, if it can be made to run on Android devices, performance should be much better than ART’s.

Licensing wank :confused:

Hence Zulu, which is nice GPL2 code and probably a lot less bother in general.

Cas :slight_smile:

Ah right, looking at the pricing for the licence, it seems pretty expensive and not worth it for distributing games even if it did work on android.

Zulu Embedded does look nice, but can’t find any information about it running on Android.

Zulu basically runs atop Linux. It’s armhf native code, which means with the tiniest bit of glue it should be invokable as a standard embedded JVM using JNI and the Android NDK. Presumably headless.

Cas :slight_smile:

The main thing would be if it supports the Hotspots JIT on ARM.

There is the OpenJDK 9 Android Port but seems like it only supports the Zero Interpreter on ARM. Not sure if the speed hit will make it unusable but might get round some of ART specific issues raised by Spasi. They also have a similar port to iOS.

Zulu is the real deal - full speed, Hotspotted JIT for ARMhf. It’s fast-as, I’ve tried it :slight_smile:

Cas :slight_smile:

The example Android Studio project is now available at LWJGL/android-test. The README includes build instructions.

For those that simply want to try it out, you can find arm64-v8a binaries here (warning: unsigned, built on my workstation):

gears-debug.apk
hellovulkan-debug.apk
lwjgl.aar

Gears & Vulkan works a treat here (Nexus 5X, Android 7.1)! Well done, that’s awesome stuff. Gives me the urge to play with Android again.
Anybody with time care to see if they can get Zulu to invoke using NDK?

Cas :slight_smile:

Once again a solid effort Spasi! I just sent off the business card mini-flyer for GDC and beyond pimping this major LWJGL announcement. Here it is (looks like the forum cut it off / it’s also a link to the image):


http://www.typhonrt.org/lwjgl_businesscard-front.png

I’m going to beat the street and even bit the bullet further and upgraded to a full GDC pass so to not miss any bloggers and other press that might pick up a story. Fingers crossed! As mentioned in PM I’ll try and get around to over the weekend creating an in-depth tutorial wiki entry with step by step picts.

Alright… dev on Android and beyond is going to be exciting from here on out! ;D