Problems with glCompressedTexSubImage3D

Hello all,

I am getting some behavior which I don’t understand when trying to replace pieces of a compressed texture. The texture is created like this :

glBindTexture(GL_TEXTURE_3D, texId);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
glCompressedTexImage3D(GL_TEXTURE_3D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, depth, 0, bufSize, buffer);

Then replacing texture with already compressed image :

glCompressedTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, subTexWidth, subTexHeight, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, subTexSize, subTexBuffer);

This works fine when “depth” above is 1, but not for any larger number. Creating the buffer is still fine, however glGetError() returns “invalid operation” after the call to glCompressedTexSubImage3D.

Also, it works fine if I use an uncompressed image and do replacement like this:
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, subTexSize, subTexSize, 1, GL_RGBA, GL_UNSIGNED_BYTE, unCompBuf);

I assume in this case it is compressing for me when uploading the image.

I also have one more question about this, which I believe is a separate issue. The largest width/height I can use seems to be 512/512 (anything larger causes glGetError() give “invalid value”). When creating an uncompressed 3d texture I can use 4096/4096 without any problems on the same hardware.

Thanks in advance.

EXT_texture_compression_s3tc doesn’t support 3D textures.

NV_texture_compression_vtc does support S3TC formats with 3D textures, but you have to edit on 4x4x4 boundaries. Your CompressedTexSubImage call has a depth of 1, so that should fail (unless the texture is only 1 slice deep, or you’re editing the last slice, and that slice starts on a 4-slice boundary.)

Thanks for your quick response.
Reading about NV_texture_compression_vtc made this much clearer for me. I was expecting compression on a per slice basis (4x4x1 rather than 4x4x4). It is interesting that it handles this correctly for an uncompressed image, even when replacing only one slice.

I think what I really want here is to use an array texture, but I was trying to do this with a regular 3d texture because I get “invalid enumerant” when I try to do glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, texId).
My goal here is to create a 3D texture atlas. Any suggestions would be welcome.

Thanks again.

It depends on what you need. Mipmapping? Filtering between slices? Fast updates? Hardware compatibility?

Any mipmapping or repeat wrapping won’t play well with atlases in general. If you need filtering in XY and Z, 2D_ARRAY isn’t a good choice. Array textures need EXT_texture_array, which is generally only on SM4 hardware.

An uncompressed 3D texture is the simplest solution with the most hardware compatibility (but watch out for MAX_3D_TEXTURE_SIZE, which can be as low as 128.)