DXGKDDI_BUILDPAGINGBUFFER コールバック関数 (d3dkmddi.h)

DxgkDdiBuildPagingBuffer 関数は、メモリ操作用のページング バッファーを構築します。

構文

DXGKDDI_BUILDPAGINGBUFFER DxgkddiBuildpagingbuffer;

NTSTATUS DxgkddiBuildpagingbuffer(
  [in]     IN_CONST_HANDLE hAdapter,
  [in/out] IN_PDXGKARG_BUILDPAGINGBUFFER pBuildPagingBuffer
)
{...}

パラメーター

[in] hAdapter

ディスプレイ アダプターに関連付けられているコンテキスト ブロックへのハンドル。 ディスプレイ ミニポート ドライバーは、DxgkDdiAddDevice 関数の MiniportDeviceContext 出力パラメーターの Microsoft DirectX グラフィックス カーネル サブシステムにこのハンドルを以前に提供しました。

[in/out] pBuildPagingBuffer

ページング バッファーを構築するための情報を含む DXGKARG_BUILDPAGINGBUFFER 構造体へのポインター。

戻り値

DxgkDdiBuildPagingBuffer は 、次のいずれかの値を返します。

リターン コード 説明
STATUS_SUCCESS DxgkDdiBuildPagingBuffersuccessfully にページング バッファーを構築しました。
STATUS_GRAPHICS_ALLOCATION_BUSY GPU は現在、ページング バッファーの割り当てを使用しています。
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER ページング バッファーには、より多くの領域が必要です (つまり、pBuildPagingBuffer パラメーターが指 すDXGKARG_BUILDPAGINGBUFFER 構造体の pDmaBuffer メンバー内)。

注釈

DxgkDdiBuildPagingBuffer 関数は、ページング バッファーと呼ばれる特別な目的のダイレクト メモリ アクセス (DMA) バッファーを構築するために呼び出されます。 ページング バッファーには、割り当ての一部の内容を移動する操作が含まれています。

  • 割り当てのセグメント内。
  • 割り当てのセグメント間。
  • 割り当てのセグメントからシステム メモリへ。
  • システム メモリから割り当てのセグメントまで。

ディスプレイ ミニポート ドライバーは、要求されたページング操作に従って、指定されたページング バッファー (DXGKARG_BUILDPAGINGBUFFERpDmaBuffer メンバー内) に適切なグラフィックス処理装置 (GPU) 命令を書き込む必要があります。ドライバーはページング バッファーをビデオ メモリ マネージャー (Dxgkrnl.sysの一部) に返す必要があります。 GPU スケジューラ ( Dxgkrnl.sysの一部でもある) は、ドライバーの DxgkDdiSubmitCommand 関数を呼び出して、ドライバーがページング バッファーを通常の DMA バッファーとして GPU に送信するように要求します。

メモ ビデオ メモリ マネージャーはページング バッファーを送信する前に、ドライバーの DxgkDdiPatch 関数を呼び出して、ページング バッファーに物理アドレス (つまり パッチ) を割り当てます。ただし、 DxgkDdiPatch の呼び出しでは、ビデオ メモリ マネージャーはパッチの場所リストを提供しません。 ドライバーの DxgkDdiPatch 関数は、ページング バッファーの直前の更新を実行できます。ただし、ドライバーの DxgkDdiPatch 関数はページング バッファーのサイズを変更できません。
 
ドライバーがページング バッファーを正常にビルドすると、ドライバーの DxgkDdiBuildPagingBuffer は、ページング バッファーに書き込まれた最後のバイトを指すように pDmaBuffer を更新し、STATUS_SUCCESSを返す必要があります。 DxgkDdiBuildPagingBuffer はページング バッファー内の領域が不足している場合にのみ失敗する可能性があるため、ドライバーは、バッファーに書き込む前に、ページング バッファーに十分な領域が残っていることを常に確認する必要があります。 ページング バッファーに十分な領域が残っていない場合、ドライバーはSTATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFERを返す必要があります。 その後、ビデオ メモリ マネージャーは新しいページング バッファーを取得し、ドライバーの DxgkDdiBuildPagingBuffer 関数をもう一度呼び出して、要求されたページング操作に従って新しいページング バッファーを埋めます。 複数のページング バッファーを満たす要求されたページング操作の場合、スケジューラは、各部分ページング バッファーに対してドライバーの DxgkDdiSubmitCommand 関数を 複数回呼び出して、各バッファーを個別に送信することに注意してください。

