2016-05-30 66 views
3

我正在C++/D3D11下創建一個用於教授基本圖形概念的簡單框架。該框架需要通過簡單的界面功能(例如Putpixel(x,y,r,g,b))直接操作屏幕光柵內容。如何從Direct3D 11中的CPU訪問幀緩衝區?

在D3D9下,這是一個相對簡單的目標,它通過在堆組成一個表面的堆上分配一個表面緩衝區來實現。然後,後臺緩衝區將被鎖定,並且堆緩衝區的內容被傳送到後臺緩衝區。據我瞭解,在D3D11下無法直接從CPU訪問後緩衝器。必須準備一個紋理資源,然後通過一些全屏幾何圖形將其繪製到後緩衝區。

我已經考慮過這樣一個程序的兩個系統。第一個包含D3D11_USAGE_DEFAULT紋理和D3D11_USAGE_STAGING紋理。臨時紋理首先被映射,然後從CPU中繪製。當場景完成時,暫存紋理將被取消映射並被複制到默認紋理,其中CopyResource(如果我沒有弄錯,它使用GPU執行復制),然後默認紋理通過全屏紋理四邊形繪製到後緩衝區。

第二個系統包含一個D3D11_USAGE_DYNAMIC紋理和在堆上分配的幀緩衝區。當場景合成時,動態紋理被映射,堆緩衝區的內容通過CPU被複制到動態紋理,動態紋理未被映射,然後通過全屏紋理四邊形繪製到後緩衝區。

我的印象是,使用讀寫訪問和D3D11_USAGE_STAGING創建的紋理將駐留在系統內存中,但我運行的性能測試似乎表明,情況並非如此。也就是說,通過CPU繪製一個簡單的200x200填充矩形,使用分段紋理比使用堆緩衝器慢兩倍(對於這兩種情況完全相同的反彙編(緊密的rep stos循環)),強烈暗示分段紋理駐留在圖形適配器內存中。

我寧願使用staging紋理系統,因爲它將允許渲染到backbuffer的工作以及從系統內存複製到圖形內存的工作被卸載到GPU上。不過,我想在任何情況下優先考慮CPU訪問速度。

那麼對於這種用法,哪種方法最適合?任何提示,我的兩種方法的修改,或完全不同的方法的建議將不勝感激。

回答

3

動態和暫存都可能在系統內存中,但他們很有可能是您的問題寫入組合內存。這是一種緩存模式,其中單個寫入合併在一起,但如果您嘗試讀取,因爲它沒有被緩存,每個負載都支付全部內存訪問的代價。你甚至必須非常小心,因爲C++ *data=something;有時也會導致不需要的讀取。

動態紋理沒有錯,GPU可以讀取系統內存,但是您需要小心,創建其中的一部分,並使用map_nooverwrite循環每個幀,以禁止昂貴的驅動程序緩衝區重命名丟棄。當然,不要在讀寫時做映射,只寫,否則你會引入gpu/cpu同步並殺死並行。最後,如果你想要一個持久表面,只有幾個putpixel一個框架(甚至很多),我會去一個無序的訪問視圖和一個計算着色器,使用顏色的像素位置緩衝區更新。該緩衝區將再次成爲一個帶有無覆蓋映射的動態緩衝區。使用該解決方案,主表面將駐留在視頻內存中。我個人甚至都懶得去教cpu表面操縱,這幾乎總是一種糟糕的做法和性能殺手,而不是在現代gpu架構中走的路。這在十年前已經不是一個基本的圖形概念。

+0

看起來很奇怪的是,驅動程序會爲標記爲由CPU讀取和寫入的內存指定寫入組合。感謝您對動態紋理的建議,我會嘗試使用nooverwrite創建多個紋理和循環的方法。此外,目標不是教授CPU表面操作,而是以動手方式教授2D/3D光柵圖形的基本概念(數學和算法)。 – chili