インデックス バッファー (Direct3D 9)

IDirect3DIndexBuffer9 インターフェイスで表されるインデックス バッファーは、インデックス データを格納するメモリー バッファーです。インデックス データ、またはインデックスは、頂点バッファー内の整数のオフセットであり、IDirect3DDevice9::DrawIndexedPrimitive メソッドを使用してプリミティブをレンダリングするのに使用されます。

頂点バッファーは頂点を格納します。したがって、頂点バッファーは、インデックス付きプリミティブを使用するかどうかに関係なく描画することができます。ただし、インデックス バッファーはインデックスを格納しているため、対応する頂点バッファーを用いずにインデックスバッファーを使用することはできません(なお、IDirect3DDevice9::DrawIndexedPrimitiveUP および IDirect3DDevice9::DrawPrimitiveUP のみが、インデックスおよび頂点バッファーを用いずに描画する描画メソッドです)。

インデックス バッファーの記述

インデックス バッファーについては、その機能に関する記述を行います。つまり、メモリー内のどこに存在するか、読み取りおよび書き込みをサポートするかどうか、および格納できるインデックスの型と数などです。これらの特徴は、D3DINDEXBUFFER_DESC 構造体に保持されます。

インデックス バッファーの記述により、アプリケーションに既存のバッファーがどのようにして作成されたかを通知します。以前に作成されたインデックス バッファーの機能についてシステムから情報を得るには、空の記述構造体を用意します。

  • Format メンバーは、インデックス バッファー データのサーフェス フォーマットを記述します。
  • Type はインデックス バッファーのリソース タイプを識別します。
  • Usage 構造体メンバーは、全般的な機能フラグを含みます。D3DUSAGE_SOFTWAREPROCESSING フラグは、インデックス バッファーがソフトウェア頂点処理で使用されることを示します。Usage に D3DUSAGE_WRITEONLY フラグが指定されている場合は、インデックス バッファーのメモリーは書き込み処理にのみ使用されます。これにより、ドライバーはインデックス データを自由に最適なメモリー位置に配置できるため、高速な処理とレンダリングが可能になります。D3DUSAGE_WRITEONLY フラグを使用しない場合、ドライバーが、読み込み操作の効率が悪い場所にデータを配置する可能性が低くなります。ただし、この場合、特定の処理速度およびレンダリング速度が低下することがあります。このフラグが指定されていない場合、アプリケーションがインデックス バッファー内のデータに対して読み込みと書き込み処理を実行するものと想定されます。
  • Pool はインデックス バッファーに割り当てられるメモリー クラスを指定します。D3DPOOL_SYSTEMMEM フラグは、インデックス バッファーがシステムによってシステム メモリー内に作成されたことを示します。
  • Size メンバーは、頂点バッファー データのサイズをバイト単位で格納します。
  • 最後のパラメーター pSharedHandle は使用しません。NULL に設定します。

インデックス処理の要件

インデックス処理のパフォーマンスは、メモリー内でインデックス バッファーが配置されている場所と、使用されているレンダリング デバイスのタイプに大きく影響されます。アプリケーションは、インデックス バッファーの作成時に、それらのインデックス バッファーのメモリー割り当てを制御します。D3DPOOL_SYSTEMMEM メモリー フラグが設定されている場合、インデックス バッファーはシステム メモリーに作成されます。D3DPOOL_DEFAULT メモリー フラグを使用すると、デバイス ドライバーによってインデックス バッファーのメモリー割り当てに最適な場所が決定されます。このようなメモリーはドライバー最適化メモリーとも呼ばれます。ドライバー最適化メモリーは、ローカル ビデオ メモリー、非ローカル ビデオ メモリー、またはシステム メモリーに割り当てられる場合があります。

IDirect3DDevice9::CreateIndexBuffer メソッドを呼び出すときに D3DUSAGE_SOFTWAREPROCESSING 動作フラグを設定すると、インデックス バッファーをソフトウェア頂点処理で使用するように指定できます。このフラグは、ソフトウェア頂点処理を使用するとき、混合モード頂点処理 (D3DCREATE_MIXED_VERTEXPROCESSING) で必要となります。

