謝曉燕, 耿玉榮, 楊博文,韓孟橋
(西安郵電大學(xué) a. 計算機學(xué)院; b. 電子工程學(xué)院, 西安 710121)
隨著圖形計算機產(chǎn)業(yè)領(lǐng)域的快速發(fā)展,相關(guān)圖形應(yīng)用編程接口(Application Programmig Interface, API)類型在不斷更新。傳統(tǒng)的圖形應(yīng)用程序開發(fā)是基于一定的圖形API在其專用圖形處理器上實現(xiàn)加速渲染[1-2]。但是這種“一對一”的操作會給圖像應(yīng)用場景的復(fù)雜度和高清化帶來一定的局限性。因此,開發(fā)一種可兼容多種API類型的圖形庫正在形成一種趨勢,以此滿足更高效和更靈活的圖形處理器需求[3]。
與圖形處理器配套的圖形API庫有很多,如應(yīng)用在移動設(shè)備上的OpenVG[4]和OpenGL ES[5]。OpenVG主要面向高質(zhì)量2D矢量圖形算法加速技術(shù)的便攜手持設(shè)備,具有更好的圖形渲染效果和更高的圖形場景復(fù)雜度[6-7]。但由于OpenVG圖形渲染的局限性,致使其無法完成OpenGL ES的3D渲染功能。OpenGL ES是OpenGL三維圖形API的子集,可以實現(xiàn)基于三角形圖元的3D圖形渲染,主要針對手機、PDA和游戲主機等嵌入式設(shè)備而設(shè)計的[8-9]。為了使應(yīng)用場景中支持二維矢量圖形和三維圖形的渲染實現(xiàn),科研人員進行了相關(guān)的研究。如文獻[10]中介紹了在OpenGL ES 1.x硬件加速器上實現(xiàn)對OpenVG 1.0的渲染加速。此設(shè)計充分利用了當(dāng)前嵌入式系統(tǒng)中的OpenGL ES 1.x硬件加速器,在不需要額外增加OpenVG 1.0硬件加速設(shè)備的前提下實現(xiàn)對OpenVG 1.0的加速渲染,且具有突出的低功耗特性。文獻[11]中是在總結(jié)了OpenVG支持的4種繪制模式上,提出在OpenGL ES的3D圖形管道上使用GLSL ES片元著色處理器的實現(xiàn)方法。但這些擴展方案帶來大量的計算,造成存儲及運算資源的增加,從而導(dǎo)致渲染性能較差和渲染速度較慢,不適合移動設(shè)備的應(yīng)用領(lǐng)域。
綜上,本文針對GPU設(shè)計了一種通用圖形API庫[12]。在自主設(shè)計的圖形處理器上,通過分析OpenGL ES 2.0和OpenVG 1.1兩種圖形庫標(biāo)準,采用了一種包含通用管理層、函數(shù)容錯預(yù)處理層和命令解析層的3層抽象結(jié)構(gòu)來實現(xiàn)通用圖形API庫的設(shè)計。以Linaro操作系統(tǒng)和Zync-7000[13]系列芯片XC7Z045FFG900-2 FPGA搭建了軟件驗證平臺,通過編寫測試程序?qū)λO(shè)計的圖形API庫進行驗證。
如圖1所示,通用圖形API庫由通用管理層、函數(shù)容錯預(yù)處理層和命令解析層3層抽象結(jié)構(gòu)組成。應(yīng)用程序使用OpenGL ES 2.0或者OpenVG 1.1圖形標(biāo)準繪制圖像,API函數(shù)調(diào)用兼容兩種圖形API的通用圖形API庫,經(jīng)過通用管理層封裝OpenGL ES 2.0和OpenVG 1.1的共享API函數(shù)庫;由函數(shù)容錯預(yù)處理層完成圖形上下文的建立以及圖形函數(shù)參數(shù)的校驗和處理;再由命令解析層根據(jù)所定義的函數(shù)指令集完成對API函數(shù)及其參數(shù)的命令轉(zhuǎn)換,所設(shè)計的通用API庫的指令集由148位的二進制數(shù)組成,包含10位命令字、10位控制碼和128位數(shù)據(jù)位。最后通過驅(qū)動程序[14-16]將API函數(shù)指令交付給底層硬件處理器,從而達到對圖形繪制加速的目的。
圖1 圖形系統(tǒng)的分層組織結(jié)構(gòu)
通用管理層用于管理和封裝OpenGL ES 2.0和OpenVG 1.1兩種API函數(shù)庫。為了更好的對不同類型的API進行區(qū)分調(diào)用,本文采用條件分支和函數(shù)索引表的編程思想進行設(shè)計,這種設(shè)計可以方便API庫的管理和維護。首先判斷圖形API的類型,即OpenGL ES或者OpenVG。然后通過兩個相互獨立的索引表來分別表示OpenGL ES和OpenVG的API函數(shù)索引項。其中ES_Cur_Pointer是指向OpenGL ES當(dāng)前函數(shù)索引表的指針,而ES_Dis_Table是由其函數(shù)指針組成的函數(shù)索引表。同理,VG_Cur_Pointer是指向OpenVG當(dāng)前函數(shù)索引表的指針,而VG_Dis_Table是由其函數(shù)指針組成的函數(shù)索引表。其偽代碼如下:
Algorithm1Common Management
1.if(OpenGL ES 2.0 Function Type)
2. *ES_Cur_Pointer;
//Point to function index table
3. Function implementation;
4.else(OpenVG 1.1 Function Type)
5. *VG_Cur_Pointer;
//Point to function index table
6. Function implementation;
7.endif
上述偽代碼具體的實現(xiàn)過程如下:上層應(yīng)用程序首先判斷出用戶調(diào)用的API函數(shù)是所設(shè)計通用圖形API庫中OpenGL ES 2.0或者OpenVG 1.1的函數(shù)類型,其次根據(jù)條件類型判斷結(jié)果用函數(shù)宏定義找到函數(shù)索引表的當(dāng)前指針ES_Cur_Pointer或者VG_Cur_Pointer,然后由當(dāng)前指針找到該函數(shù)的具體功能實現(xiàn)即函數(shù)體部分,最后由圖形加速處理器執(zhí)行該函數(shù)體,并完成上層應(yīng)用程序所分配的具體任務(wù)。
為了提高軟件庫的穩(wěn)定性,函數(shù)容錯預(yù)處理層需要進行函數(shù)狀態(tài)檢測和容錯處理。函數(shù)容錯預(yù)處理層采用上下文機制管理OpenGL ES 2.0和OpenVG 1.1圖形API庫的狀態(tài)信息。其中圖形API庫中的上下文用一個Context結(jié)構(gòu)體表示,該結(jié)構(gòu)體包含函數(shù)索引表、驅(qū)動函數(shù)表、矩陣變換參數(shù)、渲染列表狀態(tài)、緩沖區(qū)屬性、錯誤反饋標(biāo)志等狀態(tài)信息。上述所有的狀態(tài)信息將會在通用圖形API庫預(yù)處理過程中完成初始化,并且當(dāng)上層應(yīng)用程序調(diào)用狀態(tài)信息查詢命令時,會返回當(dāng)前的狀態(tài)值。
函數(shù)容錯預(yù)處理層采用錯誤反饋機制,能夠?qū)τ脩艟帉懙膽?yīng)用程序的語法錯誤進行一系列簡單的處理,同時方便編程人員對該API函數(shù)庫的管理。當(dāng)用戶編寫的應(yīng)用程序所輸入的函數(shù)參數(shù)和圖形API庫中的函數(shù)參數(shù)不匹配或者格式不符時,在程序執(zhí)行的過程中將會跳過出錯的API函數(shù)并且將錯誤反饋給應(yīng)用程序編寫者,通過這種機制可以有效的提高圖形API庫的穩(wěn)定性。函數(shù)容錯預(yù)處理層的工作流程如下:
首先獲取上下文狀態(tài)信息,完成OpenGL ES 2.0或者OpenVG 1.1圖形API庫的初始化。當(dāng)對應(yīng)用程序的調(diào)用狀態(tài)進行查詢時,會返回當(dāng)前的狀態(tài)值。然后進行函數(shù)參數(shù)正確性的檢測和錯誤處理,通過條件分支語句對函數(shù)參數(shù)的正誤進行判斷處理。函數(shù)參數(shù)的驗證是通過Para_Check函數(shù)進行判斷的,其偽代碼如下:
Algorithm2Function Parameter Validation
1.VoidPara_Check(char des[],
char src[],
int pos)
2. inti= 0; intj= 0;
3.if(pos == D0) //Correctness check
4.for(i= 0;i< 32;i++)
5. des[i] = src[j];
6.j++;
7.elseif(pos == D1)
8.for(i= 32;i< 64;i++)
9. des[i] = src[j];
10.j++;
11. …
12.elseif(pos == D4)
13. …
14.elseReturn Error ;
上述偽代碼具體的實現(xiàn)過程如下:如果用戶輸入的函數(shù)參數(shù)是正確的,則在上下文中管理對應(yīng)的函數(shù)參數(shù)并調(diào)用命令解析控制層對應(yīng)的函數(shù),并在命令解析層完成API函數(shù)參數(shù)轉(zhuǎn)換成特定格式的命令標(biāo)識符;如果用戶輸入的函數(shù)參數(shù)是錯誤的,則程序在處理的過程中會直接忽略出錯的API函數(shù),并在程序執(zhí)行結(jié)束后將錯誤信息反饋給程序用戶輸入者。
為了將函數(shù)功能參數(shù)轉(zhuǎn)換為底層硬件可以識別的指令序列,設(shè)計命令解析層負責(zé)OpenGL ES 2 .0.或者OpenVG 1.1的API函數(shù)轉(zhuǎn)換成指定格式的命令標(biāo)識。OpenGL ES 2.0和OpenVG 1.1圖形API庫的指令集是由148位的二進制數(shù)組成的,從高到低分別是命令字(147-138)、控制碼(137-128)和數(shù)據(jù)段(127-0),如圖2所示。
圖2 指令編碼格式
命令字用于識別OpenGL ES 2.0和OpenVG 1.1函數(shù)庫接口以及不同的API函數(shù)命令,控制碼用來指定數(shù)據(jù)組織和存儲格式即函數(shù)參數(shù)的個數(shù)以及參數(shù)的數(shù)據(jù)類型,數(shù)據(jù)段用來按控制碼段指定的格式命令存儲和傳遞要使用的參數(shù),其中包括參數(shù)Data3、Data2、Data1和Data0。
如將OpenGL ES 2.0的函數(shù)glClearColor(GLclampf red,GLclampf green, GLclampf blue,GLclampf alpha) 轉(zhuǎn)換成148位的命令標(biāo)識符,具體轉(zhuǎn)換過程如下:
(1) 查找函數(shù)glClearColor的命令字碼,通過查找命令字碼表可得命令字是0110000100。
(2) 查找控制字(Ctrl),通過查找函數(shù)glClearColor對應(yīng)的控制字表可得控制字是0100000011;Ctrl[2:0]表示函數(shù)參數(shù)的數(shù)據(jù)類型控制字(見表1)。
表1 函數(shù)參數(shù)數(shù)據(jù)類型
(3) 函數(shù)參數(shù)red、green、blue、alpha分別轉(zhuǎn)換為32位二進制數(shù),分別作為參數(shù)D3、參數(shù)D2、參數(shù)D1、參數(shù)D0。所有的圖形API函數(shù)均采用類似的方法進行編譯。
函數(shù)glClearColor(GLclampf red,GLclampf green, GLclampf blue,GLclampf alpha) 在命令解析層的處理流程圖如圖3所示,部分偽代碼如下:
Algorithm3Command parsing
1.VoidglClearColor(GLclampf red,
GLclampf green,
GLclampf blue,
GLclampf alpha)
2. code_init(); //initialization
3. float_to_fixed(red, para);
//Data conversion
4. … …
5. para_cat(glcode, para, D0);
//Get function parameters
6. … …
7. get_ctrl(ctr, 10); //Get the control code
8. opcode_cat(glcode,CLEARCOLOR);
//Get the command word
9. save_Data(); //save data
圖3 命令解析層處理流程圖
為了區(qū)別OpenGL ES 2.0和OpenVG 1.1兩種圖形API函數(shù)庫,將命令字段的最高位作為區(qū)別標(biāo)識符。若命令字段最高位置0,則表示OpenGL ES 2.0的API函數(shù);若命令字段最高位置1,則表示OpenVG 1.1的API函數(shù)。每一條指令對應(yīng)唯一一組命令編碼,用于區(qū)分不同的命令;由于有些命令的參數(shù)比較多,可能需要2條或3條命令才能傳送完成,控制字用于指示是否為最后命令的最后一條。
本文所提出的移動圖形處理器(Mobile Graphics Processor,MGP)硬件設(shè)計如圖4所示,主要包括CPU_IF模塊、前端處理器(Front End Processor,FEP)、統(tǒng)一架構(gòu)染色器(Unified Shading Processor,USP)、屏幕坐標(biāo)產(chǎn)生單元(Screen-coordinate Generating Unit,SGU)、Tile產(chǎn)生單元(Tile Generating Unit,TGU)、幀緩沖區(qū)(Frame Buffer,F(xiàn)B)等處理模塊。其中CPU_IF模塊負責(zé)與主處理器的數(shù)據(jù)、狀態(tài)、控制信息的交互,支持AXI總線協(xié)議,并完成總線數(shù)據(jù)與圖形處理硬件的信號同步。FEP模塊負責(zé)圖形渲染任務(wù)的分解、組織與初步調(diào)度。FEP以可編程形式解析OpenGL ES 2.0和OpenVG 1.1的圖形API命令。
圖4 移動圖形處理器體系結(jié)構(gòu)
使用vivado 2015.4集成設(shè)計工具將移動終端顯示控制芯片IP核電路設(shè)計封裝成有AXI接口的自定義IP核[17],通過制作SD卡啟動鏡像,將封裝好的IP核做為協(xié)處理器掛載到Zynq-7000開發(fā)板的ARM Cortex-A9處理器上。驅(qū)動程序?qū)⒅噶顢?shù)據(jù)存儲在開發(fā)板的外部存儲設(shè)備DDR3中,并在處理系統(tǒng)(Processing System,PS)端完成數(shù)據(jù)的讀取和寫回控制,在可編程邏輯(Programmable Logic,PL)端完成圖形渲染處理,如圖5所示。
圖5 系統(tǒng)總體架構(gòu)圖
CPU_IF模塊通過AXI總線讀取DDR3中的圖形API指令,然后將指令透傳到FEP模塊進行命令解析和下一步的渲染操作。
采用通用管理層、函數(shù)容錯預(yù)處理層和命令解析層的3層抽象結(jié)構(gòu)來實現(xiàn)通用圖形API庫,由于軟硬件存儲指令方式的不同需要由驅(qū)動程序?qū)χ噶钚蛄羞M行數(shù)據(jù)進制的轉(zhuǎn)換。所設(shè)計的通用圖形API庫在命令解析層處理完成后,生成148位的二進制數(shù)據(jù)。驅(qū)動程序?qū)⒚罱馕鰧觽鬟f下來的148位二進制數(shù)據(jù)流轉(zhuǎn)換成五部分,每部分由32位二進制數(shù)據(jù)組成。因為五部分32位二進制數(shù)據(jù)為160位數(shù)據(jù)比傳遞下來的148二進制數(shù)據(jù)流多12位,所以通過高位補零的方式將命令字和控制碼字段合并為一個32位二進制字段,如圖6所示。再將轉(zhuǎn)換過的數(shù)據(jù)存儲在Zynq-7000開發(fā)板PS端的DDR3中,DDR3作為外部緩沖區(qū)。同時要將二進制指令在外部緩沖區(qū)中的存儲地址和指令條數(shù)分別寫入GPU內(nèi)部的渲染列表基址寄存器和渲染狀態(tài)字寄存器中。MGP會根據(jù)這兩個寄存器中存儲的地址以及命令條數(shù)在外部緩沖區(qū)DDR3中讀取相應(yīng)的渲染命令,完成軟件到硬件的數(shù)據(jù)通信。
圖6 指令轉(zhuǎn)換
MGP內(nèi)部的控制命令寄存器會根據(jù)指令存儲地址在指令緩存區(qū)中讀取啟動渲染操作指令,在由MGP處理完成后,根據(jù)寫回源選擇寄存器中的地址值寫回到幀緩沖區(qū)對應(yīng)的地址中,再由顯示設(shè)備讀取幀緩沖區(qū)中的像素數(shù)據(jù),完成圖形顯示操作。
本文采用Linaro操作系統(tǒng)和Zynq-7000系列芯片XC7Z045FFG900-2 FPGA搭建了軟件驗證平臺,通過編寫大量測試程序在圖形處理系統(tǒng)上對其進行測試,以此來驗證對所設(shè)計圖形API庫正確性。
為了驗證所設(shè)計的通用圖形API庫的正確性,編寫大量的測試例子對圖形庫進行測試。圖7所示為使用OpenGL ES 2.0編寫的圖形應(yīng)用程序,其中圖7(a)是使用本文所設(shè)計通用圖形API庫繪制的測試例子,圖7(b)是使用標(biāo)準的圖形庫進行繪制的。圖8(a)是使用所設(shè)計的圖形庫對OpenVG 1.1藍色正方形例子的測試,圖8(b)為標(biāo)準的OpenVG 1.1繪制的圖形。
(a)(b)
圖7 OpenGL ES 2.0繪制圖形比較
測試表明本文所設(shè)計的通用圖形應(yīng)用編程接口庫可以滿足OpenGL ES 2.0和OpenVG 1.1基本函數(shù)功能的渲染操作。
(a)(b)
圖8 OpenVG 1.1繪制圖形比較
對測試圖形進行渲染數(shù)據(jù)分析,如表2和表3所示。
表2 OpenGL ES 2.0繪制數(shù)據(jù)分析
表3 OpenVG 1.1繪制數(shù)據(jù)分析
數(shù)據(jù)表明本文所設(shè)計的通用圖形應(yīng)用編程接口庫繪制性能能夠滿足基本圖形繪制的需求。
本文基于自主設(shè)計的移動GPU硬件架構(gòu)設(shè)計了一種的通用圖形API庫,在滿足圖形渲染性能和速度的前提下,通過分析OpenGL ES 2.0和OpenVG 1.1兩種圖形庫標(biāo)準,采用了一種包含通用管理層、函數(shù)容錯預(yù)處理層和命令解析層的3層抽象結(jié)構(gòu)來實現(xiàn)通用圖形API庫的設(shè)計,并以Linaro操作系統(tǒng)和Zynq-7000系列芯片XC7Z045FFG900-2 FPGA搭建了軟件驗證平臺,完成了對所設(shè)計圖形API庫的驗證,實現(xiàn)了基本圖形的渲染操作。