Skip to content

XUBC7 Usage Guide

Richard Geldreich edited this page Jul 4, 2026 · 8 revisions

XUBC7 Usage Guide

Copyright (C) 2025-2026 Binomial LLC. All rights reserved except as granted under the Apache 2.0 LICENSE.

Table of Contents


Quick Start

See the project's README for information on how to either compile the basisu command line tool, or use our precompiled platform independent .wasm executables (checked into the repository in the bin directory) with a WASM runtime such as Wasmtime.

  • For lossless supercompression of the encoded BC7 texture data (the default mode):

basisu -xubc7 input.png

  • For lossy compression using Weight Grid DCT (smaller files):

basisu -xubc7 -quality 75 input.png

  • For even smaller files, combining DCT with block-level RDO and a higher effort level:

basisu -xubc7 -quality 60 -xubc7_rdo_level 25 -effort 7 input.png

  • For the highest quality BC7 base encoding (slower), using the bc7e_scalar base encoder:

basisu -xubc7 -xubc7_bc7e_scalar_level 4 input.png

  • For tangent space RGB normal maps or other linear (non-sRGB) content:

basisu -linear -xubc7 input.png

  • For the maximum compression ratio (at the cost of decode parallelism):

basisu -xubc7 -xubc7_stripes 1 input.png

  • To unpack a .KTX2 file to individual .PNG, .DDS, .KTX, etc. files:

basisu input.ktx2

Add -stats and -debug to see output statistics and debug/development information.

Intro

XUBC7, new in Basis Universal v2.50, is a supercompressed BC7 codec: the encoder first packs the input image to BC7 blocks using a real-time BC7 encoder, then losslessly (or lossily) supercompresses that BC7 texture data. On the transcoding side, XUBC7's natural target is BC7 — a fast direct path, since the file contains supercompressed BC7 data — but like the other codecs in the system it can also be transcoded to the other supported LDR texture formats or raster images (see Transcoding below).

