Wednesday, June 30, 2010

GPU Pro Review - 3D Engine Design Section

I recently started reading GPU Pro and it is outstanding! I love the full color and syntax highlighting! Many of the articles are even useful research for our own book. I'd like to write a full review but who knows when I'll get through the 700+ pages. So I'm going to write a review as I read each section. These reviews will be more about the ideas the articles give me than a complete review of the contents, writing style, etc. But isn't that the point of reading anyway - to get new ideas?

The 3D Engine Design section was the first section that peeked my interest. Of which, I read two of the four articles:

Porting Code between Direct3D 9 and OpenGL 2.0 - Wojciech Sterna

A chapter in our book is on designing an abstraction layer over OpenGL so the rest of the book can contain API agnostic discussion and code examples (with the exception of the use of GLSL for shaders). This isn't just important for book writing, all major graphics applications should have a renderer abstraction layer for flexibility, portability, performance, and most importantly, ease of development.

If you count a graduate class project, this is third time I've designed such a layer (check it out on sourceforge). Every time, I've done so with OpenGL so I was excited to see this article on the differences between Direct3D and OpenGL. While designing the layer, I looked at the Direct3D documentation from time to time but I am not positive that it is ideal for both APIs so I looked forward to learning more from this article.

And I did learn quite a bit. Perhaps I should be embarrassed to say, but I didn't know anything about the fine grain control available in Direct3D with memory pools. I also felt good learning that many things like vertex buffers and textures seem very similar between the two APIs.

I liked the mention of Cg - since I was recently asked why not use Cg instead of duplicating shaders in GLSL and HLSL. Although it sounds like two slightly different Cg shaders would need to be written anyway. If anyone has experience with maintaining shaders for different APIs, I'd like to hear about it.

Overall, this article was pretty good and I like that it was only 11 pages and right to the point. If I had to criticize it, I would have liked it to be about Direct3D 10/11 and OpenGL 3.2 core profile. But I understand that Direct3D 9 is still widely used and OpenGL 3.2 might not of even been out when this article was written. It would have also been nice to see more tips on designing an abstraction layer that allows for reasonable implementations using both APIs instead of just the API differences - although, the example code more than makes up for this.

Practical Thread Rendering for DirectX 9 - David Pangerl

This article also jumped out at me since I am preparing to write the threading material for our book. My focus is on using threads for out-of-core rendering: reading data from secondary storage, CPU intensive processing of that data (.e.g, computing normals, etc), then finally creating renderer resources (e.g., vertex buffers, textures, etc) - assuming I get all the example code working!

This short article is on another use of threading: using a dedicated thread for issuing rendering commands. The basic idea is to fill a command buffer instead of directly issuing Direct3D calls (I'm pretty sure this would also work with OpenGL). A dedicated rendering thread then executes the command buffer. Filling the command buffer is much faster than calling Direct3D functions, which reduces the CPU usage of your main thread. An interesting statistic from the article is the author found an average Direct3D function call takes 15,231 instructions. Using the dedicated rendering thread, the author saw improvements up to 200% in tests, and a 15% in a real-time game. Considering all that is going on in a game, 15% is great!

One thing I'm curious about is what happens when uploading large objects like vertex buffers and textures? Its not clear to me if a copy of the data is made for the rendering thread or if this falls into their category of commands that synchronize with the rendering thread and execute immediately. I'm also curious about operations like compiling and linking shaders which may be threaded by the driver anyway. I suppose this can happen offline in Direct3D.

It's worth mentioning that if you have an abstraction layer over your rendering API (and you should!), this could all be done behind the scenes with the user having no idea that there is a dedicated rendering thread.

In closing, I think this is a worthwhile idea that I'd like to implement myself at some point. Also, I'm not sure how this compares to multithreaded rendering in Direct3D 11.

Now onto the Game Postmortems section!


  1. Hi,

    I also recently acquired the book and I share your enthusiasm, however I feel a bit overwhelmed by the quantity (and complexity) of the information !

    I'd like to mention that Cg is a great language, and I really love its editor FX Composer.
    However there are certain caveats you should be aware before switching to Cg:

    On ATI cards you will be locked out of the newer profiles (basically have to fall back to compatibility arb profiles), with a good 60% chance your shaders won't compile (I realized that after switching to an ATI card).

    You will be totally dependent on Nvidia to release updates to their runtime.
    This may seem okay, but for example I got tired of waiting for the DirectX 11 runtime and switched my whole engine to a custom solution based on HLSL. (The D3D11 runtime is now available though)
    The same goes for any bugs you may encounter.

    Finally the runtime seems to behave odly from time to time and makes a lot of un-necessary API calls (as seen from PIX / glIntercept).

    Unity seems to be using Cg and I would really like to know how they manage it, they must have some sort of custom compiler back-end / runtime.

    As a final note, I'm a bit sad I could not find the full implementation of the multi-threaded DX9 device on the CD; I really wanted to run some benchmarks myself.


  2. Hi Julien,

    Thanks for all the information on Cg. If you are writing an engine that supports both Direct3D and OpenGL, do you think it is better to have separate shaders written in HLSL and GLSL? For the code in my book, I avoided Cg because of ATI concerns (although I didn't know they were as bad as you described) and also because of my familiarly with GLSL and the related OpenGL API. If we do a Direct3D version of the code, I figured porting from GLSL to HLSL is almost mechanical.

    I also agree with you that GPU Pro has an almost overwhelming amount of content - but that is a good thing! You can just read chapters individually in no particular order as you have time. It might take me a year or more to actually read a book like this cover to cover. I've read most of the Games Postmortem section and will write up a review when I get a chance.



Note: Only a member of this blog may post a comment.