DxgkDdiBuildPagingBuffer がページング操作に複数のページング バッファーが必要であると判断した場合、ドライバーは、DXGKARG_BUILDPAGINGBUFFERMultipassOffset メンバーに情報を指定でき、ページング操作の複数の繰り返しにわたってこの情報を使用できます。 ビデオ メモリ マネージャーは、最初のページング操作要求の前に MultipassOffset の情報を 0 に初期化し、イテレーションの間に MultipassOffset の情報を変更しません。 そのため、ドライバーは MultipassOffset を 使用して、イテレーション間の進行状況を保存できます。 たとえば、ドライバーは、ページベースの転送のために最後に転送されたページ番号を格納できます。

ページング バッファーは現在、次の種類の操作用に構築されています。

  • 転送

    転送操作では、ある場所から別の場所に割り当ての内容が移動されます。 この操作は、メモリ操作の最も一般的な種類です。

    割り当ては常に、ある場所から別の場所に完全に転送されます。 ただし、メモリ制約のため、割り当ての転送は複数のサブ転送に分割できます (つまり、割り当ての一部は場所 A から B に移動され、次の部分は移動され、割り当て全体が転送されるまで移動されます)。 割り当ての最初のサブ転送は、DXGKARG_BUILDPAGINGBUFFERの Transfer メンバーの Flags メンバーの TransferStart ビット フィールド フラグでマークされます。割り当ての最後のサブ転送は、TransferEnd ビット フィールド フラグでマークされます。 ドライバーが新しい転送の開始を受け取る前に、保留中の転送の終了 (つまり、最後のサブ転送) を受け取る保証されます。

    各サブ転送では、 完了するために DxgkDdiBuildPagingBuffer への複数の呼び出しが必要になる場合があります (たとえば、ドライバーが DMA バッファー領域を使い果たしている可能性があります)。 そのため、ドライバーが DxgkDdiBuildPagingBuffer の呼び出しで TransferEnd フラグを受け取るまで、ドライバーは DxgkDdiBuildPagingBuffer への複数の呼び出しで TransferStart フラグを受け取る可能性があります。 TransferStart フラグを複数回受信しても、複数の新しい転送の開始は示されません。これは、割り当てのサブ転送に複数のイテレーションが必要であることを示します (たとえば、ドライバーが DMA バッファー領域を使い果たした場合)。 ドライバーは、DXGKARG_BUILDPAGINGBUFFERMultipassOffset メンバーを使用して、DxgkDdiBuildPagingBuffer の複数のイテレーションにわたって特定のサブ転送の進行状況を追跡できます。

    通常、転送は 1 回の操作で行われます。 このような状況では、 TransferStart ビット フィールド フラグと TransferEnd ビット フィールド フラグの両方が設定されます。

    一部のシナリオでは、特定の割り当てがメモリ内またはメモリ外にページングされるときに、ハードウェア リソースを設定するためにドライバーが必要になる場合があります。 既定では、GPU は DxgkDdiBuildPagingBuffer の呼び出し中に参照される割り当てを使用している可能性があります。 このようなシナリオでは、ドライバーが必要なハードウェア リソースをプログラムする前に、ドライバーが割り当てをアイドル状態にする必要がある場合があります (つまり、ハードウェア リソースのプログラミングは、指定された DMA バッファーでキューに登録できません)。 このようなシナリオでは、ドライバーは、STATUS_GRAPHICS_ALLOCATION_BUSYを使用して DxgkDdiBuildPagingBuffer の呼び出しを失敗させることができます。

    ドライバーがSTATUS_GRAPHICS_ALLOCATION_BUSYを返す場合、ビデオ メモリ マネージャーは、現在の割り当てへの参照で GPU が完了するまで待機し、ドライバーの DxgkDdiBuildPagingBuffer 関数をもう 一度呼び出します。 DxgkDdiBuildPagingBuffer の 2 回目の呼び出しで、ビデオ メモリ マネージャーは、DXGKARG_BUILDPAGINGBUFFER の Transfer メンバーの Flags メンバーに AllocationIsIdle ビット フィールド フラグを設定し、参照されている割り当てがアイドル状態であることを示します。 アイドル フラグが設定されていない場合、ドライバーは常に割り当てが現在ビジー状態であるか、すぐにビジー状態になる可能性があることを判断する必要があります。 アイドル フラグが設定されている場合、ビデオ メモリ マネージャーは、 DxgkDdiBuildPagingBuffer の呼び出しの間、参照されている割り当てがアイドル状態のままであることを保証します。

    DXGKARG_BUILDPAGINGBUFFERの hAllocation メンバーが NULL の場合、ドライバーは、スウィズリングやタイリングを実行せずに、ソース内のデータをコピー先にコピーする必要があります。

  • 塗りつぶし

    塗りつぶし操作は、指定したパターンで割り当てを塗りつぶします。 塗りつぶし操作は、割り当ての初期コンテンツを設定するために使用されます。 割り当ての内容が入力されると、割り当てはアイドル状態であることが保証されます (つまり、GPU では使用されません)。 フィル操作は、メモリ セグメントでのみ実行できます。 ビデオ メモリ マネージャーは、ディスプレイ ミニポート ドライバーが開口セグメントを埋めるように要求することはありません。

  • コンテンツを破棄する

    コンテンツの破棄操作は、メモリ セグメント内の割り当ての現在の場所から割り当てが破棄されることをドライバーに通知します。 つまり、割り当ては削除され、システム メモリにコピーされません。

    一部のシナリオでは、特定の割り当てがメモリ内またはメモリ外にページングされるときに、ハードウェア リソースを設定するためにドライバーが必要になる場合があります。 既定では、GPU は DxgkDdiBuildPagingBuffer の呼び出し中に参照される割り当てを使用する場合があります。 このようなシナリオでは、ドライバーが必要なハードウェア リソースをプログラムする前に、ドライバーが割り当てをアイドル状態にする必要がある場合があります (つまり、ハードウェア リソースのプログラミングは、指定された DMA バッファーでキューに登録できません)。 このようなシナリオでは、ドライバーは、STATUS_GRAPHICS_ALLOCATION_BUSYを使用して DxgkDdiBuildPagingBuffer の呼び出しを失敗させることができます。

    ドライバーがSTATUS_GRAPHICS_ALLOCATION_BUSYを返す場合、ビデオ メモリ マネージャーは、現在の割り当てへの参照で GPU が完了するまで待機し、ドライバーの DxgkDdiBuildPagingBuffer 関数をもう 一度呼び出します。 DxgkDdiBuildPagingBuffer の 2 回目の呼び出しで、ビデオ メモリ マネージャーは、参照されている割り当てがアイドル状態であることを示すために、DXGKARG_BUILDPAGINGBUFFER構造体の DiscardContent メンバーの Flags メンバーに AllocationIsIdle ビット フィールド フラグを設定します。 アイドル フラグが設定されていない場合、ドライバーは常に割り当てが現在ビジー状態であるか、すぐにビジー状態になる可能性があることを判断する必要があります。 アイドル フラグが設定されている場合、ビデオ メモリ マネージャーは、 DxgkDdiBuildPagingBuffer の呼び出しの間、参照されている割り当てがアイドル状態のままであることを保証します。

  • 物理読み取り

    読み取り/物理操作は、指定された物理メモリ アドレスから読み取ります。 ドライバーは、操作の GPU をプログラムするように要求されます。 読み取り用にアクセスする物理メモリのサイズは、1 バイトから 8 バイトまでです。 読み取られたデータは無関係であるため、データを返すために DxgkDdiBuildPagingBuffer は必要ありません。 ただし、GPU がその AGP メモリに書き込んだ後に CPU が AGP メモリから読み取ろうとするシナリオでは、メモリの一貫性を確保するために、読み取り/物理操作が重要です。

  • 物理書き込み

    書き込み物理操作は、指定された物理アドレスに書き込みます。 ドライバーは、操作の GPU をプログラムするように要求されます。 書き込み操作にアクセスする物理メモリのサイズは、1 バイトから 8 バイトまでです。 書き込まれるデータは無関係であるため、 DxgkDdiBuildPagingBuffer は任意のデータをメモリに書き込むことができます。 ただし、GPU がその AGP メモリに書き込んだ後に CPU が AGP メモリから読み取ろうとするシナリオでは、メモリの一貫性を確保するために書き込み物理操作が重要です。

  • マップ絞りセグメント

    map-aperture-segment 操作は、指定されたメモリ記述子リスト (MDL) を、指定されたページ数の指定されたセグメント オフセットで指定された開口セグメントにマップします。 CacheCoherent ビット フィールド フラグが、DXGKARG_BUILDPAGINGBUFFER構造体の MapApertureSegment メンバーの Flags メンバーに設定されている場合、ドライバーは、マップされるページにキャッシュの一貫性が適用されていることを確認する必要があります。それ以外の場合は、マップされるページにキャッシュの一貫性は必要ありません。

    メモCacheCoherent ビット フィールド フラグは、キャッシュ可能メモリがキャッシュコヒーレント開口セグメントにマップされている場合にのみ設定され、キャッシュコヒーレントでないアパーチャ セグメントまたはキャッシュコヒーレント セグメントにマップされる書き込み結合割り当てでは設定されません。
     
    ドライバーは、必要に応じてメモリ マップ I/O (MMIO) を使用して、開口セグメントを構成できます。 GPU は、構成時に絞り範囲にアクセスしません。 ただし、この絞り構成は GPU の実行に干渉してはなりません。 dxgkDdiBuildPagingBuffer がDXGK_OPERATION_MAP_APERTURE_SEGMENT操作の種類を設定して呼び出されると、GPU はアイドル状態になりません。また、再構成中の絞りセグメントの他の部分へのアクセスで GPU がビジー状態になっている可能性があります。
  • 絞りセグメントのマップ解除

    unmap-aperture-segment 操作は、指定された絞りセグメントの以前にマップされた範囲のマップを解除します。 ドライバーは、マップされていない範囲を、DXGKARG_BUILDPAGINGBUFFER構造体の UnmapApertureSegment メンバーの DummyPage メンバーが指定するダミー ページにマップする必要があります。

    メモ ドライバーがダミー ページにマップ解除すると、DirectX グラフィックス カーネル サブシステムが破損の問題を検出できるように、ドライバーは、指定された絞り範囲を介して GPU アクセスを有効にする必要があります。 この状況をチェックするための準拠テストが存在します。
     
    ビデオ メモリ マネージャーは、アパーチャのマップされていない部分にあるダミー ページを使用して、メモリ マネージャーが絞りセグメントにアクセスする困難を判断します。

    ドライバーは、必要に応じて MMIO を使用して絞りセグメントを構成できます。 GPU は構成時に絞り範囲にアクセスしません。 ただし、この絞り構成は GPU の実行に干渉してはなりません。 dxgkDdiBuildPagingBuffer がDXGK_OPERATION_UNMAP_APERTURE_SEGMENT操作の種類を設定して呼び出されると、GPU はアイドル状態になりません。また、再構成中の絞りセグメントの他の部分へのアクセスが GPU でビジー状態になっている可能性があります。

  • 特殊ロック転送

    特殊ロック転送操作は、通常の転送操作に似ています。 ただし、割り当ての内容を割り当ての元または割り当ての通常のバッキング ストアに転送する代わりに、特別なロック転送操作は、割り当ての内容を、useAlternateVA ビット フィールド フラグを設定して pfnLockCb 関数が呼び出されたときに割り当て用に設定された代替仮想アドレスに転送します。

    特殊ロック転送操作は、次のいずれかのシナリオでのみ行われます。

    • 割り当ては現在、代替仮想アドレスを使用して CPU にアクセスでき、削除されています。
    • 前の行頭文字で説明されている状況など、以前に削除された割り当てがページインされています。
    UseAlternateVA ビット フィールド フラグの使用をサポートしていないドライバーは、特別なロック転送操作を実行するために呼び出されません。

    一部のシナリオでは、特定の割り当てがメモリ内またはメモリ外にページングされるときに、ドライバーがハードウェア リソースを設定する必要がある場合があります。 既定では、GPU は DxgkDdiBuildPagingBuffer の呼び出し中に参照される割り当てを使用している可能性があります。 これらのシナリオでは、ドライバーが必要なハードウェア リソースをプログラムする前に、ドライバーが割り当てをアイドル状態にする必要がある場合があります (つまり、指定された DMA バッファーでハードウェア リソースをプログラミングすることはできません)。 このようなシナリオでは、ドライバーは、STATUS_GRAPHICS_ALLOCATION_BUSYを使用して DxgkDdiBuildPagingBuffer の呼び出しに失敗する可能性があります。

    ドライバーから STATUS_GRAPHICS_ALLOCATION_BUSYが返された場合、ビデオ メモリ マネージャーは、現在の割り当てへの参照を使用して GPU が完了するまで待機し、ドライバーの DxgkDdiBuildPagingBuffer 関数をもう一度呼び出します。 DxgkDdiBuildPagingBuffer の 2 回目の呼び出しでは、ビデオ メモリ マネージャーは、参照されている割り当てがアイドル状態であることを示すために、DXGKARG_BUILDPAGINGBUFFER構造体の SpecialLockTransfer メンバーの Flags メンバーに AllocationIsIdle ビット フィールド フラグを設定します。 アイドル 状態のフラグが設定されていない場合、ドライバーは常に割り当てが現在ビジー状態であるか、すぐにビジー状態になる可能性があることを判断する必要があります。 アイドル フラグが設定されている場合、ビデオ メモリ マネージャーは、 DxgkDdiBuildPagingBuffer の呼び出しの間、参照されている割り当てがアイドル状態のままであることを保証します。

