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 (的使用者模式顯示驅動程式函式, LockResourceMap 函式) 必須將此錯誤碼傳回 Direct3D 運行時間。
Direct3D 第 9 版 注意:如需傳回錯誤碼的詳細資訊,請參閱 傳回從運行時間函式收到的錯誤碼
Direct3D 版本 10 和 11 注意:如果驅動程式函式未傳回值 (,則具有傳回參數類型的 VOID) ,驅動程式函式會呼叫 pfnSetErrorCb 函式,將錯誤碼傳回運行時間。 如需處理錯誤碼的詳細資訊,請參閱 處理錯誤

此函式也可能傳回其他 HRESULT 值。

備註

使用者模式顯示驅動程式可以呼叫 Microsoft Direct3D 運行時間的 pfnLockCb 函式來鎖定配置,並從顯示迷你埠驅動程式或視訊記憶體管理員取得配置指標。 使用者模式顯示驅動程式通常會呼叫 pfnLockCb ,以回應其 LockResourceMap 函式的呼叫 (或其他 ResourceMap 變化,例如 DynamicIABufferMapDiscard) ,以鎖定資源內的資源或表面。 從 LockResourceMap 呼叫傳回之前,使用者模式顯示驅動程式必須先將資源或表面對應到適當的配置,然後呼叫 pfnLockCb 來鎖定配置。 配置必須先鎖定,才能讀取或寫入設定,因為鎖定:

  • 保證配置虛擬位址範圍在鎖定期間維持不變、有效、可讀取和可寫入。 視訊記憶體管理員提供此保證。
  • 提供將配置讀取和寫入作業與配置硬體存取同步處理的方式。 視訊記憶體管理員和顯示迷你埠驅動程式會執行同步處理。
Direct3D 第 9 版附注:

使用者模式顯示驅動程式通常會呼叫 pfnLockCbpfnUnlockCb 函式,分別對應至其 LockUnlock 函式的每個呼叫,除非驅動程式處理動態位字段旗標在建立資源時的 FlagsD3DDDIARG_CREATERESOURCE 成員中設定動態位欄位旗標的資源。 運行時間經常要求驅動程式鎖定這些類型的資源,通常會在 D3DDDIARG_LOCK 結構的 Flags 成員中設定 NoOverwrite 位字段旗標。 由於這類資源中的數據不應修改 (,如 NoOverwrite) 所指示,因此針對每個鎖定要求呼叫 pfnLockCb 會耗用過多的處理時間。 若要避免針對每個鎖定要求呼叫 pfnLockCb,驅動程式可以在呼叫具有 NoOverwrite 位字段旗標的 NoOverwrite 位字段旗標時,在 D3DDDIARG_LOCK 的 pSurfData 成員中傳回的虛擬記憶體指標快取。 不過,每當呼叫具有 [捨棄位字段旗標] 或未設定任何旗標的Lock函式時,驅動程式都可以繼續呼叫 pfnLockCb

Direct3D 版本 10 和 11 附注:

使用者模式顯示驅動程式通常會呼叫 pfnLockCb 和 pfnUnlockCb 函式,這些函式會對應至其 ResourceMapResourceUnmap 函式的每個呼叫 (或這些函式的其他變化) 。 當驅動程式處理資源建立時,D3D10DDIARG_CREATERESOURCE或D3D11DDIARG_CREATERESOURCE結構的Usage成員中設定D3D10_DDI_USAGE_DYNAMIC值的資源時,不會發生這種情況。 運行時間經常要求驅動程式鎖定這些類型的資源,通常是將D3D10_DDI_MAP_WRITE_NOOVERWRITE值傳遞至 ResourceMap 呼叫中的 DDIMap 參數。 由於這類資源中的數據不應修改 (,如D3D10_DDI_MAP_WRITE_NOOVERWRITE) 所示,因此針對每個鎖定要求呼叫 pfnLockCb 會耗用過多的處理時間。 若要避免針對每個鎖定要求呼叫 pfnLockCb,驅動程式可以在呼叫其 ResourceMap 函式時,快取其以 D3D10_DDI_MAP_WRITE_NOOVERWRITE 在 pMappedSubResource 參數中傳回的虛擬記憶體指標。 不過,每當呼叫其 ResourceMap 函式時,驅動程式可以使用傳遞至 DDIMap 參數的 D3D10_DDI_MAP_WRITE_DISCARD 值或 0,繼續呼叫 pfnLockCb

