UASTC implementation details
.basis files now support both UASTC and ETC1S data. In UASTC mode, there is no extra compression applied apart from UASTC itself, so the raw UASTC .basis file sizes are quite large (8-bpp). However, the encoder supports an optional rate-distortion mode, which reduces the entropy of the output data. This trades off quality for fewer LZ compressed bits, in an intelligent way that tries to increase the probability/density of close (low distance) LZ matches. In our experiences, we've seen bitrates (using Deflate) ranging between 2-7bpp, with the typical usable bitrate being around 5-7bpp. With the current RDO encoder, the sweet spot is around 6-7 bpp.
Note that the optional RDO encoder function is not super well optimized for perf. yet. That's coming. It can also be greatly improved to achieve better quality per compressed bit. Our highest priority was to ship something that shows that RDO encoding can be accomplished on UASTC texture data, in a simple way.
A previously unused field in .basis files now indicates the internal universal texture format (ETC1S or UASTC). See
basis_file_header::m_tex_format. UASTC files reuse all the existing ETC1S file structures. There are no codebooks in UASTC mode, so a bunch of header fields (like
m_endpoint_cb_file_ofs, etc.) are zero. The helper method
basisu_transcoder::get_tex_format() can be used to determine the texture format of a .basis file.
The transcoder API transparently supports both ETC1S and UASTC files. The UASTC code was added to the transcoder in
transcoder/basisu_transcoder.cpp. It can be optionally disabled by setting the
BASISD_SUPPORT_UASTC preprocessor macro to 0.
There are three ways of accessing the new UASTC functionality:
Use the command line tool to encode UASTC .basis files using the -uastc, -uastc_rdo_q, and -uastc_level options. Then use
transcode_slice()which transparently support both ETC1S and UASTC files. This is the way web developers use the system, by compiling the transcoder's cpp file to WebAssembly.
A lowlevel class,
basisu_lowlevel_uastc_transcoder, was added with a single method that transcodes UASTC data to GPU texture data in any format:
basisu_lowlevel_uastc_transcoder::transcode_slice(). Internally, this is what
basisu_transcoder::transcode_image_level()uses on UASTC .basis files.
You could roll your own file format and just call this helper to transcode the UASTC data.
- For even lower level access to the UASTC functionality, developers can ignore .basis and our high/low level helpers completely and just use the very lowest level UASTC block functions directly.
transcoder/basisu_transcoder_uastc.hdeclares the UASTC transcode functions, and
basisu_uastc_enc.hdeclares the UASTC encode functions.
Note that before using any encoder functions you MUST call
basisu_encoder_init(). Similarly, before calling any transcoder functions you must call
The two functions
uastc_rdo() are used for encoding individual blocks (with no RDO), or groups of blocks with RDO. They are very simple to use. You call them with a pointer to 4x4 RGBA pixel blocks, and flags/options, and you get back packed 128-bit UASTC blocks.
The key lowest-level block transcoder functions defined in
Note that we will be optimizing
transcode_uastc_to_etc2_eac_rg11() to be roughly 2-2.5x faster. We targeted too high a quality for EAC R11/RG11. We will also be further optimizing UASTC->ASTC and UASTC->BC7. I would expect ~2x faster without using any SIMD.