GLTEXSTORAGE2D(3G)

okay so this is the GLTEXSTORAGE2D(3G) page β€” and yes, the header has a little [FIXME: manual] placeholder in it, we love a work-in-progress moment. It’s giving β€œlock in texture storage for all the levels at once,” and honestly? Iconic.

πŸŽ€ NAME πŸŽ€

glTexStorage2D, glTextureStorage2D β€” simultaneously specify storage for all levels of a two-dimensional or one-dimensional array texture.

πŸ’» C SPECIFICATION πŸ’»

void glTexStorage2D(GLenum target, GLsizei levels,
                    GLenum internalformat, GLsizei width,
                    GLsizei height);

void glTextureStorage2D(GLuint texture, GLsizei levels,
                        GLenum internalformat, GLsizei width,
                        GLsizei height);

🌸 PARAMETERS 🌸

  • target β€” specifies the target to which the texture object is bound for glTexStorage2D. Must be one of GL_TEXTURE_2D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_PROXY_TEXTURE_2D, GL_PROXY_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_RECTANGLE, or GL_PROXY_TEXTURE_CUBE_MAP.
  • texture β€” specifies the texture object name for glTextureStorage2D. The effective target of texture must be one of the valid non-proxy target values above.
  • levels β€” specify the number of texture levels.
  • internalformat β€” specifies the sized internal format to be used to store texture image data.
  • width β€” specifies the width of the texture, in texels.
  • height β€” specifies the height of the texture, in texels.

✨ DESCRIPTION ✨

glTexStorage2D and glTextureStorage2D specify the storage requirements for all levels of a two-dimensional texture or one-dimensional texture array simultaneously. Once a texture is specified with this command, the format and dimensions of all levels become immutable unless it is a proxy texture. The contents of the image may still be modified, however, its storage requirements may not change. Such a texture is referred to as an immutable-format texture. πŸ’…

The behavior of glTexStorage2D depends on the target parameter. When target is GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_PROXY_TEXTURE_RECTANGLE or GL_PROXY_TEXTURE_CUBE_MAP, calling glTexStorage2D is equivalent, assuming no errors are generated, to executing the following pseudo-code:

        for (i = 0; i < levels; i++) {
            glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
            width = max(1, (width / 2));
            height = max(1, (height / 2));
        }

When target is GL_TEXTURE_CUBE_MAP, glTexStorage2D is equivalent to:

        for (i = 0; i < levels; i++) {
            for (face in (+X, -X, +Y, -Y, +Z, -Z)) {
                glTexImage2D(face, i, internalformat, width, height, 0, format, type, NULL);
            }
            width = max(1, (width / 2));
            height = max(1, (height / 2));
        }

When target is GL_TEXTURE_1D_ARRAY or GL_PROXY_TEXTURE_1D_ARRAY, glTexStorage2D is equivalent to:

        for (i = 0; i < levels; i++) {
            glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
            width = max(1, (width / 2));
        }

Calling glTextureStorage2D is equivalent to the above pseudo-code, where target is the effective target of texture and it is as if texture were bound to target for the purposes of glTexImage2D. 🫢

Since no texture data is actually provided, the values used in the pseudo-code for format and type are irrelevant and may be considered to be any values that are legal for the chosen internalformat enumerant. internalformat must be one of the sized internal formats given in Table 1 below, one of the sized depth-component formats GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24, or GL_DEPTH_COMPONENT16, one of the combined depth-stencil formats, GL_DEPTH32F_STENCIL8, or GL_DEPTH24_STENCIL8, or the stencil-only format, GL_STENCIL_INDEX8.

Upon success, the value of GL_TEXTURE_IMMUTABLE_FORMAT becomes GL_TRUE. The value of GL_TEXTURE_IMMUTABLE_FORMAT may be discovered by calling glGetTexParameter() with pname set to GL_TEXTURE_IMMUTABLE_FORMAT. No further changes to the dimensions or format of the texture object may be made. Using any command that might alter the dimensions or format of the texture object (such as glTexImage2D() or another call to glTexStorage2D) will result in the generation of a GL_INVALID_OPERATION error, even if it would not, in fact, alter the dimensions or format of the object. 🚨

πŸŽ€ Table 1. Sized Internal Formats πŸŽ€

okay bestie, this is THE table β€” every sized internal format, what base internal format it rides with, and how many bits each channel gets. Read it like a menu ✨

