Compressed Volume Texture SubImage uploading

All,

Reading the OpenGL specifications for NV_texture_compression_vtc, it seems that it should be possible to upload a sub-region of a volume texture. This does work, however if the depth of that texture is not a multiple of 4 there seems to be no way to update the last slices of the texture.

The following code shows this … in short, I have found no way to upload the last slices of a texture if the depth is not a multiple of 4 slices.


GLuint	texture_obj;
glGenTextures( 1, &texture_obj );
assert( glGetError() == GL_NO_ERROR );

glBindTexture( GL_TEXTURE_2D, texture_obj );
assert( glGetError() == GL_NO_ERROR );

glTexImage3D( GL_TEXTURE_3D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 1920, 1080, 90, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL );
assert( glGetError() == GL_NO_ERROR );

const int posn[] = { 0, 0, 88 };
const int size[] = { 1920, 1080, 2 };
const int block_size = (size[0]/4)*(size[1]/4)*size[2]*16;
void* p_mem = ::malloc( block_size );

glCompressedTexSubImage3D( GL_TEXTURE_3D, 0, posn[0], posn[1], posn[2], size[0], size[1], size[2], GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, block_size, p_mem );
assert( glGetError() == GL_NO_ERROR ); /* This always fails */

For the records, the following is from the vtc specifications :

Note the restrictions on CompressedTexSubImage3D depth and zoffset must be multiples of 4 still exist because the block is a 3D 4x4x4 block (or 4x4x2 and 4x4x1 in the end cases).

It clearly seems that the 4x4x2 and 4x4x1 blocks at the end of the texture should be supported.

Thanks in advance for any help.

Andrew

doesn’t look ambiguous to me. The subimage depth/zoffset restriction is lifted for uploading uncompressed data to a compressed texture, but not for uploading already compressed data. What’s the problem? You want the spec to be revised?
Does look a bit of an odd restriction, granted, but clearly stated.

I have re-read the specifications and they actually do not entirely seem self consistent. In one section it says :

[snip] CompressedTexSubImage3D will result in an INVALID_OPERATION error only if one of the following conditions
occurs:

  • <width> is not a multiple of four or equal to TEXTURE_WIDTH.
  • <height> is not a multiple of four or equal to TEXTURE_HEIGHT.
  • <depth> is not a multiple of four or equal to TEXTURE_DEPTH.
  • <xoffset>, <yoffset>, or <zoffset> is not a multiple of four

This clearly indicates that the depth being referred to in the sub-image update has to have a multiple of 4 pixels.

It then further down says :

Note the restrictions on CompressedTexSubImage3D that depth and zoffset must be multiples of 4 still exist because the VTC block is a 3D 4x4x4 block (or 4x4x2 and 4x4x1 in the end cases).

This is clearly stating that 4x4x1 and 4x4x2 blocks van be used in the end cases, which appears to not be the case - at least in the nVidia implementation.

For what it is worth, this is actually quite a big issue for OpenGL. Obviously, when using volume textures the size of the textures can become really quite large (as in my example above!), so if you want to keep a decent refresh rate while doing other things you are going to need to upload the textures in slices. This limitation on uploading the “end slices” means that this is not possible other than when the depth of the texture is divisible by 4.

Obviously one can pad a texture out, but that is quite inelegant and means that edge modes cannot work correctly for the z-max end of the volume.

Andrew