創作內容

3 GP

【程式】新開發機的相容性問題(下)

作者:Shark│2017-07-25 19:35:51│贊助:6│人氣:503

(工作狀況示意圖)
(gdb不是我開發的軟體,所以不是鈷寶親自檢查,而是操作一台機器)
繼續跟新舊版Linux的相容性,以及不同廠牌顯卡的相容性奮鬥。

6. 艾莉兒:我再試一次……,測試程式可以了,遊戲還是有segmentation fault,一定還藏在什麼地方。
我看看……,從map檔看好像是在繪製particle的時候,但找不到是哪一行出問題。
寫個只用到particle plane的測試程式,一樣會當,那可以確定問題出在這裡。

以前寫程式很少用debugger,靠直覺就可以判斷問題出在哪,但這次好像必須動用了,就是Cyber Sprite裡那個暫停時間的道具。
艾莉兒,我build個debug版給你用。
鈷寶,執行gdb。

艾莉兒:發動breakpoint!……停在spparticleplane.cpp第85行。
鈷寶,檢查變數的值。
鈷寶:呃,好……,nowVertexIndex=0,nowCapacity=616,t2指向無效的位址。

確定是哪一行了,算particle頂點坐標的時候。
加printf印出幾個值看看
printf("%x %x %x\n",t,t2, out);
calcCoordinate(out,point,corner,scaleXY,angleV);
printf("%x %x %x\n",t,t2, out);

bfcf211c bfcf211c bfcf1fb0
bf13e8fd bf13e8fd bfcf1fb0
怪事,呼叫個calcCoordinate() t,t2就被修改了,calcCoordinate特別的地方只有它裡面用到SSE,沒修改到t和t2為何值會改變?還有為何同樣程式碼以前可以現在不行?
我要看編譯出的組合語言。

上面printf和calcCoordinate的附近是這樣
pushl %ebx
pushl %ebx
movaps %xmm3, %xmm4
pushl $.LC4
pushl $1
 ……
call __printf_chk
 ……
call _Z14calcCoordinatePfPKfS1_S1_S1_
movl %esi, (%esp)
pushl %ebx
pushl %ebx
pushl $.LC4
pushl $1
call __printf_chk

看起來t和t2是存在ebx暫存器,會不會是calcCoordinate修改到ebx的值?可是明明x86 calling convention規定函式裡不可修改ebx的值啊。
查一下gdb詳細語法,和電子妖精再試一次debugger。

艾莉兒:執行到calcCoordinate前面了。
執行指令:p t,p t2,info registers
鈷寶:t=0xbffff058,t2=0xbffff058,暫存器的值是這樣
 eax 0x20
 ecx 0xbffff038
 edx 0xbffff050
 ebx 0xbffff058
 esp 0xbfffefc0
 ebp 0xbffff028

t和t2果然是存在ebx,繼續看calcCoordinate裡面哪一行出問題。
組合語言裡看到函式開頭有push ebx,裡面應該有用到ebx,在這裡把值保留,離開函式前再用pop ebx還原。

艾莉兒:進入函式,calccoordinate.cpp裡第19行。
鈷寶:ebx=0xbffff058
艾莉兒:第20行。
鈷寶:ebx=0xbffff058
 ……
鈷寶:ebx=0xbfffeff0
在這裡改到ebx了,查一下記憶體,位址0xbfffefa0的值是0xbffff058,值保存在這裡。
 ……
艾莉兒:第36行。
鈷寶:0xbfffefa0的值是0xbf576aa4
找到了,看一下這附近的程式碼
float cs[2];
if(angle[0]>1){ sincos2(angle[1],cs); }
else{v2Copy(cs,angle);}
cs[2]=-cs[1];

第四行修改到位址0xbfffefa0,之後還原ebx就把改過的值放回去,不知為何以前都沒事,換開發機之後才出問題。
反正趕快修掉,第一行宣告改成float cs[3];
話說陣列越界通常會動到的是其他區域變數,不然就是程式立刻當掉,這次很湊巧改到上一層函式的變數。



7. 艾莉兒:總算不會當了,可是為什麼畫面一片黑?
艾莉兒:是不是back buffer物件沒有建出來?

鈷寶:忘了改GLSL?(我前陣子改過HLSL)
(在「倒立的OpenGL貼圖坐標」有提過,我沒有直接畫在主畫面,是建一個back buffer畫出畫面,最後再把它貼到主畫面上)
檢查一下,都沒問題。

做點實驗
a.這個「最後一步」的shader改成這樣,不讀貼圖直接上色。
void main(){
 gl_FragColor=vec4(0,0,1,1);
}
叫鈷寶打包shader,然後build,執行

可以畫出來,表示頂點坐標是對的。

b.讀貼圖,不用back buffer,直接畫在畫面上


艾莉兒:好像是讀不到貼圖的樣子。

再研究一下,發現是這個函式
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0,
 imageFormat, GL_UNSIGNED_BYTE, initData);
其中的internalFormat以前可以填分量數,如BGRA填4,灰階填1,現在必須填常數GL_RGBA和GL_RED才行,大概因為建context時有指定要3.3版且不相容舊版,就禁止用舊規格。



8. 換開發機後第一次看到遊戲畫面…………可是還沒結束。


艾莉兒:一個科幻風遊戲用楷書看起來好怪,本來是用黑體吧。
鈷寶:還有……方框不見了。
艾莉兒:查查看讀系統字型的部分。

