共用方式為


Direct3D 10 的變更

本節僅適用於 Windows 7 和更新版本,以及 Windows Server 2008 R2 和更新版本的 Windows作系統。

下列各節說明 Direct3D 11 如何從 Direct3D 10 變更。

駕駛員回呼函式至 Kernel-Mode 服務

當運行時間呼叫使用者模式顯示驅動程式的 CreateDevice(D3D10) 函式時,Direct3D 11 版運行時間在 D3DDDI_DEVICECALLBACKS 結構中提供的裝置特定回呼函式會隔離驅動程式與核心句柄和核心函式簽章。 Direct3D 11 版運行時間會變更回呼語意,因此,回呼函式的實作可支援自由線程模式的作業,而先前的 Direct3D 版本運行時間則不支援自由線程的作業模式。 在驅動程式指出其支援自由線程模式 (D3D11DDICAPS_FREETHREADED) 之後,就會套用自由線程模式作業的規則:否則,會套用先前嚴格限制的規則。 如需驅動程式如何指出支援自由線程模式的資訊,請參閱 線程和命令清單。 Direct3D 11 版仍存在下列限制:

  • 一次只能對 HCONTEXT 使用單一線程。 目前使用 HCONTEXT 的現有回呼函式為 pfnPresentCbpfnRenderCbpfnEscapeCbpfnDestroyContextCbpfnWaitForSynchronizationObjectCbpfnSignalSynchronizationObjectCb。 因此,如果多個線程呼叫這些回呼函式並使用相同的 HCONTEXT,驅動程式必須同步處理回呼函式的呼叫。 滿足這項需求相當自然,因為這些回調函式可能只會從操作即時上下文的線程呼叫。

  • 驅動程式只有在呼叫下列驅動程式函式時,才能使用呼叫這些驅動程式函式的相同線程來呼叫下列回呼函式:

  • pfnDeallocateCb 回調函式值得特別提及,因為驅動程式不需要在驅動程式從其 DestroyResource(D3D10) 函式傳回大部分資源類型之前呼叫 pfnDeallocateCb。 由於 DestroyResource(D3D10) 是自由線程函式,因此驅動程式必須延遲破壞物件,直到驅動程式可以有效率地確保沒有任何現有的即時內容參考仍會保留(也就是說,驅動程式必須在 pfnDeallocateCb 之前呼叫 pfnRenderCb)。 此限制甚至適用於共用資源、共用主要資料庫,或任何其他使用 HRESOURCE 來補充 HRESOURCE 使用方式與 pfnAllocateCb 的回呼函式。 此限制不適用於主要。 如需主要例外狀況的詳細資訊,請參閱 主要例外狀況。 由於某些應用程式可能需要同步銷毀的效果,因此驅動程式必須確保在呼叫 Flush(D3D10) 函式期間,針對任何已銷毀的共用資源呼叫 pfnDeallocateCb。 驅動程式在呼叫其 Flush(D3D10) 函式時,也必須清理任何先前終結的物件(僅限於那些不會阻塞管線的物件)。驅動程式這樣做是為了確保運行時能以 Flush(D3D10)作為官方機制來清理那些少數可能需要此機制的應用程式的延遲終結物件。 如需此機制的詳細資訊,請參閱延後解構和 Flush(D3D10)。 驅動程式必須還確保,在驅動程式的 DestroyDevice(D3D10) 函式在清理過程中回傳之前,任何破壞被延遲的物件都已完全摧毀。

棄用允許修改 Free-Threaded DDIs 的功能

對於 Direct3D 第 11 版,顯示設備的 API 層級概念和即時上下文仍然在 DDI 層級由顯示設備的舊概念結合在一起。 這種顯示裝置和即時內容組合可將與舊版 DDI 的相容性最大化(例如 Direct3D 版本 10 DDI),並透過多個版本的 DDI 支援多個 API 版本時減少驅動程式變換。 不過,這種顯示裝置與相關上下文的組合會造成 DDI 的困惑性增加,因為執行緒範疇並不非常明確。 相反地,若要瞭解多個介面和這些介面內函式的線程需求,驅動程式開發人員必須參考檔。

