Onto Direct3D
Sunday, 3. February 2008, 15:16:27
So now I'm doing Direct3D. I'll probably end up using D3D on Windows boxes because that seems to be well supported compared to OpenGL. I hit a problem that, while it doesn't affect Project V directly, will affect future applications. Basically, it has to do with rendering to texture (RTT). OpenGL did solve this problem with framebuffer objects (FBO), but a great many people still do not have the newest drivers installed. And while older hardware can support FBO (FBO's are software only), the drivers are no longer supported and those who have older hardware are screwed. DirectX has had this right from at least version 8 from what I've read.
I'm going through the changes and the functionality is almost identical. At least as far as the basic stuff like texturing and pixel shaders are concerned. You have to call different functions and organise things a bit differently, but it's all the same. One difference is RTT. You create a texture and set it as a render target. In OpenGL, there are three different ways of doing this. If you have really old drivers (or hardware), you have to copy the render target into a texture because you can't use the render target directly as a texture. If your hardware supports PBuffers (a Windows only extension), then you can use render targets directly as textures for other render targets. That seems optimal until you realise that PBuffers have a context associated with them and you can only have one active context per thread. You can use as many of them as you like as source textures. But as a render target, only one can be active. The problem isn't with any of that. It has to do with the context switch. It's slow. It takes over one millisecond to complete. Sometimes it takes up to 20 milliseconds. Most of the time, it goes just under one millisecond and you'd think this would be fine, but actually, that's spells the death of OpenGL if you need RTT functionality and is why I'm switching to DirectX.
Here's the deal. I'm testing my own custom codec. I use the video card to handle 90% of the encoding/decoding. So that means using OpenGL or DirectX. I want to be able to eventually code up an equivalent version in Project V. That means the lower layers must likewise be able to handle such functionality. So far, I haven't really explained where the problem is. Well, here it is. When I'm doing transformations, I can do up to 240 RTT passes per frame. These are all very simple passes and take up under 30ms total time to process with the slowest of video cards. This means I can do over 35 frames per second easy as 30ms is worst case scenario. That's great. Except for one thing. I didn't include the timings for context switches. A context switch at 1ms average will make 240 RTT passes take up 270ms. Doesn't sound bad until you realise that this allows for about 4 frames per second. That's if I'm lucky because I'm doing 30 passes right now and can't get above 9 frames per second. The context switches average about 8 or 9ms each for certain RTT passes. This makes 30 RTT passes take up about 2ms which is about right. A codec only has about 30 to 40ms to process each frame. Go over that and there's no way it can work.
This isn't just about performance. It's about good design that takes into account performance. I hope the reader sees the difference. It's not performance for the sake of performance. It's not something that you can think up as an afterthought in this case. It happens to be a fundamental property of 3D. So OpenGL missed the boat on a fundamental property of their API. It just happens to be speed, but the criticism shouldn't be on that. It should be that they took their eye off the design goals, whatever they are. In today's world, there's way too much sloppy programming and design. There's no good reason why OpenGL couldn't have had a proper solution right from the start. 3D has to do with speed and should have been a consideration. But not only that. If you have bloat at the lower levels, there's nothing that the top levels can do about it. It's one thing for application developers to say that speed or bloat doesn't matter because no one will ever use it as a library in another application (which is a terrible frame of mind BTW). It's another to disregard speed and bloat in an API. It'd be like having memcpy() spawn X bytes of extra data, copy the data in there and then copy it to its final destination. It'd be ridiculous. And that's what OpenGL is when it comes to RTT. The fact that only in 2005 or thereabouts did the specs for FBO come out is sheer insanity. Speed aside, having a context for each render target is unnecessary bloat.
People always comment that you can't spend time optimizing applications because your time is best spend elsewhere. I don't get that because there's no reason optimizing should take more than an hour's time if you have a profiler and know how to do it correctly. And it's not like the WHOLE application needs optimizing. I've never seen an application need more than 1% changes and that number's a stretch. In the case of OpenGL, one simple test would have told them the same thing I've found. It took me under 5 minutes to see it. I ran the profiler and wglMakeCurrent() was at the top of the list. Nothing I can do about it. And this is why I always recommend using your own binary platform. No VM. No interpreter. No nothing. I also recommend having drivers and libraries where you have the source so that you can fix bugs at the lower levels. It's too much of a risk if something doesn't work. Imagine a company trying to make something with OpenGL and then realise that the windows functionality is broken and can't be used! This almost happened with Doom 3. John Carmack almost ditched OpenGL in favour of Direct3D and his opinion about Direct3D wasn't the most flattering in the past. And while I don't support the idea of giants, John Carmack knows has proven himself and his comments do carry some weight (specifically since I've found the same problems he's mentioned and agree with his more recent comments on how D3D has improved).
Anyways, enough ranting. Enjoy the Super Bowl. HAHAHA! I go to the Super Bowl site and nowhere does it mention who is playing in it. Guess I'll find out at game time. I stopped following Football when the Steelers and Patriots were there all the time. I don't like those teams. Hope they're not there this time. I'll be cheering for the beer. Canadian beer.