PFND3DDDI_LOCKCB コールバック関数 (d3dumddi.h)
pfnLockCb 関数は、割り当てをロックし、ディスプレイ ミニポート ドライバーまたはビデオ メモリ マネージャーから割り当てへのポインターを取得します。
構文
PFND3DDDI_LOCKCB Pfnd3dddiLockcb;
HRESULT Pfnd3dddiLockcb(
HANDLE hDevice,
D3DDDICB_LOCK *unnamedParam2
)
{...}
パラメーター
hDevice
ディスプレイ デバイスへのハンドル (グラフィックス コンテキスト)。
unnamedParam2
pData [in, out]
ロックする割り当てを記述する D3DDDICB_LOCK 構造体へのポインター。
戻り値
pfnLockCb は 、次のいずれかの値を返します。
リターン コード | 説明 |
---|---|
S_OK | 割り当てが正常にロックされました。 |
D3DERR_NOTAVAILABLE | 絞りは使用できませんでした。 |
D3DERR_WASSTILLDRAWING | 割り当てはレンダリングに引き続き使用されていました。 |
D3DDDIERR_CANTEVICTPINNEDALLOCATION | 割り当てをロックできませんでした。これは、絞りがデスワイズリングされなくなり、割り当てがピン留めされたために割り当てを削除できなかったためです。 |
E_OUTOFMEMORY | メモリ不足のため pfnLockCb を完了できませんでした (この状況は、システムが極端に低いメモリ状態にあり、ページの配列を割り当てるのに十分な領域がない場合に発生します)。 |
E_INVALIDARG | パラメーターが検証され、正しくないと判断されました。 |
D3DDDIERR_DEVICEREMOVED | pfnLockCb は、プラグ アンド プレイ (PnP) 停止またはタイムアウト検出と回復 (TDR) イベントが発生したため、ビデオ メモリ マネージャーとディスプレイ ミニポート ドライバーが適切なアクションを実行できませんでした。 pfnLockCb (通常は Lock 関数または ResourceMap 関数) を呼び出したユーザー モードのディスプレイ ドライバー関数は、このエラー コードを Direct3D ランタイムに返す必要があります。 Direct3D バージョン 9 注: エラー コードの返し方の詳細については、「 ランタイム関数から受信したエラー コードの返し」を参照してください。 Direct3D バージョン 10 および 11 注: ドライバー関数が値を返さない場合 (つまり、戻り値のパラメーター型に VOID がある場合)、ドライバー関数は pfnSetErrorCb 関数を呼び出してランタイムにエラー コードを返します。 エラー コードの処理の詳細については、「エラーの 処理」を参照してください。 |
この関数は、他の HRESULT 値も返す場合があります。
注釈
ユーザー モードディスプレイ ドライバーは、Microsoft Direct3D ランタイムの pfnLockCb 関数を呼び出して割り当てをロックし、ディスプレイ ミニポート ドライバーまたはビデオ メモリ マネージャーから割り当てへのポインターを取得できます。 通常、ユーザー モードディスプレイ ドライバーは、Lock 関数または ResourceMap 関数 (または DynamicIABufferMapDiscard などの ResourceMap のその他のバリエーション) の呼び出しに応答して pfnLockCb を呼び出して、リソースまたはリソース内のサーフェスをロックします。 Lock 呼び出しまたは ResourceMap 呼び出しから戻る前に、ユーザー モードのディスプレイ ドライバーは、最初にリソースまたはサーフェスを適切な割り当てにマップしてから、pfnLockCb を呼び出して割り当てをロックする必要があります。 割り当ては、次のロックのために、読み取りまたは書き込み前にロックする必要があります。
- 割り当ての仮想アドレス範囲が、ロック期間中は変更されず、有効で、読み取り可能であり、書き込み可能であることを保証します。 ビデオ メモリ マネージャーは、この保証を提供します。
- 割り当ての読み取り操作と書き込み操作を、割り当てのグラフィックス ハードウェア アクセスと同期する方法を提供します。 ビデオ メモリ マネージャーとディスプレイ ミニポート ドライバーは、同期を実行します。
通常、ユーザー モードディスプレイ ドライバーは、Lock 関数と Unlock 関数の呼び出しごとに対応する pfnLockCb 関数と pfnUnlockCb 関数を呼び出します。ただし、リソースの作成時に、D3DDDIARG_CREATERESOURCE 構造体の Flags メンバーに動的ビット フィールド フラグが設定されたリソースがドライバーによって処理される場合を除きます。 ランタイムは、多くの場合、D3DDDIARG_LOCK構造体の Flags メンバーに NoOverwrite ビット フィールド フラグを設定して、ドライバーがこれらの種類のリソースをロックすることを要求します。 このようなリソース内のデータは ( NoOverwrite で示されているように) 変更しないでください。そのため、ロック要求ごとに pfnLockCb を 呼び出すと、処理時間が過剰になります。 ロック要求ごとに pfnLockCb を呼び出さないように、ドライバーは、ロック関数がNoOverwrite ビット フィールド フラグを設定して呼び出されたときに、D3DDDIARG_LOCK の pSurfData メンバーで返される仮想メモリ ポインターをキャッシュできます。 ただし、Lock 関数が呼び出されるたびに、ドライバーは引き続き pfnLockCb を呼び出すことができます、破棄ビット フィールド フラグが設定されているか、フラグが設定されません。
Direct3D バージョン 10 および 11 注:
ユーザー モードのディスプレイ ドライバーは通常、その ResourceMap 関数と ResourceUnmap 関数 (またはこれらの関数の他のバリエーション) へのすべての呼び出しに対応する pfnLockCb 関数と pfnUnlockCb 関数を呼び出します。 これは、ドライバーがリソースの作成時にD3D10DDIARG_CREATERESOURCEまたはD3D11DDIARG_CREATERESOURCE構造体の Usage メンバーでD3D10_DDI_USAGE_DYNAMIC値が設定されたリソースを処理する場合は発生しません。 ランタイムは、多くの場合、ResourceMap の呼び出しで DDIMap パラメーターにD3D10_DDI_MAP_WRITE_NOOVERWRITE値を渡すことによって、ドライバーがこれらの種類のリソースをロックするように要求します。 このようなリソース内のデータは (D3D10_DDI_MAP_WRITE_NOOVERWRITEで示されているように) 変更しないでください。そのため、ロック要求ごとに pfnLockCb を 呼び出すと、処理時間が過剰になります。 ロック要求ごとに pfnLockCb を呼び出さないように、ドライバーは、ResourceMap 関数が D3D10_DDI_MAP_WRITE_NOOVERWRITE で呼び出されたときに pMappedSubResource パラメーターで返される仮想メモリ ポインターをキャッシュできます。 ただし、D3D10_DDI_MAP_WRITE_DISCARD値または 0 を DDIMap パラメーターに渡して ResourceMap 関数が呼び出されるたびに、ドライバーは pfnLockCb を引き続き呼び出すことができます。
アプリケーションは仮想メモリ ポインターに関連付けられているリソースに対して未処理のロックを保持しませんが、通常、ドライバーは pfnRenderCb 関数を呼び出す前に pfnUnlockCb 関数を呼び出して仮想メモリ ポインターのキャッシュを解除します。 ロックがキャッシュされていない場合、またはアプリケーションにリソースがまだロックされているためにロックを解除できない場合、ハードウェアはロックされた割り当てからレンダリングされる可能性があります。 割り当てがローカル ビデオ メモリ内にある場合、ビデオ メモリ マネージャーはこの操作モードをサポートできません。そのため、メモリ マネージャーがこの状況を検出すると、メモリ マネージャーによってシステムまたは AGP メモリへの割り当てが削除されます。 システムまたは AGP メモリ セグメントで割り当てがサポートされていない場合、メモリ マネージャーは、D3DDDIERR_CANTRENDERLOCKEDALLOCATIONを使用して pfnRenderCb の呼び出しを失敗します。 したがって、 動的 ビット フィールド フラグが D3DDDIARG_CREATERESOURCE の Flags メンバー (または D3D10DDIARG_CREATERESOURCE または D3D11DDIARG_CREATERESOURCE の Usage メンバーで設定されている D3D10_DDI_USAGE_DYNAMIC) で設定されているリソースの作成に応じて割り当てられる頂点バッファーとインデックス バッファーの割り当ては、システムセグメントまたは AGP セグメントでサポートする必要があります。
pfnLockCb の呼び出しで D3DDDICB_LOCK の Flags メンバーでビット フィールド フラグを破棄すると、ビデオ メモリ マネージャーによって、ロックされている割り当ての新しいインスタンスが作成されます。 ビデオ メモリ マネージャーは、 D3DDDICB_LOCKの hAllocation メンバーのユーザー モード ディスプレイ ドライバーに新しいハンドルを返すことによって、新しいインスタンスを表します。
コマンド バッファーをフラッシュした後、ユーザー モードのディスプレイ ドライバーは 、Discard と NoExistingReference の両方のビット フィールド フラグを使用して、サーフェスをもう一度ロックする必要があります。 NoExistingReference ビット フィールド フラグは、ドライバーが現在、そのコマンド バッファーでキューにロックされている割り当てのインスタンスへの参照がないことをビデオ メモリ マネージャーに示します。 その後、ビデオ メモリ マネージャーは、割り当ての任意のインスタンスを再利用して、現在のインスタンスを含むロックを処理できます。
ビット フィールドの破棄フラグが設定されている pfnLockCb を呼び出した後、ユーザー モードのディスプレイ ドライバーは、D3DDDICB_LOCKの hAllocation メンバーの更新されたハンドル値に対して常にチェックする必要があります。 新しい割り当てハンドルが指定されている場合、ユーザー モードのディスプレイ ドライバーは、新しい割り当てハンドルを参照するように内部データ構造を更新する必要があります。 また、ユーザー モードのディスプレイ ドライバーは、ロックされた割り当てベース アドレスの再プログラミングされたバージョンを現在のコマンド バッファーに追加する必要があります (割り当てインスタンスには異なるベース アドレスが含まれているため)。 ビデオ メモリ マネージャーは、ドライバーによって使用される割り当てインスタンスの使用を検証し、割り当てインスタンスを誤って使用する DMA バッファーを拒否します (つまり、割り当てインスタンスを誤って使用すると 、pfnPresentCb と pfnRenderCb の呼び出しは失敗します)。 ドライバーが割り当ての特定のインスタンスを参照すると、ドライバーは同じ割り当ての以前のインスタンスを参照できなくなります。 たとえば、コマンド バッファーが割り当て A を使用し、現在インスタンス A0 と A1 を使用している場合、A1 が使用されるとすぐに (つまり、パッチの場所の一覧に表示されます)、A0 は無効になります。 ディスプレイ ミニポート ドライバーは、A0 と A1 の両方を参照するパッチの場所の一覧を生成できます。 ただし、参照は順序付けする必要があります (つまり、最初に A0 を使用できます)。A0 は、A2 を使用すると無効になります。A1 は、A2 を使用すると無効になります。など)。
ディスプレイ ミニポート ドライバーが実際に送信、DMA を介して、またはグラフィックス ハードウェアにこれらの割り当てを非同期的に転送する処理中である可能性があるため、ユーザー モードのディスプレイ ドライバーは、メモリが事前に割り当てられていない場合でも、システム メモリ割り当てのために pfnLockCb を呼び出す可能性があります。 したがって、アプリケーションがサーフェスへの書き込みを許可される前に、必要に応じてロックをブロックできるように、ディスプレイ ミニポート ドライバーとビデオ メモリ マネージャーに通知する必要があります。
ユーザー モードのディスプレイ ドライバーは、割り当てのサブ領域をロックすることもできます。 この種類のロックは、一般に、ハードウェアの絞りを読み取ったり直線化したりする場合に必要ありません。この状況では、ユーザー モードのディスプレイ ドライバーは、ポインターをオフセットすることによって、割り当て全体のロックをサブ領域に変換できるためです。 ただし、D3DERR_NOTAVAILABLEを使用して絞りが使用できないことを示すために pfnLockCb が失敗した場合、メモリ マネージャーは、ビデオ メモリの内容をコピーするようにユーザー モードのディスプレイ ドライバーに要求します。 ユーザーモードディスプレイドライバは、ビデオメモリの内容を別のメモリ領域にコピーするときに、ビデオメモリの内容をスウィズルまたはリニアライズします。 この状況では、ユーザー モードのディスプレイ ドライバーは、大量の割り当てで小さなサブ領域をロックするときに大量のコピーを保存するためにコピーするページの一覧を指定できます。 ユーザー モードディスプレイドライバーがD3DDDICB_LOCK構造体のFlags メンバーで LockEntire ビットフィールド フラグを設定せず、D3DDDICB_LOCKの pPages メンバーにページ リストを指定しなかった場合、メモリ マネージャーは pfnLockCb の呼び出しに失敗し、D3DERR_NOTAVAILABLEに注意してください。 ユーザー モード ディスプレイ ドライバーで LockEntire ビット フィールド フラグを設定する場合は、D3DDDICB_LOCKの NumPages メンバーと pPages メンバーをそれぞれ 0 と NULL に設定する必要があります。 永続的なバッキング ストアで作成された割り当てをロックする場合、ユーザー モードのディスプレイ ドライバーは常に pPages のページ リストを指定する必要があります。 この場合、メモリ マネージャーはページ リストを使用して特定のページのみをダーティとしてマークし、レンダリングに使用するときにバッキング ストアから割り当て全体をコピーする必要はありません。
ユーザー モード ディスプレイ ドライバーは 、pfnLockCb を呼び出して、1 つの割り当てに対して複数のスウィズリング範囲を取得できます (たとえば、MIP レベルごとに 1 つのスウィズリング範囲)。 ドライバーがいずれかの範囲を取得できない場合、Direct3D ランタイムは、ロック (すべての MIP レベル) を処理する割り当て全体を削除し、すべてのスウィズリング範囲を再利用します。
ユーザー モードディスプレイドライバーは、割り当てにスウィズリング範囲を割り当てることを要求すると、ドライバーは実質的に割り当てのまぶしいビットへのアクセスを要求します。 このような要求の場合、ビデオ メモリ マネージャーは、メモリ セグメントへの割り当て内のページと、メモリ セグメントへの割り当てまたは割り当て内のページにアクセスするスウィズル範囲を設定し、システム メモリへの割り当てを削除します。システム メモリへの割り当てをドライバーが割り当て解除するように要求します。 システム メモリに割り当てられなかった割り当ては、GPU が再び割り当てを使用する前に (ビデオ メモリにページングされることによって) 再び読み込まれます。 その結果、ドライバーは、スウィズリング範囲を取得するときに ( DonotWait ビット フィールド フラグを設定することによって) 上書きなしの種類のロックを要求できません。 同様に、ドライバーは、(DMA バッファーが拒否されるため) GPU に送信される DMA バッファーでこのような方法で割り当てロックを参照することはできません。
ユーザー モードのディスプレイ ドライバーは、スウィズルされた形式で割り当てのビットにアクセスする必要がある場合、スウィズル範囲を取得せずにスウィズル割り当てをロックする可能性があります。 この状況では、ビデオ メモリ マネージャーは、割り当てのスウィズルビットへのポインターをドライバーに提供します。 ただし、割り当て解除されたビットの要求が未処理である間は、ドライバーは割り当てのスウィズルされたビットへのポインターを要求できません (つまり、取得されたスウィズリング範囲で現在、割り当てに対するロックが保留中です)。
ユーザー モードのディスプレイ ドライバーは、次の状況で pfnLockCb 呼び出しのD3DDDICB_LOCKの Flags メンバーのビット フィールドフラグを破棄する必要があります。
- Direct3D ランタイムが、ユーザー モード ディスプレイ ドライバーの Lock 関数の呼び出しで、D3DDDIARG_LOCK構造体の Flags メンバーのビット フィールドフラグを破棄する
- ランタイムがドライバーの ResourceMap 関数の呼び出しで DDIMap パラメーターにD3D10_DDI_MAP_WRITE_DISCARD値を渡す場合
次のコード例は、pfnLockCb の呼び出しでビット フィールドフラグを破棄する方法を示しています。
HRESULT hr;
D3DDDICB_LOCK LockData;
LockData.hAllocation = AllocationToLock;
LockData.Flags.Discard = TRUE;
hr = pfnLockCb(&LockData)
if (FAILED(hr)) {
FlushAccumulatedCommandBufferToKernel();
LockData.Flags.Discard = TRUE;
LockData.Flags.NoExistingReference = TRUE;
hr = pfnLockCb(&LockData);
if (FAILED(hr)) {
// Fails the lock to the application
}
}
UpdateAllocationHandleInUMDDataStructure(LockData.hAllocation);
ProgramSurfaceBaseAddressInCurrentCommandBuffer(LockData.hAllocation);
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows Vista 以降のバージョンの Windows オペレーティング システムで使用できます。 |
対象プラットフォーム | デスクトップ |
Header | d3dumddi.h (D3dumddi.h を含む) |