Chapter 4 - Programming models & APIs: Part 2

 

4.1.2 Direct3D

Direct3D is Microsoft's platform specific API for programming 3D graphics on their operating systems. It is part of a larger collection of different APIs called the DirectX SDK. The DirectX SDK includes - besides Direct3D - APIs for sound programming, input devices and several other items of functionality. Historically, DirectX is aimed at the video games entertainment industry and therefore its focus is still heavily geared towards that sector even today. Unlike OpenGL, Direct3D underwent many radical changes since its first introduction in 1996 and very often subsequent versions are not backwards compatible to older versions of the API. Using this strategy it allowed Microsoft to evolve its API much quicker than for example OpenGL to changes in the graphics card market. That is why in recent years Direct3D seems to have led the way when it comes down to introducing new features in GPU programmability and their exposure to software development without the need to struggle with hardware vendor specific solutions but providing more or less a hardware platform independent minimal feature set application programmers can rely on.

d39pipeline

Figure 4.1: Direct3D 9 Graphics Pipeline (image courtesy of msd.microsoft.com).

The current latest version of Direct3D is Direct3D 10 [5] with a preview of Direct3D 11 currently available and a likely full release of Direct3D 11 some time this year. The numbering would assume this is the tenth major version of Direct3D which is not actually true since there never had been a version 4.

d310pipeline

Figure 4.2: Direct3D 10 Graphics Pipeline (image courtesy of msdn.microsoft.com).

The classic graphics processing pipeline of Direct3D is nearly identical to OpenGL (see Figure A.1) and its integration into the operating system can be seen in Figure 4.4. However, with Direct3D 10 the pipeline has been changed and the fixed pipeline as seen in Figure 4.1 no longer exists, instead it looks now as shown in Figure 4.2.

Also compared to OpenGL the programming model of Direct3D differs quite extensively. Remember OpenGL is a pure C procedural command style API that controls the underlying graphics processor in a state machine model. Often OpenGL has many incarnations and variations of commands for doing the same thing for example creating, sending and drawing geometry on the graphics processing unit.

Direct3D doesn't follow this model. The common state machine model of graphics processing units is abstracted in Direct3D into ATL (abstract type library) pointer objects - a very specific Microsoft Windows API construct that can be found in many other Microsoft APIs. The central object in the API is the Device. It is responsible for everything connected to the hardware. All operations that talk to the graphics processing unit are either linked to the Device or are directly executed by the Device.

d3computeb

Figure 4.3: Direct3D System Integration plus Pipeline

Up until Version 11 Direct3D has supported two main types of Devices:

  • HAL Device. The primary device type is the Hal device, which supports hardware accelerated rasterization and both hardware and software vertex processing. If the computer on which your application is running is equipped with a display adapter that supports Direct3D, your application should use it for Direct3D operations. Direct3D Hal devices implement all or part of the transformation, lighting, and rasterizing modules in hardware.
  • Reference Device. Direct3D supports an additional device type called a reference device or reference rasterizer. Unlike a software device, the reference rasterizer supports every Direct3D feature. This device is intended to be used for debugging purposes and is therefore only available on machines where the DirectX SDK has been installed. Because these features are implemented for accuracy rather than speed and are implemented in software, the results are not very fast. The reference rasterizer does make use of special CPU instructions whenever it can, but it is not intended for release type of applications.

The Reference Device in Direct3D can be used in two potential scenarios. The more significant one is probably when strange results are seen in the HAL Device leading to potential bugs in the hardware device driver or the hardware itself. These can easily be verified and identified by switching to the Reference Device. The second scenario is when the underlying hardware doesn't support (yet) a feature that is required. An application programmer still is able to program the code paths that uses the feature and actually see the behaviour even though it will run very slow.

With the current version of the DirectX SDK (November 2008) a new beta Device has been added to the list. It is called the WARP Device. Similar to the Reference Device it is a pure software rasterizer. But unlike the Reference Device it is highly optimised and takes advantage of latest CPU technology increasing the speed compared to the Reference Device by a couple of magnitudes. Additionally it reaches similar rendering quality levels as modern GPUs in Direct3D 10.

Creating a Device in Direct3D is at the beginning probably the hardest thing to understand and it needs an experienced programmer to fully grasp what is happening behind the scenes. The reason for this is that Direct3D allows to attach the Device to different graphics adapters and different SDK versions. A graphic adapter represents a single graphics processing unit installed in the system. For starters the easiest thing to do is to just use one of the many example codes that come with the DirectX SDK; they mostly contain most of the more complicated API calls for creating and housekeeping a Device.

Geometry and textures (1D,2D,3D) are created through the Device and are accessed and stored in different Resource ATL object types in Direct3D. All these objects have different methods to manipulate their content before they are sent to the graphics processing unit. During the creation of Resources different creation flags that determine the lifetime, CPU & GPU read/write access, and binding to a specific pipeline stage can be set. This provides the API and device driver hints to optimise the memory location of a Resources. Direct3D10 abstracts and generalizes the access to Resources by allowing different Views on a Resource. This means that Resource itself is just a block of memory somewhere in the system either directly on the graphics card memory or in main memory and the View describes the layout and structure of the Resource. This concept allows to have different interpretations of a Resource at the same time.

d3integration

Figure 4.4: Direct3D System Integration (image courtesy of msdn.microsoft.com).

4.1.2.1 HLSL

Since Direct3D 9C Vertex, Pixel, - and since Direct3D 10 Geometry - shaders can be written in a high-level C-style language called HLSL (High Level Shading Language). The shaders can either be compiled and linked at runtime using specific API calls or offline using a standalone compiler fxc.exe and then loaded onto the card. The output of the compiler is a hardware independent intermediate assembly language that is then linked into a hardware independent intermediate binary code which is then reinterpreted inside the hardware device driver to native code. Direct3D 9 still allows to write shaders directly in the intermediate assembly language for maximizing performance or overcoming specific shader version restriction. Direct3D 10 specific shader versions no longer allow this.

On top of HLSL Microsoft introduced the optional FX (effect system) often called HLSL FX. The effect system allows to group and combine different Geometry, Vertex and Pixel shaders and other non-programmable pipeline stages into so called Techniques. This allows easy access to constants, global variables, and texture samplers used in different shaders. Additionally all non-programmable pipeline stages, like alpha blending, culling mode, stencil buffer, alpha, stencil, depth test, etc. can be manipulated outside the application code and without changing the application code itself. This allows people without any knowledge of core Direct3D programming to change and manipulate key functionality as long as the application is taking advantage of the effect system.

Alongside the Direct3D API, the DirectX SDK provides additional useful features encapsulated in the D3DX (Direct3D extension) library. This extension library includes a complete set of vector and matrix math operations including quaternions, plus routines for loading, creating and manipulating meshes and different image file format loaders for creating texture resources.


  1. David Blythe. The direct3d 10 system. ACM Trans. Graph., 25(3):724-734, 2006.