Monday, March 23, 2009

Getting what you deserve

Money has always been relatively easy for me to come across. I think being half mathematician makes it easier for some to obtain and manage money. In any case, ever since I could make it I have never wanted for money. This is a fairly messed up fact in the grand scheme of things.

Lets talk about what people really deserve. I do not think there is such a thing as deserve. There cannot be for if this were so, humans deserve a lot of pain. This seems extreme.

Millions of children die of diseases that even given my quite opulent life by global standards I would never want to deal with. How could they deserve what they got and I deserve what I get? It isn't like I save children from burning orphanages while caring for the sick in my spare time.

Money, of course, isn't everything but health and money together are a lot. I have both and millions (or billions) of people will never have a chance at either.

So, knowing all of this, how can you be OK with money? Why not run around and devote your life to charity (this also doesn't feel right to me)? Then you surely must deserve what you get.

Except when I volunteered a lot I didn't really feel any better about myself. Every once in a while you would connect with someone and then you would feel great for a little bit, but it never lasted. The organizations weren't very professional and I always felt that a bit more could have been done if someone really took getting the job done a little more seriously. Perhaps my standards of what is professional are a little off.

So in any case, it seems impossible to make a logical argument for deserve. A very large part of what happens to someone really is just dice. Luck, destiny, call it what you will shit happens and sometimes you win and sometimes you lose.

Now there is a really high chance that some of the people that I am arrogantly feeling sorry for for not having lots of scrilla really are a lot happier than I am. Being happier than me really isn't that hard. But I don't feel unreasonably unhappy; I feel like I am happy enough to see opportunities when they lie but I have enough reserve that when something takes real discipline I can stick with it.

So is happiness the point of human existence? If deserve doesn't exist, then what does happiness mean? It would have to mean that you are just OK with your circumstances. You don't really owe anyone anything and they don't owe you.

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

Thursday, January 15, 2009

Interesting clojure issue

Worn out from complaining too aggressively

There is a lot I draw from this.

First off, people aren't replying to him on the email list. I find this incredibly lame because I believe, regardless of how he is raising it, that he raises a legitimate point that will cause consternation among people.

The basic thing is that:

user> (= (list 2 3) [2 3])
true
user> (hash (list 2 3))
-1919631535
user> (hash [2 3])
1026
user>

'=' semantics do not match hash semantics exactly. This means that if you intermix lists and vectors as keys in a hash map then you are going to get really odd results:

user> { [2 3] 4 (list 2 3) 5 }
{[2 3] 4, (2 3) 5}
user> (filter (= [2 3] %) (keys *1))
; Evaluation aborted.
user> (filter #(= [2 3] %) (keys *1))
([2 3] (2 3))
user>

You might ask how one would get into this situation, but you will get into it in some subtle ways. For instance you would (map identity [2 3]) and the result would be equal to [2 3] but it wouldn't be the same key in a hash-map.

I personally, now that I know about this, have absolutely no problem working around it. People who are used to c++ have had to work around much, *much* worse (like today I worked around a heap corruption problem that caused a failure in an unrelated piece of code).

People who are used to Java are used to a *completely* normalized environment. This is the ideal that we all strive for; no idiomatic problems that you have to deal with; just pure mathematical consistency. And perhaps a comfortable death of carbon monoxide.

I have never seen anything really cool that is that vanilla. Try using opengl in some advanced case; use c++ for a serious task (and succeed), play with CUDA. Badass tech makes sacrifices and sometimes these sacrifices are exactly in some area that causes serious problems. It is like really good scotch; you have to come to it and just take it for what it is. Judge it because it fails to wipe your ass for you and you miss out on some really fucking awesome engineering.

I think that Rich should probably fix this. But if he doesn't it is a problem that I can trivially work around. I would *much* rather use clojure because I think it is a super fun system to play with and I know that I can work around anything it throws at me, no question. I did it with .NET, I have done it with c++, I can trivially do it with the JVM and clojure.

Abstractions have leaks. And the really good abstractions still have really painful leaks. Learn them, understand them, and move on. Save the judgement for someone who cares.

Chris

Monday, January 12, 2009

Why I love clojure

There is a fundamental fact about programming languages; or rather my interaction with them. I love the newb feeling.

This is a dangerous addiction because it doesn't take long before you never have the newb feeling; at most I have another couple years where I can find languages that fascinate me.

I just thought it was damn fun trying things out in the repl and just finding interesting things.

Somehow, c++ has lost that interest for me and I think I know why.

First off, it is just butt ugly looking. Templates look like shit; although I think they are cool as a compiler-extension mechanism.

Second off, you get problems like this. Today at work, working with a large piece of legacy code that I didn't write, a co-worker and I added something that made the program just crash. During a memory-reclaim operation (embedded game engine; thus it partially does its own memory management).

We went through the obvious possibilities; the most likely being if the object were deleted twice somehow. That wasn't the case, so we wandered around the code. Finally I decided to try changing the order of inheritance for an object with multiple inheritance. That fixed the problem.

Somewhere in the code, there are lines that reinterpret_cast something they should be using static_cast for. The project doesn't have dynamic_cast enabled so that is out of the question. That pisses me off but is only one of about 100 things about it that piss me off.

Anyway, the difference is that during multiple-inheritance, the actual pointer-value will change during an upcast or a downcast. This is because the way c++ objects are stored in memory and the the vagaries of v-table implementations.

This is, coincidentally, why the diamond of death is such a big deal in c++. You end up with two representations of the top of the diamond in memory. Thus:

A
B C
D

A would be in D's memory allocation twice. Thus if you did static_cast<A*>(static_cast<B*>(d_instance)) you would get a different answer than if you did static_cast<A*>(static_cast<C*>(d_instance)). Finally if you want to avoid all of this you can use virtual inheritance in c++. This looks like class B : virtual public A.

Then, however, access to a base-classes' data takes longer because there is an extra pointer in the middle.

All of these details distract you from getting your algorithm perfect or doing a very, very good design and thus I think that most c++ programs are fundamentally worse designed than a lot of programs in other languages.

You can really concentrate on only so much simultaneously. The more you are focusing on the details of an arcane language the less you are focusing on your algorithm and its fail-cases. Or the bigger picture in the sense of where this piece of code fits in the system; or how minimally you can accomplish the task.

The pain of refactoring c++ leads you to do an inordinate amount of up-front design which is always worse unless you are solving the same problem again which you never do.

Finally, TheEyeStrainCausedByLookingAtCamelCaseClassNames, CamelOrJavaCaseVariableNamesAlongWith half_of_the_language_using_underscores_which_no_one_uses_even_though_the_damn_language's_standard_library_is_written_with_it. Mix this with reading about 10 times the characters (literally). And what exactly does this mean?
(this->*item[index])(reinterpret_cast<SomeStupidClassName*>(*data)[4]);

And tell your coding conventions to fuck themselves. I can write better, more understandable code without conventions than you will ever touch with your 10000 lines of coding conventions; most of which have never been proven to improve the readability of sections of code. Every second you spend on coding conventions you would have spent on good or god-forbid great design and frankly, just pure bad design makes things hard to work with. Not code conventions. So unless you have spent the time going through thousands of programs all in different languages all with different coding conventions so you have the breadth and depth of knowledge to make an even semi-informed opinion on what makes code understandable to other people do not write a single line of a coding convention. Because frankly, you don't have any idea what you are talking about.

Man, now that is done with. I doubt I would hate code conventions as much as I do if I haven't worked in a language that requires so much goddamn typing because its base levels of abstraction are just too low to express the vast majority of concepts clearly or precisely.

It was brilliant for java and c# to take the route that they did and take the worst aspects of c++'s type system and continue them. If you want types, use good type inference. If you don't, use a dynamic language. Piss poor required static typing is just a waste of characters. Since every line you write is a liability, that leads code that is overly verbose, hard to refactor, and *requires* sophisticated editors to manipulate in some excuse for efficiency.

I have arrived at the point in my career where I would take slow, interesting, concise code over fast boring as hell and tedious code. I have never had an unsolvable optimization problem; and I have written mmx assembly, x86, used Intel's SSE and a bit of AMD's 3d now vector instruction toolkits, not to mention some insanely fast linear algebra for large datasets using CUDA.

Some things are just tedious and kind of suck. Most things can be done elegantly. Clojure makes doing the tedious no more tedious than it was going to be anyway and doing the elegant simple and interesting.

Chris

On the fact that camel case is stupid.

Capitalization is something I do as little of as possible. I write my name Chris, and I talk about NVIDIA. After that I hate it, its just that i makes you look like a little kid sort of like i like stickers and run on sentences. I like the capitalization of letters at the beginning of a sentence because my eye gets lost without it as I sometimes miss the period. I have tried to not capitalize things altogether and I had to stop.

CamelCaseNamesDriveMeCrazy. asDoJavaCaseNames,Really. dash-case-is-the-easiest-for-me, while_underscore_case_is_a_bit_worse_but_I_can_handle_it.

I-remember-my-grandfather-use-to-write-using-dash-case-when-leaving-notes.

"Anyone-caught-running-water-into-this-basin-will-be-in-trouble. Accidental-or-other-wise!" was something he wrote.

What about syllable-case?

ChrisToPherPeTerNuernBerGer

graphics file formats

It is an odd fact of life for 3d programmers that the file formats *really* suck.

The collada specification *just the spec* is a 3.7M pdf. It doesn't have a lot of pictures.

The collada xml schema is over 400K bytes and clocks in at 11,848 lines.

The FBX toolkit has a c++ library as a file specification. They can't be bothered to publish their file format, even thought it extremely regular and pretty damn well designed by my estimation. You can see it in ascii, but I wonder if the binary version is identical to the ascii or if there is something neat about it.

Then check out lib3ds, try checking out a maya file. Obj is ok if you need something fairly simple.

Supporting any one of these in an application takes a huge amount of work.

Out of all of these I only really know collada. I did a 3ds importer a long time ago. One time I reverse engineered the excel .xls format going from partial documentation and the source code to OpenOffice's source code. Even with all of that, it took a *lot* of effort. Lots of hex dumps. Anyway...

Collada is the best out of all of them in my opinion. I bet I am one of a very very few number of knowledgeable graphics developers who believe that, but it is. They all suck, but at least on has an open development process along with a few large companies pushing it. It isn't a game engine data format; xml is big, verbose, and extremely slow to parse compared to fairly trivial binary file formats. It isn't the best designed piece of software I have ever seen, either. It isn't modular nor entirely consistent (like something of that size could be consistent, but anyway); in some places it is way overly generic and arbitrary (animations. There are at least 5 different ways to store bezier and linear key data. 5. FX composer, 3dmax, maya, and another 3d editor who's name escapes me now because they aren't sold in the US all do things them differently. It doesn't have nearly enough examples of what could be considered the right way to do things; thus everyone has just rolled their own.

But, it is something people can rally behind and we can all use it. I think the way collada does transforms is really really good. They are the source of a lot of problems, but you can do anything with them. Really goddamn good. I spent a huge amount of time getting them to work, but I think they are cool. I also think the way they store geometry data is pretty cool and lends itself perfectly to using opengl efficiently (vbos). I am not a huge fan of its shader sections; the interaction between shaders and scenes (using evaluate_scene tags) kind of annoys me. I just don't think of shaders, be they a special material on an object or a multi-pass effect in the same model and it irks me.

I like collada's extension mechanism but it is clunky. Certain really odd situations happen with different interpretations of the specification.

I wish they had used certain elements of xml schema and don't things a little differently in others. For instance, they don't break up logically different spaces using sub-schemas and xls-include. I don't know if this is for technical reasons, but it makes interpretating the entire specification tough because you *have* to look at a lot of stuff.

Why there isn't collada-geometry that includes collada core, why isn't there collada-animation in a completely different schema that includes common bits? Why doesn't the file start with their extension mechanism and use that to make pieces more modular? Perhaps you can't really have a unified ID-space if you are using different schemas? It may break schema verifiers; which for something like collada are particularly useless as it does lots of outside-schema stuff anyway, and certain large vendors produced files that didn't pass verification as it was.

I believe the FBX file format has superior architecture but it isn't open and it has weird characteristics that really irk me. I wish it had collada's geometry section, and for that record the way collada at least partially allows a good design for shaders and effects blows FBX out of the water. It starts with very generic design (essentially objects with arbitrary properties) and uses convention to and their API to ensure consistency. The details of the data in the format aren't as smart as Collada, however, and that kills it for me.

They both are light years better than 3ds files. I bet maya is pretty good design as that app is really in a league of its own with regard to really amazingly smart design. Also, for the record, Adobe can do some unbelievably cool things with applications. After Effects, even after all of these years is an amazing application. Their plugin API, while tedious and sometimes very poorly thought out, is documented with humor and looking at some of the things they allow is quite enlightening as to the application's internal architecture.

This is perhaps the weirdest thing I have admitted for a long time but file formats are really fascinating to me. API's almost always bore me or piss me off. But for some reason file formats are interesting; especially old ones. The excel file format is really damn cool, and some of the things that the microsoft applications could do was legitimately goddamn tough to do in binary. Things like in-place editing, where the app could run directly from the file without ever loading the entire file into memory at once and could write to the file in the same locations without growing its size (or growing it in a very generic way). Meaning the application could memory-map the file and then instantly use structures with no further loading, theoretically. It could also perform edits to this file while simultaneously growing its memory. This isn't shit tricks done with malloc or new; this is really good, consistent and darn hard engineering challenge that would affect the design of your entire application. On the other hand, the applications take forever to load files now and you have to wonder. Meanwhile KOffice tends to insta-load apps so fast it can be somewhat shocking.

I hate microsoft office; but I believe that in odd corners of it you find some of the most amazing engineering I have ever seen. Excel is an application that has yet to be equalled (or even close) by an opensource alternative. The best open source office suites just don't even compare to Microsoft's tools in terms of quality, features, or unified, consistent design. I guess I just hate office software in general as just the look of it forces me to puke instantly while seeing images of baby Jesus crying.

/ramble

Chris

Wednesday, January 7, 2009

Project update

Finished the first few sections of the refactoring of the project. I believe I will eliminate about 1/4 the code through eliminating dead code and careful refactoring as well as structure the code in a way that doesn't require another dev to know everything all at the same time.

I am giving a demo of its functionality to other NVIDIA people Friday so I can show off some of the really cool features. I noticed that an artist decided to attend the demo, which means I need to think a lot harder about the presentation and the audience. I intend to give another demo to the functional programming languages group later.

I want to present a couple of things. Thinking about it now, I would like to be able to present each feature in a way that everyone at the demonstration, regardless of technical ability, can really understand why it is important.

First off, I want a few of the more impressive features of the app clearly demonstrated. The live shader editing is going to be a hit, as well as perhaps some of the user interface details. This presentation is certainly not about the graphics, however. When this super clear, thorough, and much better than I could have ever written it in my entire life tutorial is working then I will have some eye candy.

I want to talk about the architecture behind the system, especially about the really heavy usage of threads. I guess I need to talk about software transactional memory and exactly why writing really safe multithreading code is much easier with this paradigm. Which means I need to explain functional datastructures, structural sharing, and software transactional memory.

I want to show off the repl a little bit. I have emacs very lightly pimped out and I know how to use the repl, so that should be fun. Having a repl may beat having an entire IDE. This is assuming you design your systems to be run from the repl. Not sure exactly how to prove this, but I just want to make the differences in the workflows very apparent.

So why is the repl so much better?

Having the repl is like having your debugger and your source code editor always running and always checking things out. You can weave in and out of editing and checking results/debugging very fluidly; this makes the distinction between writing and testing or debugging code disappear. Furthermore, being able to write small pieces of things and test them out immediately quickens your adoption of more advanced language features. Finally, you tend to test functions quite thoroughly from the repl. It is much quicker to test them and just look at their output from the repl than it is to write a unit test, run through the failures and debug the unit test.

This had the unfortunate side effect of eliminating the testing codebase I usually write; this I am not quite as pumped about as it means another dev will need to be *much* more careful about what they are doing. Well, win some and lose some.

I wonder how hard it would be to have emacs connect up to another running process? Emacs always starts the process; it can't be all that difficult to have emacs look for a connection at a given port. I wouldn't think it would be too much code to write in your app to have it open up a connection and start whatever clojure-swank starts...

Man, clojure is cool.

Chris