1// basisu_uastc_enc.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_etc.h"
17
18#include "../transcoder/basisu_transcoder_uastc.h"
19
20namespace basisu
21{
22 const uint32_t TOTAL_PACK_UASTC_LEVELS = 5;
23
24 enum
25 {
26 // Fastest is the lowest quality, although it's stil substantially higher quality vs. BC1/ETC1. It supports 5 modes.
27 // The output may be somewhat blocky because this setting doesn't support 2/3-subset UASTC modes, but it should be less blocky vs. BC1/ETC1.
28 // This setting doesn't write BC1 hints, so BC1 transcoding will be slower.
29 // Transcoded ETC1 quality will be lower because it only considers 2 hints out of 32.
30 // Avg. 43.45 dB
31 cPackUASTCLevelFastest = 0,
32
33 // Faster is ~3x slower than fastest. It supports 9 modes.
34 // Avg. 46.49 dB
35 cPackUASTCLevelFaster = 1,
36
37 // Default is ~5.5x slower than fastest. It supports 14 modes.
38 // Avg. 47.47 dB
39 cPackUASTCLevelDefault = 2,
40
41 // Slower is ~14.5x slower than fastest. It supports all 18 modes.
42 // Avg. 48.01 dB
43 cPackUASTCLevelSlower = 3,
44
45 // VerySlow is ~200x slower than fastest.
46 // The best quality the codec is capable of, but you'll need to be patient or have a lot of cores.
47 // Avg. 48.24 dB
48 cPackUASTCLevelVerySlow = 4,
49
50 cPackUASTCLevelMask = 0xF,
51
52 // By default the encoder tries to strike a balance between UASTC and transcoded BC7 quality.
53 // These flags allow you to favor only optimizing for lowest UASTC error, or lowest BC7 error.
54 cPackUASTCFavorUASTCError = 8,
55 cPackUASTCFavorBC7Error = 16,
56
57 cPackUASTCETC1FasterHints = 64,
58 cPackUASTCETC1FastestHints = 128,
59 cPackUASTCETC1DisableFlipAndIndividual = 256,
60
61 // Favor UASTC modes 0 and 10 more than the others (this is experimental, it's useful for RDO compression)
62 cPackUASTCFavorSimplerModes = 512,
63 };
64
65 // pRGBAPixels: Pointer to source 4x4 block of RGBA pixels (R first in memory).
66 // block: Reference to destination UASTC block.
67 // level: Controls compression speed vs. performance tradeoff.
68 void encode_uastc(const uint8_t* pRGBAPixels, basist::uastc_block& output_block, uint32_t flags = cPackUASTCLevelDefault);
69
70 struct uastc_encode_results
71 {
72 uint32_t m_uastc_mode;
73 uint32_t m_common_pattern;
74 basist::astc_block_desc m_astc;
75 color_rgba m_solid_color;
76 uint64_t m_astc_err;
77 };
78
79 void pack_uastc(basist::uastc_block& blk, const uastc_encode_results& result, const etc_block& etc1_blk, uint32_t etc1_bias, const eac_a8_block& etc_eac_a8_blk, bool bc1_hint0, bool bc1_hint1);
80
81 const uint32_t UASCT_RDO_DEFAULT_LZ_DICT_SIZE = 4096;
82
83 const float UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO = 10.0f;
84 const float UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH = 8.0f;
85
86 // The RDO encoder computes a smoothness factor, from [0,1], for each block. To do this it computes each block's maximum component variance, then it divides this by this factor and clamps the result.
87 // Larger values will result in more blocks being protected from too much distortion.
88 const float UASTC_RDO_DEFAULT_MAX_SMOOTH_BLOCK_STD_DEV = 18.0f;
89
90 // The RDO encoder can artifically boost the error of smooth blocks, in order to suppress distortions on smooth areas of the texture.
91 // The encoder will use this value as the maximum error scale to use on smooth blocks. The larger this value, the better smooth bocks will look. Set to 1.0 to disable this completely.
92 const float UASTC_RDO_DEFAULT_SMOOTH_BLOCK_MAX_ERROR_SCALE = 10.0f;
93
94 struct uastc_rdo_params
95 {
96 uastc_rdo_params()
97 {
98 clear();
99 }
100
101 void clear()
102 {
103 m_lz_dict_size = UASCT_RDO_DEFAULT_LZ_DICT_SIZE;
104 m_lambda = 0.5f;
105 m_max_allowed_rms_increase_ratio = UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO;
106 m_skip_block_rms_thresh = UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH;
107 m_endpoint_refinement = true;
108 m_lz_literal_cost = 100;
109
110 m_max_smooth_block_std_dev = UASTC_RDO_DEFAULT_MAX_SMOOTH_BLOCK_STD_DEV;
111 m_smooth_block_max_error_scale = UASTC_RDO_DEFAULT_SMOOTH_BLOCK_MAX_ERROR_SCALE;
112 }
113
114 // m_lz_dict_size: Size of LZ dictionary to simulate in bytes. The larger this value, the slower the encoder but the higher the quality per LZ compressed bit.
115 uint32_t m_lz_dict_size;
116
117 // m_lambda: The post-processor tries to reduce distortion+rate*lambda (rate is approximate LZ bits and distortion is scaled MS error).
118 // Larger values push the postprocessor towards optimizing more for lower rate, and smaller values more for distortion. 0=minimal distortion.
119 float m_lambda;
120
121 // m_max_allowed_rms_increase_ratio: How much the RMS error of a block is allowed to increase before a trial is rejected. 1.0=no increase allowed, 1.05=5% increase allowed, etc.
122 float m_max_allowed_rms_increase_ratio;
123
124 // m_skip_block_rms_thresh: Blocks with this much RMS error or more are completely skipped by the RDO encoder.
125 float m_skip_block_rms_thresh;
126
127 // m_endpoint_refinement: If true, the post-process will attempt to refine the endpoints of blocks with modified selectors.
128 bool m_endpoint_refinement;
129
130 float m_max_smooth_block_std_dev;
131 float m_smooth_block_max_error_scale;
132
133 uint32_t m_lz_literal_cost;
134 };
135
136 // num_blocks, pBlocks: Number of blocks and pointer to UASTC blocks to process.
137 // pBlock_pixels: Pointer to an array of 4x4 blocks containing the original texture pixels. This is NOT a raster image, but a pointer to individual 4x4 blocks.
138 // flags: Pass in the same flags used to encode the UASTC blocks. The flags are used to reencode the transcode hints in the same way.
139 bool uastc_rdo(uint32_t num_blocks, basist::uastc_block* pBlocks, const color_rgba* pBlock_pixels, const uastc_rdo_params &params, uint32_t flags = cPackUASTCLevelDefault, job_pool* pJob_pool = nullptr, uint32_t total_jobs = 0);
140} // namespace basisu
141