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
- DDS Variants
- Using Texture Arrays in Direct3D 10/11
- Common DDS File Resource Formats and Associated Header Content
- Related topics
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.