雖然應用程式不會保留與虛擬記憶體指標相關聯的資源未完成鎖定,但驅動程式通常會在驅動程式呼叫 pfnRenderCb 函式之前呼叫 pfnUnlockCb 函式來取消快取虛擬記憶體指標。 如果鎖定未解除快取,或因為應用程式仍然鎖定資源而無法取消快取鎖定,則硬體可能會從鎖定的配置轉譯。 如果配置位於本機視訊記憶體中,則視訊記憶體管理員無法支援此作業模式;因此,記憶體管理員會在記憶體管理員偵測到這種情況時,將配置收回至系統或 AGP 記憶體。 如果系統或 AGP 記憶體區段不支援配置,記憶體管理員會因為D3DDDIERR_CANTRENDERLOCKEDALLOCATION而無法呼叫 pfnRenderCb 。 因此,為了回應建立資源而配置的頂點和索引緩衝區配置,其中 動態 位欄位旗標是在 D3D10DDIARG_CREATERESOURCE D3DDDIARG_CREATERESOURCE (的 Flags 成員中設定,或在系統或 AGP 區段的 Usage 成員中設定 D3D11DDIARG_CREATERESOURCE) D3D10_DDI_USAGE_DYNAMIC值。

在呼叫 pfnLockCbFlags 成員中設定 [捨棄位欄位旗標] 旗標 D3DDDICB_LOCK,會導致視訊記憶體管理員建立鎖定配置的新實例。 視訊記憶體管理員藉由將新的句柄傳回給 hAllocation 成員中D3DDDICB_LOCK的使用者模式顯示驅動程式,來代表新的實例。

注意 建立配置的新實例時,不會呼叫顯示迷你埠驅動程式的 DxgkDdiCreateAllocation 函式。 實例會顯示為同時分頁至多個不同位置的配置顯示迷你埠驅動程式。
 
視訊記憶體管理員可能會因為視訊記憶體管理員無法建立新的實例或重複使用現有配置實例而設定 棄位欄位字段旗標的鎖定失敗。 發生此失敗時,使用者模式顯示驅動程式應該呼叫 pfnRenderCb 函式,將目前的命令緩衝區排清至核心。 此命令緩衝區的這個排清可能會淘汰某些無法使用 [捨 棄位字段] 旗標鎖定的配置實例。

排清其命令緩衝區之後,使用者模式顯示驅動程序必須使用 DiscardNoExistingReference 位字段旗標再次嘗試鎖定表面。 NoExistingReference 位字段旗標會向視訊記憶體管理員指出驅動程式目前沒有其命令緩衝區中已鎖定之配置之任何實例的參考。 然後,視訊記憶體管理員可以重複使用配置的任何實例來處理鎖定,包括目前的實例。

呼叫 pfnLockCb 並設定 [捨棄位字段旗標] 之後,使用者模式顯示驅動程式應該一律會在 D3DDDICB_LOCK的 hAllocation 成員中檢查更新的句柄值。 如果提供新的配置句柄,則使用者模式顯示驅動程式應該更新其內部數據結構,以參考新的配置句柄。 使用者模式顯示驅動程式也應該將鎖定配置基位址的重新程式設計版本新增至目前的命令緩衝區 (,因為配置實例包含不同的基位址) 。 視訊記憶體管理員會驗證驅動程式所使用的配置實例的使用方式,並拒絕使用配置實例 (的 DMA 緩衝區,也就是呼叫 pfnPresentCb 和 pfnRenderCb 時,如果錯誤地使用配置實例) ,則呼叫 pfnPresentCb 會失敗。 在驅動程式參考配置的特定實例之後,驅動程式就無法再參考相同配置的先前實例。 例如,如果命令緩衝區使用配置 A,且目前使用實例 A0 和 A1,則只要使用 A1 (即會出現在修補程式位置清單中,) A0 變成無效。 顯示迷你埠驅動程式可以產生參考 A0 和 A1 的修補程式位置清單。 不過,參考必須依序排序 (,也就是 A0 可以先使用;A0 在 A2 使用後變成無效;使用 A2 時 A1 會變成無效,依此類) 。

使用者模式顯示驅動程式可能會呼叫 pfnLockCb 進行系統記憶體配置,即使記憶體尚未預先配置,因為顯示迷你埠驅動程序實際上可能正在傳送、透過 DMA 傳送或以異步方式將這些配置傳送至圖形硬體。 因此,在允許應用程式寫入介面之前,必須通知顯示迷你埠驅動程序和視訊記憶體管理員,以便在必要時封鎖鎖定。

使用者模式顯示驅動程式也可以鎖定配置的子系。 這種鎖定類型通常不需要,因為在此情況下,使用者模式顯示驅動程式可以藉由位移指標,將整個配置上的鎖定轉譯為下層。 不過,當 pfnLockCb 使用 D3DERR_NOTAVAILABLE 來指出無法使用光圈時,記憶體管理員會要求使用者模式顯示驅動程式複製視訊記憶體內容。 使用者模式顯示驅動程式會在將視訊記憶體內容複製到另一個記憶體區域時,將驅動程式取消顯示或線性化。 在此情況下,使用者模式顯示驅動程式可以提供頁面清單,以在大型配置中鎖定小型子系時節省大量複製。 請注意,如果使用者模式顯示驅動程式未在 D3DDDICB_LOCK 結構的 Flags 成員中設定 LockEntire 位字段旗標,且未在 D3DDDICB_LOCK 的 pPages 成員中指定頁面清單,記憶體管理員就會失敗呼叫 pfnLockCb 並D3DERR_NOTAVAILABLE。 如果使用者模式顯示驅動程式設定 LockEntire 位欄位字段旗標,它也必須分別將 D3DDDICB_LOCK 的 NumPagespPages 成員設定為 0 和 NULL。 鎖定使用永久備份儲存區所建立的配置時,使用者模式顯示驅動程序應該一律在 pPages 中提供頁面清單。 在此情況下,記憶體管理員會使用頁面清單只標示為已變更的特定頁面,而且在用於轉譯時,不需要從備份存儲區複製整個配置。

