problem while loading PVRTC using glCompressedTexSubImage2D and PBO

Hello,
I have been trying to update a compressed texture of PVRTC_2BPPV2 format using PBO using OpenGL_ES 3. But every time it fails with the code GL_INVALID_OPERATION.

I am using following code to do the task:

[pre]{//buffer: (GLubyte*)holds the raw pixel data
//width: width of the texture
//height: heigth of the texture
//NUM_OF_BITS_PER_PIXEL = 2 since PVRTC_2BPPV2 is used
//so the actual data size is: (widthheight2)/8 bytes

glPixelStorei(GL_UNPACK_ALIGNMENT,1);

glGenTextures ( 1, &texId );
glBindTexture ( GL_TEXTURE_2D, texId );

glCompressedTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,width,height,0,(widthheight2)/8,0);

glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glBindTexture ( GL_TEXTURE_2D, 0 );

//creating PBO

glGenBuffers(1,&pboID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID );
glBufferData(GL_PIXEL_UNPACK_BUFFER, (width * height * 2)/8, 0, GL_STREAM_DRAW);
GLubyte* colorptr = (GLubyte*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, (width * height * 2)/8, GL_MAP_WRITE_BIT);

if(colorptr)
{
breturen = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
if(!breturen)
{
//something wrong happened
}
}

glBindTexture( GL_TEXTURE_2D, texId );
glCompressedTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,(widthheight2)/8,0);

memcpy(colorptr, buffer, (sizeof(GLubyte) * width * height *2)/8);

free ( buffer );

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0 );
glBindTexture( GL_TEXTURE_2D, 0 );}[/pre]

I have tried similarly using non-compressed textures with PBO which succeeds.
Again I have tried updating PVRTC_2BPPV2 texture using glCompressedTexSubImage2D without PBO and it succeeds too.

But the combination of Compressed texture along with PBO fails every time.

Is it not supported to update a portion/whole compressed texture using PBO or is the problem related to the emulator?

Looking forward to your replies.
Thanks.

Hi Zulkarnine,

[blockquote]Is it not supported to update a portion/whole compressed texture using PBO or is the problem related to the emulator?[/blockquote]
Unfortunately, it is not possible to replace regions of a PVRTC image.

GL_IMG_texture_compression_pvrtcThe PVRTC extension spec can be found in the Khronos registry:

Issue 5 in the specification details the sub-texturing limitations of the format:

[blockquote]5] Is sub-texturing supported?

   Resolution: Only for the reloading of complete
   images. Sub-images are not supportable because the PVRTC
   algorithm uses significant adjacency information, so there is
   no discrete block of texels that can be decoded as a standalone
   sub-unit, and so it follows that no stand alone sub-unit of
   data can be loaded without changing the decoding of surrounding
   texels.

[/blockquote]

Regards,
Joe

Hello Joe,
Thank you for your reply.

I modified the code in the following way so that the whole texture is updated:

[pre]//buffer: (GLubyte*)holds the raw pixel data
//width: width of the texture
//height: heigth of the texture
//NUM_OF_BITS_PER_PIXEL = 2 since PVRTC_2BPPV2 is used
//so the actual data size is: (widthheight2)/8 bytes

glPixelStorei(GL_UNPACK_ALIGNMENT,1);

glGenTextures ( 1, &texId );
glBindTexture ( GL_TEXTURE_2D, texId );

glCompressedTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,width,height,0,(widthheight2)/8,0);

glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glBindTexture ( GL_TEXTURE_2D, 0 );

//creating PBO

glGenBuffers(1,&pboID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID );
glBufferData(GL_PIXEL_UNPACK_BUFFER, (width * height * 2)/8, 0, GL_STREAM_DRAW);
GLubyte* colorptr = (GLubyte*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, (width * height * 2)/8, GL_MAP_WRITE_BIT);

if(colorptr)
{
GLuint breturen = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
if(!breturen)
{
//something wrong happened
}
}

glBindTexture( GL_TEXTURE_2D, texId );
glCompressedTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,width,height,0,(widthheight2)/8,0);

memcpy(colorptr, buffer, (sizeof(GLubyte) * width * height *2)/8);

free ( buffer );

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0 );
glBindTexture( GL_TEXTURE_2D, 0 );[/pre]

basically i changed:
[pre]glCompressedTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,(widthheight2)/8,0);
[/pre]
to:
[pre]glCompressedTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,width,height,0,(widthheight2)/8,0);[/pre]

But this didn’t help either. The textures is completely blank.

Am I doing something wrong or is PBO (Pixel Buffer Object) not supported with compressed textures?
Or is it a hardware bug?

Thanks again for your kind reply.

[quote quote=49301]Unfortunately, it is not possible to replace regions of a PVRTC image.

The PVRTC extension spec can be found in the Khronos registry: GL_IMG_texture_compression_pvrtc
[/quote]

