Read 8-Bit Integers in GLSL via GL_EXT_shader_8bit_storage
The GL_EXT_shader_8bit_storage extension allows GLSL
shaders to store and read 8-bit integers directly from byte-addressable
storage buffers, significantly reducing memory bandwidth and eliminating
the overhead of manual data packing. By introducing native 8-bit types
directly into buffer layouts, shaders can perform scalar and vector
byte-sized memory loads without relying on manual bit-shifting or
bitmasking operations.
Enabling the Extension
To use 8-bit integers in storage buffers, the extension must be explicitly declared in the shader:
#version 450
#extension GL_EXT_shader_8bit_storage : requireIf you also intend to perform arithmetic directly on 8-bit types
rather than automatically promoting them to larger integer types, you
will typically pair this with
GL_EXT_shader_explicit_arithmetic_types_int8.
Defining the Storage Buffer
With the extension enabled, the types int8_t,
uint8_t, and their vector variants (such as
i8vec2, u8vec4) become valid inside uniform
and shader storage buffer objects.
Under the standard layout qualifiers (such as std430),
8-bit values have a base alignment of 1 byte. This removes the
requirement to pad data to 4-byte (32-bit) boundaries.
layout(std430, binding = 0) readonly buffer InputBuffer {
uint8_t singleByte;
uint8_t byteArray[];
};Reading 8-Bit Values
Reading an 8-bit integer is syntactically identical to accessing standard 32-bit types. The hardware performs direct byte-addressed memory loads:
void main() {
uint index = gl_GlobalInvocationID.x;
// Direct scalar read
uint8_t rawValue = byteArray[index];
// Automatic type promotion
uint convertedValue = uint(rawValue);
}Under-the-Hood Mechanics
When an 8-bit read instruction executes:
- Direct Memory Addressing: Unlike standard GLSL
storage buffers that require reading a 32-bit dword and manually
extracting bytes using
bitfieldExtractor shifts (>>), the GPU generates native byte-load instructions where supported by hardware. - Alignment and Packing: Arrays of
uint8_tare packed sequentially with single-byte stride. Vector types likeu8vec4are aligned to 4 bytes, occupying exactly 4 bytes in memory. - Sign and Zero Extension: When reading signed
(
int8_t) or unsigned (uint8_t) types into wider registers (likeintoruint), the underlying assembly automatically applies sign extension or zero extension, ensuring data integrity during type promotion.