首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

真彩色轉高彩色的高效能演算法實作

     編輯:關於VC++

為什麼需要即時色深轉換?

在傳統 2D 遊戲開發中,位圖資源無論以何種色深儲存,載入後通常會統一轉換為目標顯示模式所需的色深。這類轉換多發生於初始化階段,效能壓力不大。然而,隨著遊戲技術演進,未來的 2D 引擎將支援 Voxel 物件與即時光線處理,32 級亮度已無法滿足需求,內部運算勢必採用真彩色(24/32-bit)。但在某些輸出場合(如特定顯示裝置或相容性考量),仍需輸出 15/16-bit 高彩色,因此必須尋找高速的即時轉換方案。

從 C 語言到組合語言的優化之路

最直觀的 C 語言實作如下:

red   = (truecolor >> 8) & 0xF800;
green = (truecolor >> 5) & 0x07E0;
blue  = (truecolor >> 3) & 0x001F;
hicolor = red | green | blue;

此做法因位移與遮罩操作頻繁,效能低落。改用 x86 組合語言可大幅優化:

lodsd           ; EAX = RRRRRRRR GGGGGGGG BBBBBBBB
shr eax, 3      ; 000RRRRR RRRGGGGG GGGBBBBB
shl al, 2       ; 000RRRRR RRRGGGGG GBBBBBxx
shl ax, 3       ; 000RRRRR GGGGGGBBB BBxxxxx
dec esi
shr eax, 5      ; 00000000 RRRRRGGG GGGBBBBB
stosw

雖然指令精簡,但大量使用部分暫存器(AL, AX)會造成管線停滯,效率大打折扣。優化策略包括:單迴圈處理兩像素(交錯使用 EAX/EBX),或將後段改為查表法。

MMX 平行運算:單指令處理 4 像素

MMX 的 SIMD 特性讓我們能並行處理多組資料。關鍵在於將 RGB 三通道分開儲存(例如:位圖每一列分為 R、G、B 三段),即可一次載入 4 個像素的同色通道資料,並行運算後合併寫入。範例程式碼:

; MM7 = 0xF800F800F800F800 (紅通道遮罩)
; MM6 = 0xFC00FC00FC00FC00 (綠通道遮罩)
punpcklbw mm0, [red+edx]   ; 展開紅通道
punpcklbw mm1, [green+edx] ; 展開綠通道
punpcklbw mm2, [blue+edx]  ; 展開藍通道
pand mm0, mm7              ; 保留紅高 5 位
pand mm1, mm6              ; 保留綠高 6 位
psrlw mm2, 11              ; 藍通道右移 11 位
psrlw mm1, 5               ; 綠通道右移 5 位
por mm0, mm2
por mm0, mm1               ; 合併為 RRRRRGGG GGGBBBBB
movq [dis+edx*2], mm0      ; 寫入 4 個 16-bit 像素
add edx, 4

此法單迴圈處理 4 像素,配合快取友善的資料佈局,效能遠超純標量程式碼。本文旨在拋磚引玉,期待更多高手提出更優解。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved