資源類型 (Direct3D 10)
Direct3D 管線使用的所有資源都源自於兩種基本資源類型:緩衝區和紋理。 緩衝區為原始資料 (元素) 的集合,紋理則為紋理像素 (紋理元素) 的集合。
完整指定資源配置 (或記憶體使用量) 的方式共有兩種:
項目 | 說明 |
---|---|
具類型 |
在建立資源時完整指定類型。 |
不具類型 |
在資源繫結至管線時完整指定類型。 |
緩衝區資源
緩衝區資源是一系列完全具類型的資料;緩衝區內部則會包含多個元素。 元素會由 1 到 4 個元件組成。 元素資料類型的範例會包括:已封裝的資料值 (例如 R8G8B8A8)、單一 8 位元整數、四個 32 位元浮點值。 這些資料類型會用來儲存資料,例如位置向量、法向量、頂點向量中的紋理座標、索引緩衝區中的索引,或是裝置狀態。
緩衝區會以非結構化資源的形式建立。 由於緩衝區為非結構化,因此無法包含任何 Mipmap 層級、在讀取時不會進行篩選,而且無法進行多重取樣。
緩衝區類型
頂點緩衝區
緩衝區唯一系列的元素;頂點緩衝區則包含每個頂點的資料。 最簡單的範例,就是包含一種資料類型的頂點緩衝區,例如位置資料。 其視覺化呈現方式會如下圖所示。
許多時候,頂點緩衝區會包含完整指定 3D 頂點所需的一切資料。 其中一個範例,就是包含每一頂點位置、一般和紋理座標的頂點緩衝區。 通常,這項資料會組織為一組每一頂點項目,如下圖所示。
這個頂點緩衝區會針對八個頂點包含每個頂點的資料;每個頂點都會儲存三個元素 (位置座標、法座標和紋理座標)。 位置和一般都是使用三個 32 位浮點數(DXGI_FORMAT_R32G32B32_FLOAT)和兩個 32 位浮點數的紋理座標來指定(DXGI_FORMAT_R32G32_FLOAT)。
若要存取頂點緩衝區的資料,您需要了解需要存取哪個頂點,以及下方所列的其他緩衝區參數:
- Offset - 從緩衝區開頭到第一個頂點資料的位元組數。 位移會提供給 IASetVertexBuffers。
- BaseVertexLocation - 從位移到適當繪製呼叫所使用的第一個頂點的位元組數目(請參閱 Draw Methods)。
建立頂點緩衝區之前,您必須藉由建立輸入配置對象來定義其配置;這是藉由呼叫 CreateInputLayout 來完成。 建立輸入配置對象之後,請呼叫 IASetInputLayout,將它系結至輸入組合器階段。
若要建立頂點緩衝區,請呼叫 CreateBuffer。
索引緩衝區
索引緩衝區包含一組循序的 16 位元或 32 位元索引;每個索引都會用來識別頂點緩衝區中的頂點。 使用索引緩衝區搭配一個或多個頂點緩衝區,藉此將資料提供給 IA 階段,就是所謂的索引編製。 索引緩衝區的視覺化呈現方式會如下圖所示。
儲存在索引緩衝區中的循序索引會具有下列參數:
- Offset - 從緩衝區開頭到第一個索引的位元組數。 位移會提供給 IASetIndexBuffer。
- StartIndexLocation - 從位移到適當繪製呼叫所使用的第一個頂點的位元元組數目(請參閱 Draw Methods)。
- IndexCount - 要轉譯的索引數。
若要建立索引緩衝區,請呼叫 CreateBuffer。
索引緩衝區可以分割成多個 線條或三角形 帶狀,方法是使用帶狀切割索引來分隔每一條。 寬帶切割索引可使用單一繪製呼叫來繪製多個線條或三角形寬帶。 帶狀切割索引只是索引的最大可能值(0xffff 16 位索引,0xffffffff 32 位索引)。 寬帶切割索引會重設已索引原始物件中的捲繞順序,且可用於免除變質三角形的必要性,否則,變質三角形可能需要在三角形寬帶中保持適當的捲繞順序。 下圖顯示了寬帶切割索引的範例。
常數緩衝區
Direct3D 10 引進了新的緩衝區,用於提供稱為著色器常數緩衝區或只是常數緩衝區的著色器常數。 就概念上來說,它看起來就像單一元素頂點緩衝區,如下圖所示。
視儲存的資料格式而定,每個項目都會儲存一個包含 1 個至 4 個元件的常數。
常數緩衝區可允許著色器常數組成群組並同時認可 (而非進行個別呼叫以單獨認可每個常數),藉此減少更新著色器常數所需要的頻寬。
若要建立著色器常數緩衝區,請呼叫 CreateBuffer 並指定常數緩衝區系結旗標D3D10_BIND_CONSTANT_BUFFER(請參閱D3D10_BIND_FLAG)。
若要將著色器常數緩衝區系結至管線,請呼叫下列其中一種方法:GSSetConstantBuffers、PSSetConstantBuffers 或 VSSetConstantBuffers。
請注意,使用ID3D10Effect介面介面時,ID3D10Effect介面實例會處理建立、系結和組合常數緩衝區的程式。 在此情況下,只需要使用 GetVariableByName 等其中一個 GetVariable 方法從效果中取得變數,並使用 SetMatrix 等其中一個 SetVariable 方法更新變數。 如需使用 ID3D10Effect介面 來管理常數緩衝區的範例,請參閱教學 課程07。
著色器會依照變數名稱來持續且直接讀取常數緩衝區中的變數,而讀取方法與不屬於常數緩衝區之變數所適用的方法相同。
每個著色器階段最多允許 15 個著色器常數緩衝區;每個緩衝區最多可以保存 4096 個常數。
使用常數緩衝區,即可儲存資料流輸出階段的結果。
如需在著色器中宣告常數緩衝區的範例,請參閱著色器常數 (DirectX HLSL)。
紋理資源
紋理資源是專為儲存紋理像素所設計的一系列結構化資料。 不同於緩衝區,紋理可使用紋理取樣器篩選,因為它們會由著色器單位讀取。 紋理類型會影響紋理的篩選方式。 紋理像素代表紋理的最小單位,且可由管線讀取或寫入。 每個紋理像素都包含 1 到 4 個元件,並使用其中一種 DXGI 格式加以排列 (請參閱 DXGI_FORMAT)。
紋理會建立為結構化資源,以便告知其大小。 不過,只要在紋理系結至管線時,使用檢視完全指定類型,每個紋理都可以在資源建立期間輸入或輸入較少。
紋理類型
紋理包含多種類型:1D、2D 和 3D,而每個類型都可使用或不使用 Mipmap 加以建立。 Direct3D 10 也支援紋理陣列和多重取樣紋理。
1D 紋理
1D 紋理為最簡單的形式,而當中包含的紋理資料可使用單一紋理座標來定址;它可視覺化為紋理像素陣列,如下圖所示。
視儲存資料的格式而定,每個紋理像素都包含多個色彩元件。 只要新增更多複雜度,您就能建立具有 Mipmap 層級的 1D 紋理,如下圖所示。
Mipmap 層級是一種紋理,會比上一個層級小二次方。 最上層包含最多詳細資料,每個後續層級都會越來越小;對 1D Mipmap 而言,最小層級會包含一個紋理像素。 不同層級會由名為 LOD (詳細資料層級) 的索引進行識別;轉譯並未盡可能接近相機的幾何時,您可以使用 LOD 存取較小的紋理。
1D 紋理陣列
Direct3D 10 也有提供適用於紋理陣列的新資料架構。 就概念上而言,1D 紋理陣列會如下圖所示。
這個紋理陣列包含三個紋理。 三個紋理的寬度都是 5 (這也是第一層中的元素數量)。 每個紋理也包含一個 3 層 Mipmap。
Direct3D 中的所有紋理陣列都是紋理的同質陣列;這表示,紋理陣列中的每個紋理,都必須使用相同的資料格式和大小 (包括紋理寬度和 Mipmap 層級的數量。) 您可以建立不同大小的紋理陣列,只要每個陣列中的所有紋理都使用相同的大小即可。
2D 紋理和 2D 紋理陣列
Texture2D 資源包含一個 2D 紋理像素方格。 每個紋理像素都可透過 u、v 向量定址。 由於它是紋理資源,因此,當中可能包含 Mipmap 層級和子資源。 完整填入的 2D 紋理資源會如下圖所示。
這個紋理資源包含單一 3x5 紋理,且具有三個 Mipmap 層級。
Texture2DArray 資源為 2D 紋理的同質陣列;這表示,每個紋理都有相同的資料格式和維度 (包括 Mipmap 層級)。 其配置與 1D 紋理陣列相似,而兩者的差異在於:紋理現在包含 2D 資料,因此會如下圖所示。
這個紋理陣列包含三個紋理;每個紋理都是 3x5,且具有兩個 Mipmap 層級。
將 Texture2DArray 做為紋理立方體
紋理立方體是一個 2D 紋理陣列,當中包含 6 個紋理,立方體的每一面各一個紋理。 完整填入的紋理立方體會如下圖所示。
包含 6 個紋理的 2D 陣列使用立方體紋理檢視繫結至管線後,就能從具有立方體對應內建函式的立方體著色器中讀取。 紋理立方體可從具有自紋理立方體中心指向之 3D 向量的著色器來定址。
3D 紋理
Texture3D 資源 (又稱為體積紋理) 包含一個 3D 紋理像素體積。 由於它是紋理資源,因此可能包含 Mipmap 層級。 完整填入 的 3D 紋理 看起來像下圖。
當 3D 紋理 Mipmap 配量繫結為轉譯目標輸出 (使用轉譯目標檢視) 時,3D 紋理的行為就會與具有 n 配量之 2D 紋理相同。 從 geometry 著色器階段選擇特定的轉譯配量,方法是將輸出數據的純量元件宣告為系統值SV_RenderTargetArrayIndex。
由於 3D 紋理陣列概念並不存在;因此,3D 紋理子資源為單一 Mipmap 層級。
子資源
Direct3D 10 API 會參考整個資源或資源的子集。 為了指定部分資源,Direct3D 已產生子資源一詞,這表示資源的子集。
緩衝區會定義為單一子資源。 紋理則比較複雜一點,因為存在許多不同的紋理類型 (1D、2D 等),而有些類型可支援 Mipmap 層級和/或紋理陣列。 從最簡單的案例開始,1D 紋理會定義為單一子資源,如下圖所示。
這表示,組成 1D 紋理的紋理像素陣列會包含在單一子資源中。
如果展開具有三個 Mipmap 層級的 1D 紋理,就能像這樣將其視覺化。
請將此視為由三個子紋理組成的單一紋理。 每個子紋理都會視為子資源,因此,這個 1D 紋理包含 3 個子資源。 子紋理 (或子資源) 可使用單一紋理的詳細資料層級 (LOD) 編製索引。 使用紋理陣列時,必須具備 LOD 和特定紋理,才能存取特定子紋理。 或者,API 可將這兩個資訊片段合併為單一以零為基底的子資源索引,如下方所示。
選取子資源
有些 API 會存取整個資源(例如 CopyResource),其他則存取資源的一部分(例如 UpdateSubresource 或 CopySubresourceRegion)。 存取資源一部分的 API 通常會使用檢視描述(例如 D3D10_TEX2D_ARRAY_DSV)來指定要存取的子資源。
這些數字會說明檢視描述在存取紋理陣列時使用的詞彙。
陣列配量
假設有一個紋理陣列,當中的每個紋理都具備 Mipmap,則紋理配量 (使用白色矩形表示) 會包含一個紋理及其所有子紋理,如下圖所示。
Mip 配量
Mip 配量 (使用白色矩形表示) 會在陣列中的每個紋理內包含一個 Mipmap 層級,如下圖所示。
選取單一子資源
您可以使用這兩個類型的配量來選擇單一子資源,如下圖所示。
選取多個子資源
或者,您可以使用這兩個類型的配量搭配 Mipmap 層級和/或紋理數量,以選擇多個子資源。
不論您使用何種紋理類型,無論使用或不使用mipmap,不論紋理陣列為何,都可以使用協助程式函式 D3D10CalcSubresource 來計算特定子資源的索引。
強式與弱式輸入
建立完全具類型資源,即可將資源限縮在當初建立時所使用的格式中。 這可讓運行時間優化存取,特別是如果資源是使用旗標來建立,表示應用程式無法 對應 它。 使用特定類型建立的資源,將無法使用檢視機制來重新解譯。
在較少類型的資源中,第一次建立資源時,數據類型是未知的。 應用程式必須從可用的類型中選擇較少格式(請參閱 DXGI_FORMAT)。 您必須指定要配置的記憶體大小,以及執行階段是否需要在 Mipmap 中產生子紋理。 不過,在資源繫結至具有檢視的管線前,將不會判斷確切的資料格式 (無論記憶體是否將解譯為整數、浮點值、不帶正負號的整數等)。 由於紋理格式會保有彈性,直到紋理繫結至管線為止,因此,資源會稱為弱式具類型儲存。 弱勢具類型儲存的優勢在於:只要新格式的元件位元與舊格式的位元計數相符,就可重複使用或重新解譯 (使用其他格式)。
只要每個館現階段都有唯一的檢視,以完全符合每個位置的格式,單一資源就能繫結至多個管線階段。 例如,使用格式建立的資源DXGI_FORMAT_R32G32B32A32_TYPELESS可以同時作為管線中不同位置的DXGI_FORMAT_R32G32B32A32_FLOAT和DXGI_FORMAT_R32G32B32A32_UINT。
相關主題