Сбой GLKTextureLoader при первой загрузке определенной текстуры, но во второй раз

Я делаю приложение для iPhone с OpenGL ES 2.0, используя GLKit. Я использую GLKTextureLoader для синхронной загрузки текстур.

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

The operation couldn’t be completed. (GLKTextureLoaderErrorDomain error 8.)

Для этого кода ошибки в документации Apple сказано следующее:


GLKTextureLoaderErrorUncompressedTextureUpload
An uncompressed texture could not be uploaded.
Available in iOS 5.0 and later.
Declared in GLKTextureLoader.h.

(не очень много).

Могу ли я пытаться загрузить текстуру, когда контекст opengl находится в состоянии занятости или что-то в этом роде?

Заметки:

  • Перед загрузкой этой текстуры я загружаю другие текстуры, и они работают с первой попытки. Кроме того, точно такой же файл текстуры будет загружаться нормально со второй попытки.
  • Свободной видеопамяти должно быть достаточно, так как перед этим у меня загружено всего несколько текстур.
  • Текстура представляет собой несжатый PNG с альфа-каналом, но я также попытался с TGA (24-битный и 32-битный), но не повезло.

Любые идеи приветствуются, спасибо

РЕДАКТИРОВАТЬ:

Больше информации:

  • контекст opengl используется всеми моими экранами. Я делаю это, чтобы мои шейдеры и текстуры загружались между экранами.

  • проблема выше происходит, когда я иду на мой второй экран. На первом экране я рисую текстурные вещи без проблем (хотя другие текстуры).

  • Проблема выше возникает, когда я загружаю свой контент (игровые объекты) в игровой мир. Каждый объект пытается загрузить текстуру. У меня есть простая система кэширования, которая загружает текстуру только один раз, а затем возвращает тот же идентификатор для всех других объектов. Я загружаю объекты синхронно, одним способом. Первая сущность не может загрузить текстуру, затем приходит вторая и успешно, а третья получает кэшированный идентификатор.

  • Я вызываю метод загрузки сущностей в viewDidAppear и я пытался добавить сон на 2 секунды, прежде чем загружать какие-либо объекты, но ничего не изменилось.

РЕДАКТИРОВАТЬ:

Код загрузки текстуры:


- (GLKTextureInfo *)loadTextureAtPath:(NSString*)path ofType:(NSString*)type withKey:(NSString *)key 
{
    GLKTextureInfo* tex;

    tex = [self textureWithKey:key];
    if (tex)
        return tex;

    NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
                              [NSNumber numberWithBool:NO],
                              GLKTextureLoaderOriginBottomLeft, 
                              nil];

    NSError * error;    
    NSString *bundlepath = [[NSBundle mainBundle] pathForResource:path ofType:type];

    tex = [GLKTextureLoader textureWithContentsOfFile:bundlepath options:options error:&error];
    if (tex == nil) 
        DLOG_LOCAL(@"Error loading texture: %@", [error localizedDescription]);                
    else
        [textures setObject:tex forKey:key];

    return tex;
}


8 ответов

Решение

Я также получал

The operation couldn’t be completed. (GLKTextureLoaderErrorDomain error 8.)

при загрузке текстуры в конце времени выполнения, когда несколько предыдущих текстур были успешно загружены ближе к запуску. Я смог решить эту проблему, вставив следующую строку кода перед GLKTextureLoader вызов:

NSLog(@"GL Error = %u", glGetError());

Конечно, GL сообщал об ошибке, но мне не требовалось исправлять ее, чтобы GLKTextureLoader работать. Достаточно просто получить ошибку GL.

Я получил это при включении текстур перед загрузкой текстуры. Просто переместил glEnable(GL_TEXTURE) после загрузки и проблема исчезла.

Может быть, вы решили эту проблему, но вы используете несколько контекстов? возможно, вам следует загружать текстуру асинхронно с помощью sharegroup.

поэтому вместо использования tex = [GLKTextureLoader textureWithContentsOfFile: параметры пути пакета: параметры ошибки:& ошибка];

использовать что-то вроде:

GLKTextureLoader *textureloader = [[GLKTextureLoader alloc] initWithSharegroup:self.eaglContext.sharegroup];
GLKTextureInfo *myTexture;
[textureloader textureWithCGImage:_currentForegroundImage.CGImage options:nil queue:nil completionHandler:^(GLKTextureInfo *textureInfo, NSError *error) {
        myTexture = textureInfo;
        if(error) {
            // log stuff
        }
        // do something
}];

У меня была похожая проблема. Это было вызвано текстурой, ширина / высота которой не была равна 2. GLKTextureLoader не удалось загрузить это и следующие изображения. Проверка glGetError() после каждой загрузки текстуры выявляла нарушителей:-).

Хорошо, я попробую еще раз, когда снова столкнулся с ошибкой. Похоже, что происходит, если есть еще один glError, который не был обработан, то у вас будут проблемы с загрузкой текстуры в первый раз.

Перед загрузкой текстуры, которая не работает, проверьте наличие glError, а затем отследите, где произошла эта ошибка. Или вы можете захватить фрейм opengl до того, где будет загружена текстура, и посмотреть, не было ли выброшено glError. Это случилось со мной оба раза, когда я столкнулся с ошибкой 8, и оба раза эта ошибка исчезла, как только я исправил ошибку, которая произошла ранее.

Я также обнаружил, что вы получаете эту ошибку при попытке создать 2D текстуру с изображением, размер которого превышает максимальный размер текстуры. Максимальный размер вы можете увидеть в заметках Apple OpenGLESPlatform, хотя они не выглядят корректными для более новых устройств, поэтому лучше всего получить значение напрямую.

Я столкнулся с той же проблемой. Я не совсем уверен, почему это произошло именно потому, что оказалось, что одновременно выполнялось несколько файловых операций. Например, выполнение загрузки файла (для данных модели) сразу ПОСЛЕ использования загрузчика текстур в первый раз вызовет ошибку 8. Я исправил это в своей программе, заставив некоторые другие операции выполняться после первого вызова загрузчика текстур.

У меня была очень похожая проблема, и она была решена путем вызова setCurrentContext.

self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:self.context];
Другие вопросы по тегам