Thursday, September 3, 2026

Fitting a neural texture decoder with ES (no backprop)

This is something I prototyped for fun in an evening: Toy neural texture compression, trained entirely with Evolution Strategies (no backprop, no derivatives). A 128×128×8 latent texture + a 1035-weight MLP decoder reconstruct a 512×512 image (kodim23 crop) at 32.2 dB PSNR. Latent quantizes to 8 bits with only 0.04 dB loss: ~4 bpp raw, ~3.3 bpp entropy coded. Trained in 150 s on CPU. Single C++ file, ~600 lines, stb_image for I/O.

The trick that makes ES viable: each latent texel only affects a small pixel footprint through bilinear filtering, so one full-image decode pair yields a gradient estimate for every texel at once.
Rate/distortion sweep, all 3,000 iters, 8-bit latent:
64×64×4 → 26.9 dB @ 0.47 bpp
64×64×8 → 28.2 dB @ 0.87 bpp
128×128×4 → 30.3 dB @ 1.65 bpp
128×128×8 → 32.2 dB @ 3.27 bpp

Output:


The latent:


Notes:
  • No training framework. Dependencies are stb_image, stb_image_write, and OpenMP. The encoder and decoder share the same forward function.
  • MLP training: antithetic ES with 32 perturbation pairs per step, each pair evaluated on the same random 4096-pixel minibatch. The estimated gradient goes through Adam.
  • Latent training: all 131072 latent values perturbed at once, two full-image decodes per pair, 4 pairs per step. Each pixel's loss change is credited only to the 4 texels its bilinear tap reads, so every texel gets its own local estimate from one decode pair.
  • Quantization is post-hoc.
  • Trained for 3,000 iterations, each iteration one ES update of the MLP followed by one ES update of the latent. The curve was still rising slowly at the end; 6000 iterations gained another ~0.3 dB.

Monday, August 31, 2026

XUBC7 Low-Level Format Document

GPU texture blocks (ASTC, BC7, ETC1/2, etc.) can serve as a latent representation for a modern intra codec. GPU texture formats aren't merely final compressed bitstreams; they can be treated as intermediate learned-by-hand representations upon which another serious codec can operate. So far we've shipped two latent-space GPU texture codecs in the Basis Universal library: XUASTC LDR and XUBC7.

The low-level format of the XUBC7 v1 codec (which, to my knowledge, is the first DCT-based BC7 codec) is being documented here:


More updates to this document are coming today.

It supports lossless or lossy coding of the entire BC7 format (all modes, all mode features, all partition patterns, all mode options), absolute DCT, residual DCT using dozens of predictors (like a modern image codec such as WebP), threaded decompression, all-integer deterministic decompression, and SIMD is optional (so a good fit for WASM).

XUBC7's lossless bitrate is ~3.5-5.6 bpp, and ~1.2-2.5 bpp lossy. (Plain BC7 is 8.0 bpp.) XUBC7 in lossless mode (relative to BC7) is so effective it can hold its own against lossy RDO BC7+LZ codecs, i.e. without sacrificing any quality. v2 will adaptively use 2x2-4x4 macroblocks, pushing its lossy bitrate much lower (below 1.0 bpp).

