basisu_comp.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. // basisu_comp.h
  2. // Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #pragma once
  16. #include "basisu_frontend.h"
  17. #include "basisu_backend.h"
  18. #include "basisu_basis_file.h"
  19. #include "../transcoder/basisu_transcoder.h"
  20. #include "basisu_uastc_enc.h"
  21. #define BASISU_LIB_VERSION 116
  22. #define BASISU_LIB_VERSION_STRING "1.16"
  23. #ifndef BASISD_SUPPORT_KTX2
  24. #error BASISD_SUPPORT_KTX2 is undefined
  25. #endif
  26. #ifndef BASISD_SUPPORT_KTX2_ZSTD
  27. #error BASISD_SUPPORT_KTX2_ZSTD is undefined
  28. #endif
  29. #if !BASISD_SUPPORT_KTX2
  30. #error BASISD_SUPPORT_KTX2 must be enabled when building the encoder. To reduce code size if KTX2 support is not needed, set BASISD_SUPPORT_KTX2_ZSTD to 0
  31. #endif
  32. namespace basisu
  33. {
  34. struct opencl_context;
  35. typedef opencl_context* opencl_context_ptr;
  36. const uint32_t BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION = 16384;
  37. // Allow block's color distance to increase by 1.5 while searching for an alternative nearby endpoint.
  38. const float BASISU_DEFAULT_ENDPOINT_RDO_THRESH = 1.5f;
  39. // Allow block's color distance to increase by 1.25 while searching the selector history buffer for a close enough match.
  40. const float BASISU_DEFAULT_SELECTOR_RDO_THRESH = 1.25f;
  41. const int BASISU_DEFAULT_QUALITY = 128;
  42. const float BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH = 2.0f;
  43. const uint32_t BASISU_MAX_IMAGE_DIMENSION = 16384;
  44. const uint32_t BASISU_QUALITY_MIN = 1;
  45. const uint32_t BASISU_QUALITY_MAX = 255;
  46. const uint32_t BASISU_MAX_ENDPOINT_CLUSTERS = basisu_frontend::cMaxEndpointClusters;
  47. const uint32_t BASISU_MAX_SELECTOR_CLUSTERS = basisu_frontend::cMaxSelectorClusters;
  48. const uint32_t BASISU_MAX_SLICES = 0xFFFFFF;
  49. const int BASISU_RDO_UASTC_DICT_SIZE_DEFAULT = 4096; // 32768;
  50. const int BASISU_RDO_UASTC_DICT_SIZE_MIN = 64;
  51. const int BASISU_RDO_UASTC_DICT_SIZE_MAX = 65536;
  52. struct image_stats
  53. {
  54. image_stats()
  55. {
  56. clear();
  57. }
  58. void clear()
  59. {
  60. m_filename.clear();
  61. m_width = 0;
  62. m_height = 0;
  63. m_basis_rgb_avg_psnr = 0.0f;
  64. m_basis_rgba_avg_psnr = 0.0f;
  65. m_basis_a_avg_psnr = 0.0f;
  66. m_basis_luma_709_psnr = 0.0f;
  67. m_basis_luma_601_psnr = 0.0f;
  68. m_basis_luma_709_ssim = 0.0f;
  69. m_bc7_rgb_avg_psnr = 0.0f;
  70. m_bc7_rgba_avg_psnr = 0.0f;
  71. m_bc7_a_avg_psnr = 0.0f;
  72. m_bc7_luma_709_psnr = 0.0f;
  73. m_bc7_luma_601_psnr = 0.0f;
  74. m_bc7_luma_709_ssim = 0.0f;
  75. m_best_etc1s_rgb_avg_psnr = 0.0f;
  76. m_best_etc1s_luma_709_psnr = 0.0f;
  77. m_best_etc1s_luma_601_psnr = 0.0f;
  78. m_best_etc1s_luma_709_ssim = 0.0f;
  79. m_opencl_failed = false;
  80. }
  81. std::string m_filename;
  82. uint32_t m_width;
  83. uint32_t m_height;
  84. // .basis compressed (ETC1S or UASTC statistics)
  85. float m_basis_rgb_avg_psnr;
  86. float m_basis_rgba_avg_psnr;
  87. float m_basis_a_avg_psnr;
  88. float m_basis_luma_709_psnr;
  89. float m_basis_luma_601_psnr;
  90. float m_basis_luma_709_ssim;
  91. // BC7 statistics
  92. float m_bc7_rgb_avg_psnr;
  93. float m_bc7_rgba_avg_psnr;
  94. float m_bc7_a_avg_psnr;
  95. float m_bc7_luma_709_psnr;
  96. float m_bc7_luma_601_psnr;
  97. float m_bc7_luma_709_ssim;
  98. // Highest achievable quality ETC1S statistics
  99. float m_best_etc1s_rgb_avg_psnr;
  100. float m_best_etc1s_luma_709_psnr;
  101. float m_best_etc1s_luma_601_psnr;
  102. float m_best_etc1s_luma_709_ssim;
  103. bool m_opencl_failed;
  104. };
  105. template<bool def>
  106. struct bool_param
  107. {
  108. bool_param() :
  109. m_value(def),
  110. m_changed(false)
  111. {
  112. }
  113. void clear()
  114. {
  115. m_value = def;
  116. m_changed = false;
  117. }
  118. operator bool() const
  119. {
  120. return m_value;
  121. }
  122. bool operator= (bool v)
  123. {
  124. m_value = v;
  125. m_changed = true;
  126. return m_value;
  127. }
  128. bool was_changed() const { return m_changed; }
  129. void set_changed(bool flag) { m_changed = flag; }
  130. bool m_value;
  131. bool m_changed;
  132. };
  133. template<typename T>
  134. struct param
  135. {
  136. param(T def, T min_v, T max_v) :
  137. m_value(def),
  138. m_def(def),
  139. m_min(min_v),
  140. m_max(max_v),
  141. m_changed(false)
  142. {
  143. }
  144. void clear()
  145. {
  146. m_value = m_def;
  147. m_changed = false;
  148. }
  149. operator T() const
  150. {
  151. return m_value;
  152. }
  153. T operator= (T v)
  154. {
  155. m_value = clamp<T>(v, m_min, m_max);
  156. m_changed = true;
  157. return m_value;
  158. }
  159. T operator *= (T v)
  160. {
  161. m_value *= v;
  162. m_changed = true;
  163. return m_value;
  164. }
  165. bool was_changed() const { return m_changed; }
  166. void set_changed(bool flag) { m_changed = flag; }
  167. T m_value;
  168. T m_def;
  169. T m_min;
  170. T m_max;
  171. bool m_changed;
  172. };
  173. struct basis_compressor_params
  174. {
  175. basis_compressor_params() :
  176. m_compression_level((int)BASISU_DEFAULT_COMPRESSION_LEVEL, 0, (int)BASISU_MAX_COMPRESSION_LEVEL),
  177. m_selector_rdo_thresh(BASISU_DEFAULT_SELECTOR_RDO_THRESH, 0.0f, 1e+10f),
  178. m_endpoint_rdo_thresh(BASISU_DEFAULT_ENDPOINT_RDO_THRESH, 0.0f, 1e+10f),
  179. m_mip_scale(1.0f, .000125f, 4.0f),
  180. m_mip_smallest_dimension(1, 1, 16384),
  181. m_max_endpoint_clusters(512),
  182. m_max_selector_clusters(512),
  183. m_quality_level(-1),
  184. m_pack_uastc_flags(cPackUASTCLevelDefault),
  185. m_rdo_uastc_quality_scalar(1.0f, 0.001f, 50.0f),
  186. m_rdo_uastc_dict_size(BASISU_RDO_UASTC_DICT_SIZE_DEFAULT, BASISU_RDO_UASTC_DICT_SIZE_MIN, BASISU_RDO_UASTC_DICT_SIZE_MAX),
  187. m_rdo_uastc_max_smooth_block_error_scale(UASTC_RDO_DEFAULT_SMOOTH_BLOCK_MAX_ERROR_SCALE, 1.0f, 300.0f),
  188. m_rdo_uastc_smooth_block_max_std_dev(UASTC_RDO_DEFAULT_MAX_SMOOTH_BLOCK_STD_DEV, .01f, 65536.0f),
  189. m_rdo_uastc_max_allowed_rms_increase_ratio(UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO, .01f, 100.0f),
  190. m_rdo_uastc_skip_block_rms_thresh(UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH, .01f, 100.0f),
  191. m_resample_width(0, 1, 16384),
  192. m_resample_height(0, 1, 16384),
  193. m_resample_factor(0.0f, .00125f, 100.0f),
  194. m_ktx2_uastc_supercompression(basist::KTX2_SS_NONE),
  195. m_ktx2_zstd_supercompression_level(6, INT_MIN, INT_MAX),
  196. m_pJob_pool(nullptr)
  197. {
  198. clear();
  199. }
  200. void clear()
  201. {
  202. m_uastc.clear();
  203. m_use_opencl.clear();
  204. m_status_output.clear();
  205. m_source_filenames.clear();
  206. m_source_alpha_filenames.clear();
  207. m_source_images.clear();
  208. m_source_mipmap_images.clear();
  209. m_out_filename.clear();
  210. m_y_flip.clear();
  211. m_debug.clear();
  212. m_validate_etc1s.clear();
  213. m_debug_images.clear();
  214. m_perceptual.clear();
  215. m_no_selector_rdo.clear();
  216. m_selector_rdo_thresh.clear();
  217. m_read_source_images.clear();
  218. m_write_output_basis_files.clear();
  219. m_compression_level.clear();
  220. m_compute_stats.clear();
  221. m_print_stats.clear();
  222. m_check_for_alpha.clear();
  223. m_force_alpha.clear();
  224. m_multithreading.clear();
  225. m_swizzle[0] = 0;
  226. m_swizzle[1] = 1;
  227. m_swizzle[2] = 2;
  228. m_swizzle[3] = 3;
  229. m_renormalize.clear();
  230. m_disable_hierarchical_endpoint_codebooks.clear();
  231. m_no_endpoint_rdo.clear();
  232. m_endpoint_rdo_thresh.clear();
  233. m_mip_gen.clear();
  234. m_mip_scale.clear();
  235. m_mip_filter = "kaiser";
  236. m_mip_scale = 1.0f;
  237. m_mip_srgb.clear();
  238. m_mip_premultiplied.clear();
  239. m_mip_renormalize.clear();
  240. m_mip_wrapping.clear();
  241. m_mip_fast.clear();
  242. m_mip_smallest_dimension.clear();
  243. m_max_endpoint_clusters = 0;
  244. m_max_selector_clusters = 0;
  245. m_quality_level = -1;
  246. m_tex_type = basist::cBASISTexType2D;
  247. m_userdata0 = 0;
  248. m_userdata1 = 0;
  249. m_us_per_frame = 0;
  250. m_pack_uastc_flags = cPackUASTCLevelDefault;
  251. m_rdo_uastc.clear();
  252. m_rdo_uastc_quality_scalar.clear();
  253. m_rdo_uastc_max_smooth_block_error_scale.clear();
  254. m_rdo_uastc_smooth_block_max_std_dev.clear();
  255. m_rdo_uastc_max_allowed_rms_increase_ratio.clear();
  256. m_rdo_uastc_skip_block_rms_thresh.clear();
  257. m_rdo_uastc_favor_simpler_modes_in_rdo_mode.clear();
  258. m_rdo_uastc_multithreading.clear();
  259. m_resample_width.clear();
  260. m_resample_height.clear();
  261. m_resample_factor.clear();
  262. m_pGlobal_codebooks = nullptr;
  263. m_create_ktx2_file.clear();
  264. m_ktx2_uastc_supercompression = basist::KTX2_SS_NONE;
  265. m_ktx2_key_values.clear();
  266. m_ktx2_zstd_supercompression_level.clear();
  267. m_ktx2_srgb_transfer_func.clear();
  268. m_validate_output_data.clear();
  269. m_pJob_pool = nullptr;
  270. }
  271. // True to generate UASTC .basis file data, otherwise ETC1S.
  272. bool_param<false> m_uastc;
  273. bool_param<false> m_use_opencl;
  274. // If m_read_source_images is true, m_source_filenames (and optionally m_source_alpha_filenames) contains the filenames of PNG images to read.
  275. // Otherwise, the compressor processes the images in m_source_images.
  276. basisu::vector<std::string> m_source_filenames;
  277. basisu::vector<std::string> m_source_alpha_filenames;
  278. basisu::vector<image> m_source_images;
  279. // Stores mipmaps starting from level 1. Level 0 is still stored in m_source_images, as usual.
  280. // If m_source_mipmaps isn't empty, automatic mipmap generation isn't done. m_source_mipmaps.size() MUST equal m_source_images.size() or the compressor returns an error.
  281. // The compressor applies the user-provided swizzling (in m_swizzle) to these images.
  282. basisu::vector< basisu::vector<image> > m_source_mipmap_images;
  283. // Filename of the output basis file
  284. std::string m_out_filename;
  285. // The params are done this way so we can detect when the user has explictly changed them.
  286. // Flip images across Y axis
  287. bool_param<false> m_y_flip;
  288. // If true, the compressor will print basis status to stdout during compression.
  289. bool_param<true> m_status_output;
  290. // Output debug information during compression
  291. bool_param<false> m_debug;
  292. bool_param<false> m_validate_etc1s;
  293. // m_debug_images is pretty slow
  294. bool_param<false> m_debug_images;
  295. // ETC1S compression level, from 0 to BASISU_MAX_COMPRESSION_LEVEL (higher is slower).
  296. // This parameter controls numerous internal encoding speed vs. compression efficiency/performance tradeoffs.
  297. // Note this is NOT the same as the ETC1S quality level, and most users shouldn't change this.
  298. param<int> m_compression_level;
  299. // Use perceptual sRGB colorspace metrics instead of linear
  300. bool_param<true> m_perceptual;
  301. // Disable selector RDO, for faster compression but larger files
  302. bool_param<false> m_no_selector_rdo;
  303. param<float> m_selector_rdo_thresh;
  304. bool_param<false> m_no_endpoint_rdo;
  305. param<float> m_endpoint_rdo_thresh;
  306. // Read source images from m_source_filenames/m_source_alpha_filenames
  307. bool_param<false> m_read_source_images;
  308. // Write the output basis file to disk using m_out_filename
  309. bool_param<false> m_write_output_basis_files;
  310. // Compute and display image metrics
  311. bool_param<false> m_compute_stats;
  312. // Print stats to stdout, if m_compute_stats is true.
  313. bool_param<true> m_print_stats;
  314. // Check to see if any input image has an alpha channel, if so then the output basis file will have alpha channels
  315. bool_param<true> m_check_for_alpha;
  316. // Always put alpha slices in the output basis file, even when the input doesn't have alpha
  317. bool_param<false> m_force_alpha;
  318. bool_param<true> m_multithreading;
  319. // Split the R channel to RGB and the G channel to alpha, then write a basis file with alpha channels
  320. char m_swizzle[4];
  321. bool_param<false> m_renormalize;
  322. // If true the front end will not use 2 level endpoint codebook searching, for slightly higher quality but much slower execution.
  323. // Note some m_compression_level's disable this automatically.
  324. bool_param<false> m_disable_hierarchical_endpoint_codebooks;
  325. // mipmap generation parameters
  326. bool_param<false> m_mip_gen;
  327. param<float> m_mip_scale;
  328. std::string m_mip_filter;
  329. bool_param<false> m_mip_srgb;
  330. bool_param<true> m_mip_premultiplied; // not currently supported
  331. bool_param<false> m_mip_renormalize;
  332. bool_param<true> m_mip_wrapping;
  333. bool_param<true> m_mip_fast;
  334. param<int> m_mip_smallest_dimension;
  335. // Codebook size (quality) control.
  336. // If m_quality_level != -1, it controls the quality level. It ranges from [1,255] or [BASISU_QUALITY_MIN, BASISU_QUALITY_MAX].
  337. // Otherwise m_max_endpoint_clusters/m_max_selector_clusters controls the codebook sizes directly.
  338. uint32_t m_max_endpoint_clusters;
  339. uint32_t m_max_selector_clusters;
  340. int m_quality_level;
  341. // m_tex_type, m_userdata0, m_userdata1, m_framerate - These fields go directly into the Basis file header.
  342. basist::basis_texture_type m_tex_type;
  343. uint32_t m_userdata0;
  344. uint32_t m_userdata1;
  345. uint32_t m_us_per_frame;
  346. // cPackUASTCLevelDefault, etc.
  347. uint32_t m_pack_uastc_flags;
  348. bool_param<false> m_rdo_uastc;
  349. param<float> m_rdo_uastc_quality_scalar;
  350. param<int> m_rdo_uastc_dict_size;
  351. param<float> m_rdo_uastc_max_smooth_block_error_scale;
  352. param<float> m_rdo_uastc_smooth_block_max_std_dev;
  353. param<float> m_rdo_uastc_max_allowed_rms_increase_ratio;
  354. param<float> m_rdo_uastc_skip_block_rms_thresh;
  355. bool_param<true> m_rdo_uastc_favor_simpler_modes_in_rdo_mode;
  356. bool_param<true> m_rdo_uastc_multithreading;
  357. param<int> m_resample_width;
  358. param<int> m_resample_height;
  359. param<float> m_resample_factor;
  360. const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooks;
  361. // KTX2 specific parameters.
  362. // Internally, the compressor always creates a .basis file then it converts that lossless to KTX2.
  363. bool_param<false> m_create_ktx2_file;
  364. basist::ktx2_supercompression m_ktx2_uastc_supercompression;
  365. basist::ktx2_transcoder::key_value_vec m_ktx2_key_values;
  366. param<int> m_ktx2_zstd_supercompression_level;
  367. bool_param<false> m_ktx2_srgb_transfer_func;
  368. bool_param<false> m_validate_output_data;
  369. job_pool *m_pJob_pool;
  370. };
  371. // Important: basisu_encoder_init() MUST be called first before using this class.
  372. class basis_compressor
  373. {
  374. BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basis_compressor);
  375. public:
  376. basis_compressor();
  377. ~basis_compressor();
  378. // Note it *should* be possible to call init() multiple times with different inputs, but this scenario isn't well tested. Ideally, create 1 object, compress, then delete it.
  379. bool init(const basis_compressor_params &params);
  380. enum error_code
  381. {
  382. cECSuccess = 0,
  383. cECFailedInitializing,
  384. cECFailedReadingSourceImages,
  385. cECFailedValidating,
  386. cECFailedEncodeUASTC,
  387. cECFailedFrontEnd,
  388. cECFailedFontendExtract,
  389. cECFailedBackend,
  390. cECFailedCreateBasisFile,
  391. cECFailedWritingOutput,
  392. cECFailedUASTCRDOPostProcess,
  393. cECFailedCreateKTX2File
  394. };
  395. error_code process();
  396. // The output .basis file will always be valid of process() succeeded.
  397. const uint8_vec &get_output_basis_file() const { return m_output_basis_file; }
  398. // The output .ktx2 file will only be valid if m_create_ktx2_file was true and process() succeeded.
  399. const uint8_vec& get_output_ktx2_file() const { return m_output_ktx2_file; }
  400. const basisu::vector<image_stats> &get_stats() const { return m_stats; }
  401. uint32_t get_basis_file_size() const { return m_basis_file_size; }
  402. double get_basis_bits_per_texel() const { return m_basis_bits_per_texel; }
  403. bool get_any_source_image_has_alpha() const { return m_any_source_image_has_alpha; }
  404. bool get_opencl_failed() const { return m_opencl_failed; }
  405. private:
  406. basis_compressor_params m_params;
  407. opencl_context_ptr m_pOpenCL_context;
  408. basisu::vector<image> m_slice_images;
  409. basisu::vector<image_stats> m_stats;
  410. uint32_t m_basis_file_size;
  411. double m_basis_bits_per_texel;
  412. basisu_backend_slice_desc_vec m_slice_descs;
  413. uint32_t m_total_blocks;
  414. basisu_frontend m_frontend;
  415. pixel_block_vec m_source_blocks;
  416. basisu::vector<gpu_image> m_frontend_output_textures;
  417. basisu::vector<gpu_image> m_best_etc1s_images;
  418. basisu::vector<image> m_best_etc1s_images_unpacked;
  419. basisu_backend m_backend;
  420. basisu_file m_basis_file;
  421. basisu::vector<gpu_image> m_decoded_output_textures;
  422. basisu::vector<image> m_decoded_output_textures_unpacked;
  423. basisu::vector<gpu_image> m_decoded_output_textures_bc7;
  424. basisu::vector<image> m_decoded_output_textures_unpacked_bc7;
  425. uint8_vec m_output_basis_file;
  426. uint8_vec m_output_ktx2_file;
  427. basisu::vector<gpu_image> m_uastc_slice_textures;
  428. basisu_backend_output m_uastc_backend_output;
  429. bool m_any_source_image_has_alpha;
  430. bool m_opencl_failed;
  431. bool read_source_images();
  432. bool extract_source_blocks();
  433. bool process_frontend();
  434. bool extract_frontend_texture_data();
  435. bool process_backend();
  436. bool create_basis_file_and_transcode();
  437. bool write_output_files_and_compute_stats();
  438. error_code encode_slices_to_uastc();
  439. bool generate_mipmaps(const image &img, basisu::vector<image> &mips, bool has_alpha);
  440. bool validate_texture_type_constraints();
  441. bool validate_ktx2_constraints();
  442. void get_dfd(uint8_vec& dfd, const basist::ktx2_header& hdr);
  443. bool create_ktx2_file();
  444. };
  445. // Alternative simple C-style wrapper API around the basis_compressor class.
  446. // This doesn't expose every encoder feature, but it's enough to get going.
  447. // Important: basisu_encoder_init() MUST be called first before calling these functions.
  448. //
  449. // Input parameters:
  450. // source_images: Array of "image" objects, one per mipmap level, largest mipmap level first.
  451. // OR
  452. // pImageRGBA: pointer to a 32-bpp RGBx or RGBA raster image, R first in memory, A last. Top scanline first in memory.
  453. // width/height/pitch_in_pixels: dimensions of pImageRGBA
  454. //
  455. // flags_and_quality: Combination of the above flags logically OR'd with the ETC1S or UASTC level, i.e. "cFlagSRGB | cFlagGenMipsClamp | cFlagThreaded | 128" or "cFlagSRGB | cFlagGenMipsClamp | cFlagUASTC | cFlagThreaded | cPackUASTCLevelDefault".
  456. // In ETC1S mode, the lower 8-bits are the ETC1S quality level which ranges from [1,255] (higher=better quality/larger files)
  457. // In UASTC mode, the lower 8-bits are the UASTC pack level (see cPackUASTCLevelFastest, etc.). Fastest/lowest quality is 0, so be sure to set it correctly.
  458. //
  459. // uastc_rdo_quality: Float UASTC RDO quality level (0=no change, higher values lower quality but increase compressibility, initially try .5-1.5)
  460. //
  461. // pSize: Returns the output data's compressed size in bytes
  462. //
  463. // Return value is the compressed .basis or .ktx2 file data, or nullptr on failure. Must call basis_free() to free it.
  464. enum
  465. {
  466. cFlagUseOpenCL = 1 << 8, // use OpenCL if available
  467. cFlagThreaded = 1 << 9, // use multiple threads for compression
  468. cFlagDebug = 1 << 10, // enable debug output
  469. cFlagKTX2 = 1 << 11, // generate a KTX2 file
  470. cFlagKTX2UASTCSuperCompression = 1 << 12, // use KTX2 Zstd supercompression on UASTC files
  471. cFlagSRGB = 1 << 13, // input texture is sRGB, use perceptual colorspace metrics, also use sRGB filtering during mipmap gen, and also sets KTX2 output transfer func to sRGB
  472. cFlagGenMipsClamp = 1 << 14, // generate mipmaps with clamp addressing
  473. cFlagGenMipsWrap = 1 << 15, // generate mipmaps with wrap addressing
  474. cFlagYFlip = 1 << 16, // flip source image on Y axis before compression
  475. cFlagUASTC = 1 << 17, // use UASTC compression vs. ETC1S
  476. cFlagUASTCRDO = 1 << 18, // use RDO postprocessing when generating UASTC files (must set uastc_rdo_quality to the quality scalar)
  477. cFlagPrintStats = 1 << 19, // print image stats to stdout
  478. cFlagPrintStatus = 1 << 20 // print status to stdout
  479. };
  480. // This function accepts an array of source images.
  481. // If more than one image is provided, it's assumed the images form a mipmap pyramid and automatic mipmap generation is disabled.
  482. // Returns a pointer to the compressed .basis or .ktx2 file data. *pSize is the size of the compressed data. The returned block must be freed using basis_free_data().
  483. // basisu_encoder_init() MUST be called first!
  484. void* basis_compress(
  485. const basisu::vector<image> &source_images,
  486. uint32_t flags_and_quality, float uastc_rdo_quality,
  487. size_t* pSize,
  488. image_stats* pStats = nullptr);
  489. // This function only accepts a single source image.
  490. void* basis_compress(
  491. const uint8_t* pImageRGBA, uint32_t width, uint32_t height, uint32_t pitch_in_pixels,
  492. uint32_t flags_and_quality, float uastc_rdo_quality,
  493. size_t* pSize,
  494. image_stats* pStats = nullptr);
  495. // Frees the dynamically allocated file data returned by basis_compress().
  496. void basis_free_data(void* p);
  497. // Runs a short benchmark using synthetic image data to time OpenCL encoding vs. CPU encoding, with multithreading enabled.
  498. // Returns true if opencl is worth using on this system, otherwise false.
  499. // If pOpenCL_failed is not null, it will be set to true if OpenCL encoding failed *on this particular machine/driver/BasisU version* and the encoder falled back to CPU encoding.
  500. // basisu_encoder_init() MUST be called first. If OpenCL support wasn't enabled this always returns false.
  501. bool basis_benchmark_etc1s_opencl(bool *pOpenCL_failed = nullptr);
  502. // Parallel compression API
  503. struct parallel_results
  504. {
  505. double m_total_time;
  506. basis_compressor::error_code m_error_code;
  507. uint8_vec m_basis_file;
  508. uint8_vec m_ktx2_file;
  509. basisu::vector<image_stats> m_stats;
  510. double m_basis_bits_per_texel;
  511. bool m_any_source_image_has_alpha;
  512. parallel_results()
  513. {
  514. clear();
  515. }
  516. void clear()
  517. {
  518. m_total_time = 0.0f;
  519. m_error_code = basis_compressor::cECFailedInitializing;
  520. m_basis_file.clear();
  521. m_ktx2_file.clear();
  522. m_stats.clear();
  523. m_basis_bits_per_texel = 0.0f;
  524. m_any_source_image_has_alpha = false;
  525. }
  526. };
  527. // Compresses an array of input textures across total_threads threads using the basis_compressor class.
  528. // Compressing multiple textures at a time is substantially more efficient than just compressing one at a time.
  529. // total_threads must be >= 1.
  530. bool basis_parallel_compress(
  531. uint32_t total_threads,
  532. const basisu::vector<basis_compressor_params> &params_vec,
  533. basisu::vector< parallel_results > &results_vec);
  534. } // namespace basisu