BlogKLabは、多くのスマートフォン向けゲームを開発・提供しています。スマートフォン向けゲームの開発と運用は、Webソーシャルゲームと比べて格段に複雑で、またコンシューマゲーム開発とも異なったノウハウが求められる領域もあります。このブログでは、KLabのゲーム開発・運用の中で培われた様々な技術や挑戦とそのノウハウについて、広く紹介していきます。〜レンダリングの仕組みを追うpart2〜※この記事ではgitのタグ「v2.74」から生成したブランチ上でコードリーディングしています。頂点が頻繁に更新されるのはEditモードだよね前回の記事の続きです。前回はObjectモード時のレンダリングはGPUで行われている事を突き止めましたが、今回は頂点データが頻繁に更新されてメインメモリ<ー>GPUメモリ間のデータ転送コストが毎回発生するであろうEditモードのレンダリングについて調べてみます。Editモードのレンダリングに使われているのはCPUでしょうか?GPUでしょうか?OB_MODE_EDITで探るもレンダリング命令まで行き着かずObjectモードのときはdrawobject.cの中でObjectモードを示すenum値:OB_MODE_OBJECTの付近を探っていたら運良くレンダリング命令の部分を引き当てる事に成功しましたが、今回はEditモードを示すOB_MODE_EDITの付近を探ってみるも、レンダリング命令に行き着きませんでした。drawobject.cの中に目的の部分がある可能性は捨てず、別の方法で探す事にしました。検索条件を変えて絞り込んでいきましょう。ShadingがSolidの場合は関数ポインタdrawFacesSolidがドローコールにつながっているかもしれません。drawobject.cの中で関数ポインタdrawFacesSolidがコールされている場所は8カ所。試しに8カ所全てコメントアウトしてみるも、Editモードの時のモデルの面が消える事はありませんでした。drawFaces〜〜〜かな??ついでに「drawFaces」でdrawobject.c内を検索してみましょう。ヒットは11件で8件が先ほどのdrawFacesSolid。1件はenum値なのでこれは関係なし。残る2件はdrawFacesGLSL(GLSLはOpenGLのシェーダ言語)という関数ポインタで、EditモードはデフォルトでSolidシェーディングなのでGLSLが使われる事もなさそうだから違うだろうなと思いつつ2件ともコメントアウトしてみるもやはり該当しませんでした。「draw」ならどうか?ヒットは1311件。これは調べきれません。Objectモードのときと同じように構造体内の関数ポインタになっていると予想できるので、「->draw」で検索してみると135件。手探りで該当箇所を探るのはキツい件数ですね。Xcodeはパターン検索が出来るので「->draw〜〜〜(」という形で検索して絞り込む。絞りたい!この55件の〜〜〜の中には「Verts」(頂点)や「Edges」(辺)という文字列が含まれています。狙いは「Faces」(面)なので「->draw〜〜〜Faces」で検索。すると12件まで絞れました。これくらいの数であれば1つ1つ手で調べていけますね!この12件の中に答えがあるか!?容疑者:drawMappedFaces12件のうち1件は関数でも関数ポインタでもないので除外。10件は関数ポインタdrawMappedFaces、1件は関数ポインタdrawMappedFacesGLSLです。Objectモードのときもdraw〜〜〜という関数ポインタがレンダリング命令につながっていたので、この11件の中のどれかがEditモードの面のレンダリングにつながっているかもしれません。1件となっていました。Objectモードのときはdraw_mesh_fancy()がdrawFacesSolid()を呼び出していてレンダリング命令につながっていましたね。試しにdraw_mesh_fancy()の中のdrawMappedFaces()をコメントアウトして実行してみましたが、Editモードの面のレンダリングには関係ないようです。次はdraw_mesh_fancy()と同じように「fancy」の付くdraw_em_fancy()辺りが怪しいでしょうか?3件ともコメントアウトしてみます。↓↓↓Editモードの面が消えましたね!!結果、3つの関数ポインタdrawMappedFacesのうち最後が今回探している起動時のデフォルト状態からEditモードに切り替えた直後の面のレンダリング部分につながっているようです。関数ポインタが指す関数本体は?さて、狙いの関数ポインタdrawMappedFacesも見つかった事ですし、ステップ実行してこのdrawMappedFacesが指し示している関数本体を探してみましょう。するとdrawMappedFacesはeditderivedmesh.c内のemDM_drawMappedFaces()を指し示している事がわかります。emDM_drawMappedFaces()の中ではやはりOpenGLのレンダリング命令が使われており、GPUレンダリングが行われているようです。CPUか?GPUか?答えが出ましたね!おまけObjectモードのときはglDrawArraysで頂点データの格納された配列の中身を一気にレンダリングしていました。Editモードのときはこれと違い、for文の中で三角形を1つずつレンダリングしているようです。頻繁な頂点の追加&削除の負荷に耐えるためでしょう。