アプリケーションは、ドライバー最適化メモリー内に割り当てられたインデックス バッファーにインデックスを直接書き込むことができます。このテクニックにより、その後の冗長なコピー処理が防止されます。アプリケーションがインデックス バッファーから再びデータを読み込む場合は、ホストによって実行されるドライバー最適化メモリーからの読み込み操作が遅くなることがあるため、この方法は適切に機能しない場合があります。このため、アプリケーションで処理中にデータの読み取りやバッファーへのデータの書き込みを不規則に実行する必要がある場合は、システム メモリーのインデックス バッファーを選択するほうが効果的です。

    D3DPOOL_DEFAULT は必ずを使用してください。ただし、ビデオ メモリーを使用しない場合、またはドライバーが頂点またはインデックス バッファーを AGP メモリーに書き込むときに、大量のページ ロック RAM を使用することを望まない場合はその限りではありません。

インデックス バッファーを作成する

インデックス バッファー オブジェクトは、IDirect3DDevice9::CreateIndexBuffer メソッドを呼び出して作成します。このメソッドは、6 つのパラメーターを取得します。

  • 最初のパラメーターは、インデックス バッファーの長さをバイト単位で指定します。

  • 2 番目のパラメーターは使用法の制御です。特に、このパラメーターの値によって、インデックスで参照されている頂点がクリッピング情報を含むことができるかどうかが示されます。パフォーマンスを向上するために、クリッピングが必要ではない場合には D3DUSAGE_DONOTCLIP を指定します。

    D3DUSAGE_SOFTWAREPROCESSING フラグは、ミックスモードまたはソフトウェアによる頂点処理 (D3DCREATE_MIXED_VERTEXPROCESSING/D3DCREATE_SOFTWARE_VERTEXPROCESSING) が該当デバイスで有効な場合に設定できます。ソフトウェアによる頂点処理をミックス モードで使用するバッファーでは D3DUSAGE_SOFTWAREPROCESSING を設定する必要がありますが、ハードウェアによる頂点処理 (D3DCREATE_HARDWARE_VERTEXPROCESSING) をミックス モードで使用するときにパフォーマンスを可能な限り上げるには、このフラグは指定しないでください。ただし、1 つの バッファーをハードウェアによる頂点処理とソフトウェアによる頂点処理の両方に使用する場合は、D3DUSAGE_SOFTWAREPROCESSING を設定するしかオプションはありません。D3DUSAGE_SOFTWAREPROCESSING は、ミックス デバイスの場合もソフトウェア デバイスの場合も指定できます。

    D3DPOOL_SYSTEMMEM を指定することにより、インデックス処理がハードウェアで実行されている場合でも、頂点バッファーとインデックス バッファーを強制的にシステム メモリー内に配置できます。これは、ドライバーがそれらのバッファーを AGP メモリー内に格納しているとき、過度に大量のページロック メモリーが生じるのを回避するための 1 つの方法となります。

  • 3 番目のパラメーターは、各インデックスのサイズを指定する D3DFORMAT 列挙型の D3DFMT_INDEX16 または D3DFMT_INDEX32 メンバーのいずれかになります。

  • 4 番目のパラメーターは、メモリー内のどこに新しいインデックス バッファーを配置するかをシステムに指定する D3DPOOL 列挙型のメンバーです。

  • IDirect3DDevice9::CreateIndexBuffer が取得する最後のパラメーターは、呼び出しが成功した場合に、インデックス バッファー オブジェクトの新しい IDirect3DIndexBuffer9 インターフェイスへのポインターを格納する変数のアドレスです。

次の C++ コードの例は、インデックス バッファーの作成方法を示しています。

/*
 * For the purposes of this example, the d3dDevice variable is the 
 * address of an IDirect3DDevice9 interface exposed by a 
 * Direct3DDevice object, g_IB is a variable of type 
 * LPDIRECT3DINDEXBUFFER9.
 */

if( FAILED( d3dDevice->CreateIndexBuffer( 16384 *sizeof(WORD),
           D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, 
           &g_IB, NULL ) ) )
    return E_FAIL;

