Load texture from other mipmap not working

This topic contains 10 replies, has 2 voices, and was last updated by  Tobias Hector 4 years, 11 months ago.

Viewing 11 posts - 1 through 11 (of 11 total)
  • Author
    Posts
  • #30779

    Glennx
    Member

    I just upgraded my project to the latest SDK and it seems that

    PVRTTextureLoadFromPointer is failing when the nLoadFromLevel parameter is anything other than 0.

    Textures seem to appear completely black when passed a 1.

    This seems to be true for various formats including:

    PVRTC 4 bit

    RGBA 4444

    IA 88

    I’m pretty much relying on this to handle memory issues on older iOS devices so will have to move back to an older version unless it’s fixed or somebody can tell me what I’m doing wrong.

    Thanks

    Glenn.

    #35538

    Hi Glenn,

    Which API are you using? OGLES1 or OGLES2? Also is this the GDC release or has this come from our website?

    Thanks,

    Tobias

    #35539

    Glennx
    Member

    GLES2, it’s the latest build from the website. Downloaded two days ago. If i’m not doing anything stupid and i’m right about the error it should be possible to make anything that uses PVRTTextureLoadFromPointer fail by changing loadFrom to 1.

    #35540

    Hi Glenn,

    Your usage appears to be correct, there are a couple of missing bits of code in the loading function. It seems that none of our demos actually use this functionality which is why it didn’t get caught before.

    I’ll push a fix to the website later, but for now you can fix it yourself it you open “<sdk>/Tools/OGLES2/PVRTTextureAPI.cpp”, and on lines 485,486,592,593,745,746,797 and 798, if you add ‘>>nLoadFromLevel’ to the end of these lines, it should fix your problem. Basically the dimensions that the texture is being loaded with are incorrect when loading from a different level.

    Thanks,

    Tobias

    Tobias2012-03-15 11:57:02

    #35541

    Glennx
    Member

    Maybe i’m only hitting it because the texture system is the only part of the SDK i’m currently using. I was rolling my own but I love the way yours has support for A8, I8, A8I8, 4444 etc. I have a tiny wrapper over the PVR system. I drop the top level on most textures which means my iPad2 targeted app fits comfortably in 3GS. I also selectively drop the top level on a few textures for iPhone4/iPad1 for memory and performance issues. I’m surprised this method isn’t used all the time as it handles almost all of my memory worries on older devices.

    I’ll try that fix as soon ASAP. Thanks very much for looking into it so quickly

    My Blog

    #35542

    Glennx
    Member

    I just tried updating to version 3.0 and it seems that this problem still exists even though the changes you describe have been made.

    I managed a partial fix by inserting this:

    for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<nLoadFromLevel; ++uiMIPLevel)
    {
    uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false);
    pTempData+=uiCurrentMIPSize;
    }

    at line 811, it seems that although the sizes were correct, the source data wasn’t being stepped into enough.
    I think I need to make this change in a few more places for legacy/other formats to fix completely.

    #35543

    Glennx
    Member

    Pasting that for loop in twice seems to fix it in all cases (that i’ve tried) at 772 & 817

    Glad I fixed this as I may well be about to start using more than just the texture system and I wouldn’t want to be stuck on an old version

    #35544

    Glennx
    Member

    Somehow that loop got corrupted, maybe this’ll work
    for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<nLoadFromLevel; ++uiMIPLevel)
    {
    uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false);
    pTempData+=uiCurrentMIPSize;
    }

    #35545

    Hi Glenn,

    Yep you’re right, not sure how I missed this since I tested that this worked before giving you the fix… but simple code inspection shows that there’s no way it worked correctly. I’m just going to assume that I went temporarily insane 🙂

    The easiest fix I can see is to just loop through all levels, and have an if statement for the levels that you actually load (beyond nLoadFromLevel). So in other words, from lines 744 to 851, replace with:

    //Initialise the width/height
    PVRTuint32 u32MIPWidth = sTextureHeader.u32Width;
    PVRTuint32 u32MIPHeight = sTextureHeader.u32Height;

    //Temporary data to save on if statements within the load loops.
    PVRTuint8* pTempData=NULL;
    PVRTextureHeaderV3 *psTempHeader=NULL;
    if (bIsCompressedFormat && !bIsCompressedFormatSupported)
    {
    pTempData=(PVRTuint8*)pDecompressedData;
    psTempHeader=&sTextureHeaderDecomp;
    }
    else
    {
    pTempData=pTextureData;
    psTempHeader=&sTextureHeader;
    }

    //Loop through all MIP levels.
    if (bIsLegacyPVR)
    {
    //Temporary texture target.
    GLint eTextureTarget=eTarget;

    //Loop through all the faces.
    for (PVRTuint32 uiFace=0; uiFaceu32NumFaces; ++uiFace)
    {
    //Loop through all the mip levels.
    for (PVRTuint32 uiMIPLevel=0; uiMIPLevelu32MIPMapCount; ++uiMIPLevel)
    {
    //Get the current MIP size.
    uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false);

    if (uiMIPLevel>=nLoadFromLevel)
    {
    //Upload the texture
    if (bIsCompressedFormat && bIsCompressedFormatSupported)
    {
    glCompressedTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData);
    }
    else
    {
    glTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData);
    }
    }
    pTempData+=uiCurrentMIPSize;

    //Reduce the MIP Size.
    u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1);
    u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1);
    }

    //Increase the texture target.
    eTextureTarget++;

    //Reset the current MIP dimensions.
    u32MIPWidth=psTempHeader->u32Width;
    u32MIPHeight=psTempHeader->u32Height;

    //Error check
    if(glGetError())
    {
    FREE(pDecompressedData);
    PVRTErrorOutputDebug(“PVRTTextureLoadFromPointer failed: glTexImage2D() failed.n”);
    return PVR_FAIL;
    }
    }
    }
    else
    {
    for (PVRTuint32 uiMIPLevel=0; uiMIPLevelu32MIPMapCount; ++uiMIPLevel)
    {
    //Get the current MIP size.
    uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false);

    GLint eTextureTarget=eTarget;

    for (PVRTuint32 uiFace=0; uiFaceu32NumFaces; ++uiFace)
    {
    if (uiMIPLevel>=nLoadFromLevel)
    {
    //Upload the texture
    if (bIsCompressedFormat && bIsCompressedFormatSupported)
    {
    glCompressedTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData);
    }
    else
    {
    glTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData);
    }
    }
    pTempData+=uiCurrentMIPSize;
    eTextureTarget++;
    }

    //Reduce the MIP Size.
    u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1);
    u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1);

    //Error check
    if(glGetError())
    {
    FREE(pDecompressedData);
    PVRTErrorOutputDebug(“PVRTTextureLoadFromPointer failed: glTexImage2D() failed.n”);
    return PVR_FAIL;
    }
    }
    }

    That should work – I did a quick test to verify (twice).

    Thanks,
    Tobias

    #35546

    Glennx
    Member

    Thanks Tobias but my few lines pasted in two places effectively skips through the source data correctly, for my apps at least.

    I’m really surprised that more people don’t make use of this, I have some textures that load from level 0, 1 or 2 depending on the detected device, this not only saves memory and is the only thing that lets my game fit in 3gs, smaller textures also make the iPad1 version run measurably faster.

    I’ll stick with my own fix as it’s much smaller but if I run into any problems i’ll use yours instead.

    #35547

    No problem, I basically posted my fix just in case you ran into any problems 🙂 The code I’ve posted should be in our 3.1 release next year.

    I hadn’t actually considered this use case (I’m guessing many other developers are in the same boat?), I’m looking into redoing the texture loading to be a little neater and more reliable, so I’ll keep this in mind.

Viewing 11 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic.