1

iOS での VAO の作成に問題があります。場合によっては問題なく動作し、glGenVertexArraysOES は 2 番目の引数を介してゼロ以外の VAO を返しますが、それ以外の場合は、glGetError() を介して単にゼロを返し、エラーはありません。

私は2つのケースを持っています。1つは機能しますが、もう1つは機能しません。どちらも初期化コードであり、どちらも多かれ少なかれ同じコードです。

働く:

glGenBuffers(1, &m_vertexBufferObject);
errorCheck();

GLuint vao = 0;
glGenVertexArraysOES(1, &vao);
errorCheck();
glBindVertexArrayOES(vao);
errorCheck();

(vao set up goes here)

(vao != 0)

動作していません:

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArrayOES(0);

errorCheck();
GLuint vao = 0;
glGenVertexArraysOES(1, &vao);
errorCheck();
glBindVertexArrayOES(vao);
errorCheck();

(vao == 0)

動作していないブロックの glBind* 関数は、以前にバインドされた状態を緩和することで問題を解決しようとする試みにすぎません。役に立ちませんでした。

コードはマルチスレッドです。私は 1 つのコンテキストを持っており、ミューテックスを介して一度に 1 つのスレッドのみがそれを使用することが許可されています。スレッドがコンテキストを取得したら、ミューテックスをロックして setCurrentContext を呼び出します。その後、現在のコンテキストを nil に戻します。私が他の場所で読んだことから、これは許容できるマルチスレッド設定であると信じています。いずれにせよ、スレッド化を無効にしてすべてを同じスレッドで実行しても違いはありません!

成功のケースは、開始時、つまり初期化時に発生します。それはうまくいきます...他のケースは、レンダリングループが進行している間、ロード時に発生します(ただし、前述のクリティカルセクションとコンテキスト割り当てによってまだマーシャリングされています)。これは失敗するケースです。

基本的に、glGenVertexArrayOES の実行には、満たされていない何らかの前提条件が必要であると想定しています。後者の場合、実際には VAO セットアップの本体ではないと思います。最初の VAO セットアップの成功と、その後のセットアップの試行の間に発生するものだと思います。

sim と電話の両方で失敗するので、明らかに何かが起こっています... しかし、それはサイレントエラーなので、調査する角度がありません. OS X の OpenGL で問題なく動作します。さらに、エラーまたは同様の状態を再現しようとします (たとえば、サンプル コードのさまざまな部分のスレッド化が失敗しました。

何か案は?

ありがとう。

4

2 に答える 2

1

これは、GLKViewController から派生したビューのクラスです。

@interface IncubeViewController : GLKViewController {
      ...
}

これは私がvaoをロードする方法です:

- (void) loadGeometry
{
        /* Pieces */
        for (int i = ptFirst; i < ptLast; i++) {
                glGenVertexArraysOES(1, &pieceObject[i].array);
                glBindVertexArrayOES(pieceObject[i].array);

                glGenBuffers(1, &pieceObject[i].buffer);
                glBindBuffer(GL_ARRAY_BUFFER, pieceObject[i].buffer);

                glBufferData(GL_ARRAY_BUFFER, vertextData[i].vertNumber * sizeof(Vertex),
                             vertextData[i].vertArray, GL_STATIC_DRAW);

                glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_TRUE,
                                      sizeof(Vertex), (void *)offsetof(Vertex, position));
                glEnableVertexAttribArray(GLKVertexAttribPosition);
                glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_TRUE,
                                      sizeof(Vertex), (void *)offsetof(Vertex, normal));
                glEnableVertexAttribArray(GLKVertexAttribNormal);
        }

        /* Cube */
        glGenVertexArraysOES(1, &cubeObject.array);
        glBindVertexArrayOES(cubeObject.array);

        glGenBuffers(1, &cubeObject.buffer);
        glBindBuffer(GL_ARRAY_BUFFER, cubeObject.buffer);

        glBufferData(GL_ARRAY_BUFFER, CubeDataNumberOfVertices * sizeof(Vector3),
                     CubeData, GL_STATIC_DRAW);

        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE,
                              0, (void *)0);
        glEnableVertexAttribArray(GLKVertexAttribPosition);

        /* Sphere */
        glGenVertexArraysOES(1, &sphereObject.array);
        glBindVertexArrayOES(sphereObject.array);

        glGenBuffers(1, &sphereObject.buffer);
        glBindBuffer(GL_ARRAY_BUFFER, sphereObject.buffer);

        glBufferData(GL_ARRAY_BUFFER, SphereDataNumberOfVertices * sizeof(Vertex),
                     SphereData, GL_STATIC_DRAW);

        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE,
                              sizeof(Vertex), (void *)offsetof(Vertex, position));
        glEnableVertexAttribArray(GLKVertexAttribPosition);
        glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE,
                              sizeof(Vertex), (void *)offsetof(Vertex, normal));
        glEnableVertexAttribArray(GLKVertexAttribNormal);

        /* Diagonal grid */
        glGenVertexArraysOES(1, &diagonalGridObject.array);
        glBindVertexArrayOES(diagonalGridObject.array);

        glGenBuffers(1, &diagonalGridObject.buffer);
        glBindBuffer(GL_ARRAY_BUFFER, diagonalGridObject.buffer);

        glBufferData(GL_ARRAY_BUFFER, sizeof(diagonalGridData),
                     diagonalGridData, GL_STATIC_DRAW);

        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE,
                              sizeof(Vector3), (void *)0);
        glEnableVertexAttribArray(GLKVertexAttribPosition);

        glBindVertexArrayOES(0);
}

