2015-10-15 511 views
5

我正在爲Windows Store編寫電子書閱讀器應用程序。我使用Direct2D + DXGI交換鏈在屏幕上呈現書籍頁面。高效的Direct2D多線程

我的圖書內容有時非常複雜(幾何圖形,位圖,蒙版等),所以最多可能需要100 ms的時間來渲染。所以我試圖在一個單獨的線程中對一個位圖進行離屏渲染,然後在主線程中顯示這個位圖。

但是,我不知道如何有效地做到這一點。

到目前爲止,我已經試過兩種方法:

  1. 使用單一ID2D1Factory與D2D1_FACTORY_TYPE_MULTI_THREADED標誌,創建ID2D1BitmapRenderTarget,並用它在後臺線程閉屏渲染。 (這還需要ID2D1Multithread::Enter/LeaveIDXGISwapChain::Present操作)。問題是,後臺線程中的ID2D1RenderTarget::EndDraw操作有時需要長達100ms,並且由於內部Direct2D鎖定,主線程呈現在此期間被阻止。

  2. 在後臺線程中使用單獨的ID2D1Factory(如http://www.sdknews.com/ios/using-direct2d-for-server-side-rendering中所述)並關閉內部Direct2D同步。在這種情況下,兩條線之間沒有交叉鎖定。不幸的是,在這種情況下,我無法直接在主要的ID2D1Factory中使用結果位圖,因爲它屬於不同的工廠。我必須將位圖數據移至CPU內存,然後將其複製到主內存ID2D1Factory的GPU內存中。這個操作也會引入顯着的延遲(我相信這是由於大容量的內存訪問,但我不確定)。

有沒有辦法有效地做到這一點?

P.S.這裏的所有時間都是針對宏碁Switch 10平板電腦的。在常規Core i7 PC上,兩種方法都沒有任何明顯的滯後。

回答

4

好的,我找到了一個解決方案。

基本上,我所需要的就是修改方法2以在兩個DirectX工廠集之間使用DXGI資源共享。我將跳過所有的血淋淋的細節(他們可以在這裏找到:http://xboxforums.create.msdn.com/forums/t/66208.aspx),但基本步驟是:

  1. 創建兩套DirectX的資源:主(這將被用來渲染屏幕)和二級(用於屏外渲染)。
  2. 從主要資源集中使用ID3D11Device2,通過CreateTexture2DD3D11_BIND_RENDER_TARGETD3D11_BIND_SHADER_RESOURCED3D11_RESOURCE_MISC_SHARED_NTHANDLED3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX標誌創建D3D 2D紋理。
  3. 通過將它轉換爲IDXGIResource1並從XGI_SHARED_RESOURCE_READDXGI_SHARED_RESOURCE_WRITE中調用CreateSharedHandle來獲取它的共享句柄。
  4. 通過調用ID3D11Device2::OpenSharedResource1在後臺線程中的輔助資源集中打開此共享紋理。
  5. 獲取此紋理的鍵控互斥體(IDXGIKeyedMutex::AcquireSync),從中創建渲染目標(ID2D1Factory2::CreateDxgiSurfaceRenderTarget),在其上繪製並釋放互斥體(IDXGIKeyedMutex::ReleaseSync)。
  6. 在主線程中,在主資源集中,獲取互斥量並從步驟2中創建的紋理創建共享位圖,繪製該位圖,然後釋放互斥量。

請注意,互斥鎖的東西是必要的。不這樣做會導致一些神祕的DirectX調試錯誤消息,以及錯誤的操作甚至崩潰。

0

tl; dr:在軟件模式下渲染到後臺線程上的位圖。從位圖中繪製,以硬件模式呈現UI線程上的目標。

我已經能夠迄今爲止找到的最好的方法是使用後臺線程與軟件渲染(IWICImagingFactory::CreateBitmapID2D1Factory::CreateWicBitmapRenderTarget),然後將其與硬件通過ID2D1RenderTarget::CreateBitmapFromWicBitmap複製到一個硬件位圖後面的線程渲染目標。然後blit使用ID2D1RenderTarget::DrawBitmap

這是paint.net 4.0如何做選擇渲染。當您使用套索工具繪製選區時,它將使用後臺線程異步繪製選擇輪廓(UI線程不會等待它完成)。由於筆畫風格和動畫,最終可能會形成一個非常複雜的多邊形。我將它渲染4次,其中每個動畫幀對於虛線描邊樣式具有略微不同的偏移量。

很顯然,隨着多邊形變得更加複雜(也就是說,如果你持續塗鴉一段時間),這種渲染可能需要一段時間。當您使用移動選擇工具(允許您進行轉換(旋轉,平移,縮放))時,我還有其他一些特殊優化:如果後臺線程尚未使用新轉換重新呈現當前多邊形,則I將應用新的變換渲染舊的位圖(使用當前的多邊形和舊的變換)。在後臺線程追上時,選擇大綱可能會失真(縮放)或剪裁(在可視區域之外進行翻譯),但爲60fps的響應速度付出的代價很小。此優化效果非常好,因爲您無法同時修改多邊形變形變換。