DirectX 11 學習筆記-01【Device/Device Context/Resource/ResourceView/Swap Chain/Viewport】

目錄

Device和Device Context 

Resource和ResourceView 

Swap Chain和Viewport 

參考資料


計算機繪圖本質上繪製的是一張2D的平面圖像。DirectX作爲底層繪圖API,提供了一組軟件接口,我們可以通過這組接口來控制繪圖硬件。而一個DirectX程序完成的工作,就是把一系列的信息轉換爲一張2D平面圖形,並讓它顯示在屏幕上。 

Device和Device Context 

Device是程序與硬件交互的接口。在DirectX中使用 ID3D11Device來表示一個Device,它被用於檢測顯示適配器功能和分配資源。每個應用都必須至少有一個Device。 

Device Context可以認爲是Device的環境或者說是配置。更具體的說來,Device Context用於設置管線狀態,將資源綁定到圖形管線和生成渲染命令。 

Resource和ResourceView 

資源(Resource)好比構建Scene的磚塊,DirectX用於渲染場景的大部分數據來自於Resource。 

Resource包括以下幾種類型的數據:geometry, textures, shader data。

使用Device來創建一個新的資源。資源對CPU和GPU可以有不同的訪問權限。在一個每一個管線階段,最多只能有128個資源被綁定。 

比較常見的資源類型有紋理。紋理的用途之一是用於存儲圖像數據,但不侷限於此(例如法線貼圖)。紋理有1D,2D和3D紋理,分別代表不同維度的數據元素數組。但實際上,由於mipmap的存在,紋理可以是一組數據數組。 

在創建資源時,可以用枚舉DXGI_FORMAT指定資源的格式。當然也可以指定弱類型(typeless)格式,預先分配內存空間,然後在紋理綁定到管線時重新解釋數據內容。使用弱類型時,程序無法對它進行訪問優化。 

資源被存儲爲通用的內存格式,因此它可以被多個管線階段所共享。在管線階段中,使用資源視圖(ResourceView)來解釋資源數據,資源視圖概念上類似於對資源數據的轉換(casting),以便用於特定的管線中。資源視圖告訴DirectX我們將如何使用這一資源,同一個資源可以有不同的用途,這種情況下我們只需要爲它創建不同的資源視圖即可。例如一個紋理在同時作爲渲染目標和着色器資源時,我們需要爲它創建兩種視圖:渲染目標視圖(ID3D11RenderTargetView)和着色器資源視圖(ID3D11ShaderResourceView)。 

需要注意的是,資源的用途在資源創建時就已經通過BindFlags確定,如果BindFlags中不包含資源視圖類型所對應的Mask,那麼創建資源視圖時程序會報錯。 

Swap Chain和Viewport 

爲了避免在動畫過程中出現閃爍,最好的做法是在一個離屏紋理中執行所有的動畫幀繪製工作,繪製完成後再把它作爲完整的幀顯示在屏幕上。在圖形學中,交換鏈(swap chain)包含一系列能被顯卡和圖形API所利用的幀緩存。以雙緩衝(有兩個紋理緩衝區的交換鏈)爲例,兩個緩衝區分別被稱爲前臺緩衝區(front buffer)和後臺緩衝區(back buffer)。前臺緩衝區存儲了當前屏幕上顯示的圖像數據,而繪圖工作在後臺緩衝區上完成。程序將場景繪製在後臺緩衝區中,當繪製完成時,兩個緩衝區的作用將互換,後臺緩衝區將作爲前臺緩衝區並將內容顯示在顯示器中,而前臺緩衝區變爲後臺緩衝區,程序在新的後臺緩衝區中繪製下一幀。這個過程被稱爲Present。 交換通常只需要簡單的交換指針即可,所以是一個很快的過程。

在DirectX中,交換鏈在創建時可以指定交換的方式,但通常情況下只需要設置爲DXGI_SWAP_EFFECT_DISCARD,讓顯卡驅動自動選擇最高效的交換方式即可。交換鏈通常存在於顯存中,它也可以存在於系統內存中。DirectX中,交換鏈在創建時也會自動創建所需要的紋理緩衝區,我們不需要再爲它額外創建紋理,只需要獲取交換鏈中後臺緩衝區的指針,併爲它創建資源視圖(Render Target Resource View),就可以將它綁定到渲染管線中,從而向緩衝區繪製圖形。 

除了常見的雙緩衝,交換鏈可以支持更多的緩衝區。更多的緩衝區會消耗更多的顯存,遊戲中常見的是三緩衝。

雙緩衝雖然解決了畫面閃爍的問題,但當圖形繪製速度大於顯示器的刷新速率時,可能出現前臺緩衝區的內容還沒完全顯示在顯示器上,新的圖形幀就繪製完成,這時候交換鏈會交換兩個緩衝區,下一幀的內容被繪製在屏幕上,但前一幀的一部分已經被繪製出來,即屏幕上有一部分是前一幀的內容,另一部分是新的內容,畫面出現了撕裂。解決辦法之一是垂直同步,讓程序去等待屏幕刷新,例如屏幕的刷新率是60,那麼當程序的幀數大於60時強制和屏幕同步爲60。但當程序幀數不到60時,會同步到30幀,59幀也會強制同步到30幀,整體的流暢程度就大幅下降了。 

另一個解決方案是三緩衝。一個前臺緩衝區用於屏幕繪製,剩下有兩個後臺緩衝區用於程序的繪製,當一個新的幀繪製完成時,如果當前的前臺緩衝區還沒繪製完,新的幀會存放在後臺緩衝區,由於我們有兩個後臺緩衝區,那麼另一個後臺緩衝區可以用於下一幀的繪製,而屏幕刷新完畢以後,又可以立刻從後臺緩衝區中取一幀來繪製到屏幕中,這樣就不會出現畫面撕裂。當程序繪製夠快時,會有幀被丟棄的情況,但畫面流暢度得到提升。 

最後講Viewport。前面講到程序能在後臺緩衝區中繪製場景,但有些情況下我們不希望在整個後臺緩衝區中繪製,那麼我們可以使用VIewport來控制繪製的區域。Viewport指定了一個矩形區域,程序在這個矩形區域中繪製。在實際中,我們可以指定多個Viewport,並進行多次繪製,從而實現例如分屏的效果。 多次繪製多個Viewport的時候,只需要在所有繪製完成之後調用一次的Present即可。

參考資料

《Introduction to 3D Game Programming with Directx 11》

Wiki-SwapChain

What Is a Swap Chain? (Direct3D 9)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章