Traditional DirectX was a household of a couple of dozen APIs for graphics, sound, enter, networking and media. Of the 9 proven within the desk beneath, one continues to be the beneficial option to do its job on Home windows in the present day: Direct3D. The remaining had been changed, folded into one thing else, or eliminated. Code written towards them nonetheless turns up in upkeep work, in emulators, in sport preservation initiatives and in outdated tutorials, and it helps to know what every one did and what to make use of as an alternative.
This information covers the historical past of DirectX from Home windows 95 to DirectX 12 Final, what each basic element was for and what changed it, the graphics concepts that outlived DirectDraw (pixel codecs, palettes, pitch and double buffering), and a whole Direct3D 11 program that does the job a DirectDraw pattern used to do. The three C applications had been compiled with GCC 13.3 and Clang 18.1.3 beneath -std=c11 and -std=c17 with -Wall -Wextra -pedantic and no warnings, and run on Ubuntu 24.04 (x86-64), with a clear AddressSanitizer and UndefinedBehaviorSanitizer run beneath GCC; each output block is captured verbatim. The Direct3D 11 applications had been cross-compiled with MinGW-w64 GCC 13 with no warnings however weren’t run for this text; the repository’s Home windows construct runs the headless one.
The Quick Reply
Is DirectX nonetheless used? Sure. Direct3D 12 and Direct3D 11, along with DXGI for swap chains and show output, are Microsoft’s present graphics APIs for Home windows. Microsoft nonetheless ships DirectX 12 updates by way of the Agility SDK; the newest retail launch when this was written was model 1.619.6, from September 2026.
Do you have to study DirectDraw or Direct3D Retained Mode? Solely to take care of or research outdated code. Microsoft’s documentation says DirectDraw is not beneficial, and Retained Mode was dropped from Home windows with Vista.
What changed the opposite elements? DirectSound gave option to XAudio2, DirectInput to XInput after which GameInput, and DirectShow to Media Basis. The desk additional down has the complete mapping.
What Is DirectX?
DirectX is Microsoft’s assortment of low-level Home windows APIs for video games and multimedia. It started in 1995 as a method for Home windows 95 video games to succeed in graphics, sound and enter {hardware} with out going by way of the slower general-purpose Home windows layers. At the moment the title largely means Direct3D 12 and Direct3D 11, plus DXGI, Direct2D, DirectWrite and the audio and enter APIs that changed the Nineteen Nineties ones.
Most DirectX APIs are units of COM interfaces (XInput and DirectXMath are exceptions: plain C and C++ features). You create an object by way of a manufacturing unit perform reminiscent of D3D11CreateDevice, name strategies on interface pointers, verify each HRESULT, and launch the item if you find yourself carried out. That mannequin has not modified for the reason that Nineteen Nineties, which is why outdated DirectX code nonetheless reads as acquainted even when the precise APIs are gone. Microsoft’s personal reference for the primary DirectX 2-D API, the DirectDraw documentation, continues to be on-line and opens with a notice that DirectDraw is not beneficial to be used.
A Quick Historical past of DirectX
Earlier than Home windows 95, PC video games ran beneath DOS and normally used a 32-bit DOS extender reminiscent of DOS/4GW to succeed in protected mode and write to the {hardware} immediately. Home windows 95 put an working system between the sport and the {hardware}, and video games that wanted full-screen mode, quick blitting and low-latency sound had no great way by way of it. DirectX was Microsoft’s reply.
- February 1995: RenderMorphics. Microsoft purchased RenderMorphics, the London firm behind the Actuality Lab 3-D API, and its engineers constructed the primary Direct3D from that work.
- September 1995: the Home windows Recreation SDK. DirectX 1.0 shipped on September 30, 1995, beneath the title Home windows Recreation SDK, with DirectDraw, DirectSound and DirectPlay. The “DirectX” title got here from a journalist mocking the Direct-everything naming, and the group adopted it.
- 1996: Direct3D arrives. Direct3D first shipped with DirectX 2.0 in June 1996 and once more in DirectX 3.0 that September, with two modes: a low-level instant mode and a high-level, scene-graph retained mode.
- 1997: DirectX 5 (there is no such thing as a DirectX 4). Microsoft developed variations 4 and 5 on the similar time, discovered little developer curiosity in 4, and skipped it. In its March 1997 announcement Microsoft described DirectX as two layers: a low-level DirectX Basis layer for {hardware} entry, and a high-level DirectX Media layer for streaming, animation and synchronization (Microsoft press launch).
- 1999: DirectX 6.1 and seven. DirectMusic arrived in DirectX 6.1 in February 1999. DirectX 7 adopted in September 1999.
- 2000: DirectX 8. Vertex and pixel shaders made the graphics pipeline programmable, and DirectDraw stopped being developed: Direct3D 8 took over its 2-D work, whereas the DirectDraw 7 interfaces stayed out there for current applications.
- 2002–2009: DirectX 9, 10 and 11. DirectX 9 arrived in December 2002. Direct3D 10 was tied to Home windows Vista. Direct3D 11 shipped in 2009 for Home windows 7 and Home windows Vista SP2.
- 2010: the final standalone DirectX SDK. The June 2010 DirectX SDK was the ultimate separate launch. From Home windows 8 onward, the headers and libraries are a part of the Home windows SDK.
- 2015–in the present day: DirectX 12. Direct3D 12 shipped with Home windows 10 and provides the applying express management over reminiscence and command submission. DirectX 12 Final, introduced in March 2020, teams DirectX Raytracing 1.1, variable-rate shading, mesh shaders and sampler suggestions into one function stage shared with the Xbox Sequence X.
| Model | Launched | What modified |
|---|---|---|
| DirectX 1.0 | September 1995 | DirectDraw, DirectSound, DirectPlay for Home windows 95 video games |
| DirectX 2.0 | June 1996 | First Direct3D, with instant and retained modes |
| DirectX 5.0 | 1997 | Basis and Media layers; no DirectX 4 was launched |
| DirectX 6.1 | February 1999 | DirectMusic |
| DirectX 8.0 | November 2000 | Programmable shaders; DirectDraw folded into Direct3D |
| DirectX 10 | 2006 | Launched with Home windows Vista; a redesigned Direct3D |
| DirectX 11 | 2009 | Home windows 7 and Vista SP2; compute shaders and tessellation |
| DirectX 12 | 2015 | Home windows 10; express, low-overhead Direct3D |
| DirectX 12 Final | 2020 | Raytracing, mesh shaders, variable-rate shading, sampler suggestions |
Launch dates for the early variations differ by a couple of days between sources, so the desk offers months.
The Traditional DirectX Parts and What Changed Them
The Basis layer held the APIs that speak to {hardware}: DirectDraw, Direct3D Rapid Mode, DirectSound, DirectMusic, DirectInput and DirectPlay. The Media layer held higher-level providers constructed on high: Direct3D Retained Mode, DirectAnimation, DirectShow and DirectX Remodel. Right here is every one, what it did, and what new code makes use of as an alternative.
| Element | What it did | Use in the present day | Standing |
|---|---|---|---|
| Direct3D Rapid Mode | Low-level 3-D rendering on the graphics card | Direct3D 12 or Direct3D 11 | Present |
| DirectDraw | 2-D surfaces, blitting, web page flipping, palettes | Direct3D 11/12 with DXGI; Direct2D for 2-D drawing | Not beneficial |
| Direct3D Retained Mode | Scene graph of frames, meshes, lights and cameras | A scene graph in your engine or framework | Eliminated in Home windows Vista |
| DirectSound | Wave mixing, playback and seize | XAudio2; WASAPI for low-level audio | Outmoded |
| DirectMusic | Message-based music and MIDI playback | No direct successor; XAudio2 plus audio middleware | Not out there to 64-bit applications |
| DirectInput | Joysticks, gamepads, drive suggestions, keyboard and mouse | GameInput; XInput for Xbox-style controllers | Outmoded |
| DirectPlay | Multiplayer periods over modem, LAN and Web | Winsock or a platform networking service | Non-obligatory Home windows function |
| DirectShow | Media playback and video seize | Media Basis, MediaPlayer, IMFMediaEngine | Legacy |
| DirectAnimation, DirectX Remodel | Animated media and picture results | Internet requirements reminiscent of CSS and SVG | Deprecated |
DirectDraw
DirectDraw gave a program direct entry to video reminiscence as surfaces: a main floor that’s the seen display screen, again surfaces you draw into, and off-screen surfaces for sprites. It dealt with display-mode modifications, web page flipping, colour-keyed blits and palettes. Microsoft’s documentation now states that, since Direct3D 9, all 2-D performance is roofed by Direct3D and by Direct2D. For brand spanking new code meaning Direct3D 11 or 12 for something game-like, and Direct2D if you need vector shapes and textual content drawn right into a Direct3D floor.
Direct3D Rapid Mode and Retained Mode
Rapid mode is the ancestor of each Direct3D you need to use in the present day: the applying submits geometry and state, and the motive force renders it. Retained mode sat on high of it as a scene graph. You constructed a tree of frames, every holding a place and orientation relative to its father or mother, and connected visuals reminiscent of meshes to them. One mesh may dangle from many frames, which is how a forest or a fleet drew many copies of 1 mannequin.
Retained mode was not up to date after DirectX 3.0, and Home windows Vista stopped transport its runtime, d3drm.dll. The toolchain exhibits the identical cut up in the present day. MinGW-w64 11 nonetheless ships the d3drm.h header, so code that makes use of it compiles, however there is no such thing as a import library to hyperlink towards:
/usr/bin/x86_64-w64-mingw32-ld: can not discover -ld3drm: No such file or listing
collect2: error: ld returned 1 exit standing
The thought of a scene graph lives on in sport engines and frameworks; it simply stopped being a part of the working system.
DirectSound and DirectMusic
DirectSound blended and performed wave information with low latency and {hardware} acceleration the place the sound card supplied it. Microsoft’s XAudio2 documentation describes XAudio2 as DirectSound’s substitute, and XAudio2 is what new sport audio code ought to use. DirectMusic labored a stage increased, with message-based music {that a} synthesizer changed into sound and soundtracks that might change with the motion on display screen. It’s not out there to 64-bit applications. Microsoft’s later audio APIs, XACT after which XAudio2, play sound however haven’t any equal of its adaptive-music engine, in order that job moved to audio middleware.
DirectInput
DirectInput learn joysticks, gamepads, wheels and force-feedback units, and will additionally learn the keyboard and mouse. XInput later simplified Xbox-controller enter. Microsoft’s present advice is GameInput, which its documentation describes as a useful superset of DirectInput, XInput and Uncooked Enter. GameInput is out there on Home windows 10 (Might 2019 replace) and later by way of a NuGet bundle.
DirectPlay
DirectPlay managed multiplayer periods over modems, native networks and the Web, impartial of the transport beneath. It’s now a Home windows function that’s off by default, discovered beneath Legacy Parts in Flip Home windows options on or off, and older video games that use it could ask you to allow it. New code makes use of Winsock immediately or the networking service of the platform it ships on.
DirectShow, DirectAnimation and DirectX Remodel
DirectShow performed and captured audio and video by way of a graph of filters. Microsoft now marks it as a legacy function and factors new code at MediaPlayer, IMFMediaEngine and Media Basis seize (DirectShow documentation). DirectAnimation and DirectX Remodel supplied animation and picture results, largely for internet content material, and are deprecated.
DirectX Device Equipment and DirectXMath
Two newer libraries fill gaps the Nineteen Nineties SDKs left. DirectXMath is a SIMD-friendly header-only library for vectors, matrices and quaternions. The DirectX Device Equipment (DirectXTK for Direct3D 11, DirectXTK12 for Direct3D 12) supplies sprite batching, texture loading, fundamental results and audio helpers. Each are maintained by Microsoft on GitHub; DirectXTK12 had NuGet releases as not too long ago as Might 2026.
Graphics Ideas That Outlived DirectDraw
The DirectDraw API is historical past, however the concepts it taught are nonetheless in Direct3D applications in the present day: how a color is saved in a pixel, how rows of pixels are specified by reminiscence, and the way a body reaches the display screen with out flicker. The three C applications beneath are transportable and wish no Home windows headers, so you may run them anyplace.
Pixel codecs: 32-bit and 16-bit color
A pixel format says what number of bits every pixel makes use of and which bits maintain which color channel. The Nineteen Nineties modes had been 8-bit listed (256 colors from a palette), 16-bit “excessive color”, 24-bit “true color”, and 32-bit modes by which the fourth byte is both unused (XRGB) or an alpha channel (ARGB). The widespread 16-bit structure is RGB565: 5 bits of purple, 6 of inexperienced and 5 of blue, with inexperienced getting the additional bit as a result of the attention is most delicate to it. Some {hardware} used RGB555 as an alternative, so code needed to ask the floor which one it had.
/* color_formats.c - how a pixel color is specified by reminiscence:
* 32-bit XRGB8888 and 16-bit RGB565. */
#embody <stdint.h>
#embody <stdio.h>
static uint32_t pack_xrgb8888(uint8_t r, uint8_t g, uint8_t b)
(uint32_t)g << 8
static uint16_t pack_rgb565(uint8_t r, uint8_t g, uint8_t b)
(g >> 2) << 5
static void dump_bytes(const char *label, const void *p, size_t n)
{
const unsigned char *bytes = p;
printf("%-26s", label);
for (size_t i = 0; i < n; i++)
printf(" %02X", bytes[i]);
putchar('n');
}
int foremost(void)
(b5 >> 2));
return 0;
Output:
This machine is little-endian
XRGB8888 inexperienced worth: 0x0000FF00
bytes in reminiscence: 00 FF 00 00
RGB565 inexperienced worth: 0x07E0
bytes in reminiscence: E0 07
RGB(150,150,150) as RGB565 = 0x94B2
expanded again to eight bits: RGB(148,150,148)
Two issues are value studying out of that output. First, the worth and the bytes should not the identical factor. Pure inexperienced in RGB565 is the worth 0x07E0, however on a little-endian x86 or ARM machine it sits in reminiscence as E0 07, low byte first. Code that writes pixels byte by byte, or reads them from a file, has to account for that. Second, 16-bit color loses info: gray RGB(150,150,150) comes again as RGB(148,150,148), as a result of purple and blue preserve solely 5 bits and inexperienced retains 6. At the moment’s swap chains usually use DXGI_FORMAT_B8G8R8A8_UNORM or DXGI_FORMAT_R8G8B8A8_UNORM, and the identical byte-order query applies. For these 8-bit-per-channel codecs the title lists the channels in reminiscence order, so a B8G8R8A8 pixel begins with its blue byte; the repository’s Home windows check checks precisely that.
Palettes and 8-bit listed color
In an listed mode, every pixel is one byte, and that byte is an index right into a 256-entry color look-up desk, the palette. The palette holds the true RGB values. Altering a palette entry modifications each pixel that makes use of it, with out touching the picture.
/* palette_fade.c - an 8-bit listed picture fades to black by altering
* solely its 256-entry palette; the pixel bytes are by no means written. */
#embody <stdint.h>
#embody <stdio.h>
typedef struct { uint8_t r, g, b; } rgb;
enum { W = 4, H = 2 };
static void present(const uint8_t pixels[H][W], const rgb palette[256], int step)
{
printf("step %d:", step);
for (int y = 0; y < H; y++)
for (int x = 0; x < W; x++) {
rgb c = palette[pixels[y][x]];
printf(" (%3u,%3u,%3u)", c.r, c.g, c.b);
if (x == W - 1 && y == 0) printf("n ");
}
putchar('n');
}
static unsigned checksum(const uint8_t pixels[H][W])
{
unsigned sum = 0;
for (int y = 0; y < H; y++)
for (int x = 0; x < W; x++)
sum = sum * 31u + pixels[y][x];
return sum;
}
int foremost(void)
{
const uint8_t pixels[H][W] = { { 1, 2, 3, 1 }, { 3, 2, 1, 0 } };
rgb base[256] = { [0] = {0, 0, 0}, [1] = {255, 0, 0},
[2] = {0, 200, 0}, [3] = {40, 80, 255} };
rgb palette[256];
unsigned earlier than = checksum(pixels);
for (int step = 0; step <= 4; step += 2) {
for (int i = 0; i < 256; i++) { /* scale each entry */
palette[i].r = (uint8_t)(base[i].r * (4 - step) / 4);
palette[i].g = (uint8_t)(base[i].g * (4 - step) / 4);
palette[i].b = (uint8_t)(base[i].b * (4 - step) / 4);
}
present(pixels, palette, step);
}
printf("pixel checksum earlier than %u, after %un", earlier than, checksum(pixels));
return 0;
}
Output:
step 0: (255, 0, 0) ( 0,200, 0) ( 40, 80,255) (255, 0, 0)
( 40, 80,255) ( 0,200, 0) (255, 0, 0) ( 0, 0, 0)
step 2: (127, 0, 0) ( 0,100, 0) ( 20, 40,127) (127, 0, 0)
( 20, 40,127) ( 0,100, 0) (127, 0, 0) ( 0, 0, 0)
step 4: ( 0, 0, 0) ( 0, 0, 0) ( 0, 0, 0) ( 0, 0, 0)
( 0, 0, 0) ( 0, 0, 0) ( 0, 0, 0) ( 0, 0, 0)
pixel checksum earlier than 3604719997, after 3604719997
The picture light to black, but the pixel checksum is an identical earlier than and after: solely 256 palette entries modified, not the pixels. That was the attraction of palette animation on Nineteen Nineties {hardware}, the place rewriting 768 bytes of palette was far cheaper than rewriting a 64,000-byte 320×200 display screen. Trendy swap chains haven’t any 8-bit palettized format, so the identical impact is finished in a pixel shader that appears colors up in a small texture.
Pitch (stride): why rows are wider than the picture
A floor’s pitch, additionally known as its stride, is the variety of bytes from the beginning of 1 row to the beginning of the following. It’s typically bigger than the width occasions the bytes per pixel, as a result of drivers pad rows for alignment. Any code that writes right into a floor’s reminiscence should step by way of rows by the pitch the API experiences, by no means by width * 4.
/* pitch.c - why a floor's row stride (pitch) will not be width * bytes-per-pixel.
* Attracts a diagonal right into a padded 6x6 floor, as soon as with the pitch and as soon as
* with the width, then prints what the show would present. */
#embody <stdint.h>
#embody <stdio.h>
#embody <string.h>
enum { WIDTH = 6, HEIGHT = 6, BPP = 4, PITCH = 32 }; /* 32 > 6 * 4 = 24 */
static void present(const char *title, const uint8_t *floor)
{
printf("%sn", title);
for (int y = 0; y < HEIGHT; y++) {
printf(" ");
for (int x = 0; x < WIDTH; x++) /* the show reads with PITCH */
putchar(floor[(size_t)y * PITCH + (size_t)x * BPP] ? '#' : '.');
putchar('n');
}
}
int foremost(void)
{
static uint8_t floor[HEIGHT * PITCH];
memset(floor, 0, sizeof floor);
for (int i = 0; i < WIDTH; i++)
floor[(size_t)i * PITCH + (size_t)i * BPP] = 0xFF;
present("Row offset = y * pitch:", floor);
memset(floor, 0, sizeof floor);
for (int i = 0; i < WIDTH; i++)
floor[(size_t)i * (WIDTH * BPP) + (size_t)i * BPP] = 0xFF;
present("Row offset = y * width * 4:", floor);
return 0;
}
Output:
Row offset = y * pitch:
#.....
.#....
..#...
...#..
....#.
.....#
Row offset = y * width * 4:
#.....
......
.....#
....#.
...#..
......
The floor is 6 pixels vast with 4 bytes per pixel, however every row occupies 32 bytes reasonably than 24. Stepping by the true pitch attracts a clear diagonal. Stepping by width * 4 places row 1 and row 2 into the invisible padding on the finish of row 0 and row 1, so two of the six pixels vanish; the primary pixel lands appropriately and the final three run backwards. On an actual 1024-pixel-wide floor the identical bug produces a sheared picture. In Direct3D 11 the pitch comes again in D3D11_MAPPED_SUBRESOURCE::RowPitch if you map a texture, and the rule is unchanged.
Double buffering, web page flipping and tearing
Drawing straight to the seen display screen exhibits half-finished frames. Double buffering fixes that: draw the following body into an invisible again buffer, then make it seen in a single step. DirectDraw supplied two methods to do this step:
- Blitting: copy the again buffer onto the entrance buffer. Windowed DirectDraw applications had to do that, as a result of the first floor was the entire desktop.
- Web page flipping: preserve each buffers in video reminiscence and inform the show {hardware} to scan out the opposite one. Nothing is copied; back and front swap roles every body.
If the swap occurs whereas the monitor is part-way by way of drawing the display screen, the highest exhibits one body and the underside the following. That’s tearing, and the treatment is to swap in the course of the vertical clean, the hole between refreshes.
Trendy Home windows does this by way of a DXGI swap chain. The flip presentation mannequin lets the Desktop Window Supervisor compose straight out of your again buffers, with out the copy the older blit mannequin wanted, and it really works in a window in addition to full-screen. It requires between 2 and 16 buffers and doesn’t enable multisampled again buffers. Current(1, 0) waits for one vertical clean, which is the outdated “flip on vsync” in a single argument.
Clipping, misplaced surfaces and misplaced units
A windowed DirectDraw program needed to connect a clipper to the first floor so it could not draw over different home windows. With the flip mannequin, every window owns its swap chain and the compositor handles overlap, so there is no such thing as a clipper to handle.
DirectDraw surfaces might be misplaced when one other program modified the show mode, so applications checked IsLost() every body and known as Restore(). The trendy equal is a eliminated gadget: if the motive force is up to date, crashes or the GPU is disconnected, Current returns DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET, and the applying should recreate its gadget and each useful resource it created from it.
Checking HRESULTs appropriately
Most DirectX strategies return an HRESULT (a couple of, reminiscent of ClearRenderTargetView, return nothing). Check it with the SUCCEEDED() and FAILED() macros, not by evaluating towards S_OK or DD_OK. A damaging HRESULT means failure, and there’s multiple success code. S_FALSE is the standard instance:
#embody <home windows.h>
#embody <ddraw.h>
static_assert(S_FALSE == 1, "S_FALSE is a hit code with the worth 1");
static_assert(SUCCEEDED(S_FALSE) && S_FALSE != S_OK, "success will not be solely S_OK");
static_assert(FAILED(DDERR_SURFACELOST), "DirectDraw errors are damaging HRESULTs");
All three assertions maintain when compiled towards the MinGW-w64 headers. A verify written as hr == S_OK treats S_FALSE as an error; a verify written as hr != DD_OK does the identical.
From DirectDraw to Direct3D 11: The Identical Program, Rewritten
A basic DirectDraw pattern had a well-known form: create a window, create the DirectDraw object, set a cooperative stage, create back and front surfaces, connect a clipper in windowed mode, then loop: verify for misplaced surfaces, draw into the again buffer, flip or blit, repeat. Most of these steps nonetheless exist in some type; the 2 that don’t, claiming the show and clipping, went away as a result of the desktop compositor took them over.
| Step | DirectDraw (DirectX 7 and earlier) | Direct3D 11 with DXGI |
|---|---|---|
| Create the API object | DirectDrawCreate / DirectDrawCreateEx |
D3D11CreateDevice |
| Declare the show | SetCooperativeLevel, SetDisplayMode |
Not wanted in a window; DXGI handles full-screen |
| Back and front buffers | Main floor plus a again floor | Swap chain with BufferCount = 2 |
| Windowed clipping | CreateClipper, SetHWnd, SetClipper |
Not wanted; the compositor clips |
| Draw into the again buffer | Blt, Lock and write pixels |
Render-target view, ClearRenderTargetView, shaders |
| Present the body | Flip(NULL, DDFLIP_WAIT) or Blt to the first |
Current(1, 0) |
| Recuperate from loss | IsLost() then Restore() |
Deal with DXGI_ERROR_DEVICE_REMOVED by recreating the gadget |
| Launch objects | Launch() by hand |
Microsoft::WRL::ComPtr releases robotically |
Right here is the whole trendy program. It opens a 640×480 window, creates a Direct3D 11 gadget and a two-buffer flip-model swap chain, clears the again buffer to a color that drifts every body, and presents it on the vertical clean.
// d3d11_clear.cpp - a window, a Direct3D 11 gadget and a flip-model swap chain.
// Every body clears the again buffer to a slowly altering color and presents it.
#outline WIN32_LEAN_AND_MEAN
#outline NOMINMAX
#embody <home windows.h>
#embody <d3d11.h>
#embody <dxgi1_2.h>
#embody <wrl/consumer.h>
#embody <cmath>
#embody <cstdio>
utilizing Microsoft::WRL::ComPtr;
namespace {
ComPtr<ID3D11Device> g_device;
ComPtr<ID3D11DeviceContext> g_context;
ComPtr<IDXGISwapChain1> g_swapChain;
ComPtr<ID3D11RenderTargetView> g_rtv;
bool Test(HRESULT hr, const char* what)
{
if (SUCCEEDED(hr)) return true;
char buf[128];
std::snprintf(buf, sizeof buf, "%s failed: HRESULT 0xpercent08lXn",
what, static_cast<unsigned lengthy>(hr));
OutputDebugStringA(buf);
return false;
}
bool CreateTargetView()
{
ComPtr<ID3D11Texture2D> backBuffer;
return Test(g_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)), "GetBuffer") &&
Test(g_device->CreateRenderTargetView(backBuffer.Get(), nullptr, &g_rtv),
"CreateRenderTargetView");
}
bool InitD3D(HWND hwnd)
{
UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef _DEBUG
flags |= D3D11_CREATE_DEVICE_DEBUG; // wants the Graphics Instruments optionally available function
#endif
if (!Test(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, flags,
nullptr, 0, D3D11_SDK_VERSION,
&g_device, nullptr, &g_context), "D3D11CreateDevice"))
return false;
// The swap chain should come from the manufacturing unit that created the gadget.
ComPtr<IDXGIDevice> dxgiDevice;
ComPtr<IDXGIAdapter> adapter;
ComPtr<IDXGIFactory2> manufacturing unit;
if (!Test(g_device.As(&dxgiDevice), "QueryInterface(IDXGIDevice)") ||
!Test(dxgiDevice->GetAdapter(&adapter), "GetAdapter") ||
!Test(adapter->GetParent(IID_PPV_ARGS(&manufacturing unit)), "GetParent(IDXGIFactory2)"))
return false;
DXGI_SWAP_CHAIN_DESC1 desc = {}; // Width/Top 0 = the window's consumer dimension
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.SampleDesc.Depend = 1; // flip mannequin doesn't enable MSAA again buffers
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = 2; // entrance + again: double buffering
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // Home windows 10 and later
if (!Test(factory->CreateSwapChainForHwnd(g_device.Get(), hwnd, &desc,
nullptr, nullptr, &g_swapChain),
"CreateSwapChainForHwnd"))
return false;
factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
return CreateTargetView();
}
void Resize(UINT width, UINT top)
bool RenderFrame(unsigned body)
{
const float t = static_cast<float>(body) * 0.02f;
const float color[4] = { 0.5f + 0.5f * std::sin(t),
0.5f + 0.5f * std::sin(t + 2.1f),
0.5f + 0.5f * std::sin(t + 4.2f), 1.0f };
// Flip-model presentation unbinds the again buffer, so bind it each body.
g_context->OMSetRenderTargets(1, g_rtv.GetAddressOf(), nullptr);
g_context->ClearRenderTargetView(g_rtv.Get(), color);
const HRESULT hr = g_swapChain->Current(1, 0); // 1 = await vertical clean
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
Test(g_device->GetDeviceRemovedReason(), "System eliminated");
return false; // an actual software recreates the gadget right here
}
return Test(hr, "Current");
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
swap (msg) {
case WM_SIZE: Resize(LOWORD(lp), HIWORD(lp)); return 0;
case WM_DESTROY: PostQuitMessage(0); return 0;
}
return DefWindowProcW(hwnd, msg, wp, lp);
}
} // namespace
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, int present)
{
WNDCLASSW wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = inst;
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.lpszClassName = L"D3D11Clear";
if (!RegisterClassW(&wc)) return 1;
HWND hwnd = CreateWindowW(wc.lpszClassName, L"Direct3D 11 clear", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
nullptr, nullptr, inst, nullptr);
if (!hwnd || !InitD3D(hwnd)) return 1;
ShowWindow(hwnd, present);
MSG msg = {};
unsigned body = 0;
whereas (msg.message != WM_QUIT) {
if (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { // drain enter first
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else if (!RenderFrame(body++)) {
DestroyWindow(hwnd);
}
}
return static_cast<int>(msg.wParam);
}
A number of particulars in it are simple to get incorrect:
- The swap chain comes from the gadget’s personal manufacturing unit. Strolling from the gadget to its adapter after which to
IDXGIFactory2means the swap chain is created by the manufacturing unit that owns the gadget’s adapter, reasonably than by a second manufacturing unit created individually. - Resizing wants each buffer reference launched first.
ResizeBuffersfails whereas any render-target view nonetheless factors at a again buffer, soResizeunbinds the goal and resetsg_rtvearlier than calling it. Width and top of zero, which arrive when the window is minimized, are skipped. - The render goal is sure each body. With the flip mannequin,
Currentunbinds the again buffer from the pipeline, so binding it as soon as at start-up solely works for the primary body. ComPtrreplaces handbookLaunchcalls. It’s a reference-counting sensible pointer for COM objects: copying one callsAddRef, and destroying or resetting one callsLaunch. That makes it nearer tostd::shared_ptrthan tostd::unique_ptr, besides that the depend lives contained in the COM object. The article on sensible pointers in C++ covers the possession guidelines it follows.- The message loop drains enter earlier than rendering.
PeekMessageWwithPM_REMOVEprocesses each ready message, and solely when the queue is empty does this system draw a body.
It’s written to construct with Visible Studio’s MSVC or with MinGW-w64, the 2 Home windows choices coated within the information to C++ compilers:
x86_64-w64-mingw32-g++ -std=c++17 -Wall -Wextra -O2 -mwindows -o d3d11_clear.exe d3d11_clear.cpp -ld3d11
FLIP_DISCARD wants Home windows 10 or later. This system was compiled for this text with MinGW-w64 however not run, as a result of no Home windows machine was out there; the repository’s Home windows construct runs a separate headless check, described beneath, that workout routines the identical gadget and clear calls on Microsoft’s WARP software program rasterizer.
In case you are going additional than clearing the display screen, the overview of graphics applied sciences in AAA sport improvement covers what DirectX 12 Final options reminiscent of raytracing and mesh shaders are used for.
Key Takeaways
- Direct3D is the one basic DirectX element nonetheless beneficial for brand new code, as Direct3D 12 or Direct3D 11 with DXGI.
- Every retired API has a named successor: XAudio2 for DirectSound, GameInput for DirectInput, Media Basis for DirectShow, and Direct3D or Direct2D for DirectDraw.
- A pixel worth and its bytes in reminiscence are various things: RGB565 inexperienced is
0x07E0however is saved asE0 07on little-endian machines. - Step by way of floor rows by the reported pitch, not by
width * 4; the incorrect stride loses pixels into row padding. - Double buffering survives because the DXGI flip mannequin, which presents from the again buffer and not using a copy and works in a window.
- Misplaced surfaces grew to become eliminated units, and the restoration continues to be to recreate what you misplaced.
- Check HRESULTs with
SUCCEEDEDandFAILED, as a result of success has multiple worth.
Steadily Requested Questions
Conclusion
Most of basic DirectX is gone, however nearly none of it was wasted. The surfaces, palettes, pitches and flips of DirectDraw grew to become textures, codecs, row pitches and swap chains; the scene graph of Retained Mode moved into engines; DirectSound and DirectInput handed their jobs to XAudio2 and GameInput. If you meet DirectX code from the late Nineteen Nineties, the desk above tells you what every name was for and what it maps to now.
In case you are beginning contemporary, begin with Direct3D 11 for a gentler studying curve or Direct3D 12 for full management, and preserve the outdated vocabulary for studying different folks’s code. Extra graphics and engine materials is collected within the sport improvement part.
Supply Code and Checks
The applications on this web page dwell in two repositories, one per language.
To construct the C applications and examine their output with this web page:
bash exams/run_tests.sh gcc
bash exams/sanitizers.sh gcc
What the builds verify. The pixel-formats workflow compiles the three C applications with GCC and Clang beneath C11 and C17 with warnings as errors, runs them, and compares their output with the output on this web page; a second job runs them beneath AddressSanitizer and UndefinedBehaviorSanitizer, and a 3rd builds them with MSVC at /W4 /WX and compares the identical output. The d3d11-clear workflow builds each Direct3D applications with MSVC and with MinGW-w64, warnings as errors, and runs warp_clear_test on Home windows, which clears a texture to inexperienced on the WARP software program rasterizer and checks that the primary pixel reads again as 00 FF 00 FF, the identical blue-green-red-alpha byte order the pixel-format program prints. No job opens a window, so the windowed program is constructed however not run.

