Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the pixel transfer format change when uploading texture data via glTexSubImage?

I'm facing a situation where, for the sake of compatibility, first I allocate a texture's storage, then I upload texture data into it. The idea is to keep the code path similar depending on whether immutable storage is supported or not supported.

In the absence of immutable storage, the storage gets allocated via a glTexImage2D call (with a NULL data pointer, no pixel unpack buffer bound), for instance like this:

glTexImage2D(GL_TEXTURE_2D, 0,
             GL_RGBA,                           
             width, height, 0,
             GL_RGBA,                           
             GL_UNSIGNED_BYTE,
             0);

After this, the actual data gets uploaded:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
                width, height,
                GL_RGBA,
                GL_UNSIGNED_BYTE,
                data);

The problem is: at upload time, can the pixel transfer format be different from the one specified when allocating the storage? Some drivers think yes, some drivers (notably: ANGLE) think not.

In other words, is then this call supposed to worK?

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
                width, height,
                GL_RGBA,
                GL_FLOAT, // <-- DIFFERENT
                data);

To my interpretation of the OpenGL 4.5 specification, yes. Not only glTexSubImage2D is supposed to work with immutable textures (and in the glTexStorage call there's no pixel transfer format specified); the 4.5 specification says in §8.6 (emphasis mine):

TexSubImage*D and TextureSubImage*D arguments width, height, depth, format, type, and data match the corresponding arguments to the corresponding TexImage*D command (where those arguments exist), meaning that they accept the same values, and have the same meanings.

To me that means "they accept the same set of values" (any value amongst the valid ones), and not "they accept the very same value passed to glTexImage*D".

In the OpenGL ES 2.0 specification the wording is slightly different:

TexSubImage2D arguments width, height, format, type, and data match the corresponding arguments to TexImage2D, meaning that they are specified using the same values, and have the same meanings.

Again, to me, this should not imply that the pixel transfer format must match, only that the accepted values are from within the same set.


So, is my interpretation correct?


ADDENDUM.

I've been digging into the OpenGL man pages. Now of course they're not normative (the specification is), but there's a significant difference between the ES2/3 man pages and the OpenGL 4.5 one:

  • GLES 2: https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml
  • GLES 3: https://www.khronos.org/opengles/sdk/docs/man3/html/glTexImage2D.xhtml
  • GL 4.5: https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml

Note that in the GLES3 cases there's this wording: "internalFormat may be one of the unsized (base) internal formats shown, together with valid format and type combinations", strongly implying that the indeed the triple is used to allocate the storage.

However, GLES3 also has immutable storage out-of-the-box, so that makes no sense...

But anyhow that makes my call to glTexImage2D perfectly legal. Then, the problematic call becomes glTexSubImage2D:

  • GLES 2: https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexSubImage2D.xml
  • GLES 3: https://www.khronos.org/opengles/sdk/docs/man3/html/glTexSubImage2D.xhtml

In there, the only error condition referencing the internal format is this in GLES 2:

GL_INVALID_OPERATION is generated if the texture array has not been defined by a previous glTexImage2D or glCopyTexImage2D operation whose internalformat matches the format of glTexSubImage2D.

And this in GLES 3:

GL_INVALID_OPERATION is generated if the combination of internalFormat of the previously specified texture array, format and type is not valid. See glTexImage2D.

Which again means my interpretation is right: the combination of format + type passed to glTexSubImage2D, plus the internal format passed to glTexImage2D, is indeed a valid combination listed in the glTexImage2D doc.

like image 423
peppe Avatar asked Jan 17 '26 10:01

peppe


1 Answers

So, is my interpretation correct?

In one word: Yes. It's called internal format and pixel data format for a reason. ANGLE is an emulation of OpenGL-ES and hence follows the specification and behavior as specified for that. Which is consistent with your observation.

like image 87
datenwolf Avatar answered Jan 21 '26 00:01

datenwolf