basisu_astc_hdr_enc.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // basisu_astc_hdr_enc.h
  2. #pragma once
  3. #include "basisu_enc.h"
  4. #include "basisu_gpu_texture.h"
  5. #include "../transcoder/basisu_astc_helpers.h"
  6. #include "../transcoder/basisu_astc_hdr_core.h"
  7. namespace basisu
  8. {
  9. // This MUST be called before encoding any blocks.
  10. void astc_hdr_enc_init();
  11. const uint32_t MODE11_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE11_LAST_ISE_RANGE = astc_helpers::BISE_16_LEVELS;
  12. const uint32_t MODE7_PART1_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE7_PART1_LAST_ISE_RANGE = astc_helpers::BISE_16_LEVELS;
  13. const uint32_t MODE7_PART2_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE7_PART2_LAST_ISE_RANGE = astc_helpers::BISE_8_LEVELS;
  14. const uint32_t MODE11_PART2_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE11_PART2_LAST_ISE_RANGE = astc_helpers::BISE_4_LEVELS;
  15. const uint32_t MODE11_TOTAL_SUBMODES = 8; // plus an extra hidden submode, directly encoded, for direct, so really 9 (see tables 99/100 of the ASTC spec)
  16. const uint32_t MODE7_TOTAL_SUBMODES = 6;
  17. struct astc_hdr_codec_options
  18. {
  19. float m_bc6h_err_weight;
  20. bool m_use_solid;
  21. bool m_use_mode11;
  22. bool m_mode11_uber_mode;
  23. uint32_t m_first_mode11_weight_ise_range;
  24. uint32_t m_last_mode11_weight_ise_range;
  25. bool m_mode11_direct_only;
  26. int32_t m_first_mode11_submode;
  27. int32_t m_last_mode11_submode;
  28. bool m_use_mode7_part1;
  29. uint32_t m_first_mode7_part1_weight_ise_range;
  30. uint32_t m_last_mode7_part1_weight_ise_range;
  31. bool m_use_mode7_part2;
  32. uint32_t m_mode7_part2_part_masks;
  33. uint32_t m_first_mode7_part2_weight_ise_range;
  34. uint32_t m_last_mode7_part2_weight_ise_range;
  35. bool m_use_mode11_part2;
  36. uint32_t m_mode11_part2_part_masks;
  37. uint32_t m_first_mode11_part2_weight_ise_range;
  38. uint32_t m_last_mode11_part2_weight_ise_range;
  39. float m_r_err_scale, m_g_err_scale;
  40. bool m_refine_weights;
  41. uint32_t m_level;
  42. bool m_use_estimated_partitions;
  43. uint32_t m_max_estimated_partitions;
  44. // If true, the ASTC HDR compressor is allowed to more aggressively vary weight indices for slightly higher compression in non-fastest mode. This will hurt BC6H quality, however.
  45. bool m_allow_uber_mode;
  46. astc_hdr_codec_options();
  47. void init();
  48. // TODO: set_quality_level() is preferred to configure the codec for transcoding purposes.
  49. static const int cMinLevel = 0;
  50. static const int cMaxLevel = 4;
  51. static const int cDefaultLevel = 1;
  52. void set_quality_level(int level);
  53. private:
  54. void set_quality_best();
  55. void set_quality_normal();
  56. void set_quality_fastest();
  57. };
  58. struct astc_hdr_pack_results
  59. {
  60. double m_best_block_error;
  61. double m_bc6h_block_error; // note this is not used/set by the encoder, here for convienance
  62. // Encoder results (logical ASTC block)
  63. astc_helpers::log_astc_block m_best_blk;
  64. // For statistical use
  65. uint32_t m_best_submodes[2];
  66. uint32_t m_best_pat_index;
  67. bool m_constrained_weights;
  68. bool m_improved_via_refinement_flag;
  69. // Only valid if the block is solid
  70. basist::astc_blk m_solid_blk;
  71. // The BC6H transcoded block
  72. basist::bc6h_block m_bc6h_block;
  73. // Solid color/void extent flag
  74. bool m_is_solid;
  75. void clear()
  76. {
  77. m_best_block_error = 1e+30f;
  78. m_bc6h_block_error = 1e+30f;
  79. m_best_blk.clear();
  80. m_best_blk.m_grid_width = 4;
  81. m_best_blk.m_grid_height = 4;
  82. m_best_blk.m_endpoint_ise_range = 20; // 0-255
  83. clear_obj(m_best_submodes);
  84. m_best_pat_index = 0;
  85. m_constrained_weights = false;
  86. clear_obj(m_bc6h_block);
  87. m_is_solid = false;
  88. m_improved_via_refinement_flag = false;
  89. }
  90. };
  91. void interpolate_qlog12_colors(
  92. const int e[2][3],
  93. basist::half_float* pDecoded_half,
  94. vec3F* pDecoded_float,
  95. uint32_t n, uint32_t ise_weight_range);
  96. bool get_astc_hdr_mode_11_block_colors(
  97. const uint8_t* pEndpoints,
  98. basist::half_float* pDecoded_half,
  99. vec3F* pDecoded_float,
  100. uint32_t n, uint32_t ise_weight_range, uint32_t ise_endpoint_range);
  101. bool get_astc_hdr_mode_7_block_colors(
  102. const uint8_t* pEndpoints,
  103. basist::half_float* pDecoded_half,
  104. vec3F* pDecoded_float,
  105. uint32_t n, uint32_t ise_weight_range, uint32_t ise_endpoint_range);
  106. double eval_selectors(
  107. uint32_t num_pixels,
  108. uint8_t* pWeights,
  109. const basist::half_float* pBlock_pixels_half,
  110. uint32_t num_weight_levels,
  111. const basist::half_float* pDecoded_half,
  112. const astc_hdr_codec_options& coptions,
  113. uint32_t usable_selector_bitmask = UINT32_MAX);
  114. double compute_block_error(const basist::half_float* pOrig_block, const basist::half_float* pPacked_block, const astc_hdr_codec_options& coptions);
  115. // Encodes a 4x4 ASTC HDR block given a 4x4 array of source block pixels/texels.
  116. // Supports solid color blocks, mode 11 (all submodes), mode 7/1 partition (all submodes),
  117. // and mode 7/2 partitions (all submodes) - 30 patterns, only the ones also in common with the BC6H format.
  118. // The packed ASTC weight grid dimensions are currently always 4x4 texels, but may be also 3x3 in the future.
  119. // This function is thread safe, i.e. it may be called from multiple encoding threads simultanously with different blocks.
  120. //
  121. // Parameters:
  122. // pRGBPixels - An array of 48 (16 RGB) floats: the 4x4 block to pack
  123. // pPacked_block - A pointer to the packed ASTC HDR block
  124. // coptions - Codec options
  125. // pInternal_results - An optional pointer to details about how the block was packed, for statistics/debugging purposes. May be nullptr.
  126. //
  127. // Requirements:
  128. // astc_hdr_enc_init() MUST have been called first to initialized the codec.
  129. // Input pixels are checked and cannot be NaN's, Inf's, signed, or too large (greater than MAX_HALF_FLOAT, or 65504).
  130. // Normal values and denormals are okay.
  131. bool astc_hdr_enc_block(
  132. const float* pRGBPixels,
  133. const astc_hdr_codec_options& coptions,
  134. basisu::vector<astc_hdr_pack_results> &all_results);
  135. bool astc_hdr_pack_results_to_block(basist::astc_blk& dst_blk, const astc_hdr_pack_results& results);
  136. bool astc_hdr_refine_weights(const basist::half_float* pSource_block, astc_hdr_pack_results& cur_results, const astc_hdr_codec_options& coptions, float bc6h_weight, bool* pImproved_flag);
  137. struct astc_hdr_block_stats
  138. {
  139. std::mutex m_mutex;
  140. uint32_t m_total_blocks;
  141. uint32_t m_total_2part, m_total_solid;
  142. uint32_t m_total_mode7_1part, m_total_mode7_2part;
  143. uint32_t m_total_mode11_1part, m_total_mode11_2part;
  144. uint32_t m_total_mode11_1part_constrained_weights;
  145. uint32_t m_weight_range_hist_7[11];
  146. uint32_t m_weight_range_hist_7_2part[11];
  147. uint32_t m_mode7_submode_hist[6];
  148. uint32_t m_weight_range_hist_11[11];
  149. uint32_t m_weight_range_hist_11_2part[11];
  150. uint32_t m_mode11_submode_hist[9];
  151. uint32_t m_part_hist[32];
  152. uint32_t m_total_refined;
  153. astc_hdr_block_stats() { clear(); }
  154. void clear()
  155. {
  156. std::lock_guard<std::mutex> lck(m_mutex);
  157. m_total_blocks = 0;
  158. m_total_mode7_1part = 0, m_total_mode7_2part = 0, m_total_mode11_1part = 0, m_total_2part = 0, m_total_solid = 0, m_total_mode11_2part = 0;
  159. m_total_mode11_1part_constrained_weights = 0;
  160. m_total_refined = 0;
  161. clear_obj(m_weight_range_hist_11);
  162. clear_obj(m_weight_range_hist_11_2part);
  163. clear_obj(m_weight_range_hist_7);
  164. clear_obj(m_weight_range_hist_7_2part);
  165. clear_obj(m_mode7_submode_hist);
  166. clear_obj(m_mode11_submode_hist);
  167. clear_obj(m_part_hist);
  168. }
  169. void update(const astc_hdr_pack_results& log_blk);
  170. void print();
  171. };
  172. } // namespace basisu