これは何ですか
ARM NEONとは何ですか?
-ARM®NEON™はSIMDエンジンです
...-つまり、x86 CPU SSE / SSE2のような拡張命令セットですが、ARMアーキテクチャを備えたプロセッサ向けです。
なんで?
FSAAサポートを追加するまでは、すべて順調でした。 その後、FPSは15未満に沈みました。
最適化後、再び約25 FPSになりました。 しかし、メモリには、フレームごとに10%の時間を消費する関数が1つありましたが、最適化できるものがまだわかりませんでした。
「エンジンでNEONを使用しますか」などの質問を時々してくれた私の友人のおかげで、私は(彼のサポートで)この機能をNEONに書き換えることに決めました。
構造:
単一重み変換:
forceinline void transformPointNormal4x3Weight_NoW(const Matrix44f& mat,const Vec3f& inV, const Vec3f& inN, BaseRenderScene::PN& outPN) { outPN.p.vec[0] = (inV.vec[0]*mat.mat[0][0] + inV.vec[1]*mat.mat[1][0] + inV.vec[2]*mat.mat[2][0] + mat.mat[3][0]); outPN.n.vec[0] = (inN.vec[0]*mat.mat[0][0] + inN.vec[1]*mat.mat[1][0] + inN.vec[2]*mat.mat[2][0]); outPN.p.vec[1] = (inV.vec[0]*mat.mat[0][1] + inV.vec[1]*mat.mat[1][1] + inV.vec[2]*mat.mat[2][1] + mat.mat[3][1]); outPN.n.vec[1] = (inN.vec[0]*mat.mat[0][1] + inN.vec[1]*mat.mat[1][1] + inN.vec[2]*mat.mat[2][1]); outPN.p.vec[2] = (inV.vec[0]*mat.mat[0][2] + inV.vec[1]*mat.mat[1][2] + inV.vec[2]*mat.mat[2][2] + mat.mat[3][2]); outPN.n.vec[2] = (inN.vec[0]*mat.mat[0][2] + inN.vec[1]*mat.mat[1][2] + inN.vec[2]*mat.mat[2][2]); } forceinline void transformPointNormal4x3Weight(const Matrix44f& mat,const Vec3f& inV, const Vec3f& inN, BaseRenderScene::PN& outPN,float w ) { outPN.p.vec[0] = (inV.vec[0]*mat.mat[0][0] + inV.vec[1]*mat.mat[1][0] + inV.vec[2]*mat.mat[2][0] + mat.mat[3][0])*w; outPN.n.vec[0] = (inN.vec[0]*mat.mat[0][0] + inN.vec[1]*mat.mat[1][0] + inN.vec[2]*mat.mat[2][0])*w; outPN.p.vec[1] = (inV.vec[0]*mat.mat[0][1] + inV.vec[1]*mat.mat[1][1] + inV.vec[2]*mat.mat[2][1] + mat.mat[3][1])*w; outPN.n.vec[1] = (inN.vec[0]*mat.mat[0][1] + inN.vec[1]*mat.mat[1][1] + inN.vec[2]*mat.mat[2][1])*w; outPN.p.vec[2] = (inV.vec[0]*mat.mat[0][2] + inV.vec[1]*mat.mat[1][2] + inV.vec[2]*mat.mat[2][2] + mat.mat[3][2])*w; outPN.n.vec[2] = (inN.vec[0]*mat.mat[0][2] + inN.vec[1]*mat.mat[1][2] + inN.vec[2]*mat.mat[2][2])*w; } forceinline void transformPointNormal4x3AddWeighted(const Matrix44f& mat,const Vec3f& inV, const Vec3f& inN, BaseRenderScene::PN& outPN,float w ) { outPN.p.vec[0] += (inV.vec[0]*mat.mat[0][0] + inV.vec[1]*mat.mat[1][0] + inV.vec[2]*mat.mat[2][0] + mat.mat[3][0])*w; outPN.n.vec[0] += (inN.vec[0]*mat.mat[0][0] + inN.vec[1]*mat.mat[1][0] + inN.vec[2]*mat.mat[2][0])*w; outPN.p.vec[1] += (inV.vec[0]*mat.mat[0][1] + inV.vec[1]*mat.mat[1][1] + inV.vec[2]*mat.mat[2][1] + mat.mat[3][1])*w; outPN.n.vec[1] += (inN.vec[0]*mat.mat[0][1] + inN.vec[1]*mat.mat[1][1] + inN.vec[2]*mat.mat[2][1])*w; outPN.p.vec[2] += (inV.vec[0]*mat.mat[0][2] + inV.vec[1]*mat.mat[1][2] + inV.vec[2]*mat.mat[2][2] + mat.mat[3][2])*w; outPN.n.vec[2] += (inN.vec[0]*mat.mat[0][2] + inN.vec[1]*mat.mat[1][2] + inN.vec[2]*mat.mat[2][2])*w; }
1つの頂点の変換:
const Vec3f& vx = pVerticies[v]; const Vec3f& vxN = pNormals[v]; float w = pVertexWeight[v].vec[0]; int boneIndex = pVertexBones[v].vec[0]; const Matrix44f& boneTM = pBoneTMList[boneIndex]; if( wCount==1 ) { transformPointNormal4x3Weight_NoW(boneTM,vx,vxN,skinTempPN[v]); } else {
知識のある人は、各頂点の非ゼロの重みの数を保存していることにすぐに気付くでしょう。 私の場合、ピークの約30%が同じ重量であったため、少しの間勝つことができました。
NEONを備えたASM(xCodeスタイル)
以下のコードは、ARM NEONを使用して最適化されたasm / Cコードです。
いくつかのニュアンス:
- ARM NEONの場合、すべての着信データは16バイトで整列する必要があります。 この要件のため、私はすべての受信位置と法線をVec4fに拡張しました。
- 発信データは、引き続き4バイトで整列できます。 これにより、不必要なジェスチャーをすることなく、結果を頂点バッファーに直接アップロードできました。 16バイトのアラインされたデータを持つバリアントの場合、追加の4 + 4バイトのデータをドロップし、頂点バッファーに格納する必要があります(これはすべてのフレームで発生します)。
#if defined(__ARM_NEON__) #define USE_NEON #endif #if defined(USE_NEON) #ifdef __thumb__ #error "This file should be compiled in ARM mode only."
結果
総合的なテストは行いませんでした。作業中のドラフトですべてをチェックしました。
iPhone 4の場合、〜10秒間隔で502ms(c ++)対307ms(アームネオン)(Cより39%高速)。
質問と回答
一度にいくつかの質問に答えてみてください?
Q:動作方法とARM NEONとは何ですか?
A:仕様を再評価することは意味がありません。
Q:シェーダーを使用しないのはなぜですか?
A:OpenGL 1.1
Q:OpenGL 2.0以降を使用しないのはなぜですか?
A:Windows Phone 8に移植した後のみ(FFはありません。その瞬間に、エンジンとGL 2.0に「シェーダー」を追加します)。
Q:FFにGL_OES_matrix_paletteを使用しないのはなぜですか?
A:モデルを11個の(iphone用)マトリックスのグループに分割する必要があります。これには時間がありません-将来的には。
Q:そして、どこでもっと、できれば例を使って学ぶことができますか?
A:こちらをご覧になることをお勧めします
。 LGPLに注意してください。
Q:どれくらいかかりましたか?
A:1週間-これがまさに記事を書く理由です(誰かが時間を節約してくれたら嬉しいです)。
Q:何も理解できませんでしたが、より詳細に可能ですか?
A:可能です(コメントに依存します)が、非常に明確なコードを記述しようとしました。
PS。 PMのエラー。