Appendix C: Compressed Image Formats

The compressed texture formats used by Vulkan are described in the specifically identified sections of the Khronos Data Format Specification, version 1.1.

Unless otherwise described, the quantities encoded in these compressed formats are treated as normalized, unsigned values.

Those formats listed as sRGB-encoded have in-memory representations of R, G and B components which are nonlinearly-encoded as R', G', and B'; any alpha component is unchanged. As part of filtering, the nonlinear R', G', and B' values are converted to linear R, G, and B components; any alpha component is unchanged. The conversion between linear and nonlinear encoding is performed as described in the “KHR_DF_TRANSFER_SRGB” section of the Khronos Data Format Specification.

Block-Compressed Image Formats

Table 81. Mapping of Vulkan BC formats to descriptions
VkFormat Khronos Data Format Specification description

Formats described in the “S3TC Compressed Texture Image Formats” chapter

VK_FORMAT_BC1_RGB_UNORM_BLOCK

BC1 with no alpha

VK_FORMAT_BC1_RGB_SRGB_BLOCK

BC1 with no alpha, sRGB-encoded

VK_FORMAT_BC1_RGBA_UNORM_BLOCK

BC1 with alpha

VK_FORMAT_BC1_RGBA_SRGB_BLOCK

BC1 with alpha, sRGB-encoded

VK_FORMAT_BC2_UNORM_BLOCK

BC2

VK_FORMAT_BC2_SRGB_BLOCK

BC2, sRGB-encoded

VK_FORMAT_BC3_UNORM_BLOCK

BC3

VK_FORMAT_BC3_SRGB_BLOCK

BC3, sRGB-encoded

Formats described in the “RGTC Compressed Texture Image Formats” chapter

VK_FORMAT_BC4_UNORM_BLOCK

BC4 unsigned

VK_FORMAT_BC4_SNORM_BLOCK

BC4 signed

VK_FORMAT_BC5_UNORM_BLOCK

BC5 unsigned

VK_FORMAT_BC5_SNORM_BLOCK

BC5 signed

Formats described in the “BPTC Compressed Texture Image Formats” chapter

VK_FORMAT_BC6H_UFLOAT_BLOCK

BC6H (unsigned version)

VK_FORMAT_BC6H_SFLOAT_BLOCK

BC6H (signed version)

VK_FORMAT_BC7_UNORM_BLOCK

BC7

VK_FORMAT_BC7_SRGB_BLOCK

BC7, sRGB-encoded

ETC Compressed Image Formats

The following formats are described in the “ETC2 Compressed Texture Image Formats” chapter of the Khronos Data Format Specification.

Table 82. Mapping of Vulkan ETC formats to descriptions
VkFormat Khronos Data Format Specification description

VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK

RGB ETC2

VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK

RGB ETC2 with sRGB encoding

VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK

RGB ETC2 with punch-through alpha

VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK

RGB ETC2 with punch-through alpha and sRGB

VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK

RGBA ETC2

VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK

RGBA ETC2 with sRGB encoding

VK_FORMAT_EAC_R11_UNORM_BLOCK

Unsigned R11 EAC

VK_FORMAT_EAC_R11_SNORM_BLOCK

Signed R11 EAC

VK_FORMAT_EAC_R11G11_UNORM_BLOCK

Unsigned RG11 EAC

VK_FORMAT_EAC_R11G11_SNORM_BLOCK

Signed RG11 EAC

ASTC Compressed Image Formats

ASTC formats are described in the “ASTC Compressed Texture Image Formats” chapter of the Khronos Data Format Specification.

Table 83. Mapping of Vulkan ASTC formats to descriptions
VkFormat Compressed texel block dimensions sRGB-encoded

VK_FORMAT_ASTC_4x4_UNORM_BLOCK

4 × 4

No

VK_FORMAT_ASTC_4x4_SRGB_BLOCK

4 × 4

Yes

VK_FORMAT_ASTC_5x4_UNORM_BLOCK

5 × 4

No

VK_FORMAT_ASTC_5x4_SRGB_BLOCK

5 × 4

Yes

VK_FORMAT_ASTC_5x5_UNORM_BLOCK

5 × 5

No

VK_FORMAT_ASTC_5x5_SRGB_BLOCK

5 × 5

Yes

VK_FORMAT_ASTC_6x5_UNORM_BLOCK

6 × 5

No

VK_FORMAT_ASTC_6x5_SRGB_BLOCK

6 × 5

Yes

VK_FORMAT_ASTC_6x6_UNORM_BLOCK

6 × 6

No

VK_FORMAT_ASTC_6x6_SRGB_BLOCK

6 × 6

Yes

VK_FORMAT_ASTC_8x5_UNORM_BLOCK

8 × 5

No

VK_FORMAT_ASTC_8x5_SRGB_BLOCK

8 × 5

Yes

VK_FORMAT_ASTC_8x6_UNORM_BLOCK

8 × 6

No

VK_FORMAT_ASTC_8x6_SRGB_BLOCK

8 × 6

Yes

