1

我在 iOS 上创建 VAO 时遇到问题。有时它工作得很好,glGenVertexArraysOES 通过第二个参数返回一个非零 VAO,但其他时候,它只是通过 glGetError() 返回零并且没有错误

我有两个案例。一个有效,另一个无效。它们都在初始化代码中,并且它们或多或少都是相同的代码:

在职的:

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* 函数在很大程度上只是试图通过减轻任何先前绑定的状态来解决问题。它没有帮助。

代码是多线程的。我有一个上下文,并且一次只允许一个线程通过互斥锁使用它。当线程获取上下文时,我锁定互斥体并调用 setCurrentContext。之后我将当前上下文恢复为零。我相信这应该是我在别处读到的可接受的多线程设置。无论如何,禁用线程并在同一线程上运行所有内容都没有区别!

成功的案例发生在刚开始的时候,也就是初始化的时候。这很好......另一种情况发生在加载期间,同时渲染循环正在进行(但仍被所述关键部分和上下文分配编组),这就是失败的情况。

我基本上假设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);
        }
}

虽然它没有显示你做错了什么,但如果有人需要,我在这里添加它只是为了参考。

我的一种解释是,您试图在应用程序初始化的错误时刻创建您的 vao,或者 init 不太正确(例如,未设置上下文)。

我在这里有以下堆栈:

- (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

好的,我终于破解了这个。

事实证明,我有一些类似 RAII 的代码会在线程上的一些 OpenGL 操作之前和之后调用 setCurrentContext。至关重要的是,当一个范围结束时它会 [EAGLContext setCurrentContext:nil] ......但是这些范围可以嵌套,并且它对每个嵌套范围都这样做,而不是最后一个范围。

其结果是调用 OpenGL 时当前上下文为 nil。OpenGL 调用只会“什么都不做”,而“什么也不做”包括“不抛出错误”——你会认为 glGetError() 至少可能已经说了些什么。

所以,如果你没有设置当前的上下文,那么 Mac 上的 GL 似乎崩溃了,但 IOS 上的 GLES 只是提前退出,没有错误。

于 2013-01-02T07:56:08.487 回答