An Overview of Microsoft's Direct3D 10 API
Direct3D 10 Application Development
Given the features and general information discussed so far in this article, it should be expected that application development will have to change to make use of the new API. This is true, but at the same time it's an evolution of what seasoned Direct3D programmers should be used to the core theory remains the same.
Enabled by Direct3D 10 being targeted at a new operating system, driver model and internal re-design is that it only has a few variable capabilities. This is no small change under Direct3D 9 the D3DCAPS9 structure contains enumerations that cover a huge spectrum of hardware (as demonstrated by the 'CardCaps' files in the SDK). Initial application development with such a number of potential combinations was at least an interesting balancing act; testing the final product against all combinations was difficult if not impossible.
With fixed capabilities it is conceivable that the testing will become more for performance than stability and correctness. This works well for both professional studios who can reduce the overhead (time and cost) of testing as well as for indie developers who simply don't have access to such wide-ranging resources. It has been hinted at that there will be more frequent point releases of Direct3D to allow for innovation of hardware features.
Given that the IHV's can no longer compete on who's got the best feature-set it will come down to whom has the best performance and quality. This does pose the question of whether performance-related capabilities will become the new problem an IHV might be required to provide a feature, but whether it's actually usable is another issue entirely. In current Direct3D 9 development, it is possible on some hardware to use "vertex texturing" but it is generally regarded as being too slow to rely on as a central component. With this in mind it's unlikely that a graphics engine can be abstracted completely from the hardware and that multiple code-paths will still exist (optimized for each IHV).
Another big aspect of Direct3D that has changed with this release is the push for create-time validation of resources. On the surface this is about performance moving any expensive checking to the time of creation and avoid doing it each-and-every time it's used by the core rendering functions. By having resources and configurations verified at create-time it should allow application developers to write cleaner and simpler code in the core parts of an application. Checking and handling of errors should become less of an intrusion into the core code. Also, by verifying resources when they are loaded it should give the application a better ability to handle any incorrect resources. With the increasing bias towards data-driven effects (more shaders, more textures ) any additional 'safety' can't be a bad thing!
Render states have undergone some changes with Direct3D10 that could require some changes to existing code bases. Simply put they are now organised into a number of immutable state objects. Each of these object types encompasses the group of render states related to its part of the pipeline for example the D3D10_DEPTH_STENCIL_DESC object describes render states related to depth and stencil buffering. This makes things a bit easier to manage it would be quite simple to create a number of these state objects for each effect to be used. Where it could get difficult is for existing scene graphs and state management systems that are finely tuned to the current Direct3D API. Efficient state management and ordered drawing has become the cornerstone of high performance Direct3D applications and if existing implementations are fine-grained down to individual states then this change towards immutable groups could invalidate much of that code.
HLSL and the Effects Framework
Direct3D 8's shaders were entirely written in assembly (which was still an intermediary step) and Direct3D 9 continued to allow this form but also introduced HLSL. With Direct3D 10 the use of assembly shaders has been almost eliminated effect files and "pure" shaders are now expressed only in HLSL form. The output from the HLSL compiler will still be visible so that you can use it for sanity checking and debugging, but it won't be a valid input from the application. The compiler itself has been merged into the core Direct3D 10 runtime it's no longer owned by D3DX as it was under Direct3D 9.
HLSL-only fits into the previous point about having create-time validation. By examining the input/output semantics the runtime can verify that the output of one stage matches the input of the next stage and not only produce an error indicating that the shader will fail, but also eliminate the need to check shader linkage during the core rendering segments.
The fundamentals of HLSL shaders (and their related "fx" files) hasn't changed, but there are a number of new instructions and functions available refinements on what most developers will be familiar with. It is notable that apart from a few specialist instructions (such as cut and emit in the GS) all three programmable units share a common set of instructions. 'Standard Annotations and Semantics' has featured in later Direct3D 9 updates and still exists in Direct3D 10 albeit it is more standardised and likely to be more widely used and relied upon. With annotations becoming a more basic part of the effects and HLSL systems, it should be more convenient to move effects between tools (e.g. authoring a shader effect inside 3DSMax and having it automatically picked up and used by your Direct3D application).
One of the bigger changes that will be apparent with HLSL is the introduction of "constant buffers" these apply logical groupings to the constants that the application can feed into a stage of the pipeline. These buffers allow the API and hardware to manipulate constants in a much cleaner way; in current applications it is very possible to adversely affect performance with inefficient constant updates. Despite the way they appear, they are more of a semantic than syntactic feature they don't work like namespaces (it's still a flat global namespace) and constants can get assigned to namespaces based on their usage. For example, a number of constant buffers can be created to indicate how often they are updated (always constant, per frame and user input etc..).
HLSL now allows for a full set of integer instructions and operations which appear much like you would expect from most progamming languages logical and bitwise operators. Given that stages in the pipeline can now access multiple resources, it can be useful to work in integer format so as to get correct addressing (and where filtering by floating point addressing is not desirable). With clean and direct access to the raw binary data (via bitwise operations) it will be interesting to see what geometry compression systems can be mapped directly to the GPU hardware.
Direct3D 10 shaders have no instruction count limit. Looping and extended execution time can be covered by the new Vista driver model because the GPU is considered as a shared resource the drivers and OS monitor situations where the GPU is deemed to have "hung" and require resetting.
The effects framework has undergone a complete re-design in part so that it matches the changes in the API but also to take advantage of the opportunity offered by a completely new API.
The memory footprint for effects files has been reduced by internal restructuring, but changes to the reflection system allow application developers to query for information and then discard all information that is no longer required.
Access to the internals of the effect file (constants/parameters, techniques etc ) has been refined and is now through a series of lightweight interfaces rather than through the slightly complicated handles system currently employed by Direct3D 9. Performance-wise, updating and applying changes is in line with the other design changes explained in this article fast! Validation is done at load-time such that no runtime checking is required, consequently changing becomes a constant-time operation.
Related to both of these is the ability to have "effect pools" it is advised that you load all effects into a pool such that any common information can be efficiently stored and updated.
The article you've just been reading has been focussed on the changes and enhancements in Direct3D 10 with reference to existing technologies where applicable. For this section of the article the focus does a 180 and covers some of the issues that application writers might need to consider today.
The first big change is going to be to stop relying on fixed-function processing. Obviously there will be a lot of legacy code around that uses this functionality, but any attempts to deprecate and slowly fade it away will be a good plan. Writing any new Direct3D code should be done entirely in the form of shaders (doesn't have to be via the Effect framework). Remember that FX files (via the Effect Framework) can contain fixed-function statements, so it's worth checking those as well.
Following on from this, you should also look at any shaders written in assembly code. As mentioned in the main body of the article, the new Direct3D runtimes deal with HLSL only such that your ASM code becomes obsolete. Given that most assembly code shaders are for the older 1.x targets it shouldn't be too hard to write up an equivalent HLSL version. Going forwards, it would be best to start writing all shaders in HLSL so that they are Direct3D 10 ready.
Consider making use of the new pipeline-generated values (VertexID, PrimitiveID and InstanceID). Their values can almost be simulated by attaching per-vertex attributes under Direct3D 9; but it might have to be something you need to wait before using. The reasoning for considering these attributes as it can, with a bit of creative thinking, be used to simplify the application-level code by getting the programmable pipeline to select properties for you.
When thinking about the new geometry shader functionality it is probably best not to think of it as a programmable unit for higher-order surfaces (e.g. Bezier patches) or compressed meshes. Whilst the GS has much of the functionality required for these tessellation algorithms it is quite likely that the first round of Direct3D 10 compliant hardware won't have the necessary performance to make heavy use of it. As hinted at previously in this article it is probably worth utilizing the GS as more of an optimization (single-pass rendering to multiple render targets) and a means by which to gather additional information about what is being rendered. For example, it's possible to compute plane equations and surface (rather than vertex) properties.
Combined with the increased availability of information inside the pipeline and the new grouping of render states, it will be worth considering how any scene graphs and state management algorithms work. Emulating state objects should be simple enough, and designing your algorithm(s) such that it can take advantage of the pipeline would definitely be beneficial for any future upgrades.
As you could quite rightly expect, Windows XP and DirectX 9 are still going to be around for some time yet. Officially Windows XP will cease to be supported at the end of 2006, but that doesn't mean it'll just vanish off home users machines (it may well vanish very quickly off corporate networks though). Application compatibility is a big factor in a new OS such that DirectX 9 applications built for Windows XP will still work under Windows Vista, and there will even be an updated version of DirectX 9 to take advantage of the new driver model in Vista ("DirectX 9.L").
For the time period running up to Windows Vista (currently estimated somewhere towards the end of 2006) it makes sense to continue developing for DirectX 9 with an eye towards targeting DirectX 9.L (as and when details are available). If you follow the guidelines in this article (as well as any others you can find) then updating to be Direct3D 10 compatible (or to make use of its features) should be fairly straight forward.
About The Author
Jack Hoxley is a Microsoft Most Valuable Professional (MVP) for DirectX. You can view his full profile here. He maintains a developer journal on the game development website GameDev.net and answers questions in their forums under the alias "Jollyjeffers". You can contact Jack by email at the following address: Jack *dot* Hoxley *at* f1cm *dot* co *dot* uk.
13th December 2005