VK_FORMAT_ASTC_8x8_UNORM_BLOCK

8 × 8

No

VK_FORMAT_ASTC_8x8_SRGB_BLOCK

8 × 8

Yes

VK_FORMAT_ASTC_10x5_UNORM_BLOCK

10 × 5

No

VK_FORMAT_ASTC_10x5_SRGB_BLOCK

10 × 5

Yes

VK_FORMAT_ASTC_10x6_UNORM_BLOCK

10 × 6

No

VK_FORMAT_ASTC_10x6_SRGB_BLOCK

10 × 6

Yes

VK_FORMAT_ASTC_10x8_UNORM_BLOCK

10 × 8

No

VK_FORMAT_ASTC_10x8_SRGB_BLOCK

10 × 8

Yes

VK_FORMAT_ASTC_10x10_UNORM_BLOCK

10 × 10

No

VK_FORMAT_ASTC_10x10_SRGB_BLOCK

10 × 10

Yes

VK_FORMAT_ASTC_12x10_UNORM_BLOCK

12 × 10

No

VK_FORMAT_ASTC_12x10_SRGB_BLOCK

12 × 10

Yes

VK_FORMAT_ASTC_12x12_UNORM_BLOCK

12 × 12

No

VK_FORMAT_ASTC_12x12_SRGB_BLOCK

12 × 12

Yes

ASTC decode mode

If the VK_EXT_astc_decode_mode extension is enabled the ASTC decoding described in the Khronos Data Format Specification is modified by replacing or modifying the corresponding sections as described below.

Table 84. Mapping of Vulkan ASTC decoding format to ASTC decoding modes
VkFormat Decoding mode

VK_FORMAT_R16G16B16A16_SFLOAT

decode_float16

VK_FORMAT_R8G8B8A8_UNORM

decode_unorm8

VK_FORMAT_E5B9G9R9_UFLOAT_PACK32

decode_rgb9e5

LDR and HDR Modes
Note

This replaces section 16.5 in the Khronos Data Format Specification.

The decoding process for LDR content can be simplified if it is known in advance that sRGB output is required. This selection is therefore included as part of the global configuration.

The two modes differ in various ways, as shown in ASTC differences between LDR and HDR modes.

Table 85. ASTC differences between LDR and HDR modes
Operation LDR Mode HDR Mode

Returned Value

Determined by decoding mode

Determined by decoding mode

sRGB compatible

Yes

No

LDR endpoint decoding precision

16 bits, or 8 bits for sRGB

16 bits

HDR endpoint mode results

Error color

As decoded

Error results

Error color

Vector of NaNs (0xFFFF)

The type of the values returned by the decoding process is determined by the decoding mode as shown in ASTC decoding modes.

Table 86. ASTC decoding modes
Decode mode LDR Mode HDR Mode

decode_float16

Vector of FP16 values

Vector of FP16 values

decode_unorm8

Vector of 8-bit unsigned normalized values

invalid

decode_rgb9e5

Vector using a shared exponent format

Vector using a shared exponent format

Using the decode_unorm8 decoding mode in HDR mode gives undefined results.

For sRGB, the decoding mode is ignored, and the decoding always returns a vector of 8-bit unsigned normalized values.

