Использование памяти продолжает расти со временем (GLKit - iOS)

Я почти закончил свое приложение. В одном из представлений используется GLKit. У меня просто проблема с памятью. В основном происходит то, что при отображении GLKView потребление памяти постоянно увеличивается (это видно с помощью инструментов). В определенный момент он явно падает. Я не знаю много о GLKit, поэтому я надеюсь, что вы можете мне помочь.

Проблема в том, что я показываю стрелку 3d. Если я не нарисую это, все остальное не создаст никаких проблем. Это заголовочный файл, который содержит данные вершины стрелки:

#import <GLKit/GLKit.h>

struct arrowVertexData
{
    GLKVector3      vertex;
    GLKVector3      normal;
    GLKVector2      texCoord;
};
typedef struct arrowVertexData arrowVertexData;
typedef arrowVertexData* vertexDataPtr;


static const arrowVertexData MeshVertexData[] = {
    {/*v:*/{{-0.000004, 0.0294140, -0.0562387}}, /*n:*/{{0.000000, 1.000000, 0.000000}}, /*t:*/{{0.500000, 0.333333}}},
... etc...

И это код розыгрыша:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    [self.arrowEffect prepareToDraw];
    //glGenVertexArraysOES(1, &arrowVertexArray);
    //glBindVertexArrayOES(arrowVertexArray);

    glGenBuffers(1, &arrowVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, arrowVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(MeshVertexData), MeshVertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(arrowVertexData), 0);
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_TRUE, sizeof(arrowVertexData), (void *)offsetof(arrowVertexData, normal));
    glBindVertexArrayOES(arrowVertexArray);

    // Render the object with GLKit

    glDrawArrays(GL_TRIANGLES, 0, sizeof(MeshVertexData) / sizeof(arrowVertexData));

    //reset buffers
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    //disable atttributes
    glDisableVertexAttribArray(GLKVertexAttribNormal);
    glDisableVertexAttribArray(GLKVertexAttribPosition);
}

Любое предложение? Большое спасибо за помощь!

2 ответа

Решение

Вы создаете новый буфер вершин (VBO) каждый раз, когда вызывается drawInRect, и никогда не удаляете их. GLGenBuffers и GLBindBuffer создали и новый буфер и сделали его текущим, но реальный ущерб нанесен GLBufferData, который копирует данные в новый буфер.

glBindBuffer (GL_ARRAY_BUFFER, 0); сбрасывает GL, чтобы не использовать буфер, и glDisableVertexAttribArray(GLKVertexAttribPosition); говорит GL больше не искать данные о положении в буфере, но ни один из этих вызовов не делает ничего, чтобы освободить память. Если вы хотите каждый раз освобождать память, вам необходимо вызвать GLDeleteBuffers(1, &arrowVertexBuffer); освободить память.

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

Похоже, вы также пошли по пути использования объекта Vertex Array (VAO), который был бы еще одним способом захвата состояния один раз для повторного использования, хотя может быть лучше подождать, пока VBO будет работать правильно, прежде чем пытаться это делать. И VBO, и VAO - это методы для кэширования состояний, которые со временем развивались, чтобы каждый раз снижать нагрузку в цикле рендеринга, но VAO создают гораздо более широкую сеть, что может усложнить ее правильное использование.

В качестве общего предложения вы можете привлечь больше внимания к такому вопросу, добавив более общий и популярный тег, такой как [Open GL].

Еще один инструмент отладки, который вы обязательно должны попробовать - это OpenGL Profiler. Если вы не установили его с XCode, найдите его в документации и найдите ссылку для загрузки пакета графических инструментов. Окно ресурсов позволит вам отслеживать используемые буферные объекты.

Вы пытались запустить статический анализатор в Xcode?

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

Чтобы использовать его, удерживайте кнопку мыши на кнопке "Выполнить" и выберите "Анализ" из выпадающего списка.

Если он что-то находит, он обычно указывает на них синим цветом, и вы можете видеть линии, прослеживающие место, где память распределяется, а не освобождается, и т. Д...

Дайте мне знать, если это имеет какое-либо влияние.

Другие вопросы по тегам