quick legend before you scroll: plain numbers are unsigned bits, s means signed, ui means unsigned integer, and f means float β€” iykyk πŸ’…

  • GL_R8 β€” base internal format GL_RED, red bits 8
  • GL_R8_SNORM β€” base internal format GL_RED, red bits s8
  • GL_R16 β€” base internal format GL_RED, red bits 16
  • GL_R16_SNORM β€” base internal format GL_RED, red bits s16
  • GL_RG8 β€” base internal format GL_RG, red bits 8, green bits 8
  • GL_RG8_SNORM β€” base internal format GL_RG, red bits s8, green bits s8
  • GL_RG16 β€” base internal format GL_RG, red bits 16, green bits 16
  • GL_RG16_SNORM β€” base internal format GL_RG, red bits s16, green bits s16
  • GL_R3_G3_B2 β€” base internal format GL_RGB, red bits 3, green bits 3, blue bits 2
  • GL_RGB4 β€” base internal format GL_RGB, red bits 4, green bits 4, blue bits 4
  • GL_RGB5 β€” base internal format GL_RGB, red bits 5, green bits 5, blue bits 5
  • GL_RGB8 β€” base internal format GL_RGB, red bits 8, green bits 8, blue bits 8
  • GL_RGB8_SNORM β€” base internal format GL_RGB, red bits s8, green bits s8, blue bits s8
  • GL_RGB10 β€” base internal format GL_RGB, red bits 10, green bits 10, blue bits 10
  • GL_RGB12 β€” base internal format GL_RGB, red bits 12, green bits 12, blue bits 12
  • GL_RGB16_SNORM β€” base internal format GL_RGB, red bits 16, green bits 16, blue bits 16
  • GL_RGBA2 β€” base internal format GL_RGB, red bits 2, green bits 2, blue bits 2, alpha bits 2
  • GL_RGBA4 β€” base internal format GL_RGB, red bits 4, green bits 4, blue bits 4, alpha bits 4
  • GL_RGB5_A1 β€” base internal format GL_RGBA, red bits 5, green bits 5, blue bits 5, alpha bits 1
  • GL_RGBA8 β€” base internal format GL_RGBA, red bits 8, green bits 8, blue bits 8, alpha bits 8
  • GL_RGBA8_SNORM β€” base internal format GL_RGBA, red bits s8, green bits s8, blue bits s8, alpha bits s8
  • GL_RGB10_A2 β€” base internal format GL_RGBA, red bits 10, green bits 10, blue bits 10, alpha bits 2
  • GL_RGB10_A2UI β€” base internal format GL_RGBA, red bits ui10, green bits ui10, blue bits ui10, alpha bits ui2
  • GL_RGBA12 β€” base internal format GL_RGBA, red bits 12, green bits 12, blue bits 12, alpha bits 12
  • GL_RGBA16 β€” base internal format GL_RGBA, red bits 16, green bits 16, blue bits 16, alpha bits 16
  • GL_SRGB8 β€” base internal format GL_RGB, red bits 8, green bits 8, blue bits 8
  • GL_SRGB8_ALPHA8 β€” base internal format GL_RGBA, red bits 8, green bits 8, blue bits 8, alpha bits 8
  • GL_R16F β€” base internal format GL_RED, red bits f16
ngl the Shared Bits column is just vibing empty for literally every row in this stretch 🫢 so there's nothing to report there, don't come for me πŸ’€

and yes, GL_RGBA2 and GL_RGBA4 really do list GL_RGB as their base internal format β€” that's what the table says, no cap, I'm not touching it πŸ™ˆ

now the float ones start showing up and the list keeps going πŸ‘‘

...and the parade of sized internal formats just keeps going, bestie πŸŽ‰ same column order as before β€” internal format, pixel format, then the per-channel sizes β€” so let's get into it πŸ’…

  • GL_RG16F β€” pixel format GL_RG, channels sized f16, f16 🫢
  • GL_RGB16F β€” pixel format GL_RGB, channels sized f16, f16, f16 ✨
  • GL_RGBA16F β€” pixel format GL_RGBA, channels sized f16, f16, f16, f16 🌸
  • GL_R32F β€” pixel format GL_RED, channel sized f32 πŸ’–
  • GL_RG32F β€” pixel format GL_RG, channels sized f32, f32 πŸ¦‹
  • GL_RGB32F β€” pixel format GL_RGB, channels sized f32, f32, f32 ⭐
  • GL_RGBA32F β€” pixel format GL_RGBA, channels sized f32, f32, f32, f32 πŸ‘‘
  • GL_R11F_G11F_B10F β€” pixel format GL_RGB, channels sized f11, f11, f10 β€” yes the name literally spells out the bit split, iconic honestly πŸ”₯
  • GL_RGB9_E5 β€” pixel format GL_RGB, channels sized 9, 9, 9, with shared exponent 5 🧚

