blob: c35a4508da39c93bfe76dd386313d9203a3a2453 [file] [view]
# Texture Compressor
This directory contains a compressor for GPU texture formats. It is primarily
meant for compressing thumbnails to save memory. Currently, only the ETC1 format
is supported, and this is only used on Android.
## Goals
* Fast: Compressing a 4K screenshot takes less than 100ms (roughly 100
megapixels/s). Currently, it can achieve 220 megapixels/s on x64 desktop.
* Safe: Free of memory safety issues and suitable for running in the
privileged browser process.
* Portable: SIMD code shared across x86 (SSE) and ARM (NEON). Easy to modify
and validate for correctness.
## Algorithm
Vectorization is done by assigning each 4x4 SIMD lane to a different block. This
minimizes cross-lane shuffle operations (which are typically architecture
dependent) and makes the code significantly more portable.
Compression of ETC1 is done by first searching through the flip / no-flip and
individual / differential space to decide on the quantization of average, then
searching through selector tables and values for each subblock.
Detailed comments about the algorithm can be found in the source.
## Tools
### Performance Evaluation for Decoder
This directory also contains a tool to measure decoder performance.
#### Evaluation Methodology
To ensure accurate and consistent results, the tool follows this process:
1. Warm-up: Performs an initial decoding pass (discarded) to prime the CPU caches and branch predictors.
2. Measurement: Executes the decoding process 100 times (`BENCHMARK_RUNS`).
3. Analysis: Calculates the average and standard deviation of the execution time.
#### Usage
To build and run the performance evaluation tool on an Android device:
```bash
# 1. Build
autoninja -C out/Debug/ texture_compressor_benchmark
# 2. Push executable and data
adb push out/Debug/texture_compressor_benchmark /data/local/tmp/
adb push input.png /data/local/tmp/
# 3. Run
adb shell /data/local/tmp/texture_compressor_benchmark /data/local/tmp/input.png /data/local/tmp/output.png
# 4. Pull the image decoded from ETC1 file
adb pull /data/local/tmp/output.png
```
## Similar projects
* [etcpak][etcpak] heavily inspired this project. Most of the algorithm
(except vectorization scheme) and math tricks are borrowed from etcpak.
* [ISPC Texture Compressor][ispctexcomp] influenced the vectorization scheme.
Unlike this project, the compressor is written in ISPC and requires a
dedicated compiler.
* [AOSP ETC1 library][aospetc1] also uses a similar search algorithm and is
easier to read, thanks to the scalar implementation.
While reading the code, the [ETC1 specification][etc1spec] should also be
useful.
## (Currently) Missing Pieces
This project is functional, but still a work-in-progress. The following pieces
are missing:
* Testing coverage
* Dynamic dispatch (multiversioning) and AVX2 support
* Running on stable toolchain (using the `wide` crate instead of
`#[feature(portable_simd)]`)
[etcpak]: https://github.com/wolfpld/etcpak
[ispctexcomp]: https://github.com/GameTechDev/ISPCTextureCompressor
[aospetc1]: https://cs.android.com/android/platform/superproject/main/+/main:frameworks/native/opengl/libs/ETC1/
[etc1spec]: https://registry.khronos.org/DataFormat/specs/1.1/dataformat.1.1.html#ETC1