The Great Porting Adventure: Day 8

After a few days off, The Great Porting Adventure resumes!

The TODO list has reached equilibrium – new items are discovered at about the rate that I knock them off. I figure this is a good sign, since I’m getting a handle on the remaining work and the issues that do pop up are pretty minor. Porting is a bit of a grind though. I’d much rather be working on something new and exciting at this point. The novelty of seeing my game running a Mac has all but worn off and thus I didn’t spend much time on it this week.

I started by going through the list of things that I compiled out just to get the game running in the first place. The big one was the intro “studio logo” splash which was a screen with a bit of transition flair that shows up when the game starts and loads a bunch of assets behind the scenes. I had to basically rip this out at first because it was causing a crash somewhere in OpenGL, which was about two levels of framework lower than anything I understood.

Is my code broken? Or XNA? MonoGame? MonoMac? maccore? OpenGL?

I read into it a bit and it turns out that OpenGL does not like it when you use an OpenGLContext from a different thread. This was a straightforward fix (a MakeCurrentContext() in the right place in the worker thread) because my use case was pretty simple: main thread loads assets, worker thread updates and draws the logo animation. This fixed the crash, but rendering had some serious issues. The screen fade was functional, but debug text was popping in and out over top of it. The logo itself wasn’t showing up at all, even though it was drawn in a very similar way to the screen fade.

It would eventually be revealed that none of these issues were related to OpenGL nor my multi-threaded use of it.

I spent a while trying to figure this out and lamenting the lack of PIX. At one point in my debugging, I noticed that I was multiplying some Color values by an alpha that was outside [0,1]. This turns out to be a no-go in MonoGame. I didn’t look into it much (and I don’t have the source in front of me), but I’m guessing it has something to do with the packed value representation used for Color. Not sure – needs more investigation. Certainly not the source of problems I was expecting.

The inconsistent rendering order that was causing sporadic popping of components was due to the draw order not being respected in the Game class. Or rather, the implicit draw order based on the order you added components was not always being honored. I fixed this one by explicitly assigning a DrawOrder to my components, which fixed the sorting.

After a while wrestling with this, I realized that my loading scheme was really just overly complicated and kind of hacky. I had pulled it from a previous game that loaded a lot of things up front, but the use case for DLC Quest wasn’t the same. There was no need for a second thread, and there certainly was no reason that it should be calling Present() on the GraphicsDevice. I’m pretty sure it came from the NetRumble sample, but it still felt wrong to be circumventing the Game loop like that. At any rate, I ripped it out and switched to a much simpler “show logo animation, then press start screen, then load stuff” flow. Much better.

The fiddling continued as I worked to get rid of some “dirty frame” transitions. It seems like there are some cases where I need to clear the framebuffer that don’t crop up in the XNA version of the game. I’m not sure where the discrepancy stems from, but it was easy, cheap and pretty logical to add in a Clear in one or two places. One transition problem stemmed from my use of ResetElapsedTime() to avoid a hitch after spending a long frame loading content. This method isn’t implemented in MonoGame at the moment, but I didn’t dig deep enough to find out if MonoGame would try to “catch up” on long frames anyway. It was easier just to add a few more frames to smooth out the transition.

Oh, and SoundEffectInstance.Resume() was broken. But I fixed it.

I’ve also noticed that my game throws a bunch of errors on startup (possibly when loading Mono-related libs) that look a little like this:


DLCGame.Mac(3296,0xb0183000) malloc: *** error for object 0x253f1010: pointer being freed was not allocated

*** set a breakpoint in malloc_error_break to debug

I don’t think there’s a <sarcasm> tag powerful enough to say I’m looking forward to figuring that one out.

That’s about it for Day 8. It’s getting to the nitty-gritty and game-specific stuff now. Still haven’t looked at the Mac store requirements… one of these days…

Running total: 8 days, $112.87

Advertisements

About Ben Kane
I'm a game developer with a heart of gold.

3 Responses to The Great Porting Adventure: Day 8

  1. Hey Ben

    Glad to see you continuing.

    About the threading issue you are having. On the Mac with MonoMac and Cocoa threading for graphics are a little different. Same with MonoTouch. You will want to wrap your calls in the following:

    using (var pool = new NSAutoreleasePool()) {

    }

    This keeps objects from leaking. And also do a BeginInvokeOnMainThread. This is really not anything to do with MonoGame per se but the way that MonoMac and MonoTouch work internally through and with Cocoa.

    There are a couple of examples of how to do background loading in the Samples:
    BackgroundThreadTester
    Catapult – Look at the InstructionsScreen.cs module where there is an example of both Mac and iOS

    Those two are the simplest to look through and you will not have to call makecurrent as it should just work.

    Thank you for the Resume() Fix. I missed that one. The OpenAL code is still basically untested on the public so you might run into a couple of more. Although all the samples seem to work so far including some that did not work before.

    The error you are experiencing on startup is the result of the OpenAL calls. Not sure exactly what it means but it is being thrown in the interface files themselves from MonoMac and the OpenAL interfaces. There is no problem with your program and they can be ignored.

    The DrawOrder problem is something new and seems it might be a regression in our code base as there were many after some consolidation of the classes to share more code between operating systems. If you have a specific example that we can use to sort this problem out that would be greatly appreciated.

    If there is anyway you can isolate the clear problem and send me a test I will check into what needs to be implemented in MonoGame. If I remember correctly you are using a lot of RenderTargets so that may be the culprit where I have missed implementing a parameter.

    The ResetElapsedTime() is definitely a regression and I will look into it.

    Hope this helps.

    Kenneth

  2. Hello Ben

    To let you know there is a fix for the DrawOrder regression out on Develop branch.

    Also, made an attempt at the long startup time on the first frame. You were not the only one with the problem as one of our Samples had the same problem. Also in there we try to catch up with update frames as well. Let me know how it works for you.

    Now for your clear problem if you can let us know how to recreate the problem.

    Have a good one and hope this helps you out.

    Kenneth

    • Ben Kane says:

      Thanks Kenneth! I’ll grab the updates from the develop branch next chance I get. I doubt I’ll be able to get a repro case for the Clear() problem, largely because I’m not sure it was anything to do with Mono specifically. It seemed like there was a dirty frame on startup that had the contents of the framebuffer from the last time the game was run. It was pretty strange, and not something I could easily record or reproduce.

      If I *do* manage to see it again in some consistent way, I’ll report it to you guys in the forums/IRC/etc.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: