コマンド バッファーと頂点バッファーの割り当て

Direct3D では、次の 3 種類のバッファーが使用されます。

  • 暗黙的な頂点バッファー。内部でのみ使用するために作成されます。つまり、アプリケーションはそれらを認識します。 コンテキストの作成後、常に 1 つの暗黙的な頂点バッファーが作成され、Direct3D によって頂点データが格納されます。

  • 明示的な頂点バッファー。アプリケーション要求への応答でのみ作成されます。 Direct3D は、頂点データを明示的な頂点バッファーに格納します。

  • コマンド バッファー。内部でのみ使用するために作成されます。つまり、アプリケーションはコマンド バッファーを認識できません。 Direct3D は、コマンド データをコマンド バッファーに格納します。

暗黙的な頂点バッファーは、バッチ処理のために Direct3D によって内部的に使用される特殊な頂点バッファーです。 これらはデバイスの初期化中に作成され、マルチバッファーできます。 これらは常に読み取り/書き込みであるため、ビデオ メモリに配置しないでください (Microsoft DirectX 6.0 以降のバージョンの場合)。 この種類のバッファーは、DDSCAPS2_VERTEXBUFFER フラグと DDSCAPS2_COMMANDBUFFER フラグの両方が存在しないことでマークされます。

明示的な頂点バッファーは、アプリケーションによって作成および制御されます。 DDSCAPS_WRITEONLY フラグが設定されていない限り、これらはマルチバッファーにできず、ローカルまたは非ローカルのビデオ メモリに配置できません。 明示的な頂点バッファーは、DDSCAPS_VERTEXBUFFER でマークされます。

コマンド バッファーは、コマンドをバッチ処理するために Direct3D によって使用されます。 これらはマルチバッファーにすることができ、TLVERTEX またはクリップされない実行バッファー API 呼び出しを除くすべての API に使用されます。 この種類のバッファーは、フラグ DDSCAPS2_COMMANDBUFFER によってマークされます。 明示的なフラグは設定されておらず、無効な命令が含まれることはありませんが、これらは常に書き込み専用です。

既定では、Direct3D ランタイムはこれらのバッファーをすべて割り当てます。 暗黙的な頂点バッファーとコマンド バッファーは、関連付けられているサーフェスを介してアクセスされます。 すべてのバッファーは、ドライバーの D3dDrawPrimitives2 コールバックに渡されます。

ドライバーによって割り当てられた頂点バッファーとコマンド バッファー

Direct3D ドライバーは、必要に応じてコールバック関数を提供することによって、頂点バッファーとコマンド バッファーの割り当てを実行します。 これらのコールバック関数を提供するために、Direct3D ドライバーはDD_D3DBUFCALLBACKS構造体に値を入力し、lpD3DBufCallbacks メンバー (DD_HALINFO 構造体のメンバー) でそれを指します。 DD_HALINFOは、ドライバーの DirectDraw コンポーネントの初期化に応答して DrvGetDirectDrawInfo によって返されます。 DD_D3DBUFCALLBACKS 構造体で報告されるコールバックは次のとおりです。

これらの関数は、DdXxxSurface コールバック (DdCanCreateSurface など) で呼び出され、DDSCAPS_EXECUTEBUFFER フラグが設定されている場合にのみ呼び出されます。 バッファー作成フラグは、DDSCAPS_WRITEONLY、DDSCAPS2_VERTEXBUFFER、および DDSCAPS2_COMMANDBUFFER です。

ドライバーは、次のフラグの ddsCaps メンバー (DD_SURFACE_LOCAL 構造体のメンバー) チェックすることによって要求されるバッファーの種類を判断し、この構造体は次のフラグのために CanCreateExecuteBuffer CreateExecuteBuffer コールバックに渡されます。

  • DDSCAPS_VERTEXBUFFER は、ドライバーが明示的な頂点バッファーを割り当てる必要があることを示します。

  • DDSCAPS_COMMANDBUFFER は、ドライバーがコマンド バッファーを割り当てる必要があることを示します。

  • どちらのフラグも設定されていない場合、ドライバーは暗黙的な頂点バッファーを割り当てる必要があります。

ドライバーは、内部的に頂点バッファーとコマンド バッファーを割り当て、これらのバッファーを循環します。 Direct3D は、ハードウェアが他のキューに入っているバッファーから非同期的にレンダリングする間、特定のペアを塗りつぶします。 これは、ダイレクト メモリ アクセス (DMA) で非常に便利です。

マルチバッファー セット内のバッファーは、異なるメモリの種類 (つまり、システムまたはビデオ メモリ) に格納できます。 最初のバッファーを作成するためにドライバーが呼び出されると、すぐにセットが作成され、セット内の最初のバッファーが Direct3D に返されます。 ドライバーは、フラグを使用して、セット内の各バッファーを割り当てるために使用するメモリの種類を指定します。 D3DHALDP2_SWAPVERTEXBUFFERまたはD3DHALDP2_SWAPCOMMANDBUFFER フラグが設定されている場合、ドライバーは、D3dDrawPrimitives2 への呼び出しごとにシステム メモリ内の新しいバッファーを返す必要があります。 返されたバッファーがビデオ メモリ内にある場合は、対応する D3DHALDP2_VIDMEMVERTEXBUF または D3DHALDP2_VIDMEMCOMMANDBUF フラグを設定する必要があります。

場合によっては、Direct3D は次のバッファーの最小サイズを要求します。 サイズが大きすぎる場合、ドライバーはシステム メモリ (バッキング サーフェイス) にバッファーを割り当てる必要があります。 サイズが小さすぎる場合、ドライバーは、より大きなバッファーを提供することが許可されます。 ドライバーは、バッファーの数とメモリの種類を追跡し、終了時にすべてをクリーンする必要があります。