glMapBuffer在Mac上返回NULL,在Windows上也可以正常工作

时间:2018-11-11 11:26:17

标签: opengl sdl sdl-2

在尝试将可运行的游戏代码从Windows迁移到Mac时,我遇到了一个奇怪的问题。我正在使用SDL2和OpenGL。

该游戏是一个简单的2D游戏,基本上只进行2D四方/子画面渲染。渲染架构很简单。我使用的是在启动时预填充的单个静态元素数组缓冲区(每个索引6个索引,每个顶点4个顶点),每帧我用一个sprite数据推送一个新的VBO(每个sprite 4个顶点,每个顶点包含xy位置,颜色为调制和uv纹理坐标)。

我这样做的方法是,在帧的开头调用glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY),将精灵数据推入给定的“数组”,然后在调用glUnmapBuffer(GL_ARRAY_BUFFER)的末尾插入SDL_GL_SwapWindow

一切似乎在Windows上都可以正常运行,但是当我尝试在Mac上编译并运行时,它也可以正常运行,但是每当我调用glMapBuffer时,它都会返回NULL

我尝试查找GL错误,但没有运气。调用glGetError()无济于事,因为它返回0。

我可能在某个地方遇到问题,并且在Windows上实际上也做错了一些事情(因为代码实际上是相同的)。可能是Windows上的驱动程序更加宽松,并且“让错误幻灯片”出现了,但是在我的Mac上却没有。

我真的很困惑……我不知道从这里去哪里。我尝试用glGetError()乱扔我的代码,但在我尝试过的任何地方都找不到零回报。

以下是设置代码(如果有帮助的话):

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

    glGenBuffers(1, &overlay_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, overlay_vbo);
    glBufferData(GL_ARRAY_BUFFER, MAX_OVERLAY_ELEMENTS * 4 * 8 * 4, 0, GL_STREAM_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8 * 4, 0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8 * 4, (GLvoid*)(2 * 4));
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * 4, (GLvoid*)(6 * 4));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    GLuint overlay_element_buffer;
    glGenBuffers(1, &overlay_element_buffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, overlay_element_buffer);

    Uint8 *indicesBytes = AcquireTempMemory();
    Uint16 *indices = (Uint16*)indicesBytes;

    for (int i = 0; i < MAX_OVERLAY_ELEMENTS; i++)
    {
        indices[6 * i + 0] = 4 * i + 0;
        indices[6 * i + 1] = 4 * i + 1;
        indices[6 * i + 2] = 4 * i + 2;
        indices[6 * i + 3] = 4 * i + 0;
        indices[6 * i + 4] = 4 * i + 2;
        indices[6 * i + 5] = 4 * i + 3;

    }
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_OVERLAY_ELEMENTS * 6 * 2, indicesBytes, GL_STATIC_DRAW);

AcquireTempMemory基本上只不过是malloc,我验证了它可以很好地分配,并且数组按预期填充(在两个版本上)。

在每一帧的开始,我绑定VAO和着色器程序(尽管无论如何只有一个),设置一些统一的材质,并映射缓冲区:

    glEnable(GL_BLEND);
glUseProgram(renderState.overlayShaderProgram);
glBindVertexArray(renderState.overlayVao);
glUniform1f(renderState.xMultUniformLocation, 1.0f / renderState.aspectRatio);
glUniform1i(renderState.textureUniformLocation, 0);

renderState.overlayRects = 0;
renderState.overlayBuffer = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

然后,所有精灵都被推入

    glUnmapBuffer(GL_ARRAY_BUFFER);
glDrawElements(GL_TRIANGLES, renderState.overlayRects * 6, GL_UNSIGNED_SHORT, (const GLvoid*)0);

(之后有一个呼叫SDL_GL_SwapWindow的消息)

我不确定是否相关,但是我正在从SDL_GL_GetProcAddress获取GL函数,如下所示:

    glMapBuffer = (glMapBuffer_TYPE)SDL_GL_GetProcAddress("glMapBuffer");
glUnmapBuffer = (glUnmapBuffer_TYPE)SDL_GL_GetProcAddress("glUnmapBuffer");

我真的被困住了……有没有人见过这样的东西,或者可以指出我做错了什么?

1 个答案:

答案 0 :(得分:0)

如果使用的是OpenGL 3.3,则意味着OSX版本单独提供了OGL函数指针。无需通过任何GetProcAddress调用来检索它们。

最糟糕的是,您使用的名称与GL API的名称相同:glMapBuffer,而不是诸如myglMapBuffer之类的名称。苹果对此表示反对:
来自Apple doc

  

请注意,每个函数指针都使用前缀pf来区分它   从它指向的功能。尽管使用此前缀不是   要求,最好避免使用确切的函数名称。

为了在Windows,Linux和OSX上使用相同的代码,我建议不要使用#ifndef来扭曲OSX代码,例如:

#ifndef __APPLE__
  glMapBuffer = (glMapBuffer_TYPE)SDL_GL_GetProcAddress("glMapBuffer");
  glUnmapBuffer = (glUnmapBuffer_TYPE)SDL_GL_GetProcAddress("glUnmapBuffer");
  //etc
#endif

此外,您可能需要此Apple测试(如果未将SDL考虑在内):

#ifdef __APPLE__
  #define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
  #include <OpenGL/gl3.h>
#endif