The previous blog post expressed the opinion that Microsoft’s new Direct2D API is bad. Some people might have been thinking, hey, that’s just your opinion, Direct2D is actually kind of neat.
As responsible party Thomas Olsen says on his blog, Direct2D is layered on top of Direct3D. The goal of such an abstraction layer ought to be to make the underlying functionality easy to understand, use and debug.
It seems like a natural question, then: if we take that hideous Rectangle demo application and re-implement it in Direct3D, what does it look like?
I have the answer for you; today I wrote a Direct3D version of this application. The output looks like this (click for full-sized image):
My version (Direct3D) is 308 lines long. Microsoft’s version (Direct2D) is 519 lines long, or 69% bigger. There are some reasons why this code size comparison may not be equally weighted, which I’ll discuss at the end of the posting. But let’s get to the important point.
Just look at the code for the two of these examples. We know that 2D is a lot simpler than 3D. So, looking at the Direct2D code, it should be much easier to understand, right? Looking at these samples side by side, do you find that to be true? Honestly?
There are a couple of functions in the Direct3D code that might be confusing to someone who hasn’t done any 3D stuff; I think rendering_2d() is the main one. But (a) hey, if I were to write a 2D API, that function would just be the default and the user would never see it; (b) at least it is only confusing in terms of having some obscure numbers being computed — not in terms of having control flow go somewhere surprising, or having resources allocated and destroyed behind your back and not understanding the scope of when things exist (both of which are much, much worse).
Which brings up an important point:
The Direct3D version does not need to allocate permanent resources that would need to be tracked, destroyed on a reset, etc. Direct2D has you allocating ludicrous things like solid-color brushes, which for some reason are intimately tied to the device and need to be reset all the time. The D3D version of the code proves this isn’t necessary. The only allocated objects in use are the D3D interface and device. This makes the program easier to write, easier to understand, and more robust.
Now, about the code length comparison:
- I started with the Microsoft .cpp and edited it. I kept the ridiculous 5-6 line block comments that don’t say anything useful, just to keep the size comparison more even (though the more you write fundamentally-understandable code, the less you find it necessary to drown the code in comments). I couldn’t bring myself to add these huge block comments to new functions, though, so if I were to do that, my version would be a bit longer. Also, I don’t have a big copyright notice.
- I am not using their bloated overkill DemoApp class or any structure related to that. This results in a significant drop in program size, and an increase in understandability. Some people would say that it’s bad style not to use a wrapper class or something like that; those people are wrong, and probably believe too much of what they were taught at school. But the point is, if I were to write the Direct2D app without using that DemoApp structure, it would be smaller and simper as well (but not to the degree of the Direct3D app, I think). But then the real point is, Direct2D is designed by people who think this kind of DemoApp structure is a good idea.
- Again to keep length comparisons fair, I kept their 1-function-argument-per-line style in places like the CreateWindow call, but again, I couldn’t bring myself to do that very many places in the new code that I wrote. Hint: If you are so scared of function arguments that you need to put each one on a separate line or else they might bite you, then you are making way too big a deal out of calling a function. You are signaling that maybe you find calling a function a little difficult — maybe you can barely manage it! Mr. Microsoft, I think you’re making the problem more difficult than it really is.
- I didn’t vary the thickness of the grid lines or the non-filled rectangle in a device-independent way. This would be some more lines of code (10-20 maybe?) but again, that is something that would be built into a well-designed 2D API at a fundamental level, so it’s not really part of the comparison. Because…
My point is, “what would a Direct2D sample program look like if it were exactly Direct3D except with appropriate simplifications?” And the answer is, “like the program I wrote here, but simpler.” And that of course raises the next question, how could they have made this so much worse?
My impression is that Microsoft is pushing this API as the new thing for app writers in general to use when they do 2D stuff. It’s a noble aspiration to want to replace GDI, but this train-wreck of an API is about the worst they could have chosen.
Direct3D used to be terrible; in its initial release, it was very hard to make games with it. Over all the many versions from DirectX3 to the DirectX9 used here, Microsoft slowly learned to cut the bullshit and aim the API toward things that people actually want to use. (They never got all the way there; an OpenGL version of this app would be even shorter and simpler, and a more-complicated OpenGL program has none of the annoying problems with reference counting that Direct3D has; Microsoft, cut it out with the reference counting already, you are only making life harder!) With each revision of DirectX, game developers had to rewrite their games. But we did that, because hardware was evolving rapidly, and our games got big benefits out of being redesigned every 1-2 years anyway.
This will not work for general application authors. Whatever Microsoft releases as the initial version of Direct2D, however horrible it is, they are going to be stuck supporting it for damn near forever, with full backward compatibility. That’s going to make it harder for them to revise the API, to evolve it toward something reasonable.
For these reasons, I hope Direct2D doesn’t catch on. I hope it is DOA. Because if it goes into widespread use, software developers’ lives are going to get a lot more complicated for no particular reason. Software itself will become that much harder to write, and thus will become even slower and more bug-filled.
I think I have ranted about this enough.