2012-03-10 32 views
4

私はAMD Radeon HD 6630MでMacMini '11を使用しています。私は配列の構造を使ってメッシュを描画しています。すべて60 fps(CVDisplayLinkを使用)です。私は組み込みの属性を持つシェーダを使用します。人生は素晴らしい。私は構造の配列(インターリーブされた)を使用することに切り替えています。なぜなら、これは「現代の」GPUで好まれていることを理解しているからです。属性はシェーダで定義されています。メッシュは美しく描かれています。しかし、これを行うと、フレームレートは約33%(40fpsに)下がります。そして、それらの呼び出しの複数のコピーがあります。楽器を使用して:時間プロファイラを、私は次の比較を取得:構造体または配列構造の配列パフォーマンス

Using structure of arrays (60 fps) 
Running Time Self Symbol Name 
3.0ms 0.0% 3.0 0x21b76c4   ATIRadeonX3000GLDriver 
2.0ms 0.0% 0.0 gldUpdateDispatch ATIRadeonX3000GLDriver 
2.0ms 0.0% 0.0 gleDoDrawDispatchCore  GLEngine 
2.0ms 0.0% 0.0  glDrawElements_ACC_Exec GLEngine 
2.0ms 0.0% 0.0  glDrawElements  libGL.dylib 
2.0ms 0.0% 0.0  -[Mesh draw]  me 

Using array of structures (40 fps) 
Running Time Self  Symbol Name 
393.0ms 7.4% 393.0 0x86f6695    ? 
393.0ms 7.4% 0.0 gleDrawArraysOrElements_ExecCore GLEngine 
393.0ms 7.4% 0.0 glDrawElements_IMM_Exec  GLEngine 
393.0ms 7.4% 0.0  glDrawElements   libGL.dylib 
393.0ms 7.4% 0.0  -[Mesh draw]   me 

libGLは異なる方向に行くための意思決定をしている、と構造体の配列は、X3000のドライバが呼び出さ取得されていないように見えるように見えます。アップルのソフトウェアエミュレータで実行されていますか?私は配列の構造にとどまるべきですか?誰もこれのようなものを見たことがありますか?


属性のコードは、Appleの例であり、これらの領域でパフォーマンスが低下することなく、アプリ全体(少なくとも10の他の領域)で使用されています。これは遅いバージョンからのものです。私が言及したように、データはインターリーブされないので、高速版では組み込みの属性を使用しています。レンダリングはちょっと遅いところにあります。

私は、これはあなたが探しているものであると思います

// Step 5 - Bind each of the vertex shader's attributes to the programs 
[self.meshShader addAttribute:@"inPosition"]; 
[self.meshShader addAttribute:@"inNormal"]; 
[self.meshShader addAttribute:@"inTexCoord"]; 

// Step 6 - Link the program 
if([[self meshShader] linkShader] == 0){ 
    self.posAttribute = [meshShader attributeIndex:@"inPosition"]; 
    self.normAttribute = [meshShader attributeIndex:@"inNormal"]; 
    self.texCoordAttribute = [meshShader attributeIndex:@"inTexCoord"]; 

... 


- (void) addAttribute:(NSString *)attributeName 
{ 
    if ([attributes containsObject:attributeName] == NO){ 
     [attributes addObject:attributeName]; 
     glBindAttribLocation(program, [attributes indexOfObject:attributeName],  
     [attributeName UTF8String]); 
    } 
} 

更新: さらに調査した後: 1)私はdhpoWareのmodelObjローダー(修正)を使用しています、それはのインターリーブされた配列を使用していますので、それはパフォーマンス面での構造体の配列のようにも機能します。私はインストゥルメントを誤って解釈しているかもしれませんmodelObjコードはglDrawElements_IMM_Execを呼び出し、ラウンドアバウトの方法でもgleDoDrawDispatchCoreを呼び出します。 glDrawElements_IMM_Execでたくさんの呼び出しを蓄積していて、gleDoDrawDispatchCore経由で呼び出しているかどうかはわかりません。ダニー。 2)私は、外部のフックを持たない私の未使用の内部3Dオブジェクトメソッドの1つをGLEngineが呼び出すことを示すので、Instrumentsに問題があると思います。私はXcodeのブレークポイントを設定してダブルチェックし、決してトリップしませんでした。私は3DSをやりません。

私は周りを見回し、おそらく答えにつきものになると思います。誰かが私に構造の配列が行く方法であるかどうかについての意見を与えるなら、それは認められるだろう。

解決策: このフロントエンドにVBOを追加して、すべて正常です。元のコードはOpenGL ES 2.0ガイドから来たもので、VBOを追加すると私の問題は解決しました。 60時のフレームレート、1ミリ秒のドライバーコール。コードは次のとおりです。

glGenVertexArrays(1, &vaoName); 
glBindVertexArray(vaoName); 

// new - create VBO 
glGenBuffers(1, &vboName); 
glBindBuffer(GL_ARRAY_BUFFER, vboName); 

// Allocate and load position data into the VBO 
glBufferData(GL_ARRAY_BUFFER, sizeof(struct vertexAttribs) * self.numVertices,            
        vertexAttribData, GL_STATIC_DRAW); 
// end of new 

NSUInteger vtxStride = sizeof(struct vertexAttribs); 
//GLfloat *vtxBuf = (GLfloat *)vertexAttribData; // no longer use this 
GLfloat *vtxBuf = (GLfloat *)NULL;    // use this instead 

glEnableVertexAttribArray(self.posAttribute); 
glVertexAttribPointer(self.posAttribute, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, 
         vtxStride, vtxBuf); 
vtxBuf += VERTEX_POS_SIZE; 

glEnableVertexAttribArray(self.normAttribute); 
glVertexAttribPointer(self.normAttribute, VERTEX_NORM_SIZE, GL_FLOAT, GL_FALSE, 
         vtxStride, vtxBuf); 
vtxBuf += VERTEX_NORM_SIZE; 

glEnableVertexAttribArray(self.texCoordAttribute); 
glVertexAttribPointer(self.texCoordAttribute, VERTEX_TEX_SIZE, GL_FLOAT, GL_FALSE, 
         vtxStride, vtxBuf); 
... 
+0

属性配列を設定するコードを投稿できますか?速いバージョンと遅いバージョンの両方 –

+1

解決策を回答として投稿して受け入れることができるので、他の人がこの問題が解決したことを知ることができますか? –

答えて

0

構造体のメモリ内での単位ストライドアクセスを達成するための配列は経験則です。 GPUだけでなく、Intel Xeon PhiなどのCPUSやCoプロセッサにも適用されます。

あなたのケースでは、このコード部分がGPUに送信されているとは思われません。代わりに、パフォーマンスの低下は、ユニットストライドではないメモリアクセス(CPUとメモリ間)によるものです。