- (void) unloadGeometry
{
        glDeleteBuffers(1, &diagonalGridObject.buffer);
        glDeleteVertexArraysOES(1, &diagonalGridObject.array);
        glDeleteBuffers(1, &cubeObject.buffer);
        glDeleteVertexArraysOES(1, &cubeObject.array);
        glDeleteBuffers(1, &sphereObject.buffer);
        glDeleteVertexArraysOES(1, &sphereObject.array);
        for (int i = ptFirst; i < ptLast; i++) {
                glDeleteBuffers(1, &pieceObject[i].buffer);
                glDeleteVertexArraysOES(1, &pieceObject[i].array);
        }
}

あなたが何か間違ったことをしていることを示しているわけではありませんが、誰かがそれを必要とする場合に参照するためだけにここに追加します.

私が持っている1つの説明は、アプリの初期化の間違った瞬間にvaoを作成しようとしているか、初期化が完全に正しくなかったということです(たとえば、コンテキストが設定されていません)。

ここに次のスタックがあります。

- (void)setupGL
{
        [EAGLContext setCurrentContext:self.context];

        self.effect = [[[GLKBaseEffect alloc] init] autorelease];
        if (self.effect) {
                self.effect.useConstantColor = GL_TRUE;
                self.effect.colorMaterialEnabled = GL_TRUE;
                self.effect.light0.enabled = GL_TRUE;
                self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 1.0f, 1.0f, 1.0f);
        }

        ((GLKView *)self.view).drawableMultisample = GLKViewDrawableMultisample4X;
        self.pauseOnWillResignActive = YES;
        self.resumeOnDidBecomeActive = YES;
        self.preferredFramesPerSecond = 30;

        glDisable(GL_DITHER);
        glEnable(GL_CULL_FACE);
        glEnable(GL_DEPTH_TEST);
        glLineWidth(2.0f);
        [self loadGeometry];
}

- (void)viewDidLoad
{
        [super viewDidLoad];
        self.context = [[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2] autorelease];
        if (!self.context)
                NSLog(@"Failed to create ES context");

        GLKView *view = (GLKView *)self.view;
        view.context = self.context;
        view.drawableDepthFormat = GLKViewDrawableDepthFormat24;

        [self setupGL];
}
于 2013-01-01T11:02:08.497 に答える
0

わかりました、私はついにこれをクラックしました。

スレッド上でいくつかの OpenGL ops の前後に setCurrentContext を呼び出す RAII のようなコードがいくつかあったことがわかりました。重要なことに、スコープが終了すると [EAGLContext setCurrentContext:nil] になります...しかし、これらのスコープはネストでき、最後のスコープではなく、ネストされたスコープごとにそれを行いました。

その結果、OpenGL が呼び出されたときに現在のコンテキストが nil でした。OpenGL 呼び出しは「何もしない」だけで、「何もしない」には「エラーをスローしない」が含まれます。

そのため、現在のコンテキスト セットがない場合、Mac の GL はクラッシュするように見えますが、IOS の GLES はエラーなしで早期に終了します。

于 2013-01-02T07:56:08.487 に答える