Skip to content

Commit

Permalink
git subrepo pull (merge) lib/basisu
Browse files Browse the repository at this point in the history
subrepo:
  subdir:   "lib/basisu"
  merged:   "582de288"
upstream:
  origin:   "https://github.com/BinomialLLC/basis_universal.git"
  branch:   "master"
  commit:   "646a9f82"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/MarkCallow/git-subrepo.git"
  commit:   "c1f1132"
  • Loading branch information
MarkCallow committed Oct 25, 2021
1 parent 4066903 commit 24c9f7b
Show file tree
Hide file tree
Showing 16 changed files with 158 additions and 76 deletions.
2 changes: 1 addition & 1 deletion lib/basisu/.gitrepo
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/BinomialLLC/basis_universal.git
branch = master
commit = 5337227c5d25ddda17d0510c4703b0f10f2b0b13
commit = 646a9f826131cb0b9e14b5e4740874808315f83a
parent = 02c43d5762c04d67643ec22831300691b610be4f
method = merge
cmdver = 0.4.3
69 changes: 67 additions & 2 deletions lib/basisu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ The encoder optionally uses Zstandard's single source file compressor (in zstd/z

The command line tool used to create, validate, and transcode/unpack .basis/.KTX2 files is named "basisu". Run basisu without any parameters for help.

The library and command line tool have no other 3rd party dependencies (that are not already in the repo), so it's pretty easy to build.

To build basisu (without SSE 4.1 support - the default):

