Programming Guide for DDS

Direct3D implements the DDS file format for storing uncompressed or compressed (DXTn) textures. The file format implements several slightly different types designed for storing different types of data, and supports single layer textures, textures with mipmaps, cube maps, volume maps and texture arrays (in Direct3D 10/11). This section describes the layout of a DDS file.

For help creating a texture in Direct3D 11, see How to: Create a Texture. For help in Direct3D 9, see Texture Support in D3DX (Direct3D 9).

DDS File Layout

A DDS file is a binary file that contains the following information:

  • A DWORD (magic number) containing the four character code value 'DDS ' (0x20534444).

  • A description of the data in the file.

    The data is described with a header description using DDS_HEADER; the pixel format is defined using DDS_PIXELFORMAT. Note that the DDS_HEADER and DDS_PIXELFORMAT structures replace the deprecated DDSURFACEDESC2, DDSCAPS2 and DDPIXELFORMAT DirectDraw 7 structures. DDS_HEADER is the binary equivalent of DDSURFACEDESC2 and DDSCAPS2. DDS_PIXELFORMAT is the binary equivalent of DDPIXELFORMAT.

    DWORD               dwMagic;
    DDS_HEADER          header;
    
    

    If the DDS_PIXELFORMAT dwFlags is set to DDPF_FOURCC and dwFourCC is set to "DX10" an additional DDS_HEADER_DXT10 structure will be present to accommodate texture arrays or DXGI formats that cannot be expressed as an RGB pixel format such as floating point formats, sRGB formats etc. When the DDS_HEADER_DXT10 structure is present the entire data description will looks like this.

    DWORD               dwMagic;
    DDS_HEADER          header;
    DDS_HEADER_DXT10    header10;
    
  • A pointer to an array of bytes that contains the main surface data.

    BYTE bdata[]
    
  • A pointer to an array of bytes that contains the remaining surfaces such as; mipmap levels, faces in a cube map, depths in a volume texture. Follow these links for more information about the DDS file layout for a: texture, a cube map, or a volume texture.

    BYTE bdata2[]
    

For broad hardware support, we recommend that you use the DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB, DXGI_FORMAT_BC3_UNORM, or DXGI_FORMAT_BC3_UNORM_SRGB format.

For more info about compressed texture formats, see Texture Block Compression in Direct3D 11 and Block Compression (Direct3D 10).

The D3DX library (for example, D3DX11.lib) and other similar libraries unreliably or inconsistently provide the pitch value in the dwPitchOrLinearSize member of the DDS_HEADER structure. Therefore, when you read and write to DDS files, we recommend that you compute the pitch in one of the following ways for the indicated formats:

  • For block-compressed formats, compute the pitch as:

    max( 1, ((width+3)/4) ) * block-size

    The block-size is 8 bytes for DXT1, BC1, and BC4 formats, and 16 bytes for other block-compressed formats.

  • For R8G8_B8G8, G8R8_G8B8, legacy UYVY-packed, and legacy YUY2-packed formats, compute the pitch as:

    ((width+1) >> 1) * 4

  • For other formats, compute the pitch as:

    ( width * bits-per-pixel + 7 ) / 8

    You divide by 8 for byte alignment.

Note

The pitch value that you calculate does not always equal the pitch that the runtime supplies, which is DWORD-aligned in some situations and byte-aligned in other situations. Therefore, we recommend that you copy a scan line at a time rather than try to copy the whole image in one copy.

DDS Variants

There are many tools that create and consume DDS files, but they can vary in the details of what they require in the header. Writers should populate the headers as fully as possible, and readers should check the minimal values for maximum compatibility. To validate a DDS file, a reader should ensure the file is at least 128 bytes long to accommodate the magic value and basic header, the magic value is 0x20534444 ("DDS "), the DDS_HEADER size is 124, and the DDS_PIXELFORMAT in the header size is 32. If the DDS_PIXELFORMAT dwFlags is set to DDPF_FOURCC and a dwFourCC is set to "DX10", then the total file size needs to be at least 148 bytes.

There are some common variants in use where the pixel format is set to a DDPF_FOURCC code where dwFourCC is set to a D3DFORMAT or DXGI_FORMAT enumeration value. There is no way to tell if an enumeration value is a D3DFORMAT or a DXGI_FORMAT, so it is highly recommended that the "DX10" extension and DDS_HEADER_DXT10 header is used instead to store the dxgiFormat when the basic DDS_PIXELFORMAT cannot express the format.

The standard DDS_PIXELFORMAT should be preferred for maximum compatibility to store RGB uncompressed data and DXT1-5 data as not all DDS tools support the DX10 extension.

Using Texture Arrays in Direct3D 10/11

The new DDS structures (DDS_HEADER and DDS_HEADER_DXT10) in Direct3D 10/11 extend the DDS file format to support an array of textures, which is a new resource type in Direct3D 10/11. Here is some sample code that shows how to access the different mipmap levels in an array of textures, using the new headers.

DWORD               dwMagic;
DDS_HEADER          header;
DDS_HEADER_DXT10    header10;
   
for (int iArrayElement = 0; iArrayElement < header10.arraySize; iArrayElement++)
{
   for (int iMipLevel = 0; iMipLevel < header.dwMipMapCount; iMipLevel++)
   {
     ...
   }
}       

Common DDS File Resource Formats and Associated Header Content