Direct3D 11 版 API 的主要功能是允許多個線程同時進入建立和終結函式。 這類功能與允許驅動程式交換函式數據表指標以進行建立和終結不相容,因為 D3D10DDI_DEVICEFUNCS 和允許D3D10_1DDI_DEVICEFUNCS所指定函式的 Direct3D 10 DDI 語意。 因此,在驅動程式傳回 CreateDevice(D3D10)函式指標之後,當驅動程式在 Direct3D 版本 11 DDI 下執行並支援 DDI 線程時,驅動程式不應該嘗試透過修改這些特定的函式指標來改變行為。 這項限制適用於以 pfnCreatepfnOpenpfnDestroypfnCalcPrivatepfnCheck 開頭的所有裝置函式。 其餘所有裝置功能都與即時內容有強烈關聯。 因為單個線程一次操控立即上下文,所以定義明確,繼續允許驅動程式熱插拔立即上下文函式表項。

pfnRenderCb 與 pfnPerformAmortizedProcessingCb

Direct3D 第 10 版 API 函式會連結 Direct3D 執行環境中的 pfnRenderCb 核心回呼函式進行攤銷處理(也就是說,驅動程式並非針對每次 API 函式呼叫執行特定操作,而是每隔數次 API 函式呼叫後進行累計的處理作業)。 API 通常會使用此機會來修剪高水位線,並排清其延遲的物件解構佇列等等。

為了使驅動程式的核心回呼函式能夠盡可能實現自由線程,當驅動程式支援 Direct3D 第 11 版 DDI 時,Direct3D API 不再使用 pfnRenderCb 。 因此,支援 Direct3D 11 DDI 版本的驅動程式必須在驅動程式將命令緩衝區提交至立即上下文(或類似頻率)後,從進入驅動程式 DDI 函式的相同執行緒手動呼叫 pfnPerformAmortizedProcessingCb 核心回呼函式。 由於作業應該修剪高水位線,因此在驅動程式利用 狀態重新整理 DDI 回呼函式時產生命令緩衝區前置詞之前,最好先執行該作業。

此外,驅動程式應該注意 API 攤銷問題,並嘗試平衡其使用 pfnPerformAmortizedProcessingCb 核心回呼函式的頻率。 在一個極端,驅動程式可能會導致過度處理。 例如,如果驅動程式一律呼叫 pfnPerformAmortizedProcessingCb 兩次(背靠背),可能是因為多引擎使用,則驅動程式只會呼叫 pfnPerformAmortizedProcessingCb 一次會更有效率。 在其他極端,如果驅動程式從未呼叫 pfnPerformAmortizedProcessingCb,驅動程式可能無法讓 Direct3D API 針對整個畫面執行任何工作,可能是因為交替的畫面轉譯設計所致。 驅動程式不需要比其自然頻率更常呼叫 pfnPerformAmortizedProcessingCb,因為這樣做過於頻繁(例如,如果驅動程式未在 1 毫秒的時間範圍內呼叫 pfnPerformAmortizedProcessingCb,則必須開始執行 API 當前的任務)。 驅動程式只需要判斷哪一個現有的 pfnRenderCb 呼叫應該伴隨 pfnPerformAmortizedProcessingCb ,而且自然會符合作業的線程語意。

對於支援命令清單的驅動程式,當這些驅動程式在延遲狀態中空間不足時,必須呼叫 pfnPerformAmortizedProcessingCb(其頻率與立即狀態的緩衝區刷新頻率相似)。 Direct3D 版本 11 執行時預期至少在這類作業期間減少其資源上限標記。 由於與 pfnRenderCb 相關的線程語意在 Direct3D 第 11 版中已經放寬,因此必須解決並行問題,才能讓 Direct3D 第 11 版在不受限制的情況下繼續攔截 pfnRenderCb

新的 DDI 錯誤碼

