cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

baldurk
Journeyman III

glCopyImageSubData for small compressed mips

glCopyImageSubData thows a GL_INVALID_VALUE when copying mips of a block compressed texture that are smaller than the block size in any dimension.

e.g.


GLuint tex0 = ...; // 1x1 compressed texture


GLuint tex1 = ...; // 1x1 compressed texture




glCopyImageSubData(tex0, GL_TEXTURE_2D, 0,  0, 0, 0, tex1, GL_TEXTURE_2D, 0,  0, 0, 0,  1, 1, 1); // GL_INVALID_VALUE


I think this is invalid behaviour. Note you also get an error if you 'align' the copy region to the nearest block size, e.g. replacing the last three parameters above with 4, 4, 1. The spec isn't entirely clear on how these mips should be treated, the language says:

An INVALID_VALUE error is generated if the dimensions of either subregion exceeds the boundaries of the corresponding image object, or if the image format is compressed and the dimensions of the subregion fail to meet the alignment constraints of the format.

So you could say that a 1x1 subregion doesn't meet the alignment constraints of the format (although I think that's intended as saying you can't copy the region from (5,5) to (6,6) on a 16x16 texture, for example). However you definitely cannot specify the lower mips as 'aligned' to the nearest 4x4 block size since those would exceed the boundaries of the image at that level. I think the only valid way that makes sense is if the subregion should be specified as the mip size in texels, regardless of if that's smaller than the block size in one dimension.

I'm on the latest AMD drivers, 14.12 Omega, on an R9 290X. Note that nvidia doesn't complain and performs the copy when specifying the 'real' mip size in texels, but whether that is spec-correct or not I don't know.

Baldur

0 Likes
4 Replies
cgrant78
Adept III

I posted a similar issue a while back and still haven't receive a response. Possible driver bug with glCopyImageSubdata

0 Likes
jzhou
Staff

Hi Baldur,

From your description, I think you are right, glCopyImageSubData shouldn't return GL_INVALID_VALUE. But the sample code you provide is too less. Would you please give me more code (such as glCompressedTexImage2D) ? I want to reproduce your issue and fix this bug in our driver.

Thanks,

Jin

0 Likes

Hi there, yes I can provide more source. Below I've written some example code that illustrates the problem in an easy-to-verify way with some colours. You can also check the code I have written for my original project to detect this bug and work around it, which is simpler and does not upload any data (as it's not necessary to generate the error and detect the bug): renderdoc/gl_common.cpp at master · baldurk/renderdoc · GitHub


  // single DXT1 4x4 compressed block = 8 bytes


  // the data is random, as the contents aren't important, just that it's some colour data


  unsigned char datablock[8] = {


  0xcc, 0x84, 0x11, 0x28,


  0x51, 0xba, 0x39, 0x00,


  };



  // single DXT1 4x4 compressed block = 8 bytes


  // this block is completely black. Used to illustrate that the copy did not succeed


  unsigned char blackblock[8] = {


  0x00, 0x00, 0x00, 0x00,


  0x00, 0x00, 0x00, 0x00,


  };




  GLuint texs[2];


  glGenTextures(2, texs);


  glBindTexture(GL_TEXTURE_2D, texs[0]);


  glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 2, 2);


  glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, datablock);



  glBindTexture(GL_TEXTURE_2D, texs[1]);


  glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 2, 2);


  glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, blackblock);



  // at this point, texs[0] has some colour data, texs[1] is completely black. This can be verified by


  // binding the textures and rendering with them



  GLenum err = glGetError(); // GL_NONE returned, no errors so far



  // Perform a 2x2 copy from texs[0] (with data) to texs[1] (without colour data)


  // same result happens if you specify width and height as 4x4 to align to block size.


  glCopyImageSubData(texs[0], GL_TEXTURE_2D, 0, 0, 0, 0, texs[1], GL_TEXTURE_2D, 0, 0, 0, 0, 2, 2, 1);



  err = glGetError(); // GL_INVALID_VALUE from above copy, and debug message is thrown to ARB_debug_output



  glBindTexture(GL_TEXTURE_2D, texs[1]); // texs[1] remains black


This can be placed in any suitable codebase to verify the contents of the textures.

0 Likes

Hi ! thanks for your sample code.  We will fix it shortly.

0 Likes