glMapBuffer возвращает NULL на Mac, отлично работает на Windows - PullRequest
0 голосов
/ 11 ноября 2018

У меня странная проблема с попыткой перенести рабочий код игры с Windows на Mac.Я использую SDL2 и OpenGL.

Игра представляет собой простую 2D-игру, в основном, она выполняет только 2D-рендеринг спрайтов.Архитектура рендеринга проста.Я использую один статический элементный буфер массива, который предварительно заполняется при запуске (6 индексов, 4 вершины на квад), и каждый кадр я помещаю новый VBO с данными спрайта (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)

Я не уверен, что это актуально, но я получаю функции GL от SDL_GL_GetProcAddress, например:

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

I 'я действительно застрял ... кто-нибудь когда-нибудь видел что-то подобное или может указать мне на то, что я делаю неправильно?

1 Ответ

0 голосов
/ 12 ноября 2018

Если вы используете OpenGL 3.3, это означает, что ваша версия OSX сама предоставляет указатели на функции OGL. Нет необходимости извлекать их любым GetProcAddress звонком.

Еще хуже, вы используете те же имена, что и имена GL API: glMapBuffer вместо того, что рядом, например myglMapBuffer. И Apple говорит против этого:
С Apple Doc

Обратите внимание, что каждый указатель на функцию использует префикс pf, чтобы различать его от функции, на которую он указывает. Хотя использование этого префикса не является требования, лучше избегать использования точных имен функций.

Чтобы использовать один и тот же код для Windows, Linux и OSX, я рекомендую деформировать не код OSX с помощью #ifndef следующим образом:

#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
...