Sunday, February 21, 2010

Direct 7/11

I've never been a great fan of Direct3D 8)

The first version was incredibly cubersome and slow, but I have to admit that it has changed quite a bit, actually a lot, and often for the better.
Still, I don't like it as an API (or perhaps I generally don't like any APIs ;)

Recently I've been looking into going from DX10 (that's Direct3D 10) to DX11. I've been using "Effects".
An Effect is basically a file with vertex, pixel and geometry shaders, and it also takes care of handing graphics states, such as culling direction, texture filtering, etc).
The Effects system is very convenient to leave most of the shading stuff in the hands of the TAs, where it should be, really.

Now, one thing that is key at using multiple shaders is to have some form of global variables. For example a transformation matrix for a model.. load that matrix once and use it for all the shaders used by that model.
This was handled elegantly by an "Effect pool system" in DX9 and DX10, where one would load a base parent Effect with some common variables to be shared by all subsequent child Effects.

..but, apparently this pool system has been removed in DX11 !! (The link talks about some mythical "groups", which do not appear in any of the DXSDK samples, nor would solve the fundamental problem of sharing globals across effects).

The Effect system was always considered an higer level/utility kind of API, and in DX11 the source code for it has become available, so much so that to use the Effects one has to explicitly compile that library.
So, theoretically, the pools concept could be hacked back in. But I wouldn't base a project on an utility API which is obviosuly not getting much attention from Microsoft anymore.

Another solution would be to explicity refer to global variables using specific registers IDs, like one does on the 360.
However this doesn't seem to work with DX11 Effects, and looking into the code, it seems that the specified registers aren't really used (ouch).

The official answer however seems to be that one should simply compile all Effects into one big-ass megaeffect (perhaps by using includes).
This is one of the ugliest non-solutions to the problem. It's especially bad for the developmet phase where one may want to just tweak a few Effects on the fly, without having to recompile some monster file for every little change.

What bothers me is also how the new shading system is preoccupied with dynamic linkage and inheritance.. I mean, get the simple stuff working first, and worry about the OOP fanciness later, if there is any real need for it !

Frustrating... and another reason to make my own shader compiler and renderer.. power to the programmers ! Say NO to those closed-source APIs !!

P.S. See also my questions on the XNA forum.


  1. Its hard to believe that you can not set shader constants directly.

  2. Well.. you can set the cbuffers manually.. but that's what the Effect system was for:

    * share the constant buffers between effects at load time

    * update the constant buffers transparently by keeping track of what variables one changed and by uploading whole constant buffers when a shader that refers to those is selected for rendering

    ..of course you can do all this manually.. but my complaint is that all this stuff was there and now it's not there anymore 8) (constant buffers are uploaded selectively, but aren't shared between different Effects that are in different files).

  3. I see,

    You said that you looked at the DX11 Effects code and noticed that specifed register IDs are not even used, I understood that to mean that you can not set cbuffers manually anymore.

  4. yeah that too.. ..looking into the Effects' solution at:

    C:\Program Files (x86)\Microsoft DirectX SDK (February 2010)\Samples\C++\Effects11\Effects11_2008.sln

    In Binary\EffectBinaryFormat.h, there is this SBinaryConstantBuffer structure that has a ExplicitBindPoint member.

    That's the register ID (or "bind point"), but when doing a "All Files in Solution" search, I cannot see that bind point actually making any difference...