Name EXT_texture_compression_astc_decode_mode Name Strings GL_EXT_texture_compression_astc_decode_mode GL_EXT_texture_compression_astc_decode_mode_rgb9e5 Contact Jan-Harald Fredriksen (jan-harald.fredriksen 'at' arm.com) Contributors Edvard Fielding Jan-Harald Fredriksen Jakob Fries Tom Olson Jorn Nystad IP Status No known issues. Status DRAFT Version Version 4, January 23, 2017 Number OpenGL ES Extension #276 Dependencies OpenGL ES 3.0 is required. GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr, or GL_OES_texture_compression_astc is required. This extension is written based on the wording of the OpenGL ES 3.2 specification and the GL_KHR_texture_compression_astc_hdr extension. This extension interacts with GL_KHR_texture_compression_astc_hdr. Overview Adaptive Scalable Texture Compression (ASTC) is a texture compression technology that is exposed by existing extensions and specifications. The existing specifications require that low dynamic range (LDR) textures are decompressed to FP16 values per component. In many cases, decompressing LDR textures to a lower precision intermediate result gives acceptable image quality. Source material for LDR textures is typically authored as 8-bit UNORM values, so decoding to FP16 values adds little value. On the other hand, reducing precision of the decoded result reduces the size of the decompressed data, potentially improving texture cache performance and saving power. The goal of this extension is to enable this efficiency gain on existing ASTC texture data. This is achieved by giving the application the ability to select the decoding precision. Two decoding options are provided by GL_EXT_texture_compression_astc_decode_mode - Decode to FP16: This is the default, and matches the required behavior in existing APIs. - Decode to UNORM8: This is provided as an option in LDR mode. If GL_EXT_texture_compression_astc_decode_mode_rgb9e5 is supported, then a third decoding option is provided: - Decode to RGB9_E5: This is provided as an option in both LDR and HDR mode. In this mode, negative values cannot be represented and are clamped to zero. The alpha component is ignored, and the results are as if alpha was 1.0. New Procedures and Functions None New Tokens Accepted by the parameter of TexParameter* and GetTexParameter*: TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69 Changes to 8.10 Texture Parameters Add to Table 8.19: Texture parameters and their values: ----------------------------------------------------------------------------- Name Type Legal Values ----------------------------------------------------------------------------- TEXTURE_ASTC_DECODE_PRECISION_EXT enum GL_RGBA16F GL_RGBA8 GL_RGB9_E5 (*) ----------------------------------------------------------------------------- (*) Note: GL_RGB9_E5 is legal if and only if the GL_EXT_texture_compression_astc_decode_mode_rgb9e5 extension is supported. Changes to C.2.5 LDR and HDR Modes In Table C.2.1 (Differences Between LDR and HDR Modes) in KHR_texture_compression_astc_hdr: Modify the first row of the table to read: ----------------------------------------------------------------------------- Operation LDR Mode HDR Mode ----------------------------------------------------------------------------- Returned value Determined by the Determined by the decoding mode decoding mode ----------------------------------------------------------------------------- Table C.2.1 - Differences Between LDR and HDR Modes Add the following paragraph immediately after Table C.2.1: The type of the values returned by the decoding process is determined by API state as follows: ----------------------------------------------------------------------------- Decode mode LDR Mode HDR Mode ----------------------------------------------------------------------------- GL_RGBA16F Vector of FP16 values Vector of FP16 values GL_RGBA8 Vector of UNORM8 values GL_RGB9_E5 Vector using a shared Vector using a shared exponent format exponent format ----------------------------------------------------------------------------- Table C.2.1.a - Decoding mode [[ HDR profile only ]] Using the GL_RGBA8 decoding mode in HDR mode gives undefined results. For sRGB output, the decoding mode is ignored, and the decoding always returns a vector of UNORM8 values. If the texture does not have an ASTC format, the decoding mode is ignored. [[ If GL_EXT_texture_compression_astc_decode_mode_rgb9e5 and HDR profile is supported, then add the following paragraph after the second paragraph following Table C.2.1 ]] When using the GL_RGB9_E5 decoding mode in HDR mode, error results will return the error color because NaN cannot be represented. Changes to C.2.19 (Weight Application) Replace the paragraph immediately after the expression for the value C in LDR mode with the following: If sRGB conversion is not enabled and the decoding mode is GL_RGBA16F, then if C = 65535, then 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 GL_RGBA8, then top 8 bits of the interpolation result for the R, G, B, and A channels are used as the final result. [[ The following two paragraph applies to GL_EXT_texture_compression_astc_decode_mode_rgb9e5 only. ]] If sRGB conversion is not enabled and the decoding mode is GL_RGB9_E5, 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. [[ If GL_EXT_texture_compression_astc_decode_mode_rgb9e5 and HDR profile is supported, then add the following at the end of the section. ]] If the decoding mode is GL_RGB9_E5, 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); Changes to C.2.23 (Void-Extent Blocks) [[ If GL_EXT_texture_compression_astc_decode_mode_rgb9e5 and HDR profile is supported, then add the following paragraph. ]] In the HDR case, if the decoding mode is GL_RGB9_E5, then any negative color component values are set to 0 before conversion to the shared exponent format (as described in C.2.19). New State In Table 21.10: Textures (state per texture object), add: Get value Type Get Command Initial value Description Section ---- ---- ------------- ------------- ----------- ------- TEXTURE_ASTC_DECODE_- E GetTexParameter GL_RGBA16F Decode mode C.2.5 PRECISION_EXT Interactions with GL_KHR_texture_compression_astc_hdr If GL_KHR_texture_compression_astc_hdr is not supported, then the HDR profile is not supported, all references to HDR are removed. Issues (1) Should we include the GL_RGB9_E5 mode? Proposed: Yes. (2) Are implementations allowed to decode at a higher precision than what is requested? Proposed: No. If we allow this, then this extension could be exposed on all implementations that support ASTC. But developers would have no way of knowing what precision was actually used, and thus whether image quality is sufficient at reduced precision. (3) What happens to values in void-extent blocks that are infinity or NaN when using GL_RGB9_E5? Resolved: Undefined behavior. KHR_texture_compression_astc_hdr already makes this undefined: "In the HDR case, if the color component values are infinity or NaN, this will result in undefined behavior. As usual, this must not lead to GL interruption or termination." (4) Should there be an error or a texture completeness rule when using the GL_RGBA8 decoding mode for HDR mode blocks? Resolved: No. There is no way for implementations to check this condition short of iterating through all the blocks of the texture. (5) Should the decode mode be texture image state and/or sampler state? Resolved: Texture image state only. Some implementations effectively treat the the different decode modes as different texture formats. Revision History Revision 4, January 23, 2017 - Split functionality in two name strings. Clarified interaction with KHR_texture_compression_astc_hdr Added issue 5. Revision 3, January 18, 2017 - Tidy up. Revision 2, December 6, 2016 - Fixed type errors in rounding operation. Clarified behavior of negative values in void-extent blocks when decoding to shared exponent format. Revision 1, November 11, 2016 - Initial draft.