I have looked into some of the performance aspects of the Android port, and I’ve come to some conclusions. Firstly, after looking at the disassembly, there did not seem to be any additional code associated with exception handling, so there was no optimizing to be done there. Secondly, the compile flags meant that software floating point operations were used, rather than the built-in hardware FPU.
This gives my phone a nice 50% boost in frame-rate to about 15fps. However, on some devices this app may fail to run. This change brings the performance in line with iPhone performance for the simulation side of the program. However the OpenGL seemed slower. I guess the Qualcomm MSM 7227 does not have strong 3D acceleration \- or perhaps I am still missing something?
For comparison, you can test the flash version of the code in this directory. I get about 6\-7 fps, which is not too far from my initial software-float based results and is quite impressive. I’m not sure if the flash renderer is using software or hardware rendering \- maybe it’s worth a closer look to find out what it’s doing.
I bought myself and Android (2.1) HTC Legend phone. Obviously, the first thing I wanted to do was to get haxe/NME running on it. Now the Android platform is very well setup for Java development but, unfortunately, the haxe Java target is not fully developed at the moment. Luckily, there is also a “native” development kit (NDK) that allows you to run c++ code on the device using a Java bootstrap to load the code and JNI.
The NDK is based in the GCC toolchain, and therefore is already pretty well supported by the hxcpp haxe backend. The problem is that the standard NDK is somewhat crippled – it does not support exceptions or the STL. It is possible to rework the hxcpp backend to work without the STL, but removing exceptions may take a bit more work. I managed to work around this by using a slightly modified NDK, created by a very helpful member of the comminity over at crystax.net. In theory this should have been all that was required, however the NDK also lacks proper wchar_t support. When I finally worked this out, it was reasonably easy to substitute a simple translation layer to fix these wide-char problems. So far, I have only implemented the rendering API, with no interactive options. The OpenGL ES rendering code is exactly the same as for the iPhone, except that the initial context and display surface are setup in the Java code, rather than the Objective C code.
Developing with haxe for the Android target requires several modules to work together. First, you compile your haxe code as normal to a shared object – which is actually a JNI module. This exposes a single “main” function that can be called from Java. Your actual Android application starts with Java code, and you can setup the properties etc. from eclipse. Ultimately this will be boilerplate code and you will only need to change the bits you need to. This Java code then calls the haxe main function. In the graphical/NME environment the main thing this does is dynamically load the nme native library and setup a callback for when the graphics are finally initialized. You then return to Java code and setup a OpenGL ES context. When this is done, a JNI call is made into the nme dynamic library, which in turn calls back into your haxe application to complete setup. The “MainLoop” is then processed in Java, and events such as “Redraw” (and later “OnMouse” etc) are passed into the nme library, and then into the haxe application as registered “addEventListeners”.
So in this somewhat convoluted way, Java maintains full control of the app, and therefore correct interaction with the OS, while almost all the real work is done in the haxe code. In the example shown here, no changes were necessary to the haxe code, and the internal garbage collection also worked without modification, so it is a pretty solid cross-platform solution.
Now the bad news. The performance is way down compared to my 2nd generation iPod touch. This example is 10fps on the Android device, and about 24 on the iPod. Which is strange, because the core should actually be running a bit faster. The slowdown seems to be on both the OpenGL side, and the physics calculation side. It should also be noted that this is a first pass, so there is quite a bit of room for improvement. My guess is that the gcc compiler is generating significant runtime overhead per function because of the exception code. This is what I noted while compiling for the iPhone (it was doing a pthread lock per function!) \- but in that case the penalty was only incurred in functions that actually “threw”, so I simply moved the throwing code into a separate function. Which brings me to my second problem …
No easy profiling or debugging support for native code. This is a real pain for debugging (back to “log” debugging) and the lack of profiling makes it very hard to work out what needs optimizing for the target. I may be able to use a simple “setjump” style system for exceptions because the use of garbage collection means that there are no real destructors required for cleanup. But I would need to be sure this would help – premature optimization and all that.
I would also count the fact that you really need to use eclipse as an IDE as a big negative, but I think that this is just my personal dislike of the program. I think there may ultimately be ways around this with command-line compilers etc.
Native compiling tools for the Android target are still in active development and moving forwards, so I’m assuming that most of these problems will be overcome eventually. And of course, the big advantage of the Android OS is the openness \- so I can provide you with the actual application to run on your device \- give it a go, and let me know if it runs for you.
Into this mix, I will add another interesting option: The V8 JS engine, running using the NME library in opengl mode. This cross-over mode is actually quite easy to implement because of 3 stars aligning: 1. The NME library has a external interface that uses opaque handles that map very naturally to the v8::Value *. 2. The haxe compiler makes it possible to program JS without losing your mind, and all the existing library code is valid for this target. and 3: The Google V8 JS engine has a clean API that makes it easy to embed (you would almost think they designed it that way – dispite the frugal documentation).
The benchmark I have chosen is the “Pentagonal Rain”, which is nice and stressful for the CPU. You can try for yourself – use the ‘5’ key to switch to this demo.
So as you can see, the V8VM option is actually quite viable as a scripting vm. Since there is a lot in common between neko, v8vm and cpp haxe targets and plugin architectures, it should be relatively straight forward to switch between them.
The JS demo can run on the iPhone. But just because you can do something, it doesn’t not mean you should \- at about 2 FPS on the title screen, I can’t imagine how slow it would run in the Pentagonal Rain demo. And probably not great for your battery either 🙂
Just a quick update to let you know things are still moving forwards. I have not done very much iPhone specific stuff recently, but I have been working on the graphics code base in general. The idea is to separate the graphics code from SDL (although still use SDL most of the time) to avoid GPL issues and also allow the library to be used in a wider set of applications rather than just games. For example, inside a window in a larger desktop application, or inside Google’s Native Client plugin. Another goal is to improve rendering speed by minimising the amount of data moved between haxe and the graphics code – this involves moving code logic from haxe into c++. I have also been looking at a few minor tweaks such as setting object widths/alphas like flash does.
Once this is done and moved into Neash/NME, I will fix a few of the remaining issues on the C++ backend – maybe even get to add dynamic properties to the runtime. I would also like to spend a bit of time finishing off the internal garbage collection to make it thread-safe and run automatically – this could solve some of the problems compiling boehm-gc on various systems.
And, of course, I would like to write more tutorials…
The release this week of haXe version 2.0.4 officially includes c++ as a build target, for Windows, Mac, Linux and iPhone. You can download and install from haxe.org. In addition to the standard includes, you will need the “hxcpp” library, which can be insatlled with the included haxelib management tool.
Coincident with the hxcpp release, I have updated the neash and NME libraries to versions 1.0. You can also download these via the haxelib tool too. There are several incrental improvements, and the iPhone target has been added!
Getting started with the iPhone
Getting started with the iPhone is quite tricky at the moment, mainly because of the pain of setting up an Xcode project. Also, getting the simplest program onto the device is hard due to the code signing requirements. So if you can already get one of the existing application templates to work, you are half way there.
Note that this solution uses the “SDL” library, and must statically link against this. SDL is covered by the LGPL license, and this has implications should you choose to release your software. I am hoping to remove the LGPL restiction at a later date.
The binaries used here are have been compiled for the “2.2.1” iPhone SDK. So choose this version when compiling for simulator or device.
Get Xcode with iphone sdk support – visit apple.com
Get a Developer key (you can try simulator without it). You will need to pay to sign up as a developer on the apple site.
Fire up Xcode and do File > New Project.
Choose iPhone OS > Application. Here choose a “Windows-Based Application”
but infact we will use the delegate setup in the SDL code, so we will have
to delete the one created by the wizard.
Select a name & directory for the project. I’m calling it “Haxe Test”.
Now as it stands, you should be able to build for the Simulator and
get a lovely white screen and a program called “Haxe Test” in the simulator
Next thing is to delete(to trash) the “…AppDelegate.h” “…AppDelegate.m”,
the “Nib Files” group, Resources/MainWindow.xib and “main.m”.
Finally, select the “Haxe Test” executable (in the Targets section) and from the “Get Info” –
“Properties” tab, clear the reference to “MainWindow”.
We will add replacements for these soon.
Add “main.cpp” from the NME project.
Select the top-level project folder and then use Action > Add > Existing Files.
It is probably in /usr/lib/haxe/lib/nme/1,0/ndll/iPhone/ or
similar depending on which version of NME you have installed. It can be
very painful to get xcode to load from this location, unless you hit
Command-Shift-G at the “Add” dialog and type (at least some) of this filename in.
Choose to “Copy to destinations folder” so
that you can mess with it if you wish. Note: you need to have a cpp mainline
in order to automatically link in the correct runtime libraries.
Add the libNME.iphoneos.a and libNME.iphonesim.a files from the haxelib NME project.
You can add them both and the linker
will select the correct on depending on your build. They are in the same place
as main.cpp, you you should be able to use “iPhone” from the pull-down box
in the add dialog. Probably best not to copy these files – in case you want
to change them at some stage.
Add the whole sdl-static/lib/iPhone directory. Again probably best not to copy.
I used the “Recursively create groups” option. These will be where you stored them
in step 1.
Add the whole hxcpp/bin/iPhone directory like above. Again, this will
be in a path like /usr/lib/haxe/lib/hxcpp/1,0,2/bin/iPhone/.
Add the hxcpp include directory to the include path. Use the “Info” button
to get the project properties, and on the build tab, under “Search Paths”
add something like /usr/lib/haxe/lib/hxcpp/1,0,2/include/ to “Header Search Path”
Now we are ready for the haxe code. If you have and existing project,
then you can adapt the following instructions.
Create a new file from Xcode (Other/Empty File] Here I have called it “HaxeTest.hx”, and unticked the “Targets” option. I’m prety sure there is a way to get “Haxe File” to appear as on option here – but I don’t know the details.
In the haxe file, enter something like (Note the window size):
class HaxeTest extends Sprite
public function new()
var circle:Shape = new Shape( );
circle.graphics.beginFill( 0xff9933 , 1 );
circle.graphics.drawCircle( 0 , 0 , 40 );
circle.x = 150;
circle.y = 200;
addChild( circle );
static public function main()
neash.Lib.mOpenGL = true;
This is the “main” file for haxe, and the hxcpp compile will create a library matching
this class name.
Set up a build script to build changes you make to your haxe files into a library.
Xcode has a few issues with a straight custom build script order due to incorrect
dependency checking. This can be worked around by first adding a custom target.
Highlight the “Targets” in the Groups & Files and use the “Action > Add > New Target..”
Choose “Other > Shell Script Target” and call it something like “Compile Haxe”.
Close the pop-up and go back to the explorer. There should be a “Run Script”
entry under the “Compile Haxe” target if you expand it out.
Get info on “Run Scipt” and enter the following script
You can untick the “Show Environment” if you do not need to debug this.
One last step – drag the “Compile Haxe” target into the “Haxe Test” target.
It should now also show up as first item “under” the “Haxe Test” target.
The build order should now be correct. (See image at end of post)
Now you are ready to do the build. The first time you build, the build
results will show “Running custom shell script…” for quite a while.
Haxe compiles to cpp very quickly, but it take a while for the cpp files
to compile to a library. You can see the progress if you expand out the
middle tab bit.
At this stage, you should get a bunch or errors when linking, but also haxe
should have created a library for you. Add this library to the project –
it should be in the local cpp/HaxeTest.iphonesim.a.
Compiling now gets a bunch of unresolved functions from frameworks.
Add the following frameworks to the project (Add > Existing Frameworks):
These can be found in /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/.
So you should be good to go. Open up the debug console so you can see
Change the target to “Device – IPhone OS” from the pull-down and hit “Build and Go”.
Again, this takes quite a while the first time.
Now add the new cpp/HaxeTest.iphoneos.a library to the project.
Now you need to sort out your code signing. If you have not done so already,
setup you apple developer account & certificates on the apple web site.
Go to the info of the “Haxe Test” executable and the “properties” tab.
Change the “Identifier” to match one of your cerificates. Make sure to
match your company URL. You may want to use “*” when creating your
profile for easy changing.
Under the “Build” tab, under the “Code Signing” bit
in the “Any iPhone Device” pull down your profile. If you don’t have one then
you will need to create one on the apple website.
Connect up your iPhone(iPod touch) and build! W00t!
I have had all sorts of errors when trying to upload to the device.
So far, they have been solved by getting out of the car, walking around it and getting back in.
ie, Disconnect and power down ipod. Fully exit Xcode and the start it all up and try again. Also, uninstalling the app from the “Windows > Orgainiser” directory can help.
But now the easy bit. Change to HaxeTest.hx file, and hit Build & Go. It is that simple.
Errors should show up nicely in xcode.
You can add data files (eg, pngs, xml etc) to the project and they will be copied to device so you can open them with a relative path.
In the properties of the “Info.plist” you can set a Icon File – don’t forget to add the icon to the project too.
Not covered here (because I have not fully sorted it out myself):
Syntax highlighting in XCode
Debug build (hxcpp can do then – it’s a matter of setting up Xcode)
To progress this project a bit further, I needed a real device – so I convinced the little woman that an iPod touch would be a good thing to have around. She seems to have taken to it, so now I’m thinking I may need one each :).
After much phaffing about, I’ve finally managed to get stuff running on the actual device. I had to comment out quite a bit of NME, since I only used the base SDL, not all the extras. Boehm GC was also a bit tricky because I didn’t really know what I was doing, but I brought in some bits from the mono project and then disabled USE_MUNMAP because it caused it to crash. In the end, it seems to work – no crash, but then I may not have been running it long enough. I will have to try some memory thrashing later.
One thing I found with Xcode is that if you ever change the project name/AppID settings then you really need to clean the project, exit Xcode and get back in. But the hardest part was working out where to go the get the developer certificate! I guess I’m a bit thick, or missed the meno, but it took me ages to get to the web form to create a certificate.
So the big question is perfromance. In this demo, initally, it runs at about 2.5 frames a second (I don’t have a fps counter yet), but slows a bit later when things spread out. But this is using the high-quality, anti-aliasing software renderer. Next job is to hook up the OpenGLES renderer, then I’ll really know where I stand.
But overall, pretty positive result I think.
The c++ backend for haxe generates standard c++, suitable for the gcc compiler. iPhone dev uses gcc, and can link against c++, which make you think that iPhone dev can use haxe. Simple? Well, actually it was pretty simple. The hardest bit for me was to grok the components of an Xcode project, moving from dynamic libraries to static ones and getting SDL working.
The iPhone SDK requires you statically link everything, and I wanted to make it easy as possible to change haxe code -> generate cpp -> link to Xcode -> test of iPhone (or simulator). The solution I am currently using is to generate a library from the haxe code using the standard command line make, and include this library in the Xcode project. I hope to add a “pre build” step to drive the make system automatically.
Hxcpp executables typically use the “NME” library for graphics, which is in turn based on libSDL. The good news is that the source version of libSDL compiles for the iPhone! I tried the svn download first, but this does not seem as nicely bundled as the Apirl 13 version, which worked very nicely indeed (besides a small problem with RenderRect args changing).
Getting the hxcpp backend to generate a library was almost trivial – you take the same obj files and put them in a lib instead of an exe. The only minor difference is you do not explicitly create a “main” (ie, program entry point) call, but instead create a function (currently called \_\_hxcpp\_lib\_init) that the user supplied main line must call. This may also be good for windows applicaions that want to use a “WinMain” instead of console based main function.
Compiling the hxcpp runtime as a static library was also pretty easy after the post 0.4 code reorganisation that assimilates thirdparty code rather than linking to it. Again, it was a matter of taking the same objs and putting them in a lib instead of an dso. Initally I got link error when linking with Xcode, but if you include 1 real, small c++ file in the project, these link error go away.
Compiling “plugin” modules as static libraries (eg, NME) was slightly more difficult. I could use c++ static initialisation to auto-register the exported functions, if I could get Xcode to link to the required obj. To force objs to be included, I needed to put a special symbol in each cpp file that exports functions, and make reference to these from the main code base. It is really only something that needs to be sorted out once, and it is done now, so it should not really be a problem any more.
I also have to cull out quite a bit of code (eg fonts, image loading, opengl & sound) from NME, but I can look at adding these bits in one by one.
The astute ones among you will notice that the colour of the above circle if RGB/BGR reversed. This is something that will obviously need to be fixed.
Not being used to Xcode, it took a bit of getting used to – things like frameworks etc. However, I think that ultimately, we could end up with a very nice solution. The idea would be to create frameworks for hxcpp and nme, and a project template to link it all together. You would then create a project from the template, modifiy the boiler-plate haxe code and hit build. This would also be good for standard mac apps (rather then iPhone apps). Still a way off this, but moving in that direction.
SDL, LGPL and you
Dynamically linking against SDL (or NME) normally discharges your obligations to the GPL, however in this case, we are statically linking to it so there are still some issues. However, all is not lost because my interpretation is that you must allow others to relink your application. (ie “so that the user can modify the Library and then relink to produce a modified executable containing the modified Library”, where Library is “SDL”). So you must forefiet your hxcpp compiled library file (rather than haxe or cpp source), as well as you project files (which should be boiler-plate anyhow). So this is actually borderline acceptable, although I will work towards a GPL free solution).
To test the code, first extract the contents of the zip and then look in the bin directory. Double click the h3d.exe or h3d_ogl.bat files to run the c++ version (the h3d\_ogl.bat uses opengl, the other version uses the software renderer). You can see the flash version from the .html file (note: you will need flash player 10). You can run the neko if you have the haxelib version of nme installed by running “neko h3d.n”. All the source files are there in case you want to do some mods.
I have changed the mouse-look scheme from the original code to keep things a bit more centred. Move the mouse left/right to spin the objects, move it up/down to raise or lower the camera. You can use ‘w’ key for wireframe and the ‘p’ key for shading effects.
On my faster computer, I get about 100fps for the opengl renderer, 80fps for the software renderer, 40fps for the flash10 renderer, and 1fps for the neko/software renderer. There are some optimisations that could be done for the neash API, but really significant improvements could be gained by moving some of the engine into c++ code.
There were reports of preformance loss in opengl, and I think I may have traced it to excessive texture transactions due to the text in the status panel. To work around this, I have cached the text as glyph bitmaps (doing this was on my todo list) which seems to have helped. (This update is in the svn version of neash). I have also added a command-line switch to use a simple fps counter instead of the status panel. You can try this out with the h3d\_ogl\_simple.bat command, In the new download.