The
Direct3D 10 System
注:SIGGRAPH
2006即將在波士頓開幕,微軟也將發(fā)布DirectX10的相關(guān)資料。為此特地翻譯了源自微軟DirectX開發(fā)社區(qū)的一篇PDF文檔,“The
Direct3D 10
System”,原文地址為http://download.microsoft.com/download/f/2/d/f2d5ee2c-b7ba-4cd0-9686-b6508b5479a1/Direct3D10_web.pdf。原文的腳注有“ACM,
(2006). This is the author’s version of the work. It is posted
here by permission of ACM for your personal use. Not for
redistribution.”原文版權(quán)歸其作者以及相關(guān)組織所有,遵守ACM關(guān)于僅限個(gè)人使用,不得發(fā)布的條令。中文版由zhoubo22@hotmail.com翻譯,僅限個(gè)人學(xué)習(xí)之用。有刪節(jié)。
摘要:我們將向您展示第四代GPGPU的系統(tǒng)架構(gòu)。整套架構(gòu)新的特征將包括諸如,直接向內(nèi)存存取流式的Primitive數(shù)據(jù),統(tǒng)一頂點(diǎn)數(shù)據(jù)以及圖像數(shù)據(jù)資源的管理,以及新的存儲(chǔ)格式。我們也將向您說明一些在新的管線(Pipeline)設(shè)計(jì)中,所作的對(duì)API、Runtime、Shading
Language的一些改動(dòng)。
一、正文:
OpenGL
以及Direct3D的架構(gòu)已經(jīng)發(fā)展了好幾代。在過去五年中,技術(shù)的逐漸進(jìn)步推動(dòng)著處理模式由傳統(tǒng)的固定管線(Fixed
Function)向可編程管線過渡(Progammable
Pipeline)。在進(jìn)步過程中,實(shí)際上體現(xiàn)了設(shè)計(jì)者對(duì)通用性、性能、成本的綜合考慮。到目前為止我們已經(jīng)編寫了許多圖形加速的應(yīng)用程序,比如演示系統(tǒng),CAD,多媒體處理系統(tǒng)等等,以及游戲。這些程序無一例外的都需要管理數(shù)以G字節(jié)計(jì)算的數(shù)據(jù),比如幾何體頂點(diǎn)數(shù)據(jù)、紋理數(shù)據(jù)、動(dòng)畫數(shù)據(jù),以及處理圖形的程序,占用大量的系統(tǒng)資源,以人們可以接受的速率渲染逼真的圖形。在許多的系統(tǒng)設(shè)計(jì)中,我們都可以看到人們?nèi)绾斡行У慕鉀Q問題。如同舊版本的Direct3D一樣,Direct3D
10實(shí)際上是三方面工作的合作成果,硬件設(shè)計(jì)者,API/Runtime架構(gòu)者,以及應(yīng)用程序開發(fā)人員。參考了應(yīng)用程序開發(fā)者們反映的意見,我們把一些常見的問題進(jìn)行了整理:
-
狀態(tài)機(jī)切換代價(jià)太高(High
State-change
overhead)。改變?nèi)魏蔚臓顟B(tài),比如頂點(diǎn)格式、紋理格式、Shader參數(shù)、混合模式等,代價(jià)太高。為了盡量減少狀態(tài)的改變操作,需要我們對(duì)處理順序進(jìn)行排序,使用基于Shader的技術(shù),優(yōu)化整個(gè)程序的性能。比如,需要多重紋理貼圖時(shí),可以將幾個(gè)紋理合并到一個(gè)紋理上,然后通過對(duì)定點(diǎn)坐標(biāo)的處理,進(jìn)行多次的貼圖操作。
-
廠商之間定義的硬件加速功能過于混雜。有些時(shí)候應(yīng)用程序使用了一些專有廠商自己定義的特殊功能,導(dǎo)致無法在大部分的硬件上有效的運(yùn)行。
-
CPU
與GPU的同步問題。傳統(tǒng)結(jié)構(gòu)在管線中提取出新的數(shù)據(jù)是有次數(shù)限制的。比如渲染場景到紋理(Render
To
Texture)技術(shù),把場景拷貝出來作為紋理貼圖使用,CPU使用率并不高。盡管這樣,產(chǎn)生新的頂點(diǎn)數(shù)據(jù)或者創(chuàng)建立方體紋理依舊需要更多的坐標(biāo)數(shù)據(jù),以及GPU與CPU之間的同步,降低了效率。
-
指令的數(shù)目以及數(shù)據(jù)類型的限制。比如Vertex
Shader需要處理數(shù)據(jù)的精度,以及實(shí)現(xiàn)傳統(tǒng)的流程控制(Flow
Control)結(jié)構(gòu)。Pixel
Shader也一樣。但是無論是Vertex
Shader還是Pixel
Shader,處理整數(shù)的能力要遠(yuǎn)遠(yuǎn)強(qiáng)于處理浮點(diǎn)數(shù)據(jù)能力。應(yīng)用程序要么舍棄了這些代價(jià)太高的處理方法,要么以比如基于查招表的方式運(yùn)行。
-
資源限制。太多了,比如紋理單元(Texture
Unit)數(shù)目的限制,Shader指令數(shù)目的限制等等。所以現(xiàn)在很多程序都不得不盡量將算法簡化,或者使用多Shader的方法進(jìn)行處理。
二、背景
整個(gè)可編程GPU系統(tǒng)的發(fā)展可以分為四個(gè)階段,如下表:
-
Feature
|
1.1
2001
|
2.0
2002
|
3.0
2004
|
4.0
2006
|
Instruction
slot
|
128
|
|
≥512
|
≥64K
|
4+8
|
32+64
|
≥512
|
Constant
registers
|
≥96
|
≥256
|
≥256
|
16x4K
|
8
|
32
|
224
|
Tmp
registers
|
12
|
12
|
32
|
4K
|
2
|
12
|
32
|
Input
registers
|
16
|
16
|
16
|
16
|
4+2
|
8+2
|
10
|
32
|
Render
targets
|
1
|
4
|
4
|
8
|
Samplers
|
8
|
16
|
16
|
16
|
textures
|
|
|
4
|
128
|
8
|
16
|
16
|
2D
texture size
|
|
|
2Kx2K
|
8Kx8K
|
Integer
ops
|
|
|
|
√
|
Load
op
|
|
|
|
√
|
Sample
offsets
|
|
|
|
√
|
Transcendental
ops
|
√
|
√
|
√
|
√
|
|
√
|
√
|
Derivative
op
|
|
|
√
|
√
|
Flow
control
|
|
Static
|
Static/dynamic
|
dynamic
|
硬件實(shí)現(xiàn)實(shí)現(xiàn)了數(shù)據(jù)從Vertex
Shader到Pixel
Shader的高速處理。多Vertex
Shaders和Pixel
Shaders可以用來并行的處理獨(dú)立的頂點(diǎn)以及像素。一般來說GPU的像素處理單元要遠(yuǎn)多于頂點(diǎn)處理單元,因?yàn)樵趯?shí)際情況中需要處理的像素總是要比頂點(diǎn)多得多。
在OpenGL與Direct3D中,可編程處理管線使用低等級(jí)的抽象層與硬件交互。這個(gè)抽象層對(duì)于程序來說是完全透明的,隱藏了各種底層的實(shí)現(xiàn)。而其它平臺(tái),比如工作站,和PC平臺(tái)就完全不同,直接由硬件實(shí)現(xiàn)一切,硬件所有的特性都是向外暴露的。
早期由于硬件的限制,為了精簡指令數(shù),不得不采用匯編語言進(jìn)行編碼。如今隨著硬件的發(fā)展,處理程序的編寫完全可以使用高等級(jí)語言實(shí)現(xiàn),比如C-like的語言進(jìn)行編寫——而且,熟悉C語言的開發(fā)人員非常多??墒?,當(dāng)GPU編程語言等級(jí)提高了之后,又產(chǎn)生了一些問題,比如,硬件的編譯模型更像虛擬機(jī),Shader匯編語言比起機(jī)器語言跨平臺(tái)的特性更好。HLSL語言可以被預(yù)編譯,等到運(yùn)行時(shí)再被GPU驅(qū)動(dòng)翻譯成機(jī)器語言執(zhí)行。GLSL語言則不同,它是在運(yùn)行的時(shí)候從源代碼直接翻譯成機(jī)器語言執(zhí)行。
三、管線
Direct3D
10
依舊保留了傳統(tǒng)的硬件加速管線,不過增加了2個(gè)新的流程。如圖所示:
Input
Assembler
(IA)將從輸入流(Input
Stream)中將所有的1D頂點(diǎn)數(shù)據(jù)轉(zhuǎn)換為浮點(diǎn)格式(float32)。每一個(gè)流對(duì)象指定了一個(gè)頂點(diǎn)結(jié)構(gòu),最多包含16個(gè)頂點(diǎn)緩沖結(jié)構(gòu)。一般來說GPU按照頂點(diǎn)的輸入順序處理,必要時(shí)應(yīng)該使用索引緩沖(Index
Buffer)提高性能。IA也支持對(duì)物體進(jìn)行快速復(fù)制,類似于實(shí)例繪制(Instancing)技術(shù),不過更有效率。
Vertex
Shader
(VS)一般用來做空間變換。VS讀取一個(gè)頂點(diǎn),輸出一個(gè)頂點(diǎn)。VS可以和其他的Shader分享數(shù)據(jù),允許訪問多達(dá)128個(gè)紋理,以及16個(gè)內(nèi)部緩沖。更多的內(nèi)容請(qǐng)看第4節(jié)。
Geometry
Shader
(GS)讀取Primitive中的頂點(diǎn),輸出定點(diǎn)或者Primitive??奢斎胼敵龅?font face="Times New Roman, serif">Primitive可是是不同類型的,但它們對(duì)于Shader來說都是一樣的。GS程序可以在輸入的Primitive中插入新的頂點(diǎn),產(chǎn)生新的Primitive,進(jìn)而產(chǎn)生新的幾何結(jié)構(gòu),也可以剔除輸入的Primitive。
Stream
Output
(SO)的作用是將GS輸出的數(shù)據(jù)拷貝到輸出緩沖。可是由于硬件的限制,SO只可以實(shí)現(xiàn)1個(gè)最多包含16個(gè)Elements的Multi-Element的輸出流,或者是4個(gè)single-element輸出流。IA支持8bit以及16bit數(shù)據(jù)的讀取,轉(zhuǎn)換成float32格式,SO只能寫入32bit格式的數(shù)據(jù)。在GS可以方便的實(shí)現(xiàn)數(shù)據(jù)格式的轉(zhuǎn)換以及Packing。
Set-up
and Rasterization Stage
(RS)執(zhí)行諸如Clipping、Perspective
divide、viewport
transform、primitive
set-up、Scissoring、depth
offset、fragment
generation(不好意思沒有翻譯)。GPU的設(shè)計(jì)中一般都有Early
Depth處理。RS負(fù)責(zé)處理頂點(diǎn),Primitive的Attributes,輸出光柵化處理后的像素。
Pixel
Shader
(PS)讀取Pixel
Fragment的attribute,輸出最多包含8個(gè)attribute的Fragment。Attribute值被寫入不同的色彩緩沖,如果不符合輸出條件則丟棄(discard)這個(gè)像素。一般Depth以及Stencil值在RS中已經(jīng)被計(jì)算好。雖然說在PS中依舊可以進(jìn)行Depth的計(jì)算以及重新寫入,不過為了優(yōu)化請(qǐng)盡量在RS中進(jìn)行這些運(yùn)算。Stencil值不可以被改寫。
Out
Merger
(OM)讀取PS處理過的像素,進(jìn)行傳統(tǒng)的Stencil測(cè)試和Depth測(cè)試,以及Alpha混合。OM綁定了一個(gè)Depth/Stencil緩沖,以及最多8個(gè)Attribute緩沖。PS必須向每個(gè)渲染目標(biāo)都輸出值。當(dāng)在所有渲染目標(biāo)之間使用同一個(gè)混合函數(shù)的時(shí)候,您可以分別設(shè)置各個(gè)渲染目標(biāo)是否啟用或者禁用混合。
內(nèi)存結(jié)構(gòu)與數(shù)據(jù)Flow
GPU
需要處理大量儲(chǔ)存在諸如頂點(diǎn)緩沖、索引緩沖、紋理單元里的數(shù)據(jù)。GPU一般將數(shù)據(jù)儲(chǔ)存在自己的高速顯存中。這些數(shù)據(jù)包括1/2/3D的紋理貼圖,1D的索引以及頂點(diǎn)數(shù)據(jù)等等。在Direct3D
10中把所有的這些都統(tǒng)統(tǒng)稱為資源(resources),目的是為了提高處理效率。因?yàn)樘岣咝薀o非有兩個(gè)方法,在單通道里盡量做最多的事情,或者單通道里創(chuàng)建了Resources后在多通道里復(fù)用。
幾種Resources可以提高單通道渲染的效率。Arrayed
Resources。紋理貼圖,以及渲染目標(biāo)可以被當(dāng)作線性數(shù)組(Linear
Arrays)綁定到一個(gè)渲染通道中。Shader里用來取得紋理索引的指令被擴(kuò)展為Computed
Array
Index?,F(xiàn)在有不少的開發(fā)人員為了效率將一些紋理放到一張大的紋理上,渲染時(shí)通過紋理坐標(biāo)分割紋理。這種改變可能會(huì)給他們帶來一些壓力。當(dāng)然,Texture
Arrays不需要考慮這種特殊情況,因?yàn)樗菫榱颂幚泶罅砍叽缦嗤募y理而設(shè)計(jì)的。
當(dāng)一個(gè)渲染目標(biāo)數(shù)組(Array
of Render
Targets)綁定到OM時(shí),GS處理時(shí)可以對(duì)Primitive進(jìn)行排序或者復(fù)制。比如,當(dāng)在單通道中渲染場景生成立方體貼圖時(shí),可以把它當(dāng)作一個(gè)包括6個(gè)2D渲染目標(biāo)的數(shù)組。(Array
of 6 2D
Textures)。當(dāng)對(duì)物體進(jìn)行立方體貼圖時(shí),GS將決定使用哪一個(gè)面的像素進(jìn)行貼圖。需要了解的是,GS處理渲染目標(biāo)數(shù)組與PS的多渲染目標(biāo)輸出之間是獨(dú)立的進(jìn)行的。
為了使用渲染場景到紋理(Render
to cube
map)功能以及為了更加方便的使用數(shù)組,添加了一個(gè)新的概念——View。編碼時(shí),不需要制定資源,不需要額外的輔助參數(shù),Direct3D
10允許創(chuàng)建資源時(shí),不需要指定類型,比如究竟是float16還是snorm16,所以可能會(huì)發(fā)生非常有限的類型隱式轉(zhuǎn)換,只有相同大小的類型可以轉(zhuǎn)換,其余的不可以,比如2個(gè)float16數(shù)字絕對(duì)不可以當(dāng)作1個(gè)float32數(shù)字。資源也無法直接用于管線處理,它們必須通過View綁定。
流輸出對(duì)象特別適合處理連續(xù)的1D數(shù)據(jù)比如頂點(diǎn)坐標(biāo)等,優(yōu)點(diǎn)包括,可以支持輸出非常多的數(shù)據(jù)類型。流對(duì)象支持不支持對(duì)輸出數(shù)據(jù)進(jìn)行隨機(jī)訪問。如果有需要在VS里可以做足夠的處理。
Shader
里操作的數(shù)據(jù)是32bit的(無論是浮點(diǎn)數(shù)還是整數(shù))。此時(shí)就需要提供更加豐富的數(shù)據(jù)類型,減少內(nèi)存占用以及帶寬。數(shù)據(jù)會(huì)被自動(dòng)對(duì)齊為整數(shù)的大?。?font face="Times New Roman, serif">32bit)。幾乎所有的數(shù)據(jù)類型都可以作為頂點(diǎn)數(shù)據(jù)、紋理數(shù)據(jù),作為流輸出,以及渲染目標(biāo)。如下表:
-
Name
|
Widths
|
Range
|
UnormN,snormN
|
8,16
|
[0,1]
and [-1,1]
|
FloatN
|
32,16,11,10
|
S32e8,s10e5,6e5,5e5
|
UintN,sintN
|
8,16,32
|
[0,2^n-1]
and [-2^n-1,-2^n-1]
|
RGBE
|
32
|
999e5
|
SRGB
|
8
|
[0,1]
no-linear
|
unorm
、snorm以及半浮點(diǎn)數(shù)是用的最多的格式。比如在需要HDR的程序中,半浮點(diǎn)數(shù)可以提供最好的精度以及最合理的帶寬占用,而且硬件也支持豐富的過濾操作。DirectX10里面的32bit數(shù)字有兩種格式,第一種是,RG通道各占11bit,B占10bit,剩下1bit存儲(chǔ)共享的指數(shù);第二種,RGB各占9bit,5bit儲(chǔ)存指數(shù)。這兩種格式都能夠達(dá)到float16格式的精度。其中,低精度的11-11-10格式適合用來儲(chǔ)存HDR色彩數(shù)據(jù)。當(dāng)然Direct3D
10依舊支持低動(dòng)態(tài)范圍的壓縮紋理格式。
設(shè)計(jì)考慮
對(duì)比以前的架構(gòu),Direct3D
10要求所有的Features都由硬件來實(shí)現(xiàn)。目前問題有兩個(gè),硬件需要支持32bit紋理過濾以及渲染目標(biāo)的多重采樣以及反鋸齒。所有的可編程結(jié)構(gòu)可以模擬的固定管線處理功能,都將從核心以及API中去處,包括光照,矩陣變換,Alpha混合。固定處理管線可以很容易的用軟件模擬。不過一些較重要的傳統(tǒng)處理管線依舊保留。我們?cè)O(shè)計(jì)曾經(jīng)考慮過把IA設(shè)計(jì)成完全可編程的,但是無法證明一切會(huì)變得更加的簡單還是復(fù)雜,而在VS里可以計(jì)算。事實(shí)上,VS可以不需要進(jìn)行任何的內(nèi)存讀取操作,直接從IA中讀取數(shù)據(jù)計(jì)算。話雖如此,為了性能我們依舊保留了一些IA的復(fù)雜特征,這樣可以完全發(fā)揮可編程的優(yōu)勢(shì),在處理頂點(diǎn)時(shí)硬件可以達(dá)到最高的效率。
Gs
的設(shè)計(jì)更為復(fù)雜。GS可以進(jìn)行并行處理,保存數(shù)據(jù)(類似于Primitive)的輸入順序,這樣有多個(gè)GS單元處理數(shù)據(jù)時(shí)不會(huì)發(fā)生順序的錯(cuò)誤。這種并行的設(shè)計(jì)要求必須有一個(gè)輸出緩沖,而且數(shù)據(jù)的順序必須同輸入的數(shù)據(jù)相同。讓GS盡可能的多的代替RS的工作,比如Viewport變換等。GS可以做一部分Clipping,比如計(jì)算頂點(diǎn)到Clip-Plane的距離,把Clip-Space空間中的坐標(biāo)傳遞到RS。RS采用的依舊是傳統(tǒng)處理管線,對(duì)比GS來說精度不高,所以不可能讓GS模擬RS生成Image-Space坐標(biāo)。Om也是經(jīng)常被討論的部分。OM是整個(gè)管線中唯一可以進(jìn)行內(nèi)存讀寫的部分,也經(jīng)常被要求設(shè)計(jì)成可編程單元。不過這樣一來管線的復(fù)雜度就大大的提高,而且內(nèi)存系統(tǒng)的效率也會(huì)打折扣。曾經(jīng)提過是否可以把OM結(jié)合到PS中,可是如果這樣,多重采樣以及混合操作就會(huì)變得非常的復(fù)雜(因?yàn)?font face="Times New Roman, serif">PS不可以獲得Fragment內(nèi)存地址),而且Early
Depth/Stencil已經(jīng)可以顯著的提高性能。
Shader
Model 4
在以前版本的Direct3D中,可編程管線單元(VS
PS)是用一個(gè)特殊的虛擬機(jī)實(shí)現(xiàn)的。每個(gè)虛擬機(jī)使用馮諾伊曼架構(gòu),類似于匯編語言的指令集,擁有輸入輸出寄存器,堆棧,以及可以獲取內(nèi)存資源的Binding
Points。Direct3D
10為每個(gè)可編程管線單元定義了一個(gè)“Common
Core”,新增加了以下內(nèi)容:
-
32bit
整數(shù)指令,算術(shù)運(yùn)算,Bitwise計(jì)算,Conversion計(jì)算。
-
可尋址的(Indexable)通用寄存器,大小為4096x4
-
分開執(zhí)行Unfiltered指令與filtered內(nèi)存讀取指令(讀取以及采樣指令)
-
支持Shadow
Map采樣
-
16
個(gè)Constant(parameter)緩沖
4096x4
-
減少Texture
Bind Points(128),和Sampler
State(16)
這個(gè)統(tǒng)一模型(Unified
Model)代替CPU執(zhí)行所有的算術(shù)運(yùn)算、邏輯運(yùn)算、以及Flow
Control。資源(Resource)比如寄存器、Texture
Bind
Points,以及指令存儲(chǔ)器等等這些不應(yīng)該是軟件開發(fā)人員頭痛的問題,接下來的幾年,硬件廠商會(huì)自己對(duì)產(chǎn)品進(jìn)行性能與成本的折中。Texture
Bind Point數(shù)目的提高顯然不會(huì)對(duì)Texture
Filtering
Combinations有太多的要求。加大Constant存儲(chǔ)空間與更新Constant的效率之間的沖突不可避免。目前的系統(tǒng)一個(gè)明顯的問題就是用一般的更新操作更新Constant值效率不高,而如果程序使用了多個(gè)Shader那么效率會(huì)更加低。在實(shí)際情況中Group
Of
Constant更新的頻率并不相同,有時(shí)是每幀,或者每個(gè)物體,或者每個(gè)實(shí)例。由此我們把Constant分開存儲(chǔ)到不同的緩沖中,分開進(jìn)行操作。而Constants訪問的頻率遠(yuǎn)遠(yuǎn)高于紋理,Constants一般使用uniform索引,而紋理一般使用紋理坐標(biāo)。這也要求硬件設(shè)計(jì)者把Constant與紋理進(jìn)行分離。同時(shí)我們也提高了浮點(diǎn)數(shù)的精確度,對(duì)比IEEE754的0.5ulp,我們達(dá)到了1.0ulp。在進(jìn)行平方開放運(yùn)行時(shí),精度可以達(dá)到2.0ulp。
核心API與Runtime
核心API與Runtime作為一個(gè)瘦抽象層(Thin
Abstract
Layer)工作于硬件上,對(duì)上層的操作進(jìn)行解釋。API與Runtime負(fù)責(zé)處理內(nèi)存資源,建立View、Shaders,綁定到管線上,以及初始化渲染,提供硬件查詢等等。我們希望提高命令執(zhí)行的效率,把命令分為兩類。一類是處理資源的命令,一類是操作管線的命令。Runtime先初始化一個(gè)緩沖,API命令對(duì)緩沖執(zhí)行各種操作,等到緩沖已滿或者需要同步的時(shí)候把緩沖上傳到GPU中,比如當(dāng)回讀渲染目標(biāo)的時(shí)候。Runtime模型在PC系統(tǒng)上發(fā)展了十幾年,我們的目標(biāo)是提高命令的效率,當(dāng)命令執(zhí)行時(shí)不需要額外的處理。過去這是不可能實(shí)現(xiàn)的需求,不過我們改進(jìn)了一些設(shè)計(jì),讓這個(gè)目標(biāo)離我們更加近。其中有一些關(guān)鍵原因:
-
API
與硬件之間不兼容
-
處理延遲
-
應(yīng)用程序的真正需要
第一個(gè)問題已經(jīng)被輕松的解決,這樣在應(yīng)用程序開發(fā)者,Runtime,驅(qū)動(dòng)程序,以及硬件提供者之間,不敢說從此100%的兼容,最起碼能夠滿足不是那么苛刻的要求(壟斷加大棒)。第二個(gè)問題經(jīng)常碰到,尤其是需要做許多處理的時(shí)候。不過這樣的好處是,各個(gè)處理過程之間互不干擾是正交的。可是,這給CPU帶來了許多負(fù)擔(dān),比如當(dāng)紋理綁定發(fā)生更改時(shí)需要重新編譯Shader以符合新的紋理格式。我們希望盡可能多的消除硬件中內(nèi)在關(guān)聯(lián)的狀態(tài)操作,同時(shí)在運(yùn)行期把這些操作歸入Optional
Layer進(jìn)行單獨(dú)的操作。狀態(tài)機(jī)機(jī)制也發(fā)生了改變。在OpenGL與以前的Direct3D軟件的顆粒度非常令人滿意,比如改變混合方式的操作,樣本過濾操作等。為了提高效率可以使用OpenGL的Display
List或者是Direct3D的State
Block。我們當(dāng)然希望更加的優(yōu)化,提高效率。于是減少了不少固定處理管線。我們的研究發(fā)現(xiàn)現(xiàn)有的狀態(tài)機(jī)結(jié)構(gòu)模型無法再進(jìn)行效率的提高,所以我們把一些相關(guān)聯(lián)Functions組成一個(gè)固定集合,稱為State
Object。Direct3D
10定義了5個(gè)State
Object:InputLayer(Vertex
Buffer
Layout),Sampler,Rasterizer,DepthStencil,以及Blend。當(dāng)構(gòu)造這些對(duì)象的事后,驅(qū)動(dòng)程序先在寄存器中初始化硬件操作需要的數(shù)值。當(dāng)對(duì)象綁定到管線的時(shí)候,所有的數(shù)值被拷貝到命令緩沖里(Command
Buffer),在硬件本地提供命令以及操作。還有一些難題還無法避免,比如上面說過的Constant問題,還有比如切換資源的讀寫狀態(tài)。這需要應(yīng)用程序自己進(jìn)行優(yōu)化。
一些API的設(shè)計(jì)為了執(zhí)行期的效率沒有考慮容錯(cuò),或者只為頻繁使用的API提供容錯(cuò)。對(duì)比運(yùn)行期的錯(cuò)誤處理機(jī)制,我們更青睞在程序開發(fā)時(shí)就進(jìn)行錯(cuò)誤處理。首先我們把出現(xiàn)的錯(cuò)誤分為兩類,致命的(Critical)和非致命(Non
Critical)。運(yùn)行期時(shí)一定會(huì)報(bào)告致命的錯(cuò)誤,而非致命的錯(cuò)誤會(huì)被一個(gè)特殊的攔截層攔截。開發(fā)調(diào)試時(shí)主要使用Validation
Layer。即使如此,也不能全指望API自己的容錯(cuò)機(jī)制,驅(qū)動(dòng)程序也應(yīng)該阻止一些可能發(fā)生硬件損壞的操作。我們的目的是在渲染期間盡量不發(fā)生錯(cuò)誤,也就是說,錯(cuò)誤檢測(cè)不應(yīng)該在渲染期間執(zhí)行。致命的錯(cuò)誤包括Depth
Buffer與渲染目標(biāo)之間尺寸不符合,Shader編譯錯(cuò)誤等等。
CPU
與GPU之間共享資源也是討論已久的問題。比如,OpenGL與Direct3D都允許先在程序自己的內(nèi)存地址里創(chuàng)建一個(gè)頂點(diǎn)緩沖,然后全部上傳到顯卡中。雖然說性能有了很大的提高,但是帶寬的差距依舊非常巨大,顯卡與高速顯存只見的帶寬能夠達(dá)到50GB/s,而PCI-E總線最多只能在GPU與系統(tǒng)內(nèi)存之間實(shí)現(xiàn)2.8G/s的帶寬。即使如此,由于CPU與GPU處理的數(shù)據(jù)格式并不相同,而且數(shù)據(jù)儲(chǔ)存的格式也并不相同,所以只能期望應(yīng)用程序自己進(jìn)行性能的優(yōu)化。傳統(tǒng)意義里,GPU一般是資源的Writer,而CPU一般是Reader。為了優(yōu)化性能,需要明確的知道,那些讀取哪些資源,寫入哪些資源。幸運(yùn)的是開發(fā)人員一般都知道這一點(diǎn)。比如,渲染目標(biāo)以及紋理一般是GPU的讀取資源,限制寫入操作??蓪?duì)于頂點(diǎn)緩沖的就有了難題,因?yàn)?font face="Times New Roman, serif">GPU讀取的是靜態(tài)的網(wǎng)格,而一般由CPU進(jìn)行動(dòng)畫的計(jì)算,生成動(dòng)態(tài)的網(wǎng)格,然后在傳入GPU。這樣一來,在CPU與
GPU之間的讀寫操作就非常頻繁,占用可憐的帶寬。Direct3D
10把資源(Resource)4類:Default,Immutable,Dynamic,Staging。Default資源包括簡單的紋理,渲染目標(biāo),靜態(tài)的頂點(diǎn)緩沖,一般通過Copy操作生成。而Immutable資源不允許事先通過Copy生成,但是提供了其他的生成方式。Default與Immutable資源不能被CPU訪問。Dynamic資源可以被綁定到管線,與CPU寫操作進(jìn)行映射。比如讓CPU進(jìn)行動(dòng)畫的計(jì)算,視頻解碼等等,直接寫入Dynamic資源。Staging資源允許CPU映射,但是可以互相進(jìn)行拷貝操作。
我們也對(duì)HLSL語言進(jìn)行了改進(jìn),把底層實(shí)現(xiàn)封裝,開發(fā)人員無須了解底層虛擬機(jī)細(xì)節(jié)就可以進(jìn)行開發(fā)。特性如下:
-
無須顯式進(jìn)行任何資源的賦值操作。
-
Bind-by-Position
代替了Bind-by-name
-
盡量讓開發(fā)人員使用高級(jí)語言
開發(fā)人員一般使用在多個(gè)Shader里傳遞數(shù)值的方式進(jìn)行通信。當(dāng)有了多Multiple
Constant Buffers后,我們相信編譯器會(huì)更加對(duì)單緩沖操作進(jìn)行更好的優(yōu)化,但是開發(fā)人員依舊需要制定要寫入的Constant
Buffer。第二個(gè)變化是非常巨大的,與以前的發(fā)展發(fā)展方向完全不同。這主要是為了性能和未來的發(fā)展考慮。Shader里對(duì)輸入輸出變量的聲明更類似于C語言的原型(這一點(diǎn)GLSL已經(jīng)體現(xiàn)出來)。兼容性,在這里的意義是輸入與輸入的數(shù)據(jù)類型要完全符合。Bind-by-position也用在了頂點(diǎn)緩沖對(duì)IA與SO的邦定上。盡管這樣在這些處理階段我們還是定義了特殊的Objects,以便在運(yùn)行期執(zhí)行昂貴的Matching操作。第三項(xiàng)也是和開發(fā)密切相關(guān)的,這要求我們?cè)谛碌膶?shí)現(xiàn)中不再提供Intermediate語言的支持。我們發(fā)現(xiàn)即使非常優(yōu)化的代碼,編譯器為IL產(chǎn)生的機(jī)器碼效率低于其他單元的機(jī)器碼。而且當(dāng)與驅(qū)動(dòng)程序結(jié)合起來的時(shí)候,我們將不可能只對(duì)一個(gè)IL單元進(jìn)行額外的優(yōu)化。系統(tǒng)可以通過編譯器把IL處理過的數(shù)據(jù)作為調(diào)試信息輸出,不過不允許程序開發(fā)者在運(yùn)行期進(jìn)行對(duì)編譯器的輸出做任何更改。誰都希望編譯產(chǎn)生的代碼是最最優(yōu)化的,可是這也帶來的許多問題。最重要的是驅(qū)動(dòng)程序究竟能為IL產(chǎn)生多么優(yōu)化的機(jī)器碼。Shader復(fù)雜度提高要求開發(fā)人員自己對(duì)算法、執(zhí)行順序進(jìn)行優(yōu)化。而且,編譯關(guān)鍵部分的代碼,結(jié)果一定要相同,這樣當(dāng)使用多通道算法的時(shí)候才能產(chǎn)生相同的中間值(Intermediate),在各個(gè)Shaders之間進(jìn)行復(fù)制操作。我們考慮了一些實(shí)現(xiàn)方式,比如當(dāng)它們需要內(nèi)聯(lián)的時(shí)候,子程序被編譯為相同的碼。同時(shí)也不能忽視驅(qū)動(dòng)程序的編譯器,那也是性能優(yōu)化的關(guān)鍵。需要注意的是,我們提倡的使用模型是預(yù)先編譯好HLSL代碼,等到執(zhí)行的時(shí)候由驅(qū)動(dòng)程序編譯為機(jī)器碼,系統(tǒng)當(dāng)然也支持運(yùn)行期的動(dòng)態(tài)編譯與執(zhí)行。
我們同時(shí)也注意到,可編程管線的價(jià)值不僅僅在于Shader
Program,也應(yīng)該動(dòng)態(tài)支持的特效實(shí)現(xiàn)比如CgFX。由此,產(chǎn)生了HLSL-FX
10。FX系統(tǒng)要考慮問題是,開發(fā)人員如何使用,以及如何提高效率。應(yīng)用了FX系統(tǒng)后,如何有效地進(jìn)行狀態(tài)處理又成為了討論的主題。為了最好的性能最好的辦法依舊是只使用一個(gè)效果,渲染好所有的物體。Effect,其實(shí)是就是一系列操作的集合。為了性能效率,程序最好一次性渲染好使用同一個(gè)效果的物體。在真實(shí)的場景中,Effect只是一個(gè)環(huán)節(jié),其余還有諸如View
Position處理,紋理貼圖等等其他操作,而且,不可能總是根據(jù)Effect渲染場景,還需要考慮諸如距離,透明狀態(tài)等等。
系統(tǒng)體驗(yàn)
整個(gè)工程從2003年開始API的設(shè)計(jì),以及硬件的設(shè)計(jì),2006年公布。2004年開始測(cè)試軟件,公開于2005年。測(cè)試數(shù)據(jù)如下,不過都是舊的,因?yàn)檎嬲细竦臏y(cè)試環(huán)境還沒有。
Operation
|
Direct3D
9
|
Direct3D
10 (reference)
|
Draw
|
1470
|
154
|
Bind
VS Shader
|
6636
|
416
|
Set
Constant
|
3297
|
916
|
Set
Blend Function
|
787
|
530
|
在開發(fā)過程中,我們寫了許多關(guān)于GS,SO等的DEMO程序。包括Soft
shadow volume,Procedural
content generation,High
Order normal interpolation,motion
blur等。開發(fā)人員也在進(jìn)行程序的移植,從DirectX9過渡到DirectX10,同時(shí)我們正在與外部的開發(fā)人員使用新的API從頭開始編寫程序,估計(jì)過幾年將會(huì)出現(xiàn)完全使用DirectX10的程序。
總結(jié)
我們正在總結(jié)開發(fā)設(shè)計(jì)經(jīng)驗(yàn),等到Direct3D10真正發(fā)布的時(shí)候?qū)?font face="Times New Roman, serif">API進(jìn)行一些改動(dòng)升級(jí)。軟件一直在發(fā)展,可是硬件的發(fā)展卻很緩慢。這些都是在升級(jí)時(shí)需要考慮的。長遠(yuǎn)的,我們依舊在探討管線結(jié)構(gòu)與編程模型。系統(tǒng)的瓶頸依然在如何有效的進(jìn)行處理,硬件的發(fā)展是關(guān)鍵。比如傳統(tǒng)的過程紋理以及表面的處理,已經(jīng)即將被位移映射等新技術(shù)代替。我們相信,隨著以后的硬件軟件的發(fā)展將會(huì)在整體上超越目前的系統(tǒng)。
posted on 2006-08-01 22:14
周波 閱讀(631)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
無庸技術(shù)