Resource Format dwFlags dwRGBBitCount dwRBitMask dwGBitMask dwBBitMask dwABitMask
DXGI_FORMAT_R8G8B8A8_UNORM
D3DFMT_A8B8G8R8
DDS_RGBA 32 0xff 0xff00 0xff0000 0xff000000
DXGI_FORMAT_R16G16_UNORM
D3DFMT_G16R16
DDS_RGBA 32 0xffff 0xffff0000
**
DXGI_FORMAT_R10G10B10A2_UNORM
D3DFMT_A2B10G10R10
DDS_RGBA 32 0x3ff 0xffc00 0x3ff00000
DXGI_FORMAT_R16G16_UNORM
D3DFMT_G16R16
DDS_RGB 32 0xffff 0xffff0000
DXGI_FORMAT_B5G5R5A1_UNORM
D3DFMT_A1R5G5B5
DDS_RGBA 16 0x7c00 0x3e0 0x1f 0x8000
DXGI_FORMAT_B5G6R5_UNORM
D3FMT_R5G6B5
DDS_RGB 16 0xf800 0x7e0 0x1f
DXGI_A8_UNORM
D3DFMT_A8
DDS_ALPHA 8 0xff
D3DFMT_A8R8G8B8
DDS_RGBA 32 0xff0000 0xff00 0xff 0xff000000
D3DFMT_X8R8G8B8
DDS_RGB 32 0xff0000 0xff00 0xff
D3DFMT_X8B8G8R8
DDS_RGB 32 0xff 0xff00 0xff0000
**
D3DFMT_A2R10G10B10
DDS_RGBA 32 0x3ff00000 0xffc00 0x3ff 0xc0000000
D3DFMT_R8G8B8
DDS_RGB 24 0xff0000 0xff00 0xff
D3DFMT_X1R5G5B5
DDS_RGB 16 0x7c00 0x3e0 0x1f
D3DFMT_A4R4G4B4
DDS_RGBA 16 0xf00 0xf0 0xf 0xf000
D3DFMT_X4R4G4B4
DDS_RGB 16 0xf00 0xf0 0xf
D3DFMT_A8R3G3B2
DDS_RGBA 16 0xe0 0x1c 0x3 0xff00
D3DFMT_A8L8
DDS_LUMINANCE 16 0xff 0xff00
D3DFMT_L16
DDS_LUMINANCE 16 0xffff
D3DFMT_L8
DDS_LUMINANCE 8 0xff
D3DFMT_A4L4
DDS_LUMINANCE 8 0xf 0xf0
Resource Format dwFlags dwFourCC
DXGI_FORMAT_BC1_UNORM
D3DFMT_DXT1
DDS_FOURCC "DXT1"
DXGI_FORMAT_BC2_UNORM
D3DFMT_DXT3
DDS_FOURCC "DXT3"
DXGI_FORMAT_BC3_UNORM
D3DFMT_DXT5
DDS_FOURCC "DXT5"
*
DXGI_FORMAT_BC4_UNORM
DDS_FOURCC "BC4U"
*
DXGI_FORMAT_BC4_SNORM
DDS_FOURCC "BC4S"
*
DXGI_FORMAT_BC5_UNORM
DDS_FOURCC "ATI2"
*
DXGI_FORMAT_BC5_SNORM
DDS_FOURCC "BC5S"
DXGI_FORMAT_R8G8_B8G8_UNORM
D3DFMT_R8G8_B8G8
DDS_FOURCC "RGBG"
DXGI_FORMAT_G8R8_G8B8_UNORM
D3DFMT_G8R8_G8B8
DDS_FOURCC "GRGB"
*
DXGI_FORMAT_R16G16B16A16_UNORM
D3DFMT_A16B16G16R16
DDS_FOURCC 36
*
DXGI_FORMAT_R16G16B16A16_SNORM
D3DFMT_Q16W16V16U16
DDS_FOURCC 110
*
DXGI_FORMAT_R16_FLOAT
D3DFMT_R16F
DDS_FOURCC 111
*
DXGI_FORMAT_R16G16_FLOAT
D3DFMT_G16R16F
DDS_FOURCC 112
*
DXGI_FORMAT_R16G16B16A16_FLOAT
D3DFMT_A16B16G16R16F
DDS_FOURCC 113
*
DXGI_FORMAT_R32_FLOAT
D3DFMT_R32F
DDS_FOURCC 114
*
DXGI_FORMAT_R32G32_FLOAT
D3DFMT_G32R32F
DDS_FOURCC 115
*
DXGI_FORMAT_R32G32B32A32_FLOAT
D3DFMT_A32B32G32R32F
DDS_FOURCC 116
D3DFMT_DXT2
DDS_FOURCC "DXT2"
D3DFMT_DXT4
DDS_FOURCC "DXT4"
D3DFMT_UYVY
DDS_FOURCC "UYVY"
D3DFMT_YUY2
DDS_FOURCC "YUY2"
D3DFMT_CxV8U8
DDS_FOURCC 117
Any DXGI format DDS_FOURCC "DX10"

* = A robust DDS reader must be able to handle these legacy format codes. However, such a DDS reader should prefer to use the "DX10" header extension when it writes these format codes to avoid ambiguity.

** = Because of some long-standing issues in common implementations of DDS readers and writers, the most robust way to write out 10:10:10:2-type data is to use the "DX10" header extension with the DXGI_FORMAT code "24" (that is, the DXGI_FORMAT_R10G10B10A2_UNORM value). D3DFMT_A2R10G10B10 data should be converted to 10:10:10:2-type data before being written out as a DXGI_FORMAT_R10G10B10A2_UNORM format DDS file.

DDS