系統建立 D3DDDIERR_APPLICATIONERROR 錯誤碼,讓驅動程式參與到 Direct3D 第 11 版 API 所沒有提供的驗證功能。 先前,如果驅動程式傳回E_INVALIDARG錯誤碼,則會導致API引發例外狀況。 偵錯層的存在會導致偵錯輸出,並指出驅動程式傳回內部錯誤。 偵錯輸出顯示驅動程式存在錯誤,開發人員應注意。 如果驅動程式傳回D3DDDIERR_APPLICATIONERROR,偵錯層會改為判斷應用程式發生錯誤。

追溯性要求無鎖定線程的 CalcPrivate DDIs

Direct3D 第 11 版事後要求 Direct3D 10 DDI 函數中以 pfnCalcPrivate 開始的驅動程式函式能夠自由執行緒。 此追溯需求符合 Direct3D 11 DDI 版的行為,一律需要 pfnCalcPrivate*pfnCalcDeferredContextHandleSize 函式才能自由線程,即使驅動程式指出它不支援 DDI 線程。 如需此回溯需求的詳細資訊,請參閱 回溯要求 Free-Threaded CalcPrivate DDIs

延遲摧毀和清空 D3D10

由於所有銷毀函式現在都是自由執行緒,所以 Direct3D 執行階段無法在解構期間清除命令緩衝區。 因此,destroy 函式必須延遲物件的實際解構,直到驅動程式可以確保操作即時上下文的執行緒不再依賴該物件來生存為止。 每個立即執行的內容方法無法有效率地使用同步來解決此銷毀問題;因此,驅動程式應僅在清空命令緩衝區時使用同步。 當 Direct3D 執行時間必須處理類似的問題時,也會使用相同的設計。

由於正式批准延遲銷毀,Direct3D 運行時建議那些無法容忍延遲銷毀因應措施的應用程式改用明確的機制。 因此,驅動程式必須在呼叫 Flush(D3D10) 函式時處理其延後解構佇列(即使命令緩衝區是空的),以確保這些機制實際運作。

需要同步銷毀形式的應用程式必須使用下列其中一種模式,視其所需的複雜度而定:

  • 在應用程式確保釋放該物件的所有相依性之後(也就是命令清單、檢視、中間件等等),應用程式會使用下列模式:

    Object::Release(); // Final release
    ImmediateContext::ClearState(); // Remove all ImmediateContext references as well.
    ImmediateContext::Flush(); // Destroy all objects as quickly as possible.
    
  • 下列模式是較重量級的拆除:

    Object::Release(); // Final release
    ImmediateContext::ClearState(); // Remove all ImmediateContext references as well.
    ImmediateContext::Flush();
    ImmediateContext::End( EventQuery );
    while( S_FALSE == ImmediateContext::GetData( EventQuery ) ) ;
    ImmediateContext::Flush(); // Destroy all objects, completely.
    

主要例外狀況

主要資源是在運行期間透過呼叫驅動程式的 CreateResource(D3D11) 函式而創建的。 運行時間會將D3D11DDIARG_CREATERESOURCE結構的 pPrimaryDesc 成員設定為DXGI_DDI_PRIMARY_DESC結構的有效指標,以建立主要複本。 共用主要資料庫會遵循所有共用資源的規則。 非共用主要資料庫在上述從 Direct3D 10 到 Direct3D 11 的變更方面有下列顯著例外狀況:

  • 驅動程式的 CreateResource(D3D11)DestroyResource(D3D10) 函式都不是自由執行緒,並且它們共用即時內容執行緒域。 Concurrency 仍然可以與開頭為 pfnCreatepfnDestroy 的函式存在,其中包括 CreateResource(D3D11) 和 DestroyResource(D3D10)。 不過,主要物件的 CreateResource(D3D11)DestroyResource(D3D10) 無法並行存在。 例如,驅動程式可以偵測到其 CreateResource(D3D11)或 DestroyResource(D3D10)函式的呼叫是針對主要資源,由此判斷它可以在函式呼叫過程中安全地使用或觸及直接上下文記憶體。

  • Direct3D 執行時間無法延後主要解構,驅動程式必須在呼叫驅動程式的 DestroyResource(D3D10) 函式時適當地呼叫 pfnDeallocateCb 函式。