```
Expand Down Expand Up @@ -86,11 +88,11 @@ To compress a image to a higher quality UASTC .basis file:

To compress a image to a higher quality UASTC .basis file with RDO post processing, so the .basis file is more compressible:

`basisu -uastc -uastc_level 2 -uastc_rdo_q .75 x.png`
`basisu -uastc -uastc_level 2 -uastc_rdo_l .75 x.png`

-uastc_level X ranges from 0-4 and controls the UASTC encoder's performance vs. quality tradeoff. Level 0 is very fast, but low quality, level 2 is the default quality, while level 3 is the highest practical quality. Level 4 is impractically slow, but highest quality.

-uastc_rdo_q X controls the rate distortion stage's quality setting. The lower this value, the higher the quality, but the larger the compressed file size. Good values to try are between .2-3.0. The default is 1.0. RDO post-processing is currently pretty slow, but we'll be optimizing it over time.
-uastc_rdo_l X controls the rate distortion stage's quality setting. The lower this value, the higher the quality, but the larger the compressed file size. Good values to try are between .2-3.0. The default is 1.0. RDO post-processing is currently pretty slow, but we'll be optimizing it over time.

UASTC texture video is supported and has been tested. In RDO mode with 7zip LZMA, we've seen average bitrates between 1-2 bpp. ETC1S mode is recommended for texture video, which gets bitrates around .25-.3 bpp.

Expand Down Expand Up @@ -214,6 +216,69 @@ Both the transcoder and now the compressor (as of 12/17/2020) may be compiled us

To enable compression support compile the JavaScript wrappers in `webgl/transcoding/basis_wrappers.cpp` with `BASISU_SUPPORT_ENCODING` set to 1. See the webgl/encoding directory.

### Low-level C++ encoder API

You can call the encoder directly, instead of using the command line tool. We'll be adding documentation and some examples by the end of the year. For now, some important notes:

First, ALWAYS call ```basisu::basisu_encoder_init()``` to initialize the library. Otherwise, you'll get undefined behavior or black textures.

Create a job pool, fill in the ```basis_compress_params``` struct, then call ```basisu::basis_compressor::init()```, then ```basisu::basis_compressor::process()```. Like this for UASTC:

```
bool test()
{
basisu_encoder_init();
image img;
if (!load_image("test.png", img))
{
printf("Can't load image\n");
return false;
}
basis_compressor_params basisCompressorParams;
basisCompressorParams.m_source_images.push_back(img);
basisCompressorParams.m_perceptual = false;
basisCompressorParams.m_mip_srgb = false;
basisCompressorParams.m_write_output_basis_files = true;
basisCompressorParams.m_out_filename = "test.basis";
basisCompressorParams.m_uastc = true;
basisCompressorParams.m_rdo_uastc_multithreading = false;
basisCompressorParams.m_multithreading = false;
basisCompressorParams.m_debug = true;
basisCompressorParams.m_status_output = true;
basisCompressorParams.m_compute_stats = true;
basisu::job_pool jpool(1);
basisCompressorParams.m_pJob_pool = &jpool;
basisu::basis_compressor basisCompressor;
basisu::enable_debug_printf(true);
bool ok = basisCompressor.init(basisCompressorParams);
if (ok)
{
basisu::basis_compressor::error_code result = basisCompressor.process();
if (result == basisu::basis_compressor::cECSuccess)
printf("Success\n");
else
{
printf("Failure\n");
ok = false;
}
}
else
printf("Failure\n");
return ok;
}
```

The command line tool uses this API too, so you can always look at that to see what it does given a set of command line options.

### Repository Licensing with REUSE

The repository has been updated to be compliant with the REUSE licenese
Expand Down
8 changes: 8 additions & 0 deletions lib/basisu/basisu_tool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ static void print_usage()
" -disable_hierarchical_endpoint_codebooks: Disable hierarchical endpoint codebook usage, slower but higher quality on some compression levels\n"
" -compare_ssim: Compute and display SSIM of image comparison (slow)\n"
" -bench: UASTC benchmark mode, for development only\n"
" -resample X Y: Resample all input textures to XxY pixels using a box filter\n"
" -resample_factor X: Resample all input textures by scale factor X using a box filter\n"
" -no_sse: Forbid all SSE instruction set usage\n"
" -validate_etc1s: Validate internal ETC1S compressor's data structures during compression (slower, intended for development).\n"
Expand Down Expand Up @@ -392,6 +393,13 @@ class command_line_params

arg_count++;
}
else if (strcasecmp(pArg, "-resample") == 0)
{
REMAINING_ARGS_CHECK(2);
m_comp_params.m_resample_width = atoi(arg_v[arg_index + 1]);
m_comp_params.m_resample_height = atoi(arg_v[arg_index + 2]);
arg_count += 2;
}
else if (strcasecmp(pArg, "-resample_factor") == 0)
{
REMAINING_ARGS_CHECK(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
/**
* Basis Universal single file library. Generated using:
* \code
* ./combine.sh -r ../../transcoder -x basisu_transcoder_tables_bc7_m6.inc -o basisu_transcoder.cpp basisu_transcoder-in.cpp
* ./combine.sh -r ../../transcoder -o basisu_transcoder.cpp basisu_transcoder-in.cpp
* \endcode
*
* \note The script above excludes the BC7 mode 6 tables, a choice reflected in
* the build options.
*/

/*
* Transcoder build options for known platforms (iOS has ETC, ASTC and PVRTC;
* Emscripten adds DXT to iOS's options; Android adds PVRTC2 to Emscripten's
* options; other platforms build all except BC7 mode 6 and FXT1).
* options; other platforms build all except FXT1).
*
* See https://github.com/BinomialLLC/basis_universal#shrinking-the-transcoders-compiled-size
*/
Expand All @@ -28,11 +25,14 @@
#ifndef __ANDROID__
#define BASISD_SUPPORT_PVRTC2 0
#endif
#else
#define BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY 0
#endif
#define BASISD_SUPPORT_FXT1 0

/*
* KTX2 support disabled.
*/
#define BASISD_SUPPORT_KTX2 0

#include "basisu_transcoder.cpp"

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
OUT_FILE="tempbin"

echo "Amalgamating files... this can take a while"
echo "Note: basisu_transcoder_tables_bc7_m6.inc is excluded"
./combine.sh -r ../../transcoder -x basisu_transcoder_tables_bc7_m6.inc -o basisu_transcoder.cpp basisu_transcoder-in.cpp
./combine.sh -r ../../transcoder -o basisu_transcoder.cpp basisu_transcoder-in.cpp
# Did combining work?
if [ $? -ne 0 ]; then
echo "Combine script: FAILED"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* \n
* Compile using:
* \code
* export CC_FLAGS="-std=c++11 -Wall -Wextra -Werror -Os -g0 -flto --llvm-lto 3 -fno-exceptions -fno-rtti -lGL -DNDEBUG=1"
* export EM_FLAGS="-s ENVIRONMENT=web -s WASM=1 --shell-file shell.html --closure 1"
* export "CC_FLAGS=-std=c++11 -Wall -Wextra -Werror -Os -g0 -flto --llvm-lto 3 -fno-exceptions -fno-rtti -lGL -DNDEBUG=1"
* export "EM_FLAGS=-s ENVIRONMENT=web -s WASM=1 --shell-file shell.html --closure 1"
* emcc $CC_FLAGS $EM_FLAGS -o out.html emscripten.cpp
* \endcode
* Alternatively include \c basisu_transcoder.h and compile \c
Expand Down
4 changes: 2 additions & 2 deletions lib/basisu/encoder/apg_bmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ unsigned char* apg_bmp_read( const char* filename, int* w, int* h, unsigned int*
}

// allocate memory for the output pixels block. cast to size_t in case width and height are both the max of 65536 and n_dst_chans > 1
unsigned char* dst_img_ptr = malloc( (size_t)width * (size_t)height * (size_t)n_dst_chans );
unsigned char* dst_img_ptr = (unsigned char*)malloc( (size_t)width * (size_t)height * (size_t)n_dst_chans );
if ( !dst_img_ptr ) {
free( record.data );
return NULL;
Expand Down Expand Up @@ -480,7 +480,7 @@ unsigned int apg_bmp_write( const char* filename, unsigned char* pixels_ptr, int
dib_hdr.bitmask_b = 0x0000FF00;
}

uint8_t* dst_pixels_ptr = malloc( dst_pixels_padded_sz );
uint8_t* dst_pixels_ptr = (uint8_t*)malloc( dst_pixels_padded_sz );
if ( !dst_pixels_ptr ) { return 0; }
{
size_t dst_byte_idx = 0;
Expand Down
37 changes: 18 additions & 19 deletions lib/basisu/encoder/basisu_bc7enc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,8 @@ static void astc_init()
} // range
}

static inline uint32_t astc_interpolate(uint32_t l, uint32_t h, uint32_t w)
static inline uint32_t astc_interpolate_linear(uint32_t l, uint32_t h, uint32_t w)
{
// This is for linear values, not sRGB.
l = (l << 8) | l;
h = (h << 8) | h;
uint32_t k = (l * (64 - w) + h * w + 32) >> 6;
Expand Down Expand Up @@ -230,7 +229,7 @@ void bc7enc_compress_block_init()
{
uint32_t high = (h << 4) | h;

const int k = astc_interpolate(low, high, g_bc7_weights3[BC7ENC_ASTC_4BIT_3BIT_OPTIMAL_INDEX]);
const int k = astc_interpolate_linear(low, high, g_bc7_weights3[BC7ENC_ASTC_4BIT_3BIT_OPTIMAL_INDEX]);
const int err = (k - c) * (k - c);

if (err < best.m_error)
Expand Down Expand Up @@ -259,7 +258,7 @@ void bc7enc_compress_block_init()
{
uint32_t high = (h << 4) | h;

const int k = astc_interpolate(low, high, g_bc7_weights2[BC7ENC_ASTC_4BIT_2BIT_OPTIMAL_INDEX]);
const int k = astc_interpolate_linear(low, high, g_bc7_weights2[BC7ENC_ASTC_4BIT_2BIT_OPTIMAL_INDEX]);
const int err = (k - c) * (k - c);

if (err < best.m_error)
Expand Down Expand Up @@ -288,7 +287,7 @@ void bc7enc_compress_block_init()
{
uint32_t high = g_astc_sorted_order_unquant[7][h].m_unquant;

const int k = astc_interpolate(low, high, g_bc7_weights2[BC7ENC_ASTC_RANGE7_2BIT_OPTIMAL_INDEX]);
const int k = astc_interpolate_linear(low, high, g_bc7_weights2[BC7ENC_ASTC_RANGE7_2BIT_OPTIMAL_INDEX]);
const int err = (k - c) * (k - c);

if (err < best.m_error)
Expand Down Expand Up @@ -317,7 +316,7 @@ void bc7enc_compress_block_init()
{
uint32_t high = g_astc_sorted_order_unquant[13][h].m_unquant;

const int k = astc_interpolate(low, high, g_astc_weights4[BC7ENC_ASTC_RANGE13_4BIT_OPTIMAL_INDEX]);
const int k = astc_interpolate_linear(low, high, g_astc_weights4[BC7ENC_ASTC_RANGE13_4BIT_OPTIMAL_INDEX]);
const int err = (k - c) * (k - c);

if (err < best.m_error)
Expand Down Expand Up @@ -346,7 +345,7 @@ void bc7enc_compress_block_init()
{
uint32_t high = g_astc_sorted_order_unquant[13][h].m_unquant;

const int k = astc_interpolate(low, high, g_bc7_weights2[BC7ENC_ASTC_RANGE13_2BIT_OPTIMAL_INDEX]);
const int k = astc_interpolate_linear(low, high, g_bc7_weights2[BC7ENC_ASTC_RANGE13_2BIT_OPTIMAL_INDEX]);
const int err = (k - c) * (k - c);

if (err < best.m_error)
Expand Down Expand Up @@ -375,7 +374,7 @@ void bc7enc_compress_block_init()
{
uint32_t high = g_astc_sorted_order_unquant[11][h].m_unquant;

const int k = astc_interpolate(low, high, g_astc_weights5[BC7ENC_ASTC_RANGE11_5BIT_OPTIMAL_INDEX]);
const int k = astc_interpolate_linear(low, high, g_astc_weights5[BC7ENC_ASTC_RANGE11_5BIT_OPTIMAL_INDEX]);
const int err = (k - c) * (k - c);

if (err < best.m_error)
Expand Down Expand Up @@ -650,7 +649,7 @@ static uint64_t pack_astc_4bit_3bit_to_one_color(const color_cell_compressor_par
uint32_t low = (pResults->m_low_endpoint.m_c[i] << 4) | pResults->m_low_endpoint.m_c[i];
uint32_t high = (pResults->m_high_endpoint.m_c[i] << 4) | pResults->m_high_endpoint.m_c[i];

p.m_c[i] = (uint8_t)astc_interpolate(low, high, g_bc7_weights3[BC7ENC_ASTC_4BIT_3BIT_OPTIMAL_INDEX]);
p.m_c[i] = (uint8_t)astc_interpolate_linear(low, high, g_bc7_weights3[BC7ENC_ASTC_4BIT_3BIT_OPTIMAL_INDEX]);
}
p.m_c[3] = 255;

Expand Down Expand Up @@ -689,7 +688,7 @@ static uint64_t pack_astc_4bit_2bit_to_one_color_rgba(const color_cell_compresso
uint32_t low = (pResults->m_low_endpoint.m_c[i] << 4) | pResults->m_low_endpoint.m_c[i];
uint32_t high = (pResults->m_high_endpoint.m_c[i] << 4) | pResults->m_high_endpoint.m_c[i];

p.m_c[i] = (uint8_t)astc_interpolate(low, high, g_bc7_weights2[BC7ENC_ASTC_4BIT_2BIT_OPTIMAL_INDEX]);
p.m_c[i] = (uint8_t)astc_interpolate_linear(low, high, g_bc7_weights2[BC7ENC_ASTC_4BIT_2BIT_OPTIMAL_INDEX]);
}

uint64_t total_err = 0;
Expand Down Expand Up @@ -728,7 +727,7 @@ static uint64_t pack_astc_range7_2bit_to_one_color(const color_cell_compressor_p
uint32_t low = g_astc_sorted_order_unquant[7][pResults->m_low_endpoint.m_c[i]].m_unquant;
uint32_t high = g_astc_sorted_order_unquant[7][pResults->m_high_endpoint.m_c[i]].m_unquant;

p.m_c[i] = (uint8_t)astc_interpolate(low, high, g_bc7_weights2[BC7ENC_ASTC_RANGE7_2BIT_OPTIMAL_INDEX]);
p.m_c[i] = (uint8_t)astc_interpolate_linear(low, high, g_bc7_weights2[BC7ENC_ASTC_RANGE7_2BIT_OPTIMAL_INDEX]);
}
p.m_c[3] = 255;

Expand Down Expand Up @@ -768,7 +767,7 @@ static uint64_t pack_astc_range13_2bit_to_one_color(const color_cell_compressor_
uint32_t low = g_astc_sorted_order_unquant[13][pResults->m_low_endpoint.m_c[i]].m_unquant;
uint32_t high = g_astc_sorted_order_unquant[13][pResults->m_high_endpoint.m_c[i]].m_unquant;

p.m_c[i] = (uint8_t)astc_interpolate(low, high, g_bc7_weights2[BC7ENC_ASTC_RANGE13_2BIT_OPTIMAL_INDEX]);
p.m_c[i] = (uint8_t)astc_interpolate_linear(low, high, g_bc7_weights2[BC7ENC_ASTC_RANGE13_2BIT_OPTIMAL_INDEX]);
}

uint64_t total_err = 0;
Expand Down Expand Up @@ -807,7 +806,7 @@ static uint64_t pack_astc_range11_5bit_to_one_color(const color_cell_compressor_
uint32_t low = g_astc_sorted_order_unquant[11][pResults->m_low_endpoint.m_c[i]].m_unquant;
uint32_t high = g_astc_sorted_order_unquant[11][pResults->m_high_endpoint.m_c[i]].m_unquant;

p.m_c[i] = (uint8_t)astc_interpolate(low, high, g_astc_weights5[BC7ENC_ASTC_RANGE11_5BIT_OPTIMAL_INDEX]);
p.m_c[i] = (uint8_t)astc_interpolate_linear(low, high, g_astc_weights5[BC7ENC_ASTC_RANGE11_5BIT_OPTIMAL_INDEX]);
}

uint64_t total_err = 0;
Expand Down Expand Up @@ -863,7 +862,7 @@ static uint64_t evaluate_solution(const color_quad_u8 *pLow, const color_quad_u8
for (uint32_t i = 1; i < (N - 1); i++)
{
for (uint32_t j = 0; j < nc; j++)
weightedColors[i].m_c[j] = (uint8_t)(astc_interpolate(actualMinColor.m_c[j], actualMaxColor.m_c[j], pParams->m_pSelector_weights[i]));
weightedColors[i].m_c[j] = (uint8_t)(astc_interpolate_linear(actualMinColor.m_c[j], actualMaxColor.m_c[j], pParams->m_pSelector_weights[i]));
}
}
else
Expand Down Expand Up @@ -1300,7 +1299,7 @@ void check_best_overall_error(const color_cell_compressor_params *pParams, color

for (uint32_t i = 1; i < pParams->m_num_selector_weights - 1; i++)
for (uint32_t c = 0; c < 4; c++)
colors[i].m_c[c] = (uint8_t)astc_interpolate(colors[0].m_c[c], colors[n - 1].m_c[c], pParams->m_pSelector_weights[i]);
colors[i].m_c[c] = (uint8_t)astc_interpolate_linear(colors[0].m_c[c], colors[n - 1].m_c[c], pParams->m_pSelector_weights[i]);

uint64_t total_err = 0;
for (uint32_t p = 0; p < pParams->m_num_pixels; p++)
Expand Down Expand Up @@ -1815,10 +1814,10 @@ uint64_t color_cell_compression_est_astc(
weightedColors[num_weights - 1] = highColor;
for (uint32_t i = 1; i < (num_weights - 1); i++)
{
weightedColors[i].m_c[0] = (uint8_t)astc_interpolate(lowColor.m_c[0], highColor.m_c[0], pWeight_table[i]);
weightedColors[i].m_c[1] = (uint8_t)astc_interpolate(lowColor.m_c[1], highColor.m_c[1], pWeight_table[i]);
weightedColors[i].m_c[2] = (uint8_t)astc_interpolate(lowColor.m_c[2], highColor.m_c[2], pWeight_table[i]);
weightedColors[i].m_c[3] = (num_comps == 4) ? (uint8_t)astc_interpolate(lowColor.m_c[3], highColor.m_c[3], pWeight_table[i]) : 255;
weightedColors[i].m_c[0] = (uint8_t)astc_interpolate_linear(lowColor.m_c[0], highColor.m_c[0], pWeight_table[i]);
weightedColors[i].m_c[1] = (uint8_t)astc_interpolate_linear(lowColor.m_c[1], highColor.m_c[1], pWeight_table[i]);
weightedColors[i].m_c[2] = (uint8_t)astc_interpolate_linear(lowColor.m_c[2], highColor.m_c[2], pWeight_table[i]);
weightedColors[i].m_c[3] = (num_comps == 4) ? (uint8_t)astc_interpolate_linear(lowColor.m_c[3], highColor.m_c[3], pWeight_table[i]) : 255;
}

// Compute dots and thresholds
Expand Down
1 change: 1 addition & 0 deletions lib/basisu/encoder/basisu_bc7enc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "basisu_enc.h"
#include "../transcoder/basisu_transcoder_uastc.h"

Expand Down
Loading

0 comments on commit 24c9f7b

Please sign in to comment.