インデックス バッファーへのアクセス

アプリケーションでは、インデックス バッファー オブジェクトを使用して、インデックス データに割り当てられたメモリーに直接アクセスできます。インデックス バッファー メモリーへのポインターは、IDirect3DIndexBuffer9::Lock メソッドを呼び出すことによって取得できます。その後、必要に応じてメモリーにアクセスし、バッファーに新しいインデックス データを格納したり、既にバッファーに格納されているデータを読み取ったりすることができます。Lock メソッドは、4 つのパラメーターを取ります。最初の OffsetToLock は、インデックス データへのオフセットです。2 番目のパラメーターはバイト単位のインデックス データのサイズです。IDirect3DIndexBuffer9::Lock メソッドが取る 3 番目のパラメーター ppbData は、呼び出しが成功した場合に、インデックス データへのポインターが格納される BYTE ポインターのアドレスとなります。

最後のパラメーター、Flags は、メモリーのロック方法をシステムに指示します。このパラメーターを使用して、バッファー内のデータにアクセスする方法を指定できます。Flags パラメーターには、アプリケーションからインデックス データにアクセスする方法に応じた定数を指定します。これにより、ドライバーはメモリーをロックして、要求されたアクセスの種類で最大限のパフォーマンスを発揮することができます。D3DLOCK_READONLY フラグは、アプリケーションがインデックス バッファー メモリーから読み取りのみを行う場合に使用します。このフラグを含めると、Direct3D はメモリーへのアクセスが読み取り専用であることを前提に内部手順を最適化し、効率化を図ることができます。

インデックス データの格納または読み取りが終わったら、次のコード例に示すように IDirect3DIndexBuffer9::Unlock メソッドを呼び出します。

// This code example assumes the m_pIndexBuffer is a variable of type 
// LPDIRECT3DINDEXBUFFER9 and that g_Indices has been properly 
// initialized with indices.

// To fill the index buffer, you must lock the buffer to gain 
// access to the indices. This mechanism is required because index
// buffers may be in device memory.

VOID* pIndices;

if( FAILED( m_pIndexBuffer->Lock( 
      0,                 // Fill from start of the buffer
      sizeof(g_Indices), // Size of the data to load
      BYTE**)&pIndices,  // Returned index data
      0 ) ) )            // Send default flags to the lock
{
    SAFE_RELEASE(m_pIndexBuffer);
    return E_FAIL;
}

memcpy( pIndices, g_Indices, sizeof(g_Indices) );
m_pIndexBuffer->Unlock();

    

D3DUSAGE_WRITEONLY フラグを使用してインデックス バッファーを作成した場合は、D3DLOCK_READONLY ロッキング フラグを使用しないでください。D3DLOCK_READONLY フラグは、アプリケーションがインデックス バッファー メモリーから読み取りのみを行う場合に使用します。このフラグを含めると、Direct3D はメモリーへのアクセスが読み取り専用であることを前提に内部手順を最適化し、効率化を図ることができます。

IDirect3DIndexBuffer9::Lock メソッドの Flags パラメーターに対する D3DLOCK_DISCARD または D3DLOCK_NOOVERWRITE の使用方法の詳細については、「パフォーマンスの最適化 (Direct3D 9)」を参照してください。

C++ では、インデックス バッファーに割り当てられたメモリーに直接アクセスするため、アプリケーションが割り当てられたメモリーに適切にアクセスしていることを確認してください。そうでない場合は、無効なメモリーがレンダリングされるおそれがあります。割り当てられたバッファー内のインデックスから別のインデックスに移動するには、アプリケーションが使用するインデックス フォーマットのストライドを使用します。

IDirect3DIndexBuffer9::GetDesc メソッドを呼び出して、インデックス バッファーについての情報を取得します。このメソッドによって、D3DINDEXBUFFER_DESC 構造体のメンバーにインデックス バッファーの情報が格納されます。

関連項目

頂点バッファーとインデックス バッファーからのレンダリング (Direct3D 9), 頂点バッファー (Direct3D 9)