Не прямой ответ, но что-то, что я заметил, и это не очень подходит для комментария.
Если вы используете GLKTextureLoader
для загрузки текстур в фоновом режиме, чтобы заменить существующую текстуру, вы должныудалить существующую текстуру в главном потоке.Удаление текстуры в обработчике завершения не будет работать.
AFAIK это потому, что:
- Каждый поток iOS требует свой собственный EAGLContext, поэтому фоновая очередь имеетсвой собственный поток со своим собственным контекстом.
- Обработчик завершения запускается в очереди, в которую вы прошли, что, скорее всего, не является основной очередью.(В противном случае вы не выполняете загрузку в фоновом режиме ...)
То есть это приведет к утечке памяти .
NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft:@YES};
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[self.asyncTextureLoader textureWithContentsOfFile:@"my_texture_path.png"
options:options
queue:queue
completionHandler:^(GLKTextureInfo *texture, NSError *e){
GLuint name = self.myTexture.name;
//
// This delete textures call has no effect!!!
//
glDeleteTextures(1, &name);
self.myTexture = texture;
}];
ToОбойти эту проблему вы можете:
- Удалить текстуру до загрузки.Потенциально схематично в зависимости от того, как устроен ваш GL.
- Удалите текстуру из главной очереди в обработчике завершения.
Итак, чтобы исправить утечку, вам нужно сделать следующее:
//
// Method #1, delete before upload happens.
// Executed on the main thread so it works as expected.
// Potentially leaves some GL content untextured if you're still drawing it
// while the texture is being loaded in.
//
// Done on the main thread so it works as expected
GLuint name = self.myTexture.name;
glDeleteTextures(1, &name)
NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft:@YES};
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[self.asyncTextureLoader textureWithContentsOfFile:@"my_texture_path.png"
options:options
queue:queue
completionHandler:^(GLKTextureInfo *texture, NSError *e){
// no delete required, done previously.
self.myTexture = texture;
}];
или
//
// Method #2, delete in completion handler but do it on the main thread.
//
NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft:@YES};
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[self.asyncTextureLoader textureWithContentsOfFile:@"my_texture_path.png"
options:options
queue:queue
completionHandler:^(GLKTextureInfo *texture, NSError *e){
// you could potentially do non-gl related work here, still in the background
// ...
// Force the actual texture delete and re-assignment to happen on the main thread.
dispatch_sync(dispatch_get_main_queue(), ^{
GLuint name = self.myTexture.name;
glDeleteTextures(1, &name);
self.myTexture = texture;
});
}];