The error color is opaque fully-saturated magenta [(R,G,B,A) = (0xFF,0x00,0xFF,0xFF). This has been chosen as it is much more noticeable than black or white, and occurs far less often in valid images.

For linear RGB decode, the error color may be either opaque fully-saturated magenta (R,G,B,A) = (1.0,0.0,1.0,1.0) or a vector of four NaNs (R,G,B,A) = (NaN,NaN,NaN,NaN). In the latter case, the recommended NaN value returned is 0xFFFF.

When using the decode_rgb9e5 decoding mode in HDR mode, error results will return the error color because NaN cannot be represented.

The error color is returned as an informative response to invalid conditions, including invalid block encodings or use of reserved endpoint modes.

Future, forward-compatible extensions to ASTC may define valid interpretations of these conditions, which will decode to some other color. Therefore, encoders and applications must not rely on invalid encodings as a way of generating the error color.

Note

This replaces section 16.19 in the Khronos Data Format Specification.

Once the effective weight i for the texel has been calculated, the color endpoints are interpolated and expanded.

For LDR endpoint modes, each color component C is calculated from the corresponding 8-bit endpoint components C0 and C1 as follows:

If sRGB conversion is not enabled, or for the alpha channel in any case, C0 and C1 are first expanded to 16 bits by bit replication:

C0 = (C0 << 8) | C0;    C1 = (C1 << 8) | C1;

If sRGB conversion is enabled, C0 and C1 for the R, G, and B channels are expanded to 16 bits differently, as follows:

C0 = (C0 << 8) | 0x80;  C1 = (C1 << 8) | 0x80;

C0 and C1 are then interpolated to produce a UNORM16 result C:

C = floor( (C0*(64-i) + C1*i + 32)/64 )

If sRGB conversion is not enabled and the decoding mode is decode_float16, then if C = 65535 the final result is 1.0 (0x3C00); otherwise C is divided by 65536 and the infinite-precision result of the division is converted to FP16 with round-to-zero semantics.

If sRGB conversion is not enabled and the decoding mode is decode_unorm8, then top 8 bits of the interpolation result for the R, G, B, and A channels are used as the final result.

If sRGB conversion is not enabled and the decoding mode is decode_rgb9e5, then the final result is a combination of the (UNORM16) values of C for the three color components (Cr, Cg, and Cb) computed as follows:

int lz = clz17( Cr | Cg | Cb | 1);
if (Cr == 65535 ) { Cr = 65536; lz = 0; }
if (Cg == 65535 ) { Cg = 65536; lz = 0; }
if (Cb == 65535 ) { Cb = 65536; lz = 0; }
Cr <<= lz;
Cg <<= lz;
Cb <<= lz;
Cr = (Cr >> 8) & 0x1FF;
Cg = (Cg >> 8) & 0x1FF;
Cb = (Cb >> 8) & 0x1FF;
uint32_t exponent = 16 - lz;
uint32_t texel = (exponent << 27) | (Cb << 18) | (Cg << 9) | Cr;

The clz17() function counts leading zeros in a 17-bit value.

If sRGB conversion is enabled, then the decoding mode is ignored, and the top 8 bits of the interpolation result for the R, G and B channels are passed to the external sRGB conversion block and used as the final result. The A channle uses the decode_float16 decoding mode.

For HDR endpoint modes, color values are represented in a 12-bit pseudo-logarithmic representation, and interpolation occurs in a piecewise-approximate logarithmic manner as follows:

In LDR mode, the error result is returned.

In HDR mode, the color components from each endpoint, C0 and C1, are initially shifted left 4 bits to become 16-bit integer values and these are interpolated in the same way as LDR. The 16-bit value C is then decomposed into the top five bits, E, and the bottom 11 bits M, which are then processed and recombined with E to form the final value Cf:

C = floor( (C0*(64-i) + C1*i + 32)/64 )
E = (C & 0xF800) >> 11; M = C & 0x7FF;
if (M < 512) { Mt = 3*M; }
else if (M >= 1536) { Mt = 5*M - 2048; }
else { Mt = 4*M - 512; }
Cf = (E<<10) + (Mt>>3)

This interpolation is a considerably closer approximation to a logarithmic space than simple 16-bit interpolation.

This final value Cf is interpreted as an IEEE FP16 value. If the result is +Inf or NaN, it is converted to the bit pattern 0x7BFF, which is the largest representable finite value.

If the decoding mode is decode_rgb9e5, then the final result is a combination of the (IEEE FP16) values of Cf for the three color components (Cr, Cg, and Cb) computed as follows:

if( Cr > 0x7c00 ) Cr = 0; else if( Cr == 0x7c00 ) Cr = 0x7bff;
if( Cg > 0x7c00 ) Cg = 0; else if( Cg == 0x7c00 ) Cg = 0x7bff;
if( Cb > 0x7c00 ) Cb = 0; else if( Cb == 0x7c00 ) Cb = 0x7bff;
int Re = (Cr >> 10) & 0x1F;
int Ge = (Cg >> 10) & 0x1F;
int Be = (Cb >> 10) & 0x1F;
int Rex = Re == 0 ? 1 : Re;
int Gex = Ge == 0 ? 1 : Ge;
int Bex = Be == 0 ? 1 : Be;
int Xm = ((Cr | Cg | Cb) & 0x200) >> 9;
int Xe = Re | Ge | Be;
uint32_t rshift, gshift, bshift, expo;

if (Xe == 0)
{
    expo = rshift = gshift = bshift = Xm;
}
else if (Re >= Ge && Re >= Be)
{
    expo = Rex + 1;
    rshift = 2;
    gshift = Rex - Gex + 2;
    bshift = Rex - Bex + 2;
}
else if (Ge >= Be)
{
    expo = Gex + 1;
    rshift = Gex - Rex + 2;
    gshift = 2;
    bshift = Gex - Bex + 2;
}
else
{
    expo = Bex + 1;
    rshift = Bex - Rex + 2;
    gshift = Bex - Gex + 2;
    bshift = 2;
}

int Rm = (Cr & 0x3FF) | (Re == 0 ? 0 : 0x400);
int Gm = (Cg & 0x3FF) | (Ge == 0 ? 0 : 0x400);
int Bm = (Cb & 0x3FF) | (Be == 0 ? 0 : 0x400);
Rm = (Rm >> rshift) & 0x1FF;
Gm = (Gm >> gshift) & 0x1FF;
Bm = (Bm >> bshift) & 0x1FF;

uint32_t texel = (expo << 27) | (Bm << 18) | (Gm << 9) | (Rm << 0);

Void-Extent Blocks

Note

This modifies section 16.23 in the Khronos Data Format Specification.

In the HDR case, if the decoding mode is decode_rgb9e5, then any negative color component values are set to 0 before conversion to the shared exponent format (as described in Weight Application).