Path: blob/master/thirdparty/basis_universal/transcoder/basisu_transcoder_uastc.h
9905 views
// basisu_transcoder_uastc.h1#pragma once2#include "basisu_transcoder_internal.h"34namespace basist5{6struct color_quad_u87{8uint8_t m_c[4];9};1011const uint32_t TOTAL_UASTC_MODES = 19;12const uint32_t UASTC_MODE_INDEX_SOLID_COLOR = 8;1314const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS2 = 30;15const uint32_t TOTAL_ASTC_BC6H_COMMON_PARTITIONS2 = 27; // BC6H only supports only 5-bit pattern indices, BC7 supports 4-bit or 6-bit16const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS3 = 11;17const uint32_t TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS = 19;1819extern const uint8_t g_uastc_mode_weight_bits[TOTAL_UASTC_MODES];20extern const uint8_t g_uastc_mode_weight_ranges[TOTAL_UASTC_MODES];21extern const uint8_t g_uastc_mode_endpoint_ranges[TOTAL_UASTC_MODES];22extern const uint8_t g_uastc_mode_subsets[TOTAL_UASTC_MODES];23extern const uint8_t g_uastc_mode_planes[TOTAL_UASTC_MODES];24extern const uint8_t g_uastc_mode_comps[TOTAL_UASTC_MODES];25extern const uint8_t g_uastc_mode_has_etc1_bias[TOTAL_UASTC_MODES];26extern const uint8_t g_uastc_mode_has_bc1_hint0[TOTAL_UASTC_MODES];27extern const uint8_t g_uastc_mode_has_bc1_hint1[TOTAL_UASTC_MODES];28extern const uint8_t g_uastc_mode_has_alpha[TOTAL_UASTC_MODES];29extern const uint8_t g_uastc_mode_is_la[TOTAL_UASTC_MODES];3031struct astc_bc7_common_partition2_desc32{33uint8_t m_bc7;34uint16_t m_astc;35bool m_invert;36};3738extern const astc_bc7_common_partition2_desc g_astc_bc7_common_partitions2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2];3940struct bc73_astc2_common_partition_desc41{42uint8_t m_bc73;43uint16_t m_astc2;44uint8_t k; // 0-5 - how to modify the BC7 3-subset pattern to match the ASTC pattern (LSB=invert)45};4647extern const bc73_astc2_common_partition_desc g_bc7_3_astc2_common_partitions[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS];4849struct astc_bc7_common_partition3_desc50{51uint8_t m_bc7;52uint16_t m_astc;53uint8_t m_astc_to_bc7_perm; // converts ASTC to BC7 partition using g_astc_bc7_partition_index_perm_tables[][]54};5556extern const astc_bc7_common_partition3_desc g_astc_bc7_common_partitions3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3];5758extern const uint8_t g_astc_bc7_patterns2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][16];59extern const uint8_t g_astc_bc7_patterns3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][16];60extern const uint8_t g_bc7_3_astc2_patterns2[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][16];6162extern const uint8_t g_astc_bc7_pattern2_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][3];63extern const uint8_t g_astc_bc7_pattern3_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][3];64extern const uint8_t g_bc7_3_astc2_patterns2_anchors[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][3];6566extern const uint32_t g_uastc_mode_huff_codes[TOTAL_UASTC_MODES + 1][2];6768extern const uint8_t g_astc_to_bc7_partition_index_perm_tables[6][3];69extern const uint8_t g_bc7_to_astc_partition_index_perm_tables[6][3]; // inverse of g_astc_to_bc7_partition_index_perm_tables7071extern const uint8_t* s_uastc_to_bc1_weights[6];7273uint32_t bc7_convert_partition_index_3_to_2(uint32_t p, uint32_t k);7475inline uint32_t astc_interpolate(uint32_t l, uint32_t h, uint32_t w, bool srgb)76{77if (srgb)78{79l = (l << 8) | 0x80;80h = (h << 8) | 0x80;81}82else83{84l = (l << 8) | l;85h = (h << 8) | h;86}8788uint32_t k = (l * (64 - w) + h * w + 32) >> 6;8990return k >> 8;91}9293struct astc_block_desc94{95int m_weight_range; // weight BISE range9697int m_subsets; // number of ASTC partitions98int m_partition_seed; // partition pattern seed99int m_cem; // color endpoint mode used by all subsets100101int m_ccs; // color component selector (dual plane only)102bool m_dual_plane; // true if dual plane103104// Weight and endpoint BISE values.105// Note these values are NOT linear, they must be BISE encoded. See Table 97 and Table 107.106uint8_t m_endpoints[18]; // endpoint values, in RR GG BB etc. order107uint8_t m_weights[64]; // weight index values, raster order, in P0 P1, P0 P1, etc. or P0, P0, P0, P0, etc. order108};109110const uint32_t BC7ENC_TOTAL_ASTC_RANGES = 21;111112// See tables 81, 93, 18.13.Endpoint Unquantization113const uint32_t TOTAL_ASTC_RANGES = 21;114extern const int g_astc_bise_range_table[TOTAL_ASTC_RANGES][3];115116struct astc_quant_bin117{118uint8_t m_unquant; // unquantized value119uint8_t m_index; // sorted index120};121122extern astc_quant_bin g_astc_unquant[BC7ENC_TOTAL_ASTC_RANGES][256]; // [ASTC encoded endpoint index]123124int astc_get_levels(int range);125bool astc_is_valid_endpoint_range(uint32_t range);126uint32_t unquant_astc_endpoint(uint32_t packed_bits, uint32_t packed_trits, uint32_t packed_quints, uint32_t range);127uint32_t unquant_astc_endpoint_val(uint32_t packed_val, uint32_t range);128129const uint8_t* get_anchor_indices(uint32_t subsets, uint32_t mode, uint32_t common_pattern, const uint8_t*& pPartition_pattern);130131// BC7132const uint32_t BC7ENC_BLOCK_SIZE = 16;133134struct bc7_block135{136uint64_t m_qwords[2];137};138139struct bc7_optimization_results140{141uint32_t m_mode;142uint32_t m_partition;143uint8_t m_selectors[16];144uint8_t m_alpha_selectors[16];145color_quad_u8 m_low[3];146color_quad_u8 m_high[3];147uint32_t m_pbits[3][2];148uint32_t m_index_selector;149uint32_t m_rotation;150};151152extern const uint32_t g_bc7_weights1[2];153extern const uint32_t g_bc7_weights2[4];154extern const uint32_t g_bc7_weights3[8];155extern const uint32_t g_bc7_weights4[16];156extern const uint32_t g_astc_weights4[16];157extern const uint32_t g_astc_weights5[32];158extern const uint32_t g_astc_weights_3levels[3];159extern const uint8_t g_bc7_partition1[16];160extern const uint8_t g_bc7_partition2[64 * 16];161extern const uint8_t g_bc7_partition3[64 * 16];162extern const uint8_t g_bc7_table_anchor_index_second_subset[64];163extern const uint8_t g_bc7_table_anchor_index_third_subset_1[64];164extern const uint8_t g_bc7_table_anchor_index_third_subset_2[64];165extern const uint8_t g_bc7_num_subsets[8];166extern const uint8_t g_bc7_partition_bits[8];167extern const uint8_t g_bc7_color_index_bitcount[8];168extern const uint8_t g_bc7_mode_has_p_bits[8];169extern const uint8_t g_bc7_mode_has_shared_p_bits[8];170extern const uint8_t g_bc7_color_precision_table[8];171extern const int8_t g_bc7_alpha_precision_table[8];172extern const uint8_t g_bc7_alpha_index_bitcount[8];173174inline bool get_bc7_mode_has_seperate_alpha_selectors(int mode) { return (mode == 4) || (mode == 5); }175inline int get_bc7_color_index_size(int mode, int index_selection_bit) { return g_bc7_color_index_bitcount[mode] + index_selection_bit; }176inline int get_bc7_alpha_index_size(int mode, int index_selection_bit) { return g_bc7_alpha_index_bitcount[mode] - index_selection_bit; }177178struct endpoint_err179{180uint16_t m_error; uint8_t m_lo; uint8_t m_hi;181};182183extern endpoint_err g_bc7_mode_6_optimal_endpoints[256][2]; // [c][pbit]184const uint32_t BC7ENC_MODE_6_OPTIMAL_INDEX = 5;185186extern endpoint_err g_bc7_mode_5_optimal_endpoints[256]; // [c]187const uint32_t BC7ENC_MODE_5_OPTIMAL_INDEX = 1;188189// Packs a BC7 block from a high-level description. Handles all BC7 modes.190void encode_bc7_block(void* pBlock, const bc7_optimization_results* pResults);191192// Packs an ASTC block193// Constraints: Always 4x4, all subset CEM's must be equal, only tested with LDR CEM's.194bool pack_astc_block(uint32_t* pDst, const astc_block_desc* pBlock, uint32_t mode);195196void pack_astc_solid_block(void* pDst_block, const color32& color);197198#ifdef _DEBUG199int astc_compute_texel_partition(int seed, int x, int y, int z, int partitioncount, bool small_block);200#endif201202struct uastc_block203{204union205{206uint8_t m_bytes[16];207uint32_t m_dwords[4];208};209};210211struct unpacked_uastc_block212{213astc_block_desc m_astc;214215uint32_t m_mode;216uint32_t m_common_pattern;217218color32 m_solid_color;219220bool m_bc1_hint0;221bool m_bc1_hint1;222223bool m_etc1_flip;224bool m_etc1_diff;225uint32_t m_etc1_inten0;226uint32_t m_etc1_inten1;227228uint32_t m_etc1_bias;229230uint32_t m_etc2_hints;231232uint32_t m_etc1_selector;233uint32_t m_etc1_r, m_etc1_g, m_etc1_b;234};235236color32 apply_etc1_bias(const color32 &block_color, uint32_t bias, uint32_t limit, uint32_t subblock);237238struct decoder_etc_block;239struct eac_block;240241bool unpack_uastc(uint32_t mode, uint32_t common_pattern, const color32& solid_color, const astc_block_desc& astc, color32* pPixels, bool srgb);242bool unpack_uastc(const unpacked_uastc_block& unpacked_blk, color32* pPixels, bool srgb);243244bool unpack_uastc(const uastc_block& blk, color32* pPixels, bool srgb);245bool unpack_uastc(const uastc_block& blk, unpacked_uastc_block& unpacked, bool undo_blue_contract, bool read_hints = true);246247bool transcode_uastc_to_astc(const uastc_block& src_blk, void* pDst);248249bool transcode_uastc_to_bc7(const unpacked_uastc_block& unpacked_src_blk, bc7_optimization_results& dst_blk);250bool transcode_uastc_to_bc7(const uastc_block& src_blk, bc7_optimization_results& dst_blk);251bool transcode_uastc_to_bc7(const uastc_block& src_blk, void* pDst);252253void transcode_uastc_to_etc1(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst);254bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst);255bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst, uint32_t channel);256257void transcode_uastc_to_etc2_eac_a8(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst);258bool transcode_uastc_to_etc2_rgba(const uastc_block& src_blk, void* pDst);259260// Packs 16 scalar values to BC4. Same PSNR as stb_dxt's BC4 encoder, around 13% faster.261void encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride);262263void encode_bc1_solid_block(void* pDst, uint32_t fr, uint32_t fg, uint32_t fb);264265enum266{267cEncodeBC1HighQuality = 1,268cEncodeBC1HigherQuality = 2,269cEncodeBC1UseSelectors = 4,270};271void encode_bc1(void* pDst, const uint8_t* pPixels, uint32_t flags);272273// Alternate PCA-free encoder, around 15% faster, same (or slightly higher) avg. PSNR274void encode_bc1_alt(void* pDst, const uint8_t* pPixels, uint32_t flags);275276void transcode_uastc_to_bc1_hint0(const unpacked_uastc_block& unpacked_src_blk, void* pDst);277void transcode_uastc_to_bc1_hint1(const unpacked_uastc_block& unpacked_src_blk, const color32 block_pixels[4][4], void* pDst, bool high_quality);278279bool transcode_uastc_to_bc1(const uastc_block& src_blk, void* pDst, bool high_quality);280bool transcode_uastc_to_bc3(const uastc_block& src_blk, void* pDst, bool high_quality);281bool transcode_uastc_to_bc4(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0);282bool transcode_uastc_to_bc5(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1);283284bool transcode_uastc_to_etc2_eac_r11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0);285bool transcode_uastc_to_etc2_eac_rg11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1);286287bool transcode_uastc_to_pvrtc1_4_rgb(const uastc_block* pSrc_blocks, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool high_quality, bool from_alpha);288bool transcode_uastc_to_pvrtc1_4_rgba(const uastc_block* pSrc_blocks, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool high_quality);289290// uastc_init() MUST be called before using this module.291void uastc_init();292293} // namespace basist294295296