OpenGL之渲染優化

2021-06-20 16:41:11 字數 2951 閱讀 6606

在過去的幾年裡,硬體加速流水線獲得了無與倫比的發展.同時也日愈複雜,它們的效能特徵越來越難以理解.以前改善效能只意味著減少用於渲染的cpu內迴圈週期,現在變成確定瓶頸與系統的處理它們.此時優化效能的的主導思想是,流水線的速度由最慢的乙個階段決定.本文中討論了現代顯示卡所存在的瓶頸之一,以及部分的解決辦法.

資料在主機板中的傳遞

cpu從ram中獲得資料並且處理資料,然後寫入ram中.gpu的工作方式類似於cpu,從vram中獲得資料處理資料,然後寫入vram中並在螢幕上顯示出來.

作為gpu流水線的第一步,系統通過agp或pci express匯流排把頂點和索引傳送到gpu或區域性楨緩衝記憶體中.雖然現在的agp bus比起讓pci bus來負責傳遞資料的確快了不少,但比起ram和cpu或vram與gpu之間的速度來講,仍顯不足.當資料傳輸的不即時而造成了cpu與gpu在等待中耗費時鐘或空轉的時候,就可以確定瓶頸出在bus之上.

一般的檢查方式是通過改變頂點格式大小,來確定得到資料是否成為了應用程式的瓶頸.

由於瓶頸出在硬體構架方式上,很難得到乙個真正意義上完美的解決方案.下面是幾個可以適當提公升效果的技巧.

減少資源鎖定,即盡量避免訪問渲染期間gpu正在使用的資源

最大化一次性傳入資料

從opengl簡單的來講就是避免使用glvertex之類,轉而使用gldrawarray,對資料集進行批次傳送.在這裡它的作用不僅僅只是優化資料傳遞頻寬需求,它更可以減少函式呼叫在系統當中的消耗(在某些系統下,消耗相當可觀).

同時使用紋理atlas方法.因為在不同的物體使用不同的紋理時,批發送往往被打破.通過把許多紋理安排進單個紋理當中,並適當的設定紋理座標,就能在單個繪畫呼叫中傳送使用多個紋理的幾何體.

減少頂點傳遞開銷

在頂點格式中使用適當的位,足夠就可以了.不需要對一切都使用浮點格式.使用索引的時候,用16位代替32位.因為它更容易查詢,移動起來更輕鬆並且占用更少的記憶體.

由於頂點資料可以在現代gpu中實現快取記憶體(下面將討論的方法),在任意的記憶體層次當中以相對連續的方式訪問頂點資料,引用的空間區域性性有助於最大化高速緩衝儲存器的命中率,減少對頻寬的要求.

頂點快取

相對於上述一些技巧性的優化,使用現代顯示卡所支援的這一特性可以更有效的減低對資料傳遞頻寬的需求.

由於opengl的實現特性,資料被儲存在系統記憶體裡.在渲染過程中每次需要使用被啟用的陣列時,資料就從記憶體傳輸到視訊記憶體.為了處理這種情況opengl1.5中引入了緩衝區物件,允許把資料儲存在vram中,並且只傳輸一次.

利用緩衝區物件儲存頂點資料分為以下幾個步驟.

①建立緩衝區物件.

void glgenbuffers(glsizei n, gluint * buffers);

該函式通過buffers返回n個未被使用的緩衝區表識符(u int).

glboolean glisbuffers(gluint buffer);

確定buffer是否為已經被繫結的緩衝區表識符.

②繫結緩衝區物件.

void glbindbuffer(glenum target, gluint buffer);

target為gl_array_buffer或gl_element_array_buffer之一.此函式有三種不同的行為模式.

當buffer首次使用時,就建立乙個緩衝區,並繫結buffer作為其表識符.當繫結到乙個以前建立的緩衝區時,這個緩衝區變成為當前活動的物件.當繫結buffer值為0時,停止使用緩衝區物件.

③使用頂點資料分配初始化緩衝區物件.

void glbufferdata(glenum target, glsizeiptr size,const glvoid * data,glenum usage);

target同上,size表示分配在視訊記憶體當中的儲存單位個數.data是乙個指向記憶體的指標,用於初始化緩衝區物件.usage提示資料在分配之後如何進行度取和寫入,根據所指定的值opengl實現可能會對其進行針對性的優化,它有以下幾種可能的值:

gl_stream_draw,gl_stream_read,gl_stream_copy,

gl_static_draw,gl_static_read,gl_staic_copy,

gl_dynamic_draw,gl_dynamic_read,gl_dynamic_copy.

draw-資料作為頂點資料,用於渲染.

read-資料從乙個opengl緩衝區(楨緩衝區之類的)讀取,並在程式中與渲染並不直接相關的各種計算過程中使用.copy-資料從乙個opengl緩衝區讀取,然後作為頂點資料,用於渲染.

stream-緩衝區的物件需要時常更新,但使用次數很少.

static-只需要一次指定緩衝區物件中的資料,但使用次數很多.

dynamic-資料不僅需要時常更新,使用次數也很多.

④更新緩衝區物件內的資料

更新資料有以下兩種方式:

void glbuffersubdata(glenum target,glintptr offset,glsizeiptr size,const glvoid * data);

target同上.由於頂點陣列資料的所有格式在緩衝區物件內同樣有效.所以頂點\顏色\法線等相關資料都可以放入緩衝區中,所以需要指定乙個offset作為緩衝區物件中資料的偏移量.size為起始下標.data 指向更新的資料.

另一種:

glvoid * glmapbuffer(glenum target,glenum access);

target同上.access為訪問資料的方式,可以為以下幾個值:gl_read_only,gl_write,gl_read_write.

這個函式直接獲得乙個指向被繫結緩衝區內資料的指標,通過給值的方式讀寫緩衝區物件.在讀寫完畢之後呼叫glboolean glunmapbuffer(glenum target);表示被繫結的緩衝區物件更新完成,並且可以釋放.

⑤清除緩衝區物件

void gldeletebuffers(glsizei n,const gluint * buffers);

刪除n個緩衝區物件,由buffer表識符陣列指定.

android動畫優化 Opengl渲染模式

在專案上碰到應用多個場景電流超標,經過分析是動畫導致的,主介面動畫是opengl實現的,而opengl有兩種渲染模式 連續不斷的渲染和被動渲染,應用的動畫直接是預設的連續不斷的渲染,這樣一來只要開啟了應用gpu就會一直渲染,從而造成了功耗偏高。優化的方式就是將動畫渲染模式更改為被動渲染 a.自動模式...

OpenGL之離屏渲染

off screen rendering意為離屏渲染,指的是gpu在當前螢幕緩衝區以外新開闢乙個緩衝區進行渲染操作 因為在幀緩衝區渲染乙個檢視到螢幕中就拋棄的機制.所以當我們有多組檢視需要組合隨後統一處理的時候.需要在屏緩衝區額外開闢乙個離屏的緩衝區去記錄這些檢視.隨後統一處理.最後渲染顯示出來 我...

OpenGL渲染管線之紋理(三)

概述 紋理時乙個2d 也可以是1d或者3d 用來讓圖形看起來更真實。是一種很簡單就能夠模擬真實的方法,因為如果不使用紋理,那麼我們就必須為所有細節構建頂點和圖形,這樣的開銷會非常大,有了紋理後,我們就只需要少很多的頂點,然後把紋理貼上去就可以了,及時有些不真實,但是也看不出來。紋理座標 紋理座標的原...