Query Image Dimensions with GLSL imageSize
The GLSL imageSize built-in function provides shaders
with the ability to retrieve the runtime dimensions of bound image
variables without performing manual uniform updates from the CPU. This
article explains how imageSize operates, its syntax and
return formats across different image target types, the distinction
between it and traditional texture queries, and how it evaluates bound
mipmap levels.
How imageSize
Functions
The imageSize function inspects the internal state of a
bound image unit to determine its width, height, depth, or layer count.
Unlike traditional texture sampling functions that operate on opaque
sampler* types, imageSize is designed
specifically for read/write image variables (image1D,
image2D, image3D, imageCube, and
their array or signed/unsigned variants) introduced in OpenGL 4.2 and
GLSL 4.20 via the GL_ARB_shader_image_load_store
extension.
When invoked, the function does not read texel data or access texture filtering hardware. Instead, it extracts the dimension metadata directly from the texture descriptor currently bound to the image unit.
Return Types and Dimension Mapping
The return type of imageSize depends directly on the
dimensionality of the target image variable. The returned integer values
represent texel counts along each axis:
- 1D Images (
image1D): Returns anintrepresenting the width in texels. - 2D Images (
image2D,imageCube,imageRect): Returns anivec2containing(width, height). For cube maps, it returns the dimensions of a single face. - 3D Images (
image3D): Returns anivec3containing(width, height, depth). - Array Images (
image1DArray,image2DArray,imageCubeArray): The last component of the vector represents the number of layers. For instance, callingimageSizeon animage2DArrayreturns anivec3formatted as(width, height, layer_count). - Multisample Images (
image2DMS,image2DMSArray): Returns anivec2orivec3indicating spatial dimensions; sample counts are not part of the return vector and must be queried separately usingimageSamples.
Target Mipmap Level Evaluation
A critical distinction between imageSize and the
sampler-based textureSize function is how levels of detail
(LOD) are handled:
textureSizeaccepts an explicit LOD parameter to query specific mipmap levels of a complete texture object.imageSizedoes not take an LOD parameter. Images are bound to shader execution units using host-side API commands such asglBindImageTexture, which explicitly binds a single, specific mipmap level. Consequently,imageSizereturns the exact dimensions of that bound mipmap level rather than the base level dimensions.
Usage in Boundary Checking
A primary use case for imageSize is in compute shaders
executing image processing tasks, where invocations must ensure write
operations do not exceed the boundaries of the storage buffer:
layout(local_size_x = 16, local_size_y = 16) in;
layout(rgba32f, binding = 0) uniform writeonly image2D u_outputImage;
void main() {
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
ivec2 imgDimensions = imageSize(u_outputImage);
// Prevent out-of-bounds writes
if (pixelCoords.x >= imgDimensions.x || pixelCoords.y >= imgDimensions.y) {
return;
}
imageStore(u_outputImage, pixelCoords, vec4(1.0, 0.0, 0.0, 1.0));
}By querying the metadata dynamically at execution time, shaders remain decoupled from hardcoded resolution uniforms, ensuring flexibility across dynamic render targets and viewport sizes.