通常,需要渲染的像素比頂點數多,而頂點數又比物體數多很多。所以如果可以,盡量將運算從 FS 移到 VS,或直接通過 script 來設置某些固定值;
在使用Surface Shader時,可以通過一些指令讓shader優化很多。
通常情況下,Surface shader的很多默認選項都是開啟的,以適應大多數情況,但是很多時候,你可以關閉其中的一些選項,從而讓你的shader運行的更快: (1) apPRoxview 對于使用了 view direction 的shader,該選項會讓 view dir 的 normalize 操作 per-vertex 進行,而不是 per-pixel。這個優化通常效果明顯。 (2) halfasview 可以讓Specular shader變得快一些,使用一個介于光照方向和觀察方向之間的 half vector 來代替真正的觀察方向 viewDir 來計算光照函數。 (3) noforwardadd Forward Rende r時,完全只支持一盞方向光的 per-pixel 渲染,其余的光照全部按照 per-vertex 或 SH 渲染。這樣可以確保shader在一個pass里渲染完成。 (4) noambient 禁掉 ambient lighting 和 SH lighting,可以讓 shader 快一點兒。在移動設備上,Color Mask 也是非常昂貴的,所以盡量別使用它,除非真的是需要。
x = tex.Load();if(x == 5){ // Thread 1 & 2 使用這個路徑 out.Color = float4(1, 1, 1, 1); }else{ // Thread 3 & 4 使用這個路徑 out.Color = float4(0, 0, 0, 0);}比如在上例中,兩個分支的語句Shader Unit都會執行,只是不同的是如果在執行if分支,那么計算結果將不會寫入到thread 3 和 4的存儲中(無副作用)。這樣做就相當于運算量增加了不少,這是動態分支的主要成本。但是如果所有的線程,都走的是同一分支,那么另外一個分支就不用走了。這個時候Shader Unit也不會去傻逼一樣的執行另外一個根本不需要執行的分支。此時性能的損失也不多。并且,在實際的Shader中,除非特殊情況,大部分Warp內的線程,即便在動態分支的情況下,也多半走的是同一分支。4. 動態分支和代碼優化難度有相關性
這一點經常被忽視,就是有動態分支的代碼,因為沒準你要讀寫點什么,前后還可能有依賴,往往也難以被優化。比如說你非要鬧這樣的語句出來:if(x == 1){ color = tex1.Load(coord);}else if(x == 2){ color = tex2.Load(coord);}...你說編譯器怎么給你優化。說句題外話,為啥要有TextureArray呢?也是為了這個場合。TextureArray除了紋理不一樣,無論格式、大小、坐標、LoD、偏移,都可以是相同的。這樣甚至可以預見不同Texture Surface上取數據的內存延遲也是非常接近的。這樣有很多的操作都可以合并成SIMD,就比多個Texture分別來取快得多了。這就是一個通過增加了約束(紋理格式、大小、尋址坐標)把SISD優化成SIMD的例子。定位渲染通道瓶頸的方法
轉自:http://blog.csdn.net/rabbit729/article/details/6398343 一般來說, 定位渲染通道瓶頸的方法就是改變渲染通道每個步驟的工作量, 如果吞吐量也改變了, 那個步驟就是瓶頸.。找到了瓶頸就要想辦法消除瓶頸, 可以減少該步驟的工作量, 增加其他步驟的工作量。 一般在光柵化之前的瓶頸稱作”transform bound”, 三角形設置處理后的瓶頸稱作”fill bound”
定位瓶頸的辦法: 1. 改變幀緩沖或者渲染目標(Render Target)的顏色深度(16 到 32 位), 如果幀速改變了, 那么瓶頸應該在幀緩沖(RenderTarget)的填充率上。2. 否則試試改變貼圖大小和貼圖過濾設置, 如果幀速變了,那么瓶頸應該是在貼圖這里。3. 否則改變分辨率.如果幀速改變了, 那么改變一下pixel shader的指令數量, 如果幀速變了, 那么瓶頸應該就是pixel shader. 否則瓶頸就在光柵化過程中。4. 否則, 改變頂點格式的大小, 如果幀速改變了, 那么瓶頸應該在顯卡帶寬上。5. 如果以上都不是, 那么瓶頸就在CPU這一邊。
新聞熱點
疑難解答