The data stored inside the file is always 4x4 BC7 (8 bits/texel before supercompression), with or without alpha. What the output GPU texture is depends on which format you transcode to — the most natural target (least overhead, no additional loss) is naturally BC7 itself. The next most natural target is ASTC LDR 4x4, because most BC7 blocks can be converted using direct latent-to-latent transcoding (converting the block parameters directly, without texel-wise recompression; BC7 2/3 subset blocks whose partition pattern isn't losslessly transcodable to ASTC fall back to real-time repacking).

By default XUBC7 losslessly compresses the encoded BC7 texture data — a default XUBC7 encode is lossless relative to the BC7 encoding. (Like all GPU texture codecs, the BC7 encoding itself is of course lossy relative to the original source image.) Two optional and independent categories of lossy compression are available for smaller files: structured distortion in the frequency domain via Weight Grid DCT, and/or unstructured distortion at the block level via RDO.

Low-level details on the XUBC7 file format (the blob structure inside the supercompressed data) are documented in XUBC7 File Format. XUBC7's KTX2 container details (DFD, seek tables, supercompression scheme) are documented in KTX2 File Format Support Technical Details.

In compression performance, XUBC7 using aggressive RDO/DCT settings competes very well vs. XUASTC LDR 4x4.

When to choose XUBC7: if your primary GPU target is BC7 (desktop Direct3D/OpenGL/Vulkan, consoles), XUBC7 is the natural choice — transcoding to BC7 is a fast direct path with no block recompression, so there's no transcode-time quality loss on your main target. If your primary target is ASTC hardware (mobile), XUASTC LDR is the better fit for the same reason (and offers larger block sizes for lower bitrates).

Note: Under Direct3D, the first/largest mipmap level's dimensions for BCn compressed textures must be a multiple of 4 texels (unless D3D12_FEATURE_DATA_D3D12_OPTIONS8::UnalignedBlockTexturesSupported is true in D3D 12). This is not a constraint of Basis Universal or WebGPU/Metal/OpenGL/WebGL/Vulkan, but if you're creating mipmapped content that targets BC7 under Direct3D, it's recommended you ensure the texture dimensions are a multiple of 4 before compression.

Available Supercompression Modes

Lossless (the default)

With no -quality setting (or -quality 100), and RDO disabled (the default), XUBC7 losslessly supercompresses the encoded BC7 texture data: the transcoded BC7 output decodes identically to the BC7 blocks the base encoder produced. This is the default mode.

Weight Grid DCT

-quality X with X in [1,99] enables lossy Weight Grid DCT: perceptually structured distortion in the frequency domain, applied to the BC7 per-texel weights (similar in spirit to the XUASTC LDR codec's Weight Grid DCT — see that guide for background). Lower quality values give smaller files at lower quality. -quality 100 (or leaving it unset) disables DCT.

Like JPEG and XUASTC LDR, DCT shapes distortion in the frequency domain, making pixel-wise error metrics (PSNR, MSE) unreliable for quality evaluation — perceptual metrics like SSIMULACRA 2 are recommended.

RDO

-xubc7_rdo_level X, [0,100], enables block-level RDO: perceptually unstructured distortion, permitting bounded per-block quality drops (e.g. reusing nearby block data) in exchange for smaller files. 0 (the default) disables RDO; [1,100] enables it, with 100 the most aggressive setting.

DCT and RDO are independent — each can be enabled or disabled relative to the other, or combined for the smallest files.

Rate vs. Distortion Control

The codec's basic knobs, what they impact, and the distortion type:

Knob Affects Distortion Type
DCT quality (-quality) Bitrate (heavily), spectral energy Structured, perceptual
RDO level (-xubc7_rdo_level) Bitrate, block reuse Unstructured, blocky
Effort (-effort) Search depth, encode speed Quality ceiling
BC7 base encoder (-xubc7_bc7f/-xubc7_bc7e_scalar) Base BC7 quality, encode speed Base encoding quality
Stripes (-xubc7_stripes) Decode parallelism vs. file size None

All XUBC7 Related Command Line Options

Codec Mode Setting

  • -xubc7

Enables XUBC7 mode. This is the only selector — XUBC7 has no block size options (the output is always 4x4 BC7).

Quality and Effort Settings

  • -quality X: The primary unified "quality" option.

Enables lossy Weight Grid DCT and sets the DCT quality level, [1,100]. Higher = better quality, but higher bitrate. 100 = lossless (no DCT), which is also the behavior when -quality isn't specified at all — so a plain -xubc7 encode is lossless.

Important: use -quality, not the legacy -q option. For XUBC7, -q prints a warning and is not recommended — worse, -q values below 100 still silently enable lossy DCT (the value is clamped to the [1,100] DCT quality range), so a user reaching for the old ETC1S-style -q 128 gets lossless, but -q 50 quietly produces lossy output. Use -quality to be explicit.

  • -effort X: The primary unified "effort" option, controlling encoding time vs. compression ratio. Must be between [0,10]. Default is 3. Higher values = slower encoding but better compression (the encoder evaluates more weight-grid predictors per block — the dominant encode cost when DCT is enabled). 9 is the usual practical maximum; 10 exists for very high core counts.

The effort level also has side effects at the extremes: effort <= 1 switches the bc7f base packer to its faster default flags, and effort 10 switches it to slower, non-analytical flags for slightly higher base quality. Additionally, effort >= 3 combined with DCT quality >= 90 (which includes the lossless default) enables an extra pass that exhaustively re-optimizes each block's weights for bc7f's endpoints after the base pack.

RDO Control

  • -xubc7_rdo_level X (also -xubc7_rdo): Sets the RDO level, [0,100]. Default is 0 (no RDO). Higher values permit progressively larger per-block quality drops in exchange for smaller files; 100 is the most aggressive setting.

Encode Stripes

  • -xubc7_num_stripes X (also -xubc7_stripes): Sets the desired number of encode stripes, [1,16]. Default is 8.

More stripes = more encode/decode (transcode) parallelism, but slightly larger files. Use -xubc7_stripes 1 for the maximum compression ratio. The stripe count is automatically re-clamped per image based on its size.

BC7 Base Encoder Selection

  • -xubc7_bc7f: Use the bc7f real-time BC7 base encoder (the default) — fast; runs with partially analytical packing flags by default (see the effort side effects above).

  • -xubc7_bc7e_scalar (also -xubc7_bc7e): Use the bc7e_scalar base encoder (based on bc7e.ispc) — slower, but higher base BC7 quality.

  • -xubc7_bc7e_scalar_level X: Sets the bc7e_scalar quality level, [0,6]. Default is 2. Higher = slower/better. Note: specifying this option implicitly selects the bc7e_scalar encoder, so you don't also need -xubc7_bc7e_scalar.

Encoder Channel Weights

  • -weights X Y Z W (also -xuastc_weights, -xuastc_ldr_weights): Set unsigned integer per-channel (RGBA) error weights, each in [1,1024]. Despite the alias names, these weights apply to XUBC7 too — they're used whenever the encoder evaluates block candidates against the original pixels.

The defaults are 9,11,1,11 (Rec. 709-like sRGB/perceptual weights). The -linear and -normal_map presets reset them to 1,1,1,1 — use one of these presets (or -weights 1 1 1 1) for normal maps and other linear content. For textures with important alpha content, setting the alpha (4th) weight above the others can be quite useful.

Note the base encoders differ in weight support: bc7f (the default) supports neither channel weights nor perceptual metrics itself (the weights still steer the supercompression stage); bc7e_scalar supports either — in perceptual mode (the sRGB default) it uses its own perceptual metrics and ignores the weights, in linear mode it honors them.

Presets

  • -srgb (the default behavior): sRGB/photographic content preset.
  • -linear: linear content preset — sets linear mip filtering, linear channel weights (1,1,1,1), etc.
  • -normal_map: normal map preset — like -linear plus additional normal-map-appropriate settings.

Output File Options

  • -ktx2: Write a .KTX2 file (the default).
  • -basis: Write a .basis file instead.
  • -output_file X / -output_path X: Set the output filename or directory.

Note the KTX2 Zstandard options (-ktx2_zstandard_level, -ktx2_no_zstandard) have no effect on XUBC7 — the codec has its own built-in compression, so its KTX2 files use the KTX2_SS_XUBC7 supercompression scheme instead of Zstd.

Mipmaps

  • -mipmap: Enable automatic mipmap generation, along with the standard mipmap options (-mip_filter, -mip_scale, -mip_srgb/-mip_linear, -mip_smallest, etc.), which all work as usual with XUBC7.

Gotchas

  • Always supply a numeric value immediately after each value-taking option. A missing value (e.g. -xubc7_rdo_level -etc1s) will silently consume the next option as its argument.
  • Don't confuse -xubc7_bc7e_scalar_level with -dds_bc7e_scalar_level — the latter belongs to the separate -dds .DDS export path, not XUBC7 output.

C++ Encoder API Parameters

XUBC7 mode is selected via set_format_mode(basist::basis_tex_format::cXUBC7), or (recommended) set_format_mode_and_quality_effort() to set the mode, quality, and effort in one call. The XUBC7-specific basis_compressor_params members (m_xubc7_effort_level, m_xubc7_rdo_level, m_xubc7_num_stripes, m_xubc7_encoder, m_xubc7_bc7e_scalar_level) are fully documented in the Compressor Definitions and Classes reference, which also includes complete, tested lossless and lossy C++ code examples.

The JavaScript (emscripten) API also exposes XUBC7 via cXUBC7 — see webgl/transcoder/basis_wrappers.cpp.

Transcoding

XUBC7's natural transcode target is BC7: the file contains supercompressed BC7 data, so transcoding to BC7 is a fast direct path with no block recompression.

The next most natural target is ASTC LDR 4x4: most BC7 blocks can be converted to ASTC LDR 4x4 using direct latent-to-latent transcoding — the BC7 block parameters are converted directly to ASTC block parameters, without texel-wise recompression. The exception: if a BC7 2/3 subset block uses a partition pattern that isn't losslessly transcodable to ASTC, the transcoder unpacks that BC7 block to texels and packs it to ASTC LDR 4x4 in real-time.

Like the other codecs, XUBC7 files can also be transcoded to the other supported LDR formats: BC1, BC3, BC4, BC5, ETC1, ETC2 RGBA, ETC2 EAC R11/RG11, PVRTC1 RGB/RGBA, and the uncompressed raster pixel formats (RGBA32, RGB565, BGR565, RGBA4444). (These paths decode the BC7 data to texels and re-encode using the transcoder's real-time block encoders, so they're slower than the direct paths and quality is bounded by the intermediate BC7 encoding.)

XUBC7 mipmap levels have seek tables in the KTX2 file (the same ktx2_slice_offset_len_desc_std mechanism as XUASTC LDR), so individual mipmap levels can be transcoded without processing the whole file. See KTX2 File Format Support Technical Details.

More Tips and Low-Level System Notes

  • The default mode is lossless. A plain basisu -xubc7 input.png losslessly supercompresses the BC7 texture data. To trade quality for smaller files, add -quality (DCT), -xubc7_rdo_level (RDO), or both.
  • The base BC7 encoding sets the quality ceiling. In lossless mode the output quality is exactly the base encoder's quality — so if quality matters more than encode speed, use -xubc7_bc7e_scalar_level 4 (or higher) to improve the ceiling.
  • Stripes trade decode parallelism for size. The default of 8 stripes allows multi-threaded transcoding of each mipmap level. Content pipelines that only care about the final file size can use -xubc7_stripes 1.
  • Deblocking doesn't apply to XUBC7. The adaptive deblocking machinery (CPU and shader) exists for the large ASTC block sizes; XUBC7 is always 4x4 BC7, so there's nothing to deblock.
  • Texture arrays, cubemaps, and texture video all work with XUBC7 like the other codecs (-tex_type options).

Related Pages

Clone this wiki locally