Sunday, January 25, 2009

Its days like these

That fucking rocked. Although it didn't rock at the time, now I feel pretty good.

I decided to get my project working in windows. Since it is a clojure opengl swing program I figured this wouldn't be anything but a quick check and perhaps a couple more function calls.

Thus, instead of quickly starting work I messed around with emacs. My emacs is half-pimped at this moment. I have line numbers, tabs at the top of each frame (in windows and mac), and the theme I like. I have a github project and the same .emacs file runs on both windows and mac.

I also pimped out my clojure setup a bit. I have everything (slime, clojure, clojure-contrib swank-clojure,clojure-mode) all synced up under one dev directory. I can go into each sub directory and sync them, rebuild jars where necessary and just open emacs again and I am running with the latest. No hassle, everything just works (for now).

This all happened yesterday for the most part. I woke up this morning thinking about emacs for some reason and immediately started coding. My project now has built-in slime (remote debugging) support. If you want to connect to the running project, there is a menu item to open up a swank port and start an internal swank server. Now in emacs you can connect to this, start the slime repl, and you are doing pretty good. I don't have to start my program from the repl any more in order to change or examine it.

All this before starting to port my stuff to windows. I did the internal swank server in the mac.

Now, I start running my program under windows and it doesn't work for shit. The first problem that I hadn't anticipated was that for some reason, under windows swing, I am unable to allocate an FBO with a texture. In order to render an anti-aliased scene I have to allocate a multi-sample fbo, render to that, blit to a single sample fbo and then render the result to the main screen. The easiest and by far fastest way to do this is to setup a texture as the downsample-fbo's color render buffer. This works like magic on the mac; no problem.

So, I can't allocate this type of FBO on windows. This sort of fundamental difference on the literally the same exact computer should have fired off a warning in my head. Anyway, I worked around it (using glCopyTexImage2D to copy the read buffer off the downsample fbo. This is much slower but it works) and I saw nothing. I now have two rendering paths, one if you can allocate a texture-fbo, and one for if you can't.

Back to the annoying days of holy shit, what the hell happened?

To make a very long story short, I have all of my java defines enabled for uber fast rendering. Crazy things like:


-Dsun.java2d.opengl.fbobject=true \
-Dsun.java2d.opengl=true\
-Dsun.java2d.translaccel=true\


Note the opengl and fbooject flags. They change, very deeply, the semantics of the system w/r/t opengl and they speed up rendering a *lot*.

So, in no particular order, here are the things I figured out.

Under the mac, setting the fbo to fbo 0 effectively sets you to render to the main screen. This follows as the mac isn't using an intermediate fbo to render to; it is using a pbuffer which is a different entity altogether although they do similar things. On windows, with the fbo option enabled, fbo 0 is *not* what you are rendering to as the main buffer. Thus for the longest time I saw absolutely nothing. White, in fact, which is a little weirder than black or uninitialized memory in my opinion. I have no idea how it occurred to me this was happening but it was just one of many hard problems.

Under the mac, the gl viewport is set to 0, 0, width, height. On windows, it was more like 0, 200, width height because swing was rending to an fbo and my GLJPanel was only rendering to a portion of said FBO. Thus the viewport was setup differently *if* you have sibling swing controls.

For identical reasons, windows swing implementation is using glScissor tests to ensure you *can't* render outside a given area regardless of messing with the viewport. This is a good idea as you can't trust what another client or control will do. I hadn't taken this into account, of course, because the mac doesn't do it. The effect was that when I rendered to the multi sample fbo I only saw a portion of my scene; it took a goddamn long time to figure out whether my full-screen-quad rendering was messed up or to ensure it was fine and start looking for other options. The solution was to disable the scissor test while I was rendering to the temporary fbos and enable after, before I rendered from downsample to the main buffer.

The weirdest bug *by far* was the difference in the glsl interface. The mac gives you every single shader attribute in order, whether or not you can mess with it. So you will see program attributes that look like "gl_Vertex" even though you can't set them yourself (gl takes care of that).

Windows, on the other hand, just showed me the editable attributes. Thus I had been using the attribute index as its gl handle on the mac but on windows this failed in the oddest ways. It took a very long time to start looking around the glsl code and replace the one implicit reference to attribute index with a call to glGetAttribLocation.

Now the program started crashing when I switched from my functional graphics demo to my wave demo. I eventually figured out this was because I wasn't protecting the underlying gl implementation from my changes. Specifically I was using the gl vertex vbo only for my wave program. My multisample system used gl attributes for everything but I like to explore all options so I did it differently in the wave section.

Somehow, leaving the vertex attribute active made the outer program crash hard. Actually, it makes a lot of sense why I guess. They must be using glDrawArrays or DrawElements to render the swing pieces to the fbo. Anyway, a couple glPushAttrib and glPushClientAttrib (along with their popping siblings) solved that problem quickly once the scent had been found.

Now my program works, both demos, on windows and the mac. This probably indicates it work work on linux, as both windows and linux use sun's swing framework. The mac uses apple's swing framework and thus there are going to be hardcore, non-trivial differences between them.

I really didn't want to try to support windows. But unlike linux it is installed on my mac laptop and I can honestly say that my emacs-foo, my swing and opengl foos are a level higher because I took the time to work through the issues. My slime-swank-foo is becoming somewhat formidable.

Chris

No comments: