Wednesday, October 7, 2026
HomeC ProgrammingDirectX Parts Defined: Legacy APIs and Replacements

DirectX Parts Defined: Legacy APIs and Replacements


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.

DirectX elements: then and now What every basic API did, and what new Home windows code makes use of as an alternative CLASSIC COMPONENT USE TODAY STATUS Direct3D (instant mode) 1996, DirectX 2 → Direct3D 12 · Direct3D 11 Present DirectDraw 2-D surfaces, web page flipping → Direct3D 11/12 · Direct2D · DXGI Legacy Direct3D Retained Mode scene graph, final up to date DX3 → Your engine’s personal scene graph Eliminated DirectSound wave mixing and playback → XAudio2 · WASAPI Legacy DirectMusic 1999, DirectX 6.1 → No direct successor No 64-bit DirectInput joysticks, keyboards, mice → GameInput · XInput Legacy DirectPlay multiplayer networking → Winsock or platform providers Non-obligatory DirectShow media playback and seize → Media Basis · MediaPlayer Legacy DirectAnimation · Remodel media and picture results → Internet requirements (CSS, SVG) Deprecated Legacy: Microsoft recommends one other API for brand new code, however current applications nonetheless run. Eliminated: not shipped with Home windows (Retained Mode), or unavailable to 64-bit applications (DirectMusic). Non-obligatory: DirectPlay is a Home windows function that have to be turned on earlier than outdated video games can use it.
Solely Direct3D continues to be beneficial for brand new code. DirectDraw, DirectSound, DirectInput and DirectShow nonetheless run however have named successors; Retained Mode left Home windows with Vista, DirectMusic has no 64-bit model, and DirectPlay have to be switched on as an optionally available function. Standing displays Microsoft documentation checked in October 2026.

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 IDXGIFactory2 means 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. ResizeBuffers fails whereas any render-target view nonetheless factors at a again buffer, so Resize unbinds the goal and resets g_rtv earlier 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, Current unbinds the again buffer from the pipeline, so binding it as soon as at start-up solely works for the primary body.
  • ComPtr replaces handbook Launch calls. It’s a reference-counting sensible pointer for COM objects: copying one calls AddRef, and destroying or resetting one calls Launch. That makes it nearer to std::shared_ptr than to std::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. PeekMessageW with PM_REMOVE processes 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 0x07E0 however is saved as E0 07 on 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 SUCCEEDED and FAILED, 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.

pixel-formats
d3d11-clear

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.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments