| Name |
| |
| ARB_texture_compression_bptc |
| |
| Name Strings |
| |
| GL_ARB_texture_compression_bptc |
| |
| Contact |
| |
| Eric Werness, NVIDIA Corporation (ewerness 'at' nvidia.com) |
| Piers Daniell, NVIDIA Corporation (pdaniell 'at' nvidia.com) |
| |
| Contributors |
| |
| Barthold Lichtenbelt, NVIDIA |
| Bill Licea-Kane, AMD |
| Graham Sellers, AMD |
| Greg Roth, NVIDIA |
| Jeannot Breton, NVIDIA |
| Jeff Bolz, NVIDIA |
| Nick Haemel, AMD |
| Pat Brown, NVIDIA |
| Pierre Boudier, AMD |
| Piers Daniell, NVIDIA |
| |
| Notice |
| |
| Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at |
| http://www.khronos.org/registry/speccopyright.html |
| |
| Specification Update Policy |
| |
| Khronos-approved extension specifications are updated in response to |
| issues and bugs prioritized by the Khronos OpenGL Working Group. For |
| extensions which have been promoted to a core Specification, fixes will |
| first appear in the latest version of that core Specification, and will |
| eventually be backported to the extension document. This policy is |
| described in more detail at |
| https://www.khronos.org/registry/OpenGL/docs/update_policy.php |
| |
| Status |
| |
| Complete. Approved by the ARB at the 2010/01/22 F2F meeting. |
| Approved by the Khronos Board of Promoters on March 10, 2010. |
| |
| Version |
| |
| Last Modified Date: October 30, 2019 |
| Revision: 9 |
| |
| Number |
| |
| ARB Extension #77 |
| |
| Dependencies |
| |
| OpenGL 1.3 or ARB_texture_compression is required. |
| |
| This extension is written against the OpenGL 3.2 Specification |
| (Compatibility Profile). |
| |
| Overview |
| |
| This extension provides additional texture compression functionality |
| specific to the BPTC and BPTC_FLOAT compressed texture formats (called BC7 |
| and BC6H respectively in Microsoft's DirectX API), subject to all the |
| requirements and limitations described by the extension |
| GL_ARB_texture_compression. |
| |
| Traditional block compression methods as typified by s3tc and latc |
| compress a block of pixels into indicies along a gradient. This works well |
| for smooth images, but can have quality issues along sharp edges and |
| strong chrominance transitions. To improve quality in these problematic |
| cases, the BPTC formats can divide each block into multiple partitions, |
| each of which are compressed using an independent gradient. |
| |
| In addition, it is desirable to directly support high dynamic range |
| imagery in compressed formats, which is accomplished by the BPTC_FLOAT |
| formats. |
| |
| IP Status |
| |
| No known IP claims. |
| |
| New Procedures and Functions |
| |
| None. |
| |
| New Tokens |
| |
| Accepted by the <internalformat> parameter of TexImage2D, TexImage3D, |
| CopyTexImage2D, CopyTexImage3D, CompressedTexImage2DARB, and |
| CompressedTexImage3DARB and the <format> parameter of |
| CompressedTexSubImage2DARB and CompressedTexSubImage3DARB: |
| |
| COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C |
| COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F |
| |
| |
| Additions to Chapter 2 of the OpenGL 3.2 Specification (OpenGL Operation) |
| |
| None. |
| |
| Additions to Chapter 3 of the OpenGL 3.2 Specification (Rasterization) |
| |
| Add to Table 3.20: Generic and specific compressed internal formats |
| |
| Compressed Internal Format Base Internal Format Type |
| ========================== ==================== ======== |
| COMPRESSED_RGBA_BPTC_UNORM_ARB RGBA Specific |
| COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB RGBA Specific |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB RGB Specific |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB RGB Specific |
| |
| |
| Modify Section 3.9.2, Alternate Texture Image Specification Commands |
| |
| (add to end of TexSubImage discussion, p.231 -- after edit from the |
| ARB_texture_compression spec) |
| |
| If the internal format of the texture image being modified is |
| COMPRESSED_RGBA_BPTC_UNORM_ARB, COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, or |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB the texture is stored using the |
| specified BPTC compressed texture image format. Such images are easily |
| edited along 4x4 texel boundaries, so the limitations on TexSubImage2D, |
| TexSubImage3D, CopyTexSubImage2D, and CopyTexSubImage3D parameters are |
| relaxed. TexSubImage2D, TexSubImage3D, CopyTexSubImage2D, and |
| CopyTexSubImage3D will result in an INVALID_OPERATION error only if one of |
| the following conditions occurs: |
| |
| * <width> is not a multiple of four, <width> plus <xoffset> is not |
| equal to TEXTURE_WIDTH, and either <xoffset> or <yoffset> is |
| non-zero; |
| |
| * <height> is not a multiple of four, <height> plus <yoffset> is not |
| equal to TEXTURE_HEIGHT, and either <xoffset> or <yoffset> is |
| non-zero; or |
| |
| * <xoffset> or <yoffset> is not a multiple of four. |
| |
| The contents of any 4x4 block of texels of a BPTC compressed texture image |
| that does not intersect the area being modified are preserved during valid |
| TexSubImage2D, TexSubImage3D, CopyTexSubImage2D, and CopyTexSubImage3D |
| calls. |
| |
| |
| Add to Section 3.9.3, Compressed Texture Images (adding to the end of the |
| CompressedTexImage section introduced by the ARB_texture_compression spec) |
| |
| If <internalformat> is COMPRESSED_RGBA_BPTC_UNORM_ARB, |
| COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, or |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB the compressed texture is stored |
| using the specified BPTC compressed texture image format. The BPTC |
| texture compression algorithm supports only 2D images without borders, |
| though 3D images can be compressed as multiple slices of compressed 2D |
| images. CompressedTexImage1DARB produces an INVALID_ENUM error if |
| <internalformat> is a BPTC format. CompressedTexImage2DARB and |
| CompressedTexImage3DARB will produce an INVALID_OPERATION error if |
| <border> is non-zero. |
| |
| |
| Add to Section 3.9.3, Compressed Texture Images (adding to the end of the |
| CompressedTexSubImage section introduced by the ARB_texture_compression |
| spec) |
| |
| If the internal format of the texture image being modified is |
| COMPRESSED_RGBA_BPTC_UNORM_ARB, COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, or |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB the texture is stored using the |
| specified BPTC compressed texture image formats. Since the BPTC texture |
| compression algorithm supports only 2D images, CompressedTexSubImage1DARB |
| produces an INVALID_ENUM error if <format> is a BPTC format. Since BPTC |
| images are easily edited along 4x4 texel boundaries, the limitations on |
| CompressedTexSubImage2D and CompressedTexSubImage3D are relaxed. |
| CompressedTexSubImage2D and CompressedTexSubImage3D will result in an |
| INVALID_OPERATION error only if one of the following conditions occurs: |
| |
| * <width> is not a multiple of four, and <width> plus <xoffset> is not |
| equal to TEXTURE_WIDTH; |
| |
| * <height> is not a multiple of four, and <height> plus <yoffset> is |
| not equal to TEXTURE_HEIGHT; or |
| |
| * <xoffset> or <yoffset> is not a multiple of four. |
| |
| The contents of any 4x4 block of texels of a BPTC compressed texture image |
| that does not intersect the area being modified are preserved during valid |
| TexSubImage2D/3D and CopyTexSubImage2D/3D calls. |
| |
| Additions to Chapter 4 of the OpenGL 3.2 Specification (Per-Fragment |
| Operations and the Frame Buffer) |
| |
| None. |
| |
| Additions to Chapter 5 of the OpenGL 3.2 Specification (Special Functions) |
| |
| None. |
| |
| Additions to Chapter 6 of the OpenGL 3.2 Specification (State and |
| State Requests) |
| |
| None. |
| |
| Additions to Appendix A of the OpenGL 3.2 Specification (Invariance) |
| |
| None. |
| |
| Additions to the AGL/GLX/WGL Specifications |
| |
| None. |
| |
| GLX Protocol |
| |
| None. |
| |
| Errors |
| |
| INVALID_ENUM is generated by CompressedTexImage1DARB if <internalformat> |
| is COMPRESSED_RGBA_BPTC_UNORM_ARB, COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, or |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB. |
| |
| INVALID_OPERATION is generated by CompressedTexImage2DARB if |
| <internalformat> is COMPRESSED_RGBA_BPTC_UNORM_ARB, |
| COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, or |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB and <border> is not equal to zero. |
| |
| INVALID_ENUM is generated by CompressedTexSubImage1DARB if <format> is |
| COMPRESSED_RGBA_BPTC_UNORM_ARB, COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, or |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB. |
| |
| INVALID_OPERATION is generated by TexSubImage2D or CopyTexSubImage2D if |
| TEXTURE_INTERNAL_FORMAT is COMPRESSED_RGBA_BPTC_UNORM_ARB, |
| COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, or |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB and any of the following apply: |
| |
| * <width> is not a multiple of four, <width> plus <xoffset> is not |
| equal to TEXTURE_WIDTH, and either <xoffset> or <yoffset> is |
| non-zero; |
| |
| * <height> is not a multiple of four, <height> plus <yoffset> is not |
| equal to TEXTURE_HEIGHT, and either <xoffset> or <yoffset> is |
| non-zero; or |
| |
| * <xoffset> or <yoffset> is not a multiple of four. |
| |
| INVALID_OPERATION is generated by CompressedTexSubImage2D if |
| TEXTURE_INTERNAL_FORMAT is COMPRESSED_RGBA_BPTC_UNORM_ARB, |
| COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, or |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB and any of the following apply: |
| |
| * <width> is not a multiple of four, and <width> plus <xoffset> is not |
| equal to TEXTURE_WIDTH; |
| |
| * <height> is not a multiple of four, and <height> plus <yoffset> is |
| not equal to TEXTURE_HEIGHT; or |
| |
| * <xoffset> or <yoffset> is not a multiple of four. |
| |
| The following restrictions from the ARB_texture_compression specification |
| do not apply to BPTC texture formats, since subimage modification is |
| straightforward as long as the subimage is properly aligned. |
| |
| DELETE: INVALID_OPERATION is generated by TexSubImage1D, TexSubImage2D, |
| DELETE: TexSubImage3D, CopyTexSubImage1D, CopyTexSubImage2D, or |
| DELETE: CopyTexSubImage3D if the internal format of the texture image is |
| DELETE: compressed and <xoffset>, <yoffset>, or <zoffset> does not equal |
| DELETE: -b, where b is value of TEXTURE_BORDER. |
| |
| DELETE: INVALID_VALUE is generated by CompressedTexSubImage1DARB, |
| DELETE: CompressedTexSubImage2DARB, or CompressedTexSubImage3DARB if the |
| DELETE: entire texture image is not being edited: if <xoffset>, |
| DELETE: <yoffset>, or <zoffset> is greater than -b, <xoffset> + <width> is |
| DELETE: less than w+b, <yoffset> + <height> is less than h+b, or <zoffset> |
| DELETE: + <depth> is less than d+b, where b is the value of |
| DELETE: TEXTURE_BORDER, w is the value of TEXTURE_WIDTH, h is the value of |
| DELETE: TEXTURE_HEIGHT, and d is the value of TEXTURE_DEPTH. |
| |
| See also errors in the GL_ARB_texture_compression specification. |
| |
| New State |
| |
| In the "Textures" state table, increment the TEXTURE_INTERNAL_FORMAT |
| subscript for Z by 4 in the "Type" row. |
| |
| New Implementation Dependent State |
| |
| None |
| |
| Appendix |
| |
| BPTC Compressed Texture Image Format |
| |
| Compressed texture images stored using the BPTC compressed image formats |
| are represented as a collection of 4x4 texel blocks, where each block |
| contains 128 bits of texel data. The image is encoded as a normal 2D |
| raster image in which each 4x4 block is treated as a single pixel. If a |
| BPTC image has a width or height that is not a multiple of four, the data |
| corresponding to texels outside the image are irrelevant and undefined. |
| |
| When a BPTC image with a width of <w>, height of <h>, and block size of |
| <blocksize> (16 bytes) is decoded, the corresponding image size (in bytes) |
| is: |
| |
| ceil(<w>/4) * ceil(<h>/4) * blocksize. |
| |
| When decoding a BPTC image, the block containing the texel at offset |
| (<x>, <y>) begins at an offset (in bytes) relative to the base of the |
| image of: |
| |
| blocksize * (ceil(<w>/4) * floor(<y>/4) + floor(<x>/4)). |
| |
| The data corresponding to a specific texel (<x>, <y>) are extracted from a |
| 4x4 texel block using a relative (x,y) value of |
| |
| (<x> modulo 4, <y> modulo 4). |
| |
| There are two distinct BPTC image formats each of which has two |
| variants. COMPRESSED_RGBA_BPTC_UNORM_ARB and |
| COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB compress 8-bit fixed-point |
| data. COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB and |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB compress high dynamic range |
| floating point values. The formats are similar, so the description of the |
| float format will reference significant sections of the UNORM description. |
| |
| COMPRESSED_RGBA_BPTC_UNORM_ARB (and the SRGB_ALPHA equivalent): Each 4x4 |
| block of texels consists of 128 bits of RGBA or SRGB_ALPHA image data. |
| |
| Each block contains enough information to select and decode a pair of |
| colors called endpoints, interpolate between those endpoints in a variety |
| of ways, then remap the result into the final output. |
| |
| Each block can contain data in one of eight modes. The mode is identified |
| by the lowest bits of the lowest byte. It is encoded as zero or more zeros |
| followed by a one. For example, using x to indicate a bit not included in |
| the mode number, mode 0 is encoded as xxxxxxx1 in the low byte in binary, |
| mode 5 is xx100000, and mode 7 is 10000000. Encoding the low byte as zero |
| is reserved and should not be used when encoding a BPTC texture. |
| |
| All further decoding is driven by the values derived from the mode listed |
| in Table.M below. The fields in the block are always in the same order for |
| all modes. Starting at the lowest bit after the mode and going up from LSB |
| to MSB in byte stream order, these fields are: partition number, rotation, |
| index selection, color, alpha, per-endpoint P-bit, shared P-bit, primary |
| indices, and secondary indices. The number of bits to be read in each |
| field is determined directly from the table. |
| |
| Each block can be divided into between 1 and 3 groups of pixels with |
| independent compression parameters called subsets. A texel in a block with |
| one subset is always considered to be in subset zero. Otherwise, a number |
| determined by the number of partition bits is used to look up in the |
| partition tables Table.P2 or Table.P3 for 2 and 3 subsets |
| respectively. This partitioning is indexed by the X and Y within the block |
| to generate the subset index. |
| |
| Each block has two colors for each subset, stored first by endpoint, then |
| by subset, then by color. For example, a format with two subsets and five |
| color bits would have five bits of red for endpoint 0 of the first subset, |
| then five bits of red for endpoint 1, then the two ends of the second |
| subset, then green and blue stored similarly. If a block has non-zero |
| alpha bits, the alpha data follows the color data with the same |
| organization. If not, alpha is overridden to 1.0. These bits are treated |
| as the high bits of a fixed-point value in a byte. If the format has |
| shared P-bits, there are two endpoint bits, the lower of which applies to |
| both endpoints of subset 0 and the upper of which applies to both |
| endpoints of subset 1. If the format has a per-endpoint P-bits, then there |
| are 2*subsets P-bits stored in the same order as color and alpha. Both |
| kinds of P-bits are added as a bit below the color data stored in the |
| byte. So, for a format with 5 red bits, the P-bit ends up in bit 2. For |
| final scaling, the top bits of the value are replicated into any remaining |
| bits in the byte. For the preceding example, bits 6 and 7 would be written |
| to bits 0 and 1. |
| |
| The endpoint colors are interpolated using index values stored in the |
| block. The index bits are stored in x-major order. Each index has the |
| number of bits indicated by the mode except for one special index per |
| subset called the anchor index. Since the ordering of the endpoints is |
| unimportant, we can save one bit on one index per subset by ordering the |
| endpoints such that the highest bit is guaranteed to be zero. In partition |
| zero, the anchor index is always index zero. In other partitions, the |
| anchor index is specified by tables Table.A2 and Table.A3. If secondary |
| index bits are present, they are read in the same manner. The anchor index |
| information is only used to determine the number of bits each index has |
| when it's read from the block data. |
| |
| The endpoint color and alpha values used for final interpolation are the |
| decoded values corresponding to the applicable subset as selected |
| above. The index value for interpolating color comes from the secondary |
| index for the texel if the format has an index selection bit and its value |
| is one and from the primary index otherwise. The alpha index comes from |
| the secondary index if the block has a secondary index and the block |
| either doesn't have an index selection bit or that bit is zero and the |
| primary index otherwise. |
| |
| Interpolation is always performed using a 6-bit interpolation factor. The |
| effective interpolation factors for 2, 3, and 4 bit indices are given |
| below: |
| |
| 2: 0, 21, 43, 64 |
| 3: 0, 9, 18, 27, 37, 46, 55, 64 |
| 4: 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 |
| |
| The interpolation results in an RGBA color. If rotation bits are present, |
| this color is remapped according to: |
| |
| 0: no change |
| 1: swap(a,r) |
| 2: swap(a,g) |
| 3: swap(a,b) |
| |
| These 8-bit values show up in the shader interpreted as either RGBA8 or |
| SRGB8_ALPHA8 for COMPRESSED_RGBA_BPTC_UNORM_ARB and |
| COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB respectively. |
| |
| |
| Table.M |
| |
| Mode NS PB RB ISB CB AB EPB SPB IB IB2 |
| ---- -- -- -- --- -- -- --- --- -- --- |
| 0 3 4 0 0 4 0 1 0 3 0 |
| 1 2 6 0 0 6 0 0 1 3 0 |
| 2 3 6 0 0 5 0 0 0 2 0 |
| 3 2 6 0 0 7 0 1 0 2 0 |
| 4 1 0 2 1 5 6 0 0 2 3 |
| 5 1 0 2 0 7 8 0 0 2 2 |
| 6 1 0 0 0 7 7 1 0 4 0 |
| 7 2 6 0 0 5 5 1 0 2 0 |
| |
| The columns are as as follows: |
| |
| Mode: As described above |
| |
| NS: Number of subsets in each partition |
| |
| PB: Partition bits |
| |
| RB: Rotation bits |
| |
| ISB: Index selection bits |
| |
| CB: Color bits |
| |
| AB: Alpha bits |
| |
| EPB: Endpoint P-bits |
| |
| SPB: Shared P-bits |
| |
| IB: Index bits per element |
| |
| IB2: Secondary index bits per element |
| |
| |
| Table.P2 |
| |
| (each row is one 4x4 block) |
| |
| |
| 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1 |
| 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1 |
| 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1 |
| 0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1 |
| 0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1 |
| 0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1 |
| 0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1 |
| 0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1 |
| 0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1 |
| 0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1 |
| 0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1 |
| 0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1 |
| 0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1 |
| 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1 |
| 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1 |
| 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1 |
| 0,0,0,0,1,0,0,0,1,1,1,0,1,1,1,1 |
| 0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0 |
| 0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0 |
| 0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0 |
| 0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 |
| 0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0 |
| 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0 |
| 0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1 |
| 0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0 |
| 0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0 |
| 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0 |
| 0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0 |
| 0,0,0,1,0,1,1,1,1,1,1,0,1,0,0,0 |
| 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0 |
| 0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0 |
| 0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0 |
| 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 |
| 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1 |
| 0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0 |
| 0,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0 |
| 0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0 |
| 0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0 |
| 0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1 |
| 0,1,0,1,1,0,1,0,1,0,1,0,0,1,0,1 |
| 0,1,1,1,0,0,1,1,1,1,0,0,1,1,1,0 |
| 0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0 |
| 0,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0 |
| 0,0,1,1,1,0,1,1,1,1,0,1,1,1,0,0 |
| 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0 |
| 0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1 |
| 0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1 |
| 0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0 |
| 0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0 |
| 0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0 |
| 0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0 |
| 0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0 |
| 0,1,1,0,1,1,0,0,1,0,0,1,0,0,1,1 |
| 0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,1 |
| 0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0 |
| 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0 |
| 0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1 |
| 0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1 |
| 0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1 |
| 0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,1 |
| 0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1 |
| 0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0 |
| 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0 |
| 0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1 |
| |
| Table.P3 |
| |
| 0,0,1,1,0,0,1,1,0,2,2,1,2,2,2,2 |
| 0,0,0,1,0,0,1,1,2,2,1,1,2,2,2,1 |
| 0,0,0,0,2,0,0,1,2,2,1,1,2,2,1,1 |
| 0,2,2,2,0,0,2,2,0,0,1,1,0,1,1,1 |
| 0,0,0,0,0,0,0,0,1,1,2,2,1,1,2,2 |
| 0,0,1,1,0,0,1,1,0,0,2,2,0,0,2,2 |
| 0,0,2,2,0,0,2,2,1,1,1,1,1,1,1,1 |
| 0,0,1,1,0,0,1,1,2,2,1,1,2,2,1,1 |
| 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2 |
| 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2 |
| 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2 |
| 0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2 |
| 0,1,1,2,0,1,1,2,0,1,1,2,0,1,1,2 |
| 0,1,2,2,0,1,2,2,0,1,2,2,0,1,2,2 |
| 0,0,1,1,0,1,1,2,1,1,2,2,1,2,2,2 |
| 0,0,1,1,2,0,0,1,2,2,0,0,2,2,2,0 |
| 0,0,0,1,0,0,1,1,0,1,1,2,1,1,2,2 |
| 0,1,1,1,0,0,1,1,2,0,0,1,2,2,0,0 |
| 0,0,0,0,1,1,2,2,1,1,2,2,1,1,2,2 |
| 0,0,2,2,0,0,2,2,0,0,2,2,1,1,1,1 |
| 0,1,1,1,0,1,1,1,0,2,2,2,0,2,2,2 |
| 0,0,0,1,0,0,0,1,2,2,2,1,2,2,2,1 |
| 0,0,0,0,0,0,1,1,0,1,2,2,0,1,2,2 |
| 0,0,0,0,1,1,0,0,2,2,1,0,2,2,1,0 |
| 0,1,2,2,0,1,2,2,0,0,1,1,0,0,0,0 |
| 0,0,1,2,0,0,1,2,1,1,2,2,2,2,2,2 |
| 0,1,1,0,1,2,2,1,1,2,2,1,0,1,1,0 |
| 0,0,0,0,0,1,1,0,1,2,2,1,1,2,2,1 |
| 0,0,2,2,1,1,0,2,1,1,0,2,0,0,2,2 |
| 0,1,1,0,0,1,1,0,2,0,0,2,2,2,2,2 |
| 0,0,1,1,0,1,2,2,0,1,2,2,0,0,1,1 |
| 0,0,0,0,2,0,0,0,2,2,1,1,2,2,2,1 |
| 0,0,0,0,0,0,0,2,1,1,2,2,1,2,2,2 |
| 0,2,2,2,0,0,2,2,0,0,1,2,0,0,1,1 |
| 0,0,1,1,0,0,1,2,0,0,2,2,0,2,2,2 |
| 0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0 |
| 0,0,0,0,1,1,1,1,2,2,2,2,0,0,0,0 |
| 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0 |
| 0,1,2,0,2,0,1,2,1,2,0,1,0,1,2,0 |
| 0,0,1,1,2,2,0,0,1,1,2,2,0,0,1,1 |
| 0,0,1,1,1,1,2,2,2,2,0,0,0,0,1,1 |
| 0,1,0,1,0,1,0,1,2,2,2,2,2,2,2,2 |
| 0,0,0,0,0,0,0,0,2,1,2,1,2,1,2,1 |
| 0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2 |
| 0,0,2,2,0,0,1,1,0,0,2,2,0,0,1,1 |
| 0,2,2,0,1,2,2,1,0,2,2,0,1,2,2,1 |
| 0,1,0,1,2,2,2,2,2,2,2,2,0,1,0,1 |
| 0,0,0,0,2,1,2,1,2,1,2,1,2,1,2,1 |
| 0,1,0,1,0,1,0,1,0,1,0,1,2,2,2,2 |
| 0,2,2,2,0,1,1,1,0,2,2,2,0,1,1,1 |
| 0,0,0,2,1,1,1,2,0,0,0,2,1,1,1,2 |
| 0,0,0,0,2,1,1,2,2,1,1,2,2,1,1,2 |
| 0,2,2,2,0,1,1,1,0,1,1,1,0,2,2,2 |
| 0,0,0,2,1,1,1,2,1,1,1,2,0,0,0,2 |
| 0,1,1,0,0,1,1,0,0,1,1,0,2,2,2,2 |
| 0,0,0,0,0,0,0,0,2,1,1,2,2,1,1,2 |
| 0,1,1,0,0,1,1,0,2,2,2,2,2,2,2,2 |
| 0,0,2,2,0,0,1,1,0,0,1,1,0,0,2,2 |
| 0,0,2,2,1,1,2,2,1,1,2,2,0,0,2,2 |
| 0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,2 |
| 0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,1 |
| 0,2,2,2,1,2,2,2,0,2,2,2,1,2,2,2 |
| 0,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2 |
| 0,1,1,1,2,0,1,1,2,2,0,1,2,2,2,0 |
| |
| Table.A2 (Anchor index values for the second subset of two-subset |
| partitioning) |
| |
| (wrapped for readability - values run right then down) |
| |
| 15,15,15,15,15,15,15,15, |
| 15,15,15,15,15,15,15,15, |
| 15, 2, 8, 2, 2, 8, 8,15, |
| 2, 8, 2, 2, 8, 8, 2, 2, |
| 15,15, 6, 8, 2, 8,15,15, |
| 2, 8, 2, 2, 2,15,15, 6, |
| 6, 2, 6, 8,15,15, 2, 2, |
| 15,15,15,15,15, 2, 2,15, |
| |
| Table.A3a (Anchor index values for the second subset of three-subset |
| partitioning) |
| |
| (wrapped for readability - values run right then down) |
| |
| 3, 3,15,15, 8, 3,15,15, |
| 8, 8, 6, 6, 6, 5, 3, 3, |
| 3, 3, 8,15, 3, 3, 6,10, |
| 5, 8, 8, 6, 8, 5,15,15, |
| 8,15, 3, 5, 6,10, 8,15, |
| 15, 3,15, 5,15,15,15,15, |
| 3,15, 5, 5, 5, 8, 5,10, |
| 5,10, 8,13,15,12, 3, 3, |
| |
| Table.A3b (Anchor index values for the third subset of three-subset |
| partitioning) |
| |
| (wrapped for readability - values run right then down) |
| |
| 15, 8, 8, 3,15,15, 3, 8, |
| 15,15,15,15,15,15,15, 8, |
| 15, 8,15, 3,15, 8,15, 8, |
| 3,15, 6,10,15,15,10, 8, |
| 15, 3,15,10,10, 8, 9,10, |
| 6,15, 8,15, 3, 6, 6, 8, |
| 15, 3,15,15,15,15,15,15, |
| 15,15,15,15, 3,15,15, 8, |
| |
| COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB and |
| COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: Each 4x4 block of texels consists |
| of 128 bits of RGB data. These formats are very similar and will be |
| described together. In the description and pseudocode below, <signed> will |
| be used as a condition which is true for the SIGNED format and false for |
| the UNSIGNED format. Both formats only contain RGB data, so the returned |
| alpha value is 1.0. If a block uses a reserved or invalid encoding, the |
| return value is (0,0,0,1). |
| |
| Each block can contain data in one of 14 modes. The mode number is encoded |
| in either the low two bits or the low five bits. If the low two bits are |
| less than two, that is the mode number, otherwise the low five bits the |
| mode number. Mode numbers not listed in Table.MF are reserved (19, 23, 27, |
| and 31). |
| |
| The data for the compressed blocks is stored in a different format for |
| each mode. The formats are specified in Table.F. The format strings are |
| intended to be read from left to right with the LSB on the left. Each |
| element is of the form v[a:b]. If a>=b, this indicates to extract b-a+1 |
| bits from the block at that location and put it in the corresponding bits |
| of the variable v. If a<b, then the bits are reversed. v[a] is used as a |
| shorthand for the one bit v[a:a]. As an example, m[1:0],g2[4] would move |
| the low two bits from the block into the low two bits of m then the next |
| bit of the block into bit 4 of g2. The variable names given in the table |
| will be referred to in the language below. |
| |
| Subsets and indices work in much the same way as described for the |
| fixed-point formats above. If a float block has no partition bits, then it |
| is a single-subset block. If it has partition bits, then it is a 2 subset |
| block. The partition index references the first half of Table.P2. Indices |
| are read in the same way as the fixed-point formats including obeying the |
| anchor values for index 0 and as needed by Table.A2. |
| |
| In a single-subset blocks, the two endpoints are contained in r0,g0,b0 |
| (hence e0) and r1,g1,b1 (hence e1). In a two-subset block, the endpoints |
| for the second subset are in r2,g2,b2 and r3,g3,b3. The value in e0 is |
| sign-extended if the format of the texture is signed. The values in e1 and |
| e2 and e3 if the block is two-subset are sign-extended if the format of |
| the texture is signed or if the block mode has transformed endpoints. If |
| the mode has transformed endpoints, the values from e0 are used as a base |
| to offset all other endpoints, wrapped at the number of endpoint bits. For |
| example, r1 = (r0+r1) & ((1<<EPB)-1). |
| |
| Next, the endpoints are unquantized to maximize the usage of the bits and |
| to ensure that the negative ranges are oriented properly to interpolate as |
| a two's complement value. The following pseudocode assumes the computation |
| is being done using sufficiently large intermediate values to avoid |
| overflow. For the unsigned float format, we unquantize a value x to unq |
| by: |
| |
| if (EPB >= 15) |
| unq = x; |
| else if (x == 0) |
| unq = 0; |
| else if (x == ((1<<EPB)-1)) |
| unq = 0xFFFF; |
| else |
| unq = ((x << 15) + 0x4000) >> (EPB-1); |
| |
| The signed float unquantization is similar, but needs to worry about |
| orienting the negative range: |
| |
| s = 0; |
| if (EPB >= 16) |
| unq = x; |
| else { |
| if (x < 0) { |
| s = 1; |
| x = -x; |
| } |
| |
| if (x == 0) |
| unq = 0; |
| else if (x >= ((1<<(EPB-1))-1)) |
| unq = 0x7FFF; |
| else |
| unq = ((x << 15) + 0x4000) >> (EPB-1); |
| |
| if (s) |
| unq = -unq; |
| } |
| |
| After the endpoints are unquantized, interpolation proceeds as in the |
| fixed-point formats above including the interpolation weight table. |
| |
| The interpolated values are passed through a final unquantization |
| step. For the unsigned format, this step simply multiplies by 31/64. The |
| signed format negates negative components, multiplies by 31/32, then or's |
| in the sign bit if the original value was negative. |
| |
| The resultant value should be a legal 16-bit half float which is then |
| returned as a float to the shader. |
| |
| Table.MF |
| |
| MN Tr PB EPB Delta Bits |
| -- -- -- --- ---------- |
| 0 1 5 10 {5, 5, 5} |
| 1 1 5 7 {6, 6, 6} |
| 2 1 5 11 {5, 4, 4} |
| 6 1 5 11 {4, 5, 4} |
| 10 1 5 11 {4, 4, 5} |
| 14 1 5 9 {5, 5, 5} |
| 18 1 5 8 {6, 5, 5} |
| 22 1 5 8 {5, 6, 5} |
| 26 1 5 8 {5, 5, 6} |
| 30 0 5 6 {6, 6, 6} |
| 3 0 0 10 {10, 10, 10} |
| 7 1 0 11 {9, 9, 9} |
| 11 1 0 12 {8, 8, 8} |
| 15 1 0 16 {4, 4, 4} |
| |
| MN: Mode number |
| Tr: Transformed endpoints |
| PB: Partition bits |
| EPB: Endpoint bits |
| |
| |
| Table.F |
| |
| MN Format |
| -- ------------------------------------------------------------------------ |
| 0 m[1:0],g2[4],b2[4],b3[4],r0[9:0],g0[9:0],b0[9:0],r1[4:0],g3[4],g2[3:0], |
| g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3] |
| |
| 1 m[1:0],g2[5],g3[4],g3[5],r0[6:0],b3[0],b3[1],b2[4],g0[6:0],b2[5],b3[2], |
| g2[4],b0[6:0],b3[3],b3[5],b3[4],r1[5:0],g2[3:0],g1[5:0],g3[3:0],b1[5:0], |
| b2[3:0],r2[5:0],r3[5:0] |
| |
| 2 m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[4:0],r0[10],g2[3:0],g1[3:0],g0[10], |
| b3[0],g3[3:0],b1[3:0],b0[10],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3] |
| |
| 6 m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10],g3[4],g2[3:0],g1[4:0], |
| g0[10],g3[3:0],b1[3:0],b0[10],b3[1],b2[3:0],r2[3:0],b3[0],b3[2],r3[3:0], |
| g2[4],b3[3] |
| |
| 10 m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10],b2[4],g2[3:0],g1[3:0], |
| g0[10],b3[0],g3[3:0],b1[4:0],b0[10],b2[3:0],r2[3:0],b3[1],b3[2],r3[3:0], |
| b3[4],b3[3] |
| |
| 14 m[4:0],r0[8:0],b2[4],g0[8:0],g2[4],b0[8:0],b3[4],r1[4:0],g3[4],g2[3:0], |
| g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3] |
| |
| 18 m[4:0],r0[7:0],g3[4],b2[4],g0[7:0],b3[2],g2[4],b0[7:0],b3[3],b3[4], |
| r1[5:0],g2[3:0],g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[5:0], |
| r3[5:0] |
| |
| 22 m[4:0],r0[7:0],b3[0],b2[4],g0[7:0],g2[5],g2[4],b0[7:0],g3[5],b3[4], |
| r1[4:0],g3[4],g2[3:0],g1[5:0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0], |
| b3[2],r3[4:0],b3[3] |
| |
| 26 m[4:0],r0[7:0],b3[1],b2[4],g0[7:0],b2[5],g2[4],b0[7:0],b3[5],b3[4], |
| r1[4:0],g3[4],g2[3:0],g1[4:0],b3[0],g3[3:0],b1[5:0],b2[3:0],r2[4:0], |
| b3[2],r3[4:0],b3[3] |
| |
| 30 m[4:0],r0[5:0],g3[4],b3[0],b3[1],b2[4],g0[5:0],g2[5],b2[5],b3[2], |
| g2[4],b0[5:0],g3[5],b3[3],b3[5],b3[4],r1[5:0],g2[3:0],g1[5:0],g3[3:0], |
| b1[5:0],b2[3:0],r2[5:0],r3[5:0] |
| |
| 3 m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[9:0],g1[9:0],b1[9:0] |
| |
| 7 m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[8:0],r0[10],g1[8:0],g0[10],b1[8:0], |
| b0[10] |
| |
| 11 m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[7:0],r0[10:11],g1[7:0],g0[10:11], |
| b1[7:0],b0[10:11] |
| |
| 15 m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10:15],g1[3:0],g0[10:15], |
| b1[3:0],b0[10:15] |
| |
| |
| Issues |
| |
| (1) Are both RGB and RGBA versions interesting? |
| |
| RESOLVED. Not for the unorm formats. Every BPTC mode has a defined |
| alpha, so an RGB mode isn't needed. Also, since modes are per-block, a |
| given texture can have both RGB1 and RGBA portions. |
| |
| The float formats don't compress alpha at all, so they only have RGB |
| variants, not RGBA. |
| |
| (2) Put both BC7 and BC6H in the same spec? |
| |
| RESOLVED. Yes. They share enough that it's worthwhile to amortize the |
| "overhead". |
| |
| (3) Why are there two versions of the float BPTC formats for signed and |
| unsigned? Do they pass through the GL differently? |
| |
| RESOLVED. The unsigned formats are decoded distinctly from signed |
| formats, so it is necessary to distinguish between them. |
| |
| The values still pass through the shader and the pixel path as signed |
| floats, but the interpretation of the compressed block changes as |
| described. |
| |
| (4) Should the result of the compressed float formats be half floats or |
| single floats? |
| |
| RESOLVED. The expansion from packed to half to float will be specified |
| as part of the decompression process. |
| |
| (5) What should be expected for a driver compressor for these formats? |
| |
| RESOLVED: The current best known compression algorithms have to |
| exhaustively test all partitionings across all modes. The compressor in |
| the GL will have to make a tradeoff between performance and |
| quality. Compressing offline is highly recommended. |
| |
| (6) How should floating point specials (Inf and NaN) be handled in the |
| float formats? |
| |
| RESOLVED: Decompressor will never generate them. Compressor should |
| flush to max half float. |
| |
| (7) Does this spec require bit-exact decompression? |
| |
| RESOLVED: Yes. |
| |
| (8) Does the data format depend on the endianness of the system? |
| |
| RESOLVED: No. The data is interpeted as an endian-independent |
| byte stream. |
| |
| (9) What should be the internal format of the floating-point BPTC format? |
| |
| RESOLVED: The format has three components, with the alpha component |
| mapped to 1.0, just like RGB textures. So we should call it RGB. |
| |
| In the originally ratified version of this extension (and all versions |
| prior to January 20, 2011), such textures were treated as having a base |
| internal format of RGBA, where the alpha component was not present in |
| the texture and instead is just set to the constant 1.0. Some |
| implementations of this extension may also use a base internal format |
| of RGBA. |
| |
| There are very few places where there is a difference between an RGB |
| texture and an RGBA texture where alpha is always 1.0. Two known |
| differences: |
| |
| * A compressed "RGB" texture could be used for the generic |
| COMPRESSED_RGB format, but an "RGBA" texture should not be. |
| However, it seems unlikely that implementations would choose the |
| floating-point BPTC format as its generic COMPRESSED_RGB format. |
| |
| * Using fixed-function fragment shading in the compatibility profile, |
| a texture environment mode of REPLACE would leave alpha unmodified |
| for RGB base formats but would replace the fragment alpha with the |
| texture alpha (constant 1.0 here) for RGBA base formats. |
| |
| Revision History |
| |
| Rev. Date Author Changes |
| ---- -------- ----------- -------------------------------------------- |
| 9 30/10/19 pdaniell Fix shared p-bits specification to match |
| DX and the Khronos Data Format spec. |
| |
| 8 06/06/16 Nanley Chery Reduce the requirements to the minimal set. |
| |
| 7 01/20/11 pbrown Change the base internal format of the floating- |
| point BPTC formats from "RGBA" to "RGB" (bug |
| 7231). |
| |
| 6 01/19/11 Jon Leech Fix state table modification for |
| TEXTURE_INTERNAL_FORMAT (Bug 7239). |
| |
| 5 05/20/10 ewerness Finalize some UNRESOLVED issues |
| |
| 4 04/09/10 pdaniell Modify for inclusion into OpenGL 4.1. |
| |
| 3 12/07/09 pdaniell ARBify. |
| |
| 2 10/13/09 ewerness Fix errors in the anchor index tables caused |
| by incorrect conversion scripts and a couple |
| typos in the input. |
| |
| 1 ewerness Internal revisions. |
| |