使用者模式顯示驅動程式可以呼叫 pfnLockCb ,以取得單一配置 (的多個撥動範圍,例如,每個 MIP 層級) 的一個撥動範圍。 如果驅動程式無法取得任一範圍,Direct3D 運行時間會收回整個配置來處理所有 MIP 層級 (所有 MIP 層級) ,並回收所有雜亂範圍。

當使用者模式顯示驅動程式要求將撥動範圍指派給配置時,驅動程式會有效要求存取配置中未撥動的位。 針對這類要求,視訊記憶體管理員會將配置中的分頁分頁設定為記憶體區段,並設定一個撥動範圍,以存取配置中的配置或分頁到記憶體區段,然後收回配置給系統記憶體,同時要求驅動程式取消撥開系統記憶體上的配置。 在 GPU 再次使用配置之前,將分頁至視訊記憶體) 時,系統記憶體未撥入系統記憶體的配置會重新撥動 (。 因此,驅動程式無法藉由設定 DonotWait 位字段旗標) 取得撥動範圍時,要求無覆寫類型鎖定 (。 同樣地,驅動程式無法在提交至 GPU (的 DMA 緩衝區中參考配置鎖定,因為 DMA 緩衝區將會遭到拒絕) 。

如果使用者模式顯示驅動程式可能會鎖定雜亂配置,而不需要取得撥動範圍,如果驅動程式必須以雜亂格式存取配置的位。 在此情況下,視訊記憶體管理員會提供驅動程式的指標,指向配置的撥動位。 不過,驅動程式無法要求配置之撥動位的指標,而未撥動位的要求尚未完成,反之亦然, (,鎖定目前擱置在取得) 擷取範圍的配置上。

使用者模式顯示驅動程式應該在 pfnLockCb 呼叫中 D3DDDICB_LOCK,於 pfnLockCb 呼叫的 Flags 成員中傳遞 [捨棄位字段] 旗標:

  • 當 Direct3D 執行時間在呼叫使用者模式顯示驅動程式的 Lock 函式中,於 D3DDDIARG_LOCK 結構的 Flags 成員中傳遞 Discard 位欄位旗標時
  • 當運行時間在呼叫驅動程式的 ResourceMap 函式中將D3D10_DDI_MAP_WRITE_DISCARD值傳遞至 DDIMap 參數時
設定 [捨棄 位字段] 旗標會導致記憶體管理員判斷它是否應該重新命名配置,或應該造成應用程式線程停止,直到配置閑置為止。 如需重新命名配置的詳細資訊,請參閱 要求重新命名配置。 驅動程式可以使用自己的重新命名支援或記憶體管理員的重新命名支援。 若要使用自己的重新命名支援,驅動程式會設定 DonotWait 位字段旗標,以響應已設定捨棄位字段旗標的 Lock 呼叫,或回應具有D3D10_DDI_MAP_WRITE_DISCARD值集的 ResourceMap 呼叫。 如果圖形硬體仍在使用配置,設定 DonotWait 位字段旗標會導致記憶體管理員無法呼叫 pfnLockCb 並D3DERR_WASSTILLDRAWING。 這類失敗表示使用者模式顯示驅動程式重新命名或多重緩衝配置。
注意如果同時設定 [捨棄位字段] 旗標,DonotWait 位字段旗標不會影響記憶體管理員。
 
當使用者模式顯示驅動程式不需要記憶體管理員檢查圖形硬體是否使用配置時,應該在 D3DDDICB_LOCK 的 Flags 成員中設定 IgnoreSync 位字段旗標。 然後,使用者模式顯示驅動程式必須正確同步處理配置存取權。 如果未使用 IgnoreSync 位欄位旗標指定 DonotWait 位欄位旗標,記憶體管理員會忽略 IgnoreSync 位欄位旗標。
注意如果同時設定 [捨棄位字段] 旗標,IgnoreSync 位欄位旗標不會影響記憶體管理員。
 
範例

下列程式代碼範例示範如何在 pfnLockCb 的呼叫中使用 Discard 位字段旗標。

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 作業系統中使用。
目標平台 桌面
標頭 d3dumddi.h (include D3dumddi.h)

另請參閱

D3D10DDIARG_CREATERESOURCE

D3D11DDIARG_CREATERESOURCE

D3DDDIARG_LOCK

D3DDDICB_LOCK

D3DDDI_DEVICECALLBACKS

鎖定

ResourceMap

ResourceUnmap