Joe, it looks like Zulkarnine is using PVRTC_2BPPV2, which is defined in a different GLES extension:

This extension states (in a couple different places):

[blockquote] 2] Is sub-texturing supported?

   Resolution: Yes, at block boundaries. This is 4x4 texels for
   the 4bpp format and 8x4 for the 2bpp format. Note it is up to
   the user to ensure the compressor tool is used in the mode which
   removes block edge artefacts (sic) if subdata is going to be used for
   eg. a texture atlas.[/blockquote]

[blockquote]Joe, it looks like Zulkarnine is using PVRTC_2BPPV2, which is defined in a different GLES extension[/blockquote]
Ah - you’re right. Apologies for not spotting PVRTC2 was being used here.

[blockquote]Note it is up to
the user to ensure the compressor tool is used in the mode which
removes block edge artefacts [sic] if subdata is going to be used for
eg. a texture atlas.[/blockquote]
I’m not sure if we are exposing this in PVRTexTool. I’ll speak to the lead for that tool and will update this chain once I have an answer.

Thank you Dark_Photon for pointing this out.
[blockquote]Joe, it looks like Zulkarnine is using PVRTC_2BPPV2, which is defined in a different GLES extension:[/blockquote]
To be sure I tested with subTextures without PBO and it worked seamlessly. But I still can’t find why the texture/subTexture cannot be updated using PBO.

Some sample results:

  1. RGB Full texture update (NO PBO):

[attachment file=“nonPVRTCfullImage.PNG”]

  1. PVRTC Full texture update (NO PBO): (Yes it’s a different texture and it should look like that)

[attachment file=“fullTexture update.PNG”]

  1. RGB texture partial update + PBO :

[attachment file=“normalImageSubTextureUpdate.PNG”]

  1. PVRTC texture partial update + PBO :

[attachment file=“PVRTC_plus_PBO.PNG”]

Don’t know what is going on in the last case and that is exactly what i’m having problem with :frowning:

PVRTC2 sub-texturing
The PVRTexTool lead has given me an answer. The feature discussed in the PVRTC2 extension specification has not been added to PVRTexTool yet. I’ve filed a feature request in our tracker for this (BRN56735).

If you would like to use the feature in the meantime, you could write your own tool to write the hard-edge flag for regions within a given PVRTC2 image. Section 3.1 (“Sub-texturing” bullet point) and section 3.3.2 of our “PVRTC and Texture Compression User Guide” explains how to do this. For a texture atlasing use case, you would need to set the hard-edge flag for the regions along the bottom row and rightmost column.

Using PBOs to update textures
Our “Understanding OpenGL ES: Multi-thread and multi-window rendering” blog post explains our recommendations for asynchronously updating buffers in OpenGL ES. We expect PBOs would further improve performance as the driver would not need to perform a memcpy from application memory to driver memory.

Thanks for the detailed explanation but could you clarify the following things:

  1. Is “Hard Transition Flag” on section 3.3.2 and ‘hard-edge’ mode on section 3.1 mean the same thing?
    [blockquote]If you would like to use the feature in the meantime, you could write your own tool to write the hard-edge flag for regions within a given PVRTC2 image. Section 3.1 (“Sub-texturing” bullet point) and section 3.3.2 of our “PVRTC and Texture Compression User Guide” explains how to do this.[/blockquote]

  2. Is hard-edge flag needed even when we are using [pre]glCompressedTexImage2D[/pre]
    (NOT glCompressedTexSubImage2D)

  3. When I used glCompressedTexImage2D I got the same result as in [PVRTC texture partial update + PBO attachment (PVRTC_plus_PBO.png) ] in my previous reply. So, is this an emulator limitation? (I am using PVRFRAME version 10.0)

  4. You mentioned:
    [blockquote]The feature discussed in the PVRTC2 extension specification has not been added to PVRTexTool yet[/blockquote]
    Is that feature (SubTexturing) a must in order to use PBO?

[blockquote]Is “Hard Transition Flag” on section 3.3.2 and ‘hard-edge’ mode on section 3.1 mean the same thing?[/blockquote]
Yes. I’ve filed a bug report against the document for this to be clarified in a future release (BRN56855).

[blockquote]Is hard-edge flag needed even when we are using [glCompressedTexImage2D][/blockquote]
No. The hard-edge flag is only needed to avoid artefacts in texture atlases created from PVRTC2 sub-textures.

[blockquote]Is that feature [SubTexturing] a must in order to use PBO?[/blockquote]
support ticketAfter discussing this with the TexTool lead engineer, my understanding is that PBOs should work with full texture updates (e.g. glCompressedTexImage2D()). If you can share a binary with us that reproduces the issue, I’ll ask the PVRVFrame lead to investigate. You can share files with us confidentially by attaching them to a .

Thank you for your reply.

I have attached the sample binaries in the support ticket with PVRTrace files.