Step 1: Enumerate Depth-Buffer Formats

Before you can create a depth buffer you must determine what depth-buffer formats, if any, are supported by the rendering device. Call the IDirect3D3::EnumZBufferFormats method to enumerate the depth-buffer formats that the device supports. The ZBuffer sample uses the following code to enumerate depth-buffer formats:

    //-------------------------------------------------------------------------
    // Create the z-buffer AFTER creating the back buffer and BEFORE creating
    // the d3ddevice.
    //
    // Note: before creating the z-buffer, apps may want to check the device
    // caps for the D3DPRASTERCAPS_ZBUFFERLESSHSR flag. This flag is true for
    // certain hardware that can do HSR (hidden-surface-removal) without a
    // z-buffer. For those devices, there is no need to create a z-buffer.
    //-------------------------------------------------------------------------
 
    DDPIXELFORMAT ddpfZBuffer;  // Passing this as a VOID*
 
    g_pD3D->EnumZBufferFormats( *pDeviceGUID, 
                                EnumZBufferCallback, (VOID*)&ddpfZBuffer );
 

The EnumZBufferFormats method accepts the globally unique identifier (GUID) of the device for which the formats will be enumerated, the address of a callback function, and the address of an arbitrary data structure that will be passed to the callback function. The callback function you provide must conform to the D3DEnumPixelFormatsCallback function prototype. The system calls the specified callback function once for each supported depth-buffer format, unless the callback function returns D3DENUMRET_CANCEL. The ZBuffer sample processes callbacks as follows:

static HRESULT WINAPI EnumZBufferCallback( DDPIXELFORMAT* pddpf,
                                           VOID* pddpfDesired )
{
    // If this is ANY type of depth-buffer, stop.
    if( pddpf->dwFlags == DDPF_ZBUFFER )
    {
        memcpy( pddpfDesired, pddpf, sizeof(DDPIXELFORMAT) );
 
        // Return with D3DENUMRET_CANCEL to end the search.
        return D3DENUMRET_CANCEL;
    }
 
    // Return with D3DENUMRET_OK to continue the search.
    return D3DENUMRET_OK;
}
 

When the system calls the callback function, it passes the address of a DDPIXELFORMAT structure that describes the pixel format of the depth buffer. The dwFlags member will contain DDPF_ZBUFFER for any pixel formats that include depth-buffer bits. If so, the dwZBufferBitDepth member includes an integer that represents the number of bits in the pixel format reserved for depth information, and the dwZBitMask member masks the relevant bits.

For simplicity, this tutorial only uses z-buffers, which are the most common type of depth buffer. It ignores any other formats (such as DDPF_STENCILBUFFER) that the system enumerates. Applications could also check the bit depth of the z-buffer (8-, 16-, 24-, 32-bit) and make a choice based on that as well. If a suitable format is found, the function copies the provided DDPIXELFORMAT structure to the address passed in the second parameter (also a DDPIXELFORMAT structure), and returns D3DENUMRET_CANCEL to stop the enumeration.

After you determine the format of the depth buffer, you can create a DirectDrawSurface that uses that format, which is the topic of Step 2: Create the Depth Buffer.