glCopyImageSubData

Hey all,

I currently want to copy a texture with glCopyImageSubData, but I just get an INVALID_OPERATION. Anyone a idea?

My test source:

GLuint tex[2];
gl->glGenTextures(2, tex);
gl->glBindTexture(GL_TEXTURE_2D, tex[0]);
GLuint texData[60]; //random data
gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, 10, 6, 0, GL_RED_INTEGER, GL_INT, &texData);
gl->glBindTexture(GL_TEXTURE_2D, tex[1]);
gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, 10, 6, 0, GL_RED_INTEGER, GL_INT, nullptr);

qDebug() << "before copy " << gl->glGetError(); //0
gl->glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 0, 0, 0, tex[1], GL_TEXTURE_2D, 0, 0, 0, 0, 10, 6, 1);
qDebug() << "after copy " << gl->glGetError(); //1282 => INVALID_OPERATION

gl->glDeleteTextures(2, tex);

One thing I noticed is that texData is an array which can be implicitly cast when passing to glTexImage2D, however, you are passing a reference(&texData) to the array which ends up being interpreted as a (**), you need to either pass texData or &texData[0], to prevent GL trying to read data from an invalid address. Another thing is unless nullptr can be implictly cast to a GLvoid* I would refrain from using nullptr and use 0, if they are equivalent then all is well. Aside from that, everything else looks correct. What GPU and driver version are you using?

You are right with texData. But this don’t change anything if I fix it :(. Setting MIN_FILTER/MAG_FILTER and WRAP before, don’t help too :(.

I have a GT435M with latest driver (337.50)

Another thing to check is to consult the specification to see if the formats being copied are compatible…try with a RGBA texture and see if that works…then try again with the format you listed above. If it works with the RGBA texture and not with your GL_R32I format, then its either a driver bug or the format is not supported by the function( check the spec to verify though ).

The spec don’t list any limitation to format as long as source and target are the same. Only if you copy from compressed to uncompressed format exists limitations.

I tried it now with default texture format, but it still don’t work:

GLuint tex[2];
gl->glGenTextures(2, tex);
gl->glBindTexture(GL_TEXTURE_2D, tex[0]);
GLubyte texData[3*60]; //random data
gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 10, 6, 0, GL_RGB, GL_UNSIGNED_BYTE, texData);
gl->glBindTexture(GL_TEXTURE_2D, tex[1]);
gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 10, 6, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);

qDebug() << "before copy " << gl->glGetError(); //0
gl->glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 0, 0, 0, tex[1], GL_TEXTURE_2D, 0, 0, 0, 0, 10, 6, 1);
qDebug() << "after copy " << gl->glGetError(); //1282 => INVALID_OPERATION

gl->glDeleteTextures(2, tex);

And how I can report a driver bug?

glCopyImageSubData can generate invalid operation errors for the following reasons:
GL_INVALID_OPERATION​ is generated if the texel size of the uncompressed image is not equal to the block size of the compressed image.
GL_INVALID_OPERATION​ is generated if either object is a texture and the texture is not complete.
GL_INVALID_OPERATION​ is generated if the source and destination internal formats are not compatible, or if the number of samples do not match.

I would expect that the second condition kicks in here.
The default minification filter uses mipmaps, you didn’t provide any and didn’t say which modes you tried before on both textures.

I would try the following things:

  • Set min and mag filters to nearest on both before the copy.
  • Unbind tex[1] before doing the copy.
  • Try filling in dummy data to the tex[1] image data before the copy. (Shouldn’t be necessary.)

Additionally GL_RGB with the default glPixelStore GL_UNPACK_ALIGNMENT of 4 won’t read texture rows correctly in glTexImage2D in your case.

GL_RGB is a legacy internal format. I would recommend to always use internal formats with explicit precision qualifiers. Use GL_RGB8 or better GL_RGBA8 since that’s what it ends up internally in most implementations anyway.

Tried it now - and it works now :). Last time I tried it with setting min/mag filter is doesn’t work - this time (exact same code - have a copy of my last test code, it didn’t :/).

Working minimal example:

GLuint tex[2];
gl->glGenTextures(2, tex);
gl->glBindTexture(GL_TEXTURE_2D, tex[0]);
GLint texData[60]; //random data
gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, 10, 6, 0, GL_RED_INTEGER, GL_INT, &texData);
gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

gl->glBindTexture(GL_TEXTURE_2D, tex[1]);
gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, 10, 6, 0, GL_RED_INTEGER, GL_INT, nullptr);
gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

qDebug() << "before copy " << gl->glGetError(); //0
gl->glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 0, 0, 0, tex[1], GL_TEXTURE_2D, 0, 0, 0, 0, 10, 6, 1);
qDebug() << "after copy " << gl->glGetError(); //0

gl->glDeleteTextures(2, tex);