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:
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:
In there, the only error condition referencing the internal format is this in GLES 2:
GL_INVALID_OPERATIONis generated if the texture array has not been defined by a previousglTexImage2DorglCopyTexImage2Doperation whose internalformat matches the format ofglTexSubImage2D.
And this in GLES 3:
GL_INVALID_OPERATIONis generated if the combination of internalFormat of the previously specified texture array, format and type is not valid. SeeglTexImage2D.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With