Linux尋找系統內建字型的函式庫是Fontconfig,不過它找中文字型時比對功能不準,所以我把一般發行版有的明體、黑體字型名稱寫在程式裡,叫它先找這幾個字型,找不到時才用Fontconfig的比對功能當後備。
問題在同一個字型有不同語言的名稱,例如程式裡寫「WenQuanYi Micro Hei」,Fontconfig找到的是「文泉驛微米黑」。
之前偷懶只用「FcPatternGetString(matched, FC_FAMILY, 0, &name)」檢查第一個名稱是否符合,就以為沒找到字型,應該跑迴圈,第三參數填0,1,2……檢查所有名稱。

Windows版也有一個字型好幾個名稱的問題,如果用「微軟正黑體」在中文以外的環境會找不到,要用英文名稱「Microsoft JhengHei」。
此外看過有人用RPG Maker遇到一個問題:字型填中文名稱,在非中文環境就讀不到字型。

再來解決方框,…………查到是存放index的buffer沒設初值。(是用glDrawElements來畫,要給index陣列)
總算對了


到這裡為止,Code::Blocks無緣無故當掉的次數已經讓我無法忍受了,本來用Mint 18套件管理器裡的版本,用Ubuntu ppa安裝較新的版本,希望會穩一點。



9. 希望這是最後一關了……,有時候玩到一半突然沒聲音,再玩一下子……
艾莉兒:啊……突然動彈不得……視窗也關不掉……
(開系統監控工具強制關閉程式)
艾莉兒:得救了……,我想應該是聲音thread卡住。(聲音有開另一個thread處理)
查到是在新增聲音的時候發生,可能卡住的地方大概是OpenAL和gstreamer的函式,到底是哪裡?
是低確率隨機發生,不太好重現,只能不斷做移動游標之類的事,讓艾莉兒一直播音效等狀況出現。
……
經不斷試驗發現是在設位置,呼叫gst_element_seek_simple()的時候卡住。
為何會卡?查gstreamer的文件,看呼叫這個函式有什麼限制。

…………

再用一次debugger吧,艾莉兒、鈷寶,準備了!

(播放游標音效、打字音效、取消音效……)
艾莉兒:啊,來了,主人快檢查!
鈷寶,查看6號thread,印出stack。
鈷寶:好,我在弄……

…………

換個方法吧。
看到這篇:Running GStreamer Applications
gstreamer有輸出debug訊息的功能,用用看
GST_DEBUG=5 ./cybersprite2

…………(數小時後)

還是查不到原因,只確定是gstreamer內部卡住,沒出現錯誤訊息,gstreamer的文件也沒提到做什麼事會hang住之類的,我開始懷疑是gstreamer的bug了。
決定擱置,以前用Mint 17都沒這個問題,有點考慮要退到這一版來開發了。(Linux軟體版本都綁發行版,難以更換單一軟體的版本)



10. 結果9還不是最後一關
艾莉兒:進到遊戲關卡,……咦,怎麼這麼暗?


艾莉兒:主人,大概跟最近做的剪影功能有關吧。

我猜是讀不到貼圖,7.或許還有什麼地方沒改到。
在適當地方插入glGetError()看看,把聲音部分先註解掉免得因為9.的問題卡住。
嗯,glTexImage2D()有個常數名稱打錯,改掉就好了。

Code::Blocks當掉次數減少了但還是偶而會當,將就一下吧,用過幾個其他IDE也找不到更合用的。



11. 幾天後的事
灌了Mageia 64bit版,想試試在其他發行版上會怎麼樣,結果32bit的桯式在64bit的作業系統會出問題。
原因是gstreamer,64位元OS可以裝32位元的gstreamer函式庫,但無法讀取plugin,就變成畫面正常但沒聲音,前作因為不是用gstreamer解碼所以沒這個問題。
還有32bit和64bit開發用套件也會衝突,不能同時裝,不像Windows可以兩者共存。
Mageia和我的電腦似乎相性不良,沒執行程式電腦也會很燙,還是換個發行版吧。

不過之後再試Fedora,兩種開發用套件可以同時裝了,64位元版也可以build 32位元程式,只是gstreamer有同樣問題。



雖然有些是自己不小心,但有些問題是軟體作者的bug要我來收拾,這種情況很討厭。
32bit版gstreamer在64bit環境下無法使用也是這次才發現的,Linux版本間相容性之差已經司空見慣,這次竟然是同一發行版的32bit和64bit之間出問題,得考慮Linux版要如何發佈了。

除了本篇寫的以外還有幾個以前就發現的問題要解決,一個是改良OpenAL的播放方法,有時會因為延遲而播不出聲音(如選角時的打字音效),DirectSound沒有這個問題。

第二是檢討coroutine的使用,Windows可以用作業系統提供的fiber功能,Linux想實作coroutine只能用組合語言刻,後者在stack越界時不會自動增長,一旦stack用太多程式就當掉,是很冒險的做法。以後寫手機程式還要考慮手機能不能用這個技巧。
coroutine雖然很好用但作業系統不讓你用也沒辦法,可能得忍痛拔掉這功能。

至於Windows 10的使用感,因為有用過Windows Phone,對動態磚和新的介面風格並不陌生。

關於開頭的圖:這種畫法最累的部分其實是邊線,無線繪少掉畫線的步驟就輕鬆很多。(我的畫作無線繪佔多數這是原因之一)
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=3657403
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:程式|OpenGL|Linux|Linux程式設計

留言共 0 篇留言

我要留言提醒:您尚未登入,請先登入再留言

3喜歡★shark0r 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:【程式】新開發機的相容性... 後一篇:FF30遊戲攤位一覽&a...

追蹤私訊

作品資料夾

tfapp大家
天氣很熱,記得補水喔!小屋內容新增,歡迎大家到我的小屋,免費以及輕鬆愉快學日文看更多我要大聲說昨天22:30


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】