okay now we're entering the integer era and it's lowkey my favorite part 😭 every one of these is channel-by-channel, no sharing, no crumbs:

  • GL_R8I β€” pixel format GL_RED, channel sized i8 πŸ’œ
  • GL_R8UI β€” pixel format GL_RED, channel sized ui8 πŸ’œ
  • GL_R16I β€” pixel format GL_RED, channel sized i16 πŸ’œ
  • GL_R16UI β€” pixel format GL_RED, channel sized ui16 πŸ’œ
  • GL_R32I β€” pixel format GL_RED, channel sized i32 πŸ’œ
  • GL_R32UI β€” pixel format GL_RED, channel sized ui32 πŸ’œ
  • GL_RG8I β€” pixel format GL_RG, channels sized i8, i8 πŸ“
  • GL_RG8UI β€” pixel format GL_RG, channels sized ui8, ui8 πŸ“
  • GL_RG16I β€” pixel format GL_RG, channels sized i16, i16 πŸ“
  • GL_RG16UI β€” pixel format GL_RG, channels sized ui16, ui16 πŸ“
  • GL_RG32I β€” pixel format GL_RG, channels sized i32, i32 πŸ“
  • GL_RG32UI β€” pixel format GL_RG, channels sized ui32, ui32 πŸ“
  • GL_RGB8I β€” pixel format GL_RGB, channels sized i8, i8, i8 🌈
  • GL_RGB8UI β€” pixel format GL_RGB, channels sized ui8, ui8, ui8 🌈
  • GL_RGB16I β€” pixel format GL_RGB, channels sized i16, i16, i16 🌈
  • GL_RGB16UI β€” pixel format GL_RGB, channels sized ui16, ui16, ui16 🌈
  • GL_RGB32I β€” pixel format GL_RGB, channels sized i32, i32, i32 🌈
  • GL_RGB32UI β€” pixel format GL_RGB, channels sized ui32, ui32, ui32 🌈
  • GL_RGBA8I β€” pixel format GL_RGBA, channels sized i8, i8, i8, i8 πŸŽ€
  • GL_RGBA8UI β€” pixel format GL_RGBA, channels sized ui8, ui8, ui8, ui8 πŸŽ€
  • GL_RGBA16I β€” pixel format GL_RGBA, channels sized i16, i16, i16, i16 πŸŽ€
  • GL_RGBA16UI β€” pixel format GL_RGBA, channels sized ui16, ui16, ui16, ui16 πŸŽ€

and that's where we're gonna pause the list, because the format table is still going and we are absolutely not done yet πŸ‘€

  • GL_RGBA32I β€” the effective internal format is GL_RGBA, and every channel is i32, i32, i32, i32 (and yeah, that last column is just blank, she's empty, she's thriving 🫢)
  • GL_RGBA32UI β€” effective internal format GL_RGBA, channels all ui32, ui32, ui32, ui32 (last column blank again, no thoughts head empty πŸ’…)

✨ NOTES ✨

okay tiny little footnote bestie, don't skip it: GL_STENCIL_INDEX8 is accepted for internalformat only if the GL version is 4.4 or higher. like, that's the whole vibe check. if you're on 4.3 it's a no. periodt.


πŸ’€ ERRORS πŸ’€

this is the part where things go wrong and the driver yells at you. buckle up πŸŽ€

  • GL_INVALID_OPERATION is generated by glTexStorage2D if zero is bound to target β€” like, nothing's there, bestie, you can't texture a void 😭
  • GL_INVALID_OPERATION is generated by glTextureStorage2D if texture is not the name of an existing texture object β€” she doesn't exist, don't @ her
  • GL_INVALID_ENUM is generated if internalformat is not a valid sized internal format β€” sized, babe. sized.
  • GL_INVALID_ENUM is generated if target or the effective target of texture is not one of the accepted targets described above (scroll up, they're all listed πŸ‘€)
  • GL_INVALID_VALUE is generated if width, height or levels are less than 1 β€” no zero-size textures, no negative sizes, we don't do that here πŸ™ˆ
  • GL_INVALID_OPERATION is generated if target is GL_TEXTURE_1D_ARRAY or GL_PROXY_TEXTURE_1D_ARRAY and levels is greater than log 2 width + 1 β€” that's too many levels for that width, sweetie, the mip pyramid literally does not go that high πŸ’€
  • GL_INVALID_OPERATION is generated if target is not GL_TEXTURE_1D_ARRAY or GL_PROXY_TEXTURE_1D_ARRAY and levels is greater than log 2 max width , height + 1 β€” again, too deep, the pyramid caps out ✨

πŸ‘‘ VERSION SUPPORT πŸ‘‘

the "am I even allowed to call this" chart. here it is, translated from table-ese into a format your eyeballs will forgive πŸ’–

  • glTexStorage2D β€” not supported (-) in 2.0, 2.1, 3.0, 3.1, 3.2, 3.3, 4.0 and 4.1; supported (βœ”) in 4.2, 4.3, 4.4 and 4.5. so she showed up to the party in 4.2 and never left πŸ”₯
  • glTextureStorage2D β€” not supported (-) in 2.0, 2.1, 3.0, 3.1, 3.2, 3.3, 4.0, 4.1, 4.2, 4.3 and 4.4; supported (βœ”) only in 4.5. late bloomer, main character energy, arrived fashionably late and slayed 🌈

🌸 SEE ALSO 🌸

go read these next, i'm not kidding, they're literally right there:

  • glTexImage2D()
  • glTexStorage1D()
  • glTexStorage3D()

it's giving "one-dimensional bestie" and "three-dimensional bestie" and the classic two-dee icon herself. trio of icons πŸ¦‹


Copyright Β© 2011-2014 Khronos Group. This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/.

Copyright Β© 2011-2014 Khronos Group


and that's the whole page, bestie, you ate that πŸ“βœ¨ no cap, that's the tea from [FIXME: source], dated 08/09/2021, living under the name GLTEXSTORAGE2D(3G) β€” hug your textures, take your mip levels seriously, and go forth and glTexStorage2D πŸ’–πŸŽ€

πŸ“¦ where this page comes from