ドライバーがハードウェア絞りを使用して、アプリケーションが直接アクセスできる割り当てを直線化する必要がある場合、ドライバーは割り当ての一貫性を維持するためにシステム メモリに割り当てを転送するときに、その割り当てを解除する必要があります。 アプリケーションが割り当てにアクセスしている間に削除が発生する可能性があるため、ドライバーは割り当てをスウィズル解除する必要があります。

システムのメモリ マネージャーは、転送がアプリケーションに対して見えないようにします。 ただし、割り当てはシステム メモリ内にあり、割り当ての仮想アドレスはハードウェアの絞りを通過しなくなったため、ドライバーは、システム メモリへのバイト順序が絞りを通じて表示されたものと一致することを確認する必要があります。

DxgkDdiBuildPagingBuffer をページング可能にする必要があります。

次のコード例は、 DxgkDdiBuildPagingBuffer の使用方法を示しています。

NTSTATUS ntStatus;
DXGKARG_BUILDPAGINGBUFFER param;

// The driver receives the following paging operation to build:
//
param.Flags = 0;
param.pDmaBuffer= CurrentPagingBuffer;
param.DmaSize = CurrentPagingBufferSizeLeft;
param.pDmaBufferPrivateData = CurrentPagingBufferPrivateData; 
param.DmaBufferPrivateDataSize = CurrentPagingBufferPrivateDataSizeLeft; 
param.Operation = DXGK_OPERATION_TRANSFER; 
param.Transfer.Flags = 0; 
param.Transfer.TransferOffset = CurrentOffsetInAllocationBeingTransfered; 
param.Transfer.hAllocation = DriverContextForAllocationBeingMoved; 
param.Transfer.Source.SegmentId = 0; // Source is an MDL. 
param.Transfer.Source.pMdl = MDLDescribingPagesForAllocationBeingMoved; 
param.Transfer.Destination.SegmentId = 1; // Source to segment #1. 
param.Transfer.Destination.SegmentAddress = 0; // Source to offset 0 of segment #1.

