basisu_transcoder_uastc.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // basisu_transcoder_uastc.h
  2. #pragma once
  3. #include "basisu_transcoder_internal.h"
  4. namespace basist
  5. {
  6. struct color_quad_u8
  7. {
  8. uint8_t m_c[4];
  9. };
  10. const uint32_t TOTAL_UASTC_MODES = 19;
  11. const uint32_t UASTC_MODE_INDEX_SOLID_COLOR = 8;
  12. const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS2 = 30;
  13. const uint32_t TOTAL_ASTC_BC6H_COMMON_PARTITIONS2 = 27; // BC6H only supports only 5-bit pattern indices, BC7 supports 4-bit or 6-bit
  14. const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS3 = 11;
  15. const uint32_t TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS = 19;
  16. extern const uint8_t g_uastc_mode_weight_bits[TOTAL_UASTC_MODES];
  17. extern const uint8_t g_uastc_mode_weight_ranges[TOTAL_UASTC_MODES];
  18. extern const uint8_t g_uastc_mode_endpoint_ranges[TOTAL_UASTC_MODES];
  19. extern const uint8_t g_uastc_mode_subsets[TOTAL_UASTC_MODES];
  20. extern const uint8_t g_uastc_mode_planes[TOTAL_UASTC_MODES];
  21. extern const uint8_t g_uastc_mode_comps[TOTAL_UASTC_MODES];
  22. extern const uint8_t g_uastc_mode_has_etc1_bias[TOTAL_UASTC_MODES];
  23. extern const uint8_t g_uastc_mode_has_bc1_hint0[TOTAL_UASTC_MODES];
  24. extern const uint8_t g_uastc_mode_has_bc1_hint1[TOTAL_UASTC_MODES];
  25. extern const uint8_t g_uastc_mode_has_alpha[TOTAL_UASTC_MODES];
  26. extern const uint8_t g_uastc_mode_is_la[TOTAL_UASTC_MODES];
  27. struct astc_bc7_common_partition2_desc
  28. {
  29. uint8_t m_bc7;
  30. uint16_t m_astc;
  31. bool m_invert;
  32. };
  33. extern const astc_bc7_common_partition2_desc g_astc_bc7_common_partitions2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2];
  34. struct bc73_astc2_common_partition_desc
  35. {
  36. uint8_t m_bc73;
  37. uint16_t m_astc2;
  38. uint8_t k; // 0-5 - how to modify the BC7 3-subset pattern to match the ASTC pattern (LSB=invert)
  39. };
  40. extern const bc73_astc2_common_partition_desc g_bc7_3_astc2_common_partitions[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS];
  41. struct astc_bc7_common_partition3_desc
  42. {
  43. uint8_t m_bc7;
  44. uint16_t m_astc;
  45. uint8_t m_astc_to_bc7_perm; // converts ASTC to BC7 partition using g_astc_bc7_partition_index_perm_tables[][]
  46. };
  47. extern const astc_bc7_common_partition3_desc g_astc_bc7_common_partitions3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3];
  48. extern const uint8_t g_astc_bc7_patterns2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][16];
  49. extern const uint8_t g_astc_bc7_patterns3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][16];
  50. extern const uint8_t g_bc7_3_astc2_patterns2[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][16];
  51. extern const uint8_t g_astc_bc7_pattern2_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][3];
  52. extern const uint8_t g_astc_bc7_pattern3_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][3];
  53. extern const uint8_t g_bc7_3_astc2_patterns2_anchors[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][3];
  54. extern const uint32_t g_uastc_mode_huff_codes[TOTAL_UASTC_MODES + 1][2];
  55. extern const uint8_t g_astc_to_bc7_partition_index_perm_tables[6][3];
  56. extern const uint8_t g_bc7_to_astc_partition_index_perm_tables[6][3]; // inverse of g_astc_to_bc7_partition_index_perm_tables
  57. extern const uint8_t* s_uastc_to_bc1_weights[6];
  58. uint32_t bc7_convert_partition_index_3_to_2(uint32_t p, uint32_t k);
  59. inline uint32_t astc_interpolate(uint32_t l, uint32_t h, uint32_t w, bool srgb)
  60. {
  61. if (srgb)
  62. {
  63. l = (l << 8) | 0x80;
  64. h = (h << 8) | 0x80;
  65. }
  66. else
  67. {
  68. l = (l << 8) | l;
  69. h = (h << 8) | h;
  70. }
  71. uint32_t k = (l * (64 - w) + h * w + 32) >> 6;
  72. return k >> 8;
  73. }
  74. struct astc_block_desc
  75. {
  76. int m_weight_range; // weight BISE range
  77. int m_subsets; // number of ASTC partitions
  78. int m_partition_seed; // partition pattern seed
  79. int m_cem; // color endpoint mode used by all subsets
  80. int m_ccs; // color component selector (dual plane only)
  81. bool m_dual_plane; // true if dual plane
  82. // Weight and endpoint BISE values.
  83. // Note these values are NOT linear, they must be BISE encoded. See Table 97 and Table 107.
  84. uint8_t m_endpoints[18]; // endpoint values, in RR GG BB etc. order
  85. uint8_t m_weights[64]; // weight index values, raster order, in P0 P1, P0 P1, etc. or P0, P0, P0, P0, etc. order
  86. };
  87. const uint32_t BC7ENC_TOTAL_ASTC_RANGES = 21;
  88. // See tables 81, 93, 18.13.Endpoint Unquantization
  89. const uint32_t TOTAL_ASTC_RANGES = 21;
  90. extern const int g_astc_bise_range_table[TOTAL_ASTC_RANGES][3];
  91. struct astc_quant_bin
  92. {
  93. uint8_t m_unquant; // unquantized value
  94. uint8_t m_index; // sorted index
  95. };
  96. extern astc_quant_bin g_astc_unquant[BC7ENC_TOTAL_ASTC_RANGES][256]; // [ASTC encoded endpoint index]
  97. int astc_get_levels(int range);
  98. bool astc_is_valid_endpoint_range(uint32_t range);
  99. uint32_t unquant_astc_endpoint(uint32_t packed_bits, uint32_t packed_trits, uint32_t packed_quints, uint32_t range);
  100. uint32_t unquant_astc_endpoint_val(uint32_t packed_val, uint32_t range);
  101. const uint8_t* get_anchor_indices(uint32_t subsets, uint32_t mode, uint32_t common_pattern, const uint8_t*& pPartition_pattern);
  102. // BC7
  103. const uint32_t BC7ENC_BLOCK_SIZE = 16;
  104. struct bc7_block
  105. {
  106. uint64_t m_qwords[2];
  107. };
  108. struct bc7_optimization_results
  109. {
  110. uint32_t m_mode;
  111. uint32_t m_partition;
  112. uint8_t m_selectors[16];
  113. uint8_t m_alpha_selectors[16];
  114. color_quad_u8 m_low[3];
  115. color_quad_u8 m_high[3];
  116. uint32_t m_pbits[3][2];
  117. uint32_t m_index_selector;
  118. uint32_t m_rotation;
  119. };
  120. extern const uint32_t g_bc7_weights1[2];
  121. extern const uint32_t g_bc7_weights2[4];
  122. extern const uint32_t g_bc7_weights3[8];
  123. extern const uint32_t g_bc7_weights4[16];
  124. extern const uint32_t g_astc_weights4[16];
  125. extern const uint32_t g_astc_weights5[32];
  126. extern const uint32_t g_astc_weights_3levels[3];
  127. extern const uint8_t g_bc7_partition1[16];
  128. extern const uint8_t g_bc7_partition2[64 * 16];
  129. extern const uint8_t g_bc7_partition3[64 * 16];
  130. extern const uint8_t g_bc7_table_anchor_index_second_subset[64];
  131. extern const uint8_t g_bc7_table_anchor_index_third_subset_1[64];
  132. extern const uint8_t g_bc7_table_anchor_index_third_subset_2[64];
  133. extern const uint8_t g_bc7_num_subsets[8];
  134. extern const uint8_t g_bc7_partition_bits[8];
  135. extern const uint8_t g_bc7_color_index_bitcount[8];
  136. extern const uint8_t g_bc7_mode_has_p_bits[8];
  137. extern const uint8_t g_bc7_mode_has_shared_p_bits[8];
  138. extern const uint8_t g_bc7_color_precision_table[8];
  139. extern const int8_t g_bc7_alpha_precision_table[8];
  140. extern const uint8_t g_bc7_alpha_index_bitcount[8];
  141. inline bool get_bc7_mode_has_seperate_alpha_selectors(int mode) { return (mode == 4) || (mode == 5); }
  142. inline int get_bc7_color_index_size(int mode, int index_selection_bit) { return g_bc7_color_index_bitcount[mode] + index_selection_bit; }
  143. inline int get_bc7_alpha_index_size(int mode, int index_selection_bit) { return g_bc7_alpha_index_bitcount[mode] - index_selection_bit; }
  144. struct endpoint_err
  145. {
  146. uint16_t m_error; uint8_t m_lo; uint8_t m_hi;
  147. };
  148. extern endpoint_err g_bc7_mode_6_optimal_endpoints[256][2]; // [c][pbit]
  149. const uint32_t BC7ENC_MODE_6_OPTIMAL_INDEX = 5;
  150. extern endpoint_err g_bc7_mode_5_optimal_endpoints[256]; // [c]
  151. const uint32_t BC7ENC_MODE_5_OPTIMAL_INDEX = 1;
  152. // Packs a BC7 block from a high-level description. Handles all BC7 modes.
  153. void encode_bc7_block(void* pBlock, const bc7_optimization_results* pResults);
  154. // Packs an ASTC block
  155. // Constraints: Always 4x4, all subset CEM's must be equal, only tested with LDR CEM's.
  156. bool pack_astc_block(uint32_t* pDst, const astc_block_desc* pBlock, uint32_t mode);
  157. void pack_astc_solid_block(void* pDst_block, const color32& color);
  158. #ifdef _DEBUG
  159. int astc_compute_texel_partition(int seed, int x, int y, int z, int partitioncount, bool small_block);
  160. #endif
  161. struct uastc_block
  162. {
  163. union
  164. {
  165. uint8_t m_bytes[16];
  166. uint32_t m_dwords[4];
  167. };
  168. };
  169. struct unpacked_uastc_block
  170. {
  171. astc_block_desc m_astc;
  172. uint32_t m_mode;
  173. uint32_t m_common_pattern;
  174. color32 m_solid_color;
  175. bool m_bc1_hint0;
  176. bool m_bc1_hint1;
  177. bool m_etc1_flip;
  178. bool m_etc1_diff;
  179. uint32_t m_etc1_inten0;
  180. uint32_t m_etc1_inten1;
  181. uint32_t m_etc1_bias;
  182. uint32_t m_etc2_hints;
  183. uint32_t m_etc1_selector;
  184. uint32_t m_etc1_r, m_etc1_g, m_etc1_b;
  185. };
  186. color32 apply_etc1_bias(const color32 &block_color, uint32_t bias, uint32_t limit, uint32_t subblock);
  187. struct decoder_etc_block;
  188. struct eac_block;
  189. bool unpack_uastc(uint32_t mode, uint32_t common_pattern, const color32& solid_color, const astc_block_desc& astc, color32* pPixels, bool srgb);
  190. bool unpack_uastc(const unpacked_uastc_block& unpacked_blk, color32* pPixels, bool srgb);
  191. bool unpack_uastc(const uastc_block& blk, color32* pPixels, bool srgb);
  192. bool unpack_uastc(const uastc_block& blk, unpacked_uastc_block& unpacked, bool undo_blue_contract, bool read_hints = true);
  193. bool transcode_uastc_to_astc(const uastc_block& src_blk, void* pDst);
  194. bool transcode_uastc_to_bc7(const unpacked_uastc_block& unpacked_src_blk, bc7_optimization_results& dst_blk);
  195. bool transcode_uastc_to_bc7(const uastc_block& src_blk, bc7_optimization_results& dst_blk);
  196. bool transcode_uastc_to_bc7(const uastc_block& src_blk, void* pDst);
  197. void transcode_uastc_to_etc1(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst);
  198. bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst);
  199. bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst, uint32_t channel);
  200. void transcode_uastc_to_etc2_eac_a8(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst);
  201. bool transcode_uastc_to_etc2_rgba(const uastc_block& src_blk, void* pDst);
  202. // Packs 16 scalar values to BC4. Same PSNR as stb_dxt's BC4 encoder, around 13% faster.
  203. void encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride);
  204. void encode_bc1_solid_block(void* pDst, uint32_t fr, uint32_t fg, uint32_t fb);
  205. enum
  206. {
  207. cEncodeBC1HighQuality = 1,
  208. cEncodeBC1HigherQuality = 2,
  209. cEncodeBC1UseSelectors = 4,
  210. };
  211. void encode_bc1(void* pDst, const uint8_t* pPixels, uint32_t flags);
  212. // Alternate PCA-free encoder, around 15% faster, same (or slightly higher) avg. PSNR
  213. void encode_bc1_alt(void* pDst, const uint8_t* pPixels, uint32_t flags);
  214. void transcode_uastc_to_bc1_hint0(const unpacked_uastc_block& unpacked_src_blk, void* pDst);
  215. void transcode_uastc_to_bc1_hint1(const unpacked_uastc_block& unpacked_src_blk, const color32 block_pixels[4][4], void* pDst, bool high_quality);
  216. bool transcode_uastc_to_bc1(const uastc_block& src_blk, void* pDst, bool high_quality);
  217. bool transcode_uastc_to_bc3(const uastc_block& src_blk, void* pDst, bool high_quality);
  218. bool transcode_uastc_to_bc4(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0);
  219. bool transcode_uastc_to_bc5(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1);
  220. bool transcode_uastc_to_etc2_eac_r11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0);
  221. bool transcode_uastc_to_etc2_eac_rg11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1);
  222. bool 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);
  223. bool 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);
  224. // uastc_init() MUST be called before using this module.
  225. void uastc_init();
  226. } // namespace basist