Texture storage demands: GL_RED vs. GL_RGBA

Will an 8-bit, single-component texture (internal format: GL_R8) take roughly 1/4 of the space in graphics memory compared to a GL_RGBA8 texture?
Or are there internal details like alignment that skew the storage characteristics?

From the spec:

If a sized internal format is specified, the mapping of the R, G, B, A, depth, and stencil values to texture components is equivalent to the mapping of the corresponding base internal format’s components, as specified in table 3.11; the type (unsigned int, float, etc.) is assigned the same type specified by internalformat; and the memory allocation per texture component is assigned by the GL to match the allocations listed in tables 3.12- 3.13 as closely as possible. (The definition of closely is left up to the implementation. However, a non-zero number of bits must be allocated for each component whose desired allocation in tables 3.12- 3.13 is non-zero, and zero bits must be allocated for all other components).

So, basically it should be possible to have 4 components with GL_R8 that take up the same space as 1 component with GL_RGBA8. Still, since it’s left to the implementation you have no guarantee. However, I don’t see why an implementor would sacrifice 3 bytes of memory to align a single byte. It’s more likely that 4 components will be packed and fetched in a single op - at least that would be sensible performance wise.

Edit: Reading the last sentence again, the only guarantee you have is that the storage requirements for the desired format have to be met as a minimum. But if all other bits have to be zero according to the spec, I don’t see how an implementor has any liberty to define closely as they please. Very confusing indeed.

It’s generally best to trust that the (required) sized image formats are exactly what they say they are. Besides, if they aren’t, it’s not like you can do anything about it…

Wouldn’t it be possible to allocate a GL_RGBA8, that is 1/4 the number of elements you want, and then handle the pack/unpack yourself? Granted that it is maybe not a pretty solution.

Kopelrativ: Yes, you could do that. But as soon as you want texture filtering things get ugly…

Yes, packing is no option since I depend on texture filtering.

I’ve just tested my Radeon HD5450:
GL_RED takes exactly 1/4 of GL_RGBA’s storage space - GL_RG takes 1/2.

Besides that: With fewer channels the texture fillrate is noticeably higher.

But that’s to be expected. Afterall, you only have a quarter of data to process. If some packing and unpacking is done automatically in hardware that would effectively mean you can raster 4 pixels with a single operation.

I noticed the same when switching from 16 bits to 32 bits and the other way round when using floating-point framebuffer - again, not surprising IMHO.