// The driver receives MultipassOffset when it is initialized to zero 
// and uses it for multiple iterations of the paging operation.
//
param.MultipassOffset = 0;

do {
    // Call the driver's BuildPagingBuffer function to build a paging buffer.
    //
    ntStatus = BuildPagingBuffer(hAdapter, &param);
    // BuildPagingBuffer updates the size that is left in the 
    //  paging buffer with the amount of bytes that were written.
    //
    if (NT_SUCCESS(ntStatus)) {
        //
        // If STATUS_SUCCESS, batch the paging buffer to the 
        // scheduler after multiple paging operations are batched.
    }
    else if (ntStatus == STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER) {

        //
        // If STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER, submit the current paging buffer to the scheduler to let 
        // the GPU start working on a partial transfer.
 
        VidSchSubmitPagingBuffer(CurrentPagingBuffer, CurrentPagingBufferSizeLeft);
 
        // Acquire a new paging buffer to complete the transfer.
        //
        VidMmAcquirePagingBuffer(&CurrentPagingBuffer, &CurrentPagingBufferSizeLeft);
    }
    else {
        //
        // A critical failure occurred, so bugcheck the system. 
        // This situation should never occur because the driver can 
        // fail the call only if it requires more DMA buffer space.
    }
} while(!NT_SUCCESS(ntStatus))

要件

要件
サポートされている最小のクライアント Windows Vista
対象プラットフォーム デスクトップ
Header d3dkmddi.h
IRQL PASSIVE_LEVEL

こちらもご覧ください

DXGKARG_BUILDPAGINGBUFFER

DxgkDdiAddDevice

DxgkDdiPatch

DxgkDdiSubmitCommand

pfnLockCb