Note XUBC7 is also universal: we can transcode the BC7 latent directly to ASTC LDR 4x4's just by converting the BC7 block config to ASTC's (which is way more flexible than BC7's). In those rare cases where the BC7 partition pattern index isn't directly mappable to ASTC, we can fall back to the bc7f real-time analytical encoder running in a mode that outputs ASTC.

Sunday, August 30, 2026

In-loop deblocking of GPU textures

I posted this thread on X last night - mirroring it here:

On GPU textures the block lattice is a function of UV + known block size. This makes GPU texture seam artifacts entirely predictable, so filtering them is easy. This applies to all GPU texture formats, but is the most valuable on ASTC which supports up to 12x12 pixel block sizes.

No extra metadata is required. The geometry of GPU texture block artifacts is known before you even look at the compressed bits. It's also easy to apply the seam filter while preserving mipmapping, trilinear filtering, etc.:


For normal maps: you can apply the seam filter (which only kicks in near/on block edges) then renormalize the results.

Encoders can optimize the GPU texture block parameters taking into account the reconstruction operator (the seam filter) during compression (in-loop). We use a form of SCD: Stochastic Coordinate Descent.

Thursday, June 18, 2026

Basis Universal library .DDS support coming in v2.5

The Basis Universal GPU texture library v2.5 will have full .DDS file format support: 2D/cubemaps/texarrays+mips, BC1-7 and uncompressed, are usable on any GPU device/API. It uses near-lossless transcoding to ASTC LDR 4x4, and in cases when it can't do a format latent to latent transcode it falls back to real-time full-featured analytical encoding for other LDR formats using bc7f, etc1f etc. It supports real-time encoding to BC1-7, ETC1, ETC2 (various formats), and PVRTC1 4bpp.

It supports totally standard .DDS files written by AMD Compressonator, Microsoft DirectXTex "texconv" tool, etc. This allows desktop content to be easily deployed on mobile/tablets with low (or even no) loss. (BC1->ASTC 4x4 can be transcoded losslessly in almost all cases, and BC7 mode 6->ASTC 4x4 is near-lossless.)

This doesn't add much code to the existing transcoder because it leverages existing functionality we need anyway.

Sunday, June 14, 2026

XUBC7/XBC7: Trellis quantization added

We just added Trellis quantization to XUBC7 (supercompressed universal BC7) via AC truncation, as long as the PSNR drop is within a configurable channel-weighted PSNR window, and the PSNR doesn't fall below a lower limit. This helps at higher Q (DCT quality) levels.

Trellis quant is another video method we've ported successfully into GPU texture supercompression.

https://en.wikipedia.org/wiki/Trellis_quantization

This new encoder also supports several forms of block-level RDO (all optionally) for surprising gains.


Saturday, June 13, 2026

XBC7 planning

I've been doing this for fun as a side project, as ASTC is still way more important. (ASTC is the most deployed GPU format in the world, BC7 is niche by comparison.) It'll all be entirely open source:

- XBC7 v1 (completed, integrating ongoing): Always lossless for mode config+RGBA endpoints, lossless or lossy weights using either lossless residual DPCM or lossy absolute or residual DCT.

DPCM endpoint compression decorrelates G from R/B, properly taking into account dual plane modes (4/5). This does help.

DCT quant tables have been heavily tuned to be rotationally invariant and the very lowest H/V frequencies are now strongly protected at low Q's (i.e. tuned for 4x4). ~1.5-5.6 bpp, optionally threaded decoding, no BC7 format limits (all features, all partition patterns, 2/3 subsets etc.), near-lossless transcoding ASTC LDR 4x4, optionally threaded decoding (row strips - compressed seek table appears at start of file). Also supports transcoding to a bunch of old legacy formats using our existing real-time encoders: ETC using etc1f, PVRTC1, BC1, etc.

Encoder has a tone of unexploited headroom: Lagrangian RDO is possible. It's currently purposely quite conservative.
Future plan:
- XBC7 v2: Material stack support: 2-3 BC7 textures encoded simultaneously, correlations between textures exploited, still full transcoding to ASTC LDR 4x4. Will result in a large drop in average bpp for correlated PBR textures.
Will be able to use unified commands and shared weight grids between the textures in a material stack. Should be relatively easy to do.
- CUDA decoding of individual tiles in parallel (relatively easy, tile decoding is all-int and deterministic)
- Eventual HLSL port of CUDA decoder (will be painful and not looking forward to this)

When I show what we're doing with GPU textures to image/video codec specialists, they reply "this is totally obvious stuff - why have you guys not been using DCT/DST transforms for years already? Where have you been?"