10

I'm making an iPhone application with OpenGL ES 2.0 using the GLKit. I'm using GLKTextureLoader to load textures synchronously.

The problem is that for a certain texture, it fails to load it the first time. It gives this error:

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

For this error code, the apple documentation says the following:


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

(not very much).

Could I be trying to load the texture while the opengl context is in some busy state or something like that?

Notes:

  • Before getting to load this texture I load other textures and those work on the first try. Also, the exact same texture file will load ok on the second try.
  • There should be enough free video memory as I have only a couple of textures loaded before this one.
  • The texture is an uncompressed PNG with alpha, but I also tried with TGA (24bit & 32bit) with no luck.

Any ideas are welcomed, thanks

EDIT:

More info:

  • the opengl context is shared between all my screens. I'm doing this to keep my shaders and textures loaded between screens.

  • the problem above happens when I go to my second screen. In the first screen I draw textured stuff with no problems (other textures though).

  • The problem above happens when I load my content (game entities) in the game world. Each entity tries to load the texture. I have a simple caching system that loads the texture only once and then returns the same id for all other entities. I'm loading the entities synchronously, in one method. The first entity fails to load the texture then comes the second and succeeds and then the third one gets the cached id.

  • I am calling the load entities method in viewDidAppear and I've tried to add a sleep for 2 seconds before I load any entities but nothing changed.

EDIT:

Texture loading code:


- (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;
}


Andrei Stanescu
  • 6,353
  • 4
  • 35
  • 64
  • you say you're loading other textures fine before the problematic one - are all these (incl the one that fails) in the same method? if not it may well be that the current gl context hasn't been set. – Mike K Dec 23 '11 at 01:14
  • thanks for the comment. I've added more info to the question – Andrei Stanescu Dec 23 '11 at 08:41
  • hmm you're loading textures (not just the entities) synchronously with something like: + (GLKTextureInfo *)textureWithContentsOfFile:(NSString *)fileName options:(NSDictionary *)textureOperations error:(NSError **)outError ? – Mike K Dec 23 '11 at 08:48
  • exactly. I've posted my texture loading code above – Andrei Stanescu Dec 23 '11 at 13:46
  • Have you tried to load entities in viewDidLoad instead viewDidAppear ? – Johnmph Dec 23 '11 at 14:02
  • yes. the problem is still there – Andrei Stanescu Dec 23 '11 at 16:11
  • Brett has the answer below - do not enable GL_TEXTURE until after you've loaded. – Cthutu Jul 24 '12 at 13:53
  • @Chutu, as I said to Brett, I'm not enabling GL_TEXTURE anywhere. I'm using OpenGL ES 2.0, and it simply isn't necessary to enable GL_TEXTURE. – Andrei Stanescu Jul 25 '12 at 09:43
  • Also, I just tested the project again, and the problem went away. The project remained in the same state as when I asked the question, so I am thinking maybe it was due to a bug in the SDK? – Andrei Stanescu Jul 25 '12 at 09:47

8 Answers8

32

I was also getting

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

when loading a texture late in runtime while several previous textures had loaded successfully closer to launch. I was able to solve the problem by inserting the following line of code before the GLKTextureLoader call:

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

Sure enough, GL was reporting an error, but it did not require me to address the error in order for GLKTextureLoader to work. Merely getting the GL Error was enough.

Newman
  • 336
  • 3
  • 3
  • Yes, it's a major bug in Apple's code. Someone wasn't thinking properly, and they decided to return a "failure" if the global GL state had any errors, instead of writing the 1-line to check if it was already set on entry to their method :(. – Adam Jul 20 '13 at 22:40
  • Thank you! I have spent days with this issue of random missing textures. – shelll Nov 01 '13 at 08:32
  • +1! Worked for me too. I'm developing on Xcode5 deploying on a 6.1 device. Looks like if OpenGL has any existing error it will just cause the GLKTextureLoader to not attempt to load the texture (which is... well... I'm okay with it.) – Steven Lu Dec 06 '13 at 03:34
  • It helped me too, using xCode 7.0 on iOS 9.0 device. – CryingHippo Oct 15 '15 at 13:27
4

I got this when enabling textures before loading the texture. Simply moved glEnable(GL_TEXTURE) after the loading and the issue was gone.

Brett
  • 2,635
  • 22
  • 35
3

Maybe you've resolved this, but are you using multiple contexts? maybe you should be loading your texture asynchronously with sharegroup.

so instead of using tex = [GLKTextureLoader textureWithContentsOfFile:bundlepath options:options error:&error];

use something like:

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
}];
lzl
  • 469
  • 4
  • 10
3

I had a similar problem. Is was caused by a texture that had width / height not power of 2. GLKTextureLoader failed on loading this and the following images. Checking glGetError() after each texture load revealed the troublemakers :-).

2

Ok, I'll try this one again as I ran into the error again. What appears to happen is that if there is some other glError that has not been processed, then you will have trouble with the texture loading on the first time.

Before you load that texture that fails, check for a glError and then track down where that error occurred. Or you can capture an opengl frame prior to where the texture is loaded and see if a glError is being thrown prior. This happened to me both times when I ran into the error 8, and both times this error disappeared once I fixed the error that had occurred earlier.

John Stricker
  • 383
  • 3
  • 6
1

I've also found that you get this error when trying to create a 2D texture with an image larger than the maximum texture size. For the max size you can see Apple's Open GL ES Platform Notes, although those do not appear correct for newer devices so the best bet is to get the value directly.

Community
  • 1
  • 1
brett
  • 385
  • 3
  • 6
1

I ran into the same problem. I'm not exactly sure as to why it occurred exactly other than that it appeared that there were multiple file operations going on at the same time. For example, performing a file load (for model data) right AFTER using the texture loader for the first time would cause error 8 to pop up. I fixed it in my program by having some other operations occur after the texture loader is called for the first time.

0

I had very similar problem and it has been solved by calling setCurrentContext.

self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:self.context];
Kiril
  • 998
  • 1
  • 11
  • 20