379 lines
14 KiB
Plaintext
379 lines
14 KiB
Plaintext
// Copyright (c) 2015-2019 Khronos Group. This work is licensed under a
|
|
// Creative Commons Attribution 4.0 International License; see
|
|
// http://creativecommons.org/licenses/by/4.0/
|
|
|
|
[appendix]
|
|
= Compressed Image Formats
|
|
|
|
The compressed texture formats used by Vulkan are described in the
|
|
specifically identified sections of the <<data-format,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
|
|
[eq]#R#, [eq]#G# and [eq]#B# components which are nonlinearly-encoded as
|
|
[eq]#R'#, [eq]#G'#, and [eq]#B'#; any alpha component is unchanged.
|
|
As part of filtering, the nonlinear [eq]#R'#, [eq]#G'#, and [eq]#B'# values
|
|
are converted to linear [eq]#R#, [eq]#G#, and [eq]#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.
|
|
|
|
<<<
|
|
|
|
[[appendix-compressedtex-bc]]
|
|
== Block-Compressed Image Formats
|
|
|
|
.Mapping of Vulkan BC formats to descriptions
|
|
[width="90%",options="header",cols="5,4"]
|
|
|====
|
|
| elink:VkFormat | <<data-format,Khronos Data Format Specification>> description
|
|
2+^| Formats described in the "`S3TC Compressed Texture Image Formats`" chapter
|
|
| ename:VK_FORMAT_BC1_RGB_UNORM_BLOCK |BC1 with no alpha
|
|
| ename:VK_FORMAT_BC1_RGB_SRGB_BLOCK |BC1 with no alpha, sRGB-encoded
|
|
| ename:VK_FORMAT_BC1_RGBA_UNORM_BLOCK|BC1 with alpha
|
|
| ename:VK_FORMAT_BC1_RGBA_SRGB_BLOCK |BC1 with alpha, sRGB-encoded
|
|
| ename:VK_FORMAT_BC2_UNORM_BLOCK |BC2
|
|
| ename:VK_FORMAT_BC2_SRGB_BLOCK |BC2, sRGB-encoded
|
|
| ename:VK_FORMAT_BC3_UNORM_BLOCK |BC3
|
|
| ename:VK_FORMAT_BC3_SRGB_BLOCK |BC3, sRGB-encoded
|
|
2+^| Formats described in the "`RGTC Compressed Texture Image Formats`" chapter
|
|
| ename:VK_FORMAT_BC4_UNORM_BLOCK |BC4 unsigned
|
|
| ename:VK_FORMAT_BC4_SNORM_BLOCK |BC4 signed
|
|
| ename:VK_FORMAT_BC5_UNORM_BLOCK |BC5 unsigned
|
|
| ename:VK_FORMAT_BC5_SNORM_BLOCK |BC5 signed
|
|
2+^| Formats described in the "`BPTC Compressed Texture Image Formats`" chapter
|
|
| ename:VK_FORMAT_BC6H_UFLOAT_BLOCK |BC6H (unsigned version)
|
|
| ename:VK_FORMAT_BC6H_SFLOAT_BLOCK |BC6H (signed version)
|
|
| ename:VK_FORMAT_BC7_UNORM_BLOCK |BC7
|
|
| ename:VK_FORMAT_BC7_SRGB_BLOCK |BC7, sRGB-encoded
|
|
|====
|
|
|
|
<<<
|
|
|
|
[[appendix-compressedtex-etc2]]
|
|
== ETC Compressed Image Formats
|
|
|
|
The following formats are described in the "`ETC2 Compressed Texture Image
|
|
Formats`" chapter of the <<data-format,Khronos Data Format Specification>>.
|
|
|
|
.Mapping of Vulkan ETC formats to descriptions
|
|
[options="header",cols="1,1"]
|
|
|====
|
|
| elink:VkFormat | <<data-format,Khronos Data Format Specification>> description
|
|
| ename:VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK |RGB ETC2
|
|
| ename:VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK |RGB ETC2 with sRGB encoding
|
|
| ename:VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK |RGB ETC2 with punch-through alpha
|
|
| ename:VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK |RGB ETC2 with punch-through alpha and sRGB
|
|
| ename:VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK |RGBA ETC2
|
|
| ename:VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK |RGBA ETC2 with sRGB encoding
|
|
| ename:VK_FORMAT_EAC_R11_UNORM_BLOCK |Unsigned R11 EAC
|
|
| ename:VK_FORMAT_EAC_R11_SNORM_BLOCK |Signed R11 EAC
|
|
| ename:VK_FORMAT_EAC_R11G11_UNORM_BLOCK |Unsigned RG11 EAC
|
|
| ename:VK_FORMAT_EAC_R11G11_SNORM_BLOCK |Signed RG11 EAC
|
|
|====
|
|
|
|
<<<
|
|
|
|
[[appendix-compressedtex-astc]]
|
|
== ASTC Compressed Image Formats
|
|
|
|
ASTC formats are described in the "`ASTC Compressed Texture Image Formats`"
|
|
chapter of the <<data-format,Khronos Data Format Specification>>.
|
|
|
|
.Mapping of Vulkan ASTC formats to descriptions
|
|
[width="75%",options="header",cols="63%,15%,22%"]
|
|
|====
|
|
| elink:VkFormat ^| Compressed texel block dimensions ^| sRGB-encoded
|
|
| ename:VK_FORMAT_ASTC_4x4_UNORM_BLOCK ^|[eq]#4 {times} 4# ^|No
|
|
| ename:VK_FORMAT_ASTC_4x4_SRGB_BLOCK ^|[eq]#4 {times} 4# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_5x4_UNORM_BLOCK ^|[eq]#5 {times} 4# ^|No
|
|
| ename:VK_FORMAT_ASTC_5x4_SRGB_BLOCK ^|[eq]#5 {times} 4# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_5x5_UNORM_BLOCK ^|[eq]#5 {times} 5# ^|No
|
|
| ename:VK_FORMAT_ASTC_5x5_SRGB_BLOCK ^|[eq]#5 {times} 5# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_6x5_UNORM_BLOCK ^|[eq]#6 {times} 5# ^|No
|
|
| ename:VK_FORMAT_ASTC_6x5_SRGB_BLOCK ^|[eq]#6 {times} 5# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_6x6_UNORM_BLOCK ^|[eq]#6 {times} 6# ^|No
|
|
| ename:VK_FORMAT_ASTC_6x6_SRGB_BLOCK ^|[eq]#6 {times} 6# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_8x5_UNORM_BLOCK ^|[eq]#8 {times} 5# ^|No
|
|
| ename:VK_FORMAT_ASTC_8x5_SRGB_BLOCK ^|[eq]#8 {times} 5# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_8x6_UNORM_BLOCK ^|[eq]#8 {times} 6# ^|No
|
|
| ename:VK_FORMAT_ASTC_8x6_SRGB_BLOCK ^|[eq]#8 {times} 6# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_8x8_UNORM_BLOCK ^|[eq]#8 {times} 8# ^|No
|
|
| ename:VK_FORMAT_ASTC_8x8_SRGB_BLOCK ^|[eq]#8 {times} 8# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_10x5_UNORM_BLOCK ^|[eq]#10 {times} 5# ^|No
|
|
| ename:VK_FORMAT_ASTC_10x5_SRGB_BLOCK ^|[eq]#10 {times} 5# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_10x6_UNORM_BLOCK ^|[eq]#10 {times} 6# ^|No
|
|
| ename:VK_FORMAT_ASTC_10x6_SRGB_BLOCK ^|[eq]#10 {times} 6# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_10x8_UNORM_BLOCK ^|[eq]#10 {times} 8# ^|No
|
|
| ename:VK_FORMAT_ASTC_10x8_SRGB_BLOCK ^|[eq]#10 {times} 8# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_10x10_UNORM_BLOCK ^|[eq]#10 {times} 10# ^|No
|
|
| ename:VK_FORMAT_ASTC_10x10_SRGB_BLOCK ^|[eq]#10 {times} 10# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_12x10_UNORM_BLOCK ^|[eq]#12 {times} 10# ^|No
|
|
| ename:VK_FORMAT_ASTC_12x10_SRGB_BLOCK ^|[eq]#12 {times} 10# ^|Yes
|
|
| ename:VK_FORMAT_ASTC_12x12_UNORM_BLOCK ^|[eq]#12 {times} 12# ^|No
|
|
| ename:VK_FORMAT_ASTC_12x12_SRGB_BLOCK ^|[eq]#12 {times} 12# ^|Yes
|
|
|====
|
|
|
|
ifdef::VK_EXT_astc_decode_mode[]
|
|
|
|
=== ASTC decode mode
|
|
|
|
If the `VK_EXT_astc_decode_mode` extension is enabled the ASTC decoding
|
|
described in the <<data-format,Khronos Data Format Specification>> is
|
|
modified by replacing or modifying the corresponding sections as described
|
|
below.
|
|
|
|
.Mapping of Vulkan ASTC decoding format to ASTC decoding modes
|
|
[width="75%",options="header",cols="75%,25%"]
|
|
|====
|
|
| elink:VkFormat ^| Decoding mode
|
|
| ename:VK_FORMAT_R16G16B16A16_SFLOAT ^| decode_float16
|
|
| ename:VK_FORMAT_R8G8B8A8_UNORM ^| decode_unorm8
|
|
| ename:VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 ^| decode_rgb9e5
|
|
|====
|
|
|
|
==== LDR and HDR Modes
|
|
|
|
[NOTE]
|
|
.Note
|
|
====
|
|
This replaces section 16.5 in the <<data-format,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
|
|
<<appendix-compressedtex-astc-differences-between-ldr-and-hdr-modes, ASTC
|
|
differences between LDR and HDR modes>>.
|
|
|
|
[[appendix-compressedtex-astc-differences-between-ldr-and-hdr-modes]]
|
|
.ASTC differences between LDR and HDR modes
|
|
[width="75%",options="header"]
|
|
|====
|
|
| 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 <<appendix-compressedtex-astc-decoding-modes, ASTC
|
|
decoding modes>>.
|
|
|
|
[[appendix-compressedtex-astc-decoding-modes]]
|
|
.ASTC decoding modes
|
|
[width="75%",options="header"]
|
|
|====
|
|
| 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 [eq]#[(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 [eq]#(R,G,B,A) = (1.0,0.0,1.0,1.0)# or a vector of four NaNs
|
|
[eq]#(R,G,B,A) = (NaN,NaN,NaN,NaN)#.
|
|
In the latter case, the recommended [eq]#NaN# value returned is
|
|
[eq]#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.
|
|
|
|
|
|
[[appendix-compressedtex-astc-weight-application]]
|
|
|
|
[NOTE]
|
|
.Note
|
|
====
|
|
This replaces section 16.19 in the <<data-format,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 C~0~ and C~1~ as follows:
|
|
|
|
If sRGB conversion is not enabled, or for the alpha channel in any case,
|
|
C~0~ and C~1~ are first expanded to 16 bits by bit replication:
|
|
|
|
-----
|
|
C0 = (C0 << 8) | C0; C1 = (C1 << 8) | C1;
|
|
-----
|
|
|
|
If sRGB conversion is enabled, C~0~ and C~1~ for the R, G, and B channels
|
|
are expanded to 16 bits differently, as follows:
|
|
|
|
-----
|
|
C0 = (C0 << 8) | 0x80; C1 = (C1 << 8) | 0x80;
|
|
-----
|
|
|
|
C~0~ and C~1~ 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, C~0~ and C~1~, 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 C~f~:
|
|
|
|
-----
|
|
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 C~f~ 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]
|
|
.Note
|
|
====
|
|
This modifies section 16.23 in the <<data-format,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 <<appendix-compressedtex-astc-weight-application,
|
|
Weight Application>>).
|
|
|
|
endif::VK_EXT_astc_decode_mode[]
|