diff --git a/Source/astcenc_compress_symbolic.cpp b/Source/astcenc_compress_symbolic.cpp index 115fb83..e97a63b 100644 --- a/Source/astcenc_compress_symbolic.cpp +++ b/Source/astcenc_compress_symbolic.cpp @@ -367,15 +367,15 @@ static float compress_symbolic_block_fixed_partition_1plane( // and weight encodings; return results for the 4 best-looking modes. int partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][4]; - int quantized_weight[TUNE_MAX_TRIAL_CANDIDATES]; + int block_mode_index[TUNE_MAX_TRIAL_CANDIDATES]; // TODO: Make these enums? int color_quant_level[TUNE_MAX_TRIAL_CANDIDATES]; int color_quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES]; determine_optimal_set_of_endpoint_formats_to_use( - &bsd, pt, &blk, &ewb, &ei.ep, qwt_bitcounts, qwt_errors, - config.tune_candidate_limit, partition_format_specifiers, quantized_weight, + bsd, *pt, blk, ewb, ei.ep, qwt_bitcounts, qwt_errors, + config.tune_candidate_limit, partition_format_specifiers, block_mode_index, color_quant_level, color_quant_level_mod); // then iterate over the tune_candidate_limit believed-to-be-best modes to @@ -389,21 +389,21 @@ static float compress_symbolic_block_fixed_partition_1plane( uint8_t *u8_weight_src; - const int qw_packed_index = quantized_weight[i]; - if (qw_packed_index < 0) + const int bm_packed_index = block_mode_index[i]; + if (bm_packed_index < 0) { trace_add_data("failed", "error_block"); continue; } - assert(qw_packed_index >= 0 && qw_packed_index < bsd.block_mode_count); - const block_mode& qw_bm = bsd.block_modes[qw_packed_index]; + assert(bm_packed_index >= 0 && bm_packed_index < bsd.block_mode_count); + const block_mode& qw_bm = bsd.block_modes[bm_packed_index]; int decimation_mode = qw_bm.decimation_mode; int weight_quant_mode = qw_bm.quant_mode; const decimation_table& dt = *dts[decimation_mode]; promise(dt.weight_count > 0); - u8_weight_src = u8_quantized_decimated_quantized_weights + MAX_WEIGHTS_PER_BLOCK * qw_packed_index; + u8_weight_src = u8_quantized_decimated_quantized_weights + MAX_WEIGHTS_PER_BLOCK * bm_packed_index; trace_add_data("weight_x", dt.weight_x); trace_add_data("weight_y", dt.weight_y); @@ -771,7 +771,7 @@ static float compress_symbolic_block_fixed_partition_2planes( // decide the optimal combination of color endpoint encodings and weight encodings. int partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][4]; - int quantized_weight[TUNE_MAX_TRIAL_CANDIDATES]; + int block_mode_index[TUNE_MAX_TRIAL_CANDIDATES]; int color_quant_level[TUNE_MAX_TRIAL_CANDIDATES]; int color_quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES]; @@ -779,8 +779,8 @@ static float compress_symbolic_block_fixed_partition_2planes( merge_endpoints(ei1.ep, ei2.ep, plane2_component, epm); determine_optimal_set_of_endpoint_formats_to_use( - &bsd, pt, &blk, &ewb, &epm, qwt_bitcounts, qwt_errors, - config.tune_candidate_limit, partition_format_specifiers, quantized_weight, + bsd, *pt, blk, ewb, epm, qwt_bitcounts, qwt_errors, + config.tune_candidate_limit, partition_format_specifiers, block_mode_index, color_quant_level, color_quant_level_mod); // then iterate over the tune_candidate_limit believed-to-be-best modes to @@ -792,8 +792,8 @@ static float compress_symbolic_block_fixed_partition_2planes( { TRACE_NODE(node0, "candidate"); - const int qw_packed_index = quantized_weight[i]; - if (qw_packed_index < 0) + const int bm_packed_index = block_mode_index[i]; + if (bm_packed_index < 0) { trace_add_data("failed", "error_block"); continue; @@ -802,16 +802,16 @@ static float compress_symbolic_block_fixed_partition_2planes( uint8_t *u8_weight1_src; uint8_t *u8_weight2_src; - assert(qw_packed_index >= 0 && qw_packed_index < bsd.block_mode_count); - const block_mode& qw_bm = bsd.block_modes[qw_packed_index]; + assert(bm_packed_index >= 0 && bm_packed_index < bsd.block_mode_count); + const block_mode& qw_bm = bsd.block_modes[bm_packed_index]; int decimation_mode = qw_bm.decimation_mode; int weight_quant_mode = qw_bm.quant_mode; const decimation_table& dt = *dts[decimation_mode]; promise(dt.weight_count > 0); - u8_weight1_src = u8_quantized_decimated_quantized_weights + MAX_WEIGHTS_PER_BLOCK * (2 * qw_packed_index); - u8_weight2_src = u8_quantized_decimated_quantized_weights + MAX_WEIGHTS_PER_BLOCK * (2 * qw_packed_index + 1); + u8_weight1_src = u8_quantized_decimated_quantized_weights + MAX_WEIGHTS_PER_BLOCK * (2 * bm_packed_index); + u8_weight2_src = u8_quantized_decimated_quantized_weights + MAX_WEIGHTS_PER_BLOCK * (2 * bm_packed_index + 1); trace_add_data("weight_x", dt.weight_x); trace_add_data("weight_y", dt.weight_y); diff --git a/Source/astcenc_internal.h b/Source/astcenc_internal.h index da70bd2..db9728b 100644 --- a/Source/astcenc_internal.h +++ b/Source/astcenc_internal.h @@ -1507,21 +1507,39 @@ struct compress_symbolic_block_buffers compress_fixed_partition_buffers planes; }; +/** + * @brief Identify, for each mode, which set of color endpoint produces the best result. + * + * Returns the best @c tune_candidate_limit best looking modes, along with the ideal color encoding + * combination for each. The modified quantization level can be used when all formats are the same, + * as this frees up two additional bits of storage. + * + * @param bsd The block size information. + * @param pi The partition info for the current trial. + * @param blk The image block color data to compress. + * @param ewb The image block weighted error data. + * @param ep The ideal endpoints. + * @param qwt_bitcounts Bit counts for different quantization methods. + * @param qwt_errors Errors for different quantization methods. + * @param tune_candidate_limit The number of candidates to return. + * @param[out] partition_format_specifiers The best formats per partition. + * @param[out] block_mode The best packed block mode index. + * @param[out] quant_level The best color quant level. + * @param[out] quant_level_mod The best color quant level if endpoints are the same. + */ void determine_optimal_set_of_endpoint_formats_to_use( - const block_size_descriptor* bsd, - const partition_info* pt, - const imageblock* blk, - const error_weight_block* ewb, - const endpoints* ep, - // bitcounts and errors computed for the various quantization methods + const block_size_descriptor& bsd, + const partition_info& pi, + const imageblock& blk, + const error_weight_block& ewb, + const endpoints& ep, const int* qwt_bitcounts, const float* qwt_errors, int tune_candidate_limit, - // output data - int partition_format_specifiers[4][4], - int quantized_weight[4], - int quant_level[4], - int quant_level_mod[4]); + int partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][4], + int block_mode[TUNE_MAX_TRIAL_CANDIDATES], + int quant_level[TUNE_MAX_TRIAL_CANDIDATES], + int quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES]); /** * @brief For a given 1 plane weight set recompute the endpoint colors. diff --git a/Source/astcenc_pick_best_endpoint_format.cpp b/Source/astcenc_pick_best_endpoint_format.cpp index 58fec5d..c239cac 100644 --- a/Source/astcenc_pick_best_endpoint_format.cpp +++ b/Source/astcenc_pick_best_endpoint_format.cpp @@ -297,25 +297,31 @@ static void compute_encoding_choice_errors( } } -/* - functions to determine, for a given partitioning, which color endpoint formats are the best to use. +/** + * @brief For a given partition compute the error for every endpoint integer count and quant level. + * + * @param encode_hdr_rgb @c true if using HDR for RGB, @c false for LDR. + * @param encode_hdr_alpha @c true if using HDR for alpha, @c false for LDR. + * @param partition_index The partition index. + * @param pi The partition info. + * @param eci The encoding choice error metrics. + * @param ep The idealized endpoints. + * @param error_weight The resulting encoding choice error metrics. + * @param[out] best_error The best error for each integer count and quant level. + * @param[out] format_of_choice The preferred endpoint format for each integer count and quant level. */ - -// for a given partition, compute for every (integer-component-count, quantization-level) -// the color error. static void compute_color_error_for_every_integer_count_and_quant_level( - int encode_hdr_rgb, // 1 = perform HDR encoding, 0 = perform LDR encoding. - int encode_hdr_alpha, + bool encode_hdr_rgb, + bool encode_hdr_alpha, int partition_index, - const partition_info* pt, - const encoding_choice_errors* eci, // pointer to the structure for the CURRENT partition. - const endpoints* ep, + const partition_info& pi, + const encoding_choice_errors& eci, + const endpoints& ep, vfloat4 error_weight, - // arrays to return results back through. float best_error[21][4], int format_of_choice[21][4] ) { - int partition_size = pt->partition_texel_count[partition_index]; + int partition_size = pi.partition_texel_count[partition_index]; static const float baseline_quant_error[21] = { (65536.0f * 65536.0f / 18.0f), // 2 values, 1 step @@ -341,8 +347,8 @@ static void compute_color_error_for_every_integer_count_and_quant_level( (65536.0f * 65536.0f / 18.0f) / (255 * 255) }; - vfloat4 ep0 = ep->endpt0[partition_index]; - vfloat4 ep1 = ep->endpt1[partition_index]; + vfloat4 ep0 = ep.endpt0[partition_index]; + vfloat4 ep1 = ep.endpt1[partition_index]; float ep1_min = hmin_rgb_s(ep1); ep1_min = astc::max(ep1_min, 0.0f); @@ -539,18 +545,18 @@ static void compute_color_error_for_every_integer_count_and_quant_level( format_of_choice[i][3] = encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA; // for 6 integers, we have one HDR-RGB encoding - float full_hdr_rgb_error = (rgb_quantization_error * mode11mult) + rgb_range_error + eci->alpha_drop_error; + float full_hdr_rgb_error = (rgb_quantization_error * mode11mult) + rgb_range_error + eci.alpha_drop_error; best_error[i][2] = full_hdr_rgb_error; format_of_choice[i][2] = FMT_HDR_RGB; // for 4 integers, we have one HDR-RGB-Scale encoding - float hdr_rgb_scale_error = (rgb_quantization_error * mode7mult) + rgb_range_error + eci->alpha_drop_error + eci->rgb_luma_error; + float hdr_rgb_scale_error = (rgb_quantization_error * mode7mult) + rgb_range_error + eci.alpha_drop_error + eci.rgb_luma_error; best_error[i][1] = hdr_rgb_scale_error; format_of_choice[i][1] = FMT_HDR_RGB_SCALE; // for 2 integers, we assume luminance-with-large-range - float hdr_luminance_error = (rgb_quantization_error * mode23mult) + rgb_range_error + eci->alpha_drop_error + eci->luminance_error; + float hdr_luminance_error = (rgb_quantization_error * mode23mult) + rgb_range_error + eci.alpha_drop_error + eci.luminance_error; best_error[i][0] = hdr_luminance_error; format_of_choice[i][0] = FMT_HDR_LUMINANCE_LARGE_RANGE; } @@ -574,11 +580,11 @@ static void compute_color_error_for_every_integer_count_and_quant_level( float base_quant_error_a = error_weight.lane<3>() * static_cast(partition_size); float base_quant_error_rgba = base_quant_error_rgb + base_quant_error_a; - float error_scale_bc_rgba = eci->can_blue_contract ? 0.625f : 1.0f; - float error_scale_oe_rgba = eci->can_offset_encode ? 0.5f : 1.0f; + float error_scale_bc_rgba = eci.can_blue_contract ? 0.625f : 1.0f; + float error_scale_oe_rgba = eci.can_offset_encode ? 0.5f : 1.0f; - float error_scale_bc_rgb = eci->can_blue_contract ? 0.5f : 1.0f; - float error_scale_oe_rgb = eci->can_offset_encode ? 0.25f : 1.0f; + float error_scale_bc_rgb = eci.can_blue_contract ? 0.5f : 1.0f; + float error_scale_oe_rgb = eci.can_offset_encode ? 0.25f : 1.0f; // pick among the available LDR endpoint modes for (int i = 4; i < 21; i++) @@ -609,10 +615,10 @@ static void compute_color_error_for_every_integer_count_and_quant_level( * error_scale_bc_rgb * error_scale_oe_rgb + rgb_range_error - + eci->alpha_drop_error; + + eci.alpha_drop_error; float rgbs_alpha_error = quant_error_rgba - + eci->rgb_scale_error + + eci.rgb_scale_error + rgb_range_error + alpha_range_error; @@ -630,13 +636,13 @@ static void compute_color_error_for_every_integer_count_and_quant_level( // 4 integers can encode as RGBS or LA+LA float ldr_rgbs_error = quant_error_rgb + rgb_range_error - + eci->alpha_drop_error - + eci->rgb_scale_error; + + eci.alpha_drop_error + + eci.rgb_scale_error; float lum_alpha_error = quant_error_rgba + rgb_range_error + alpha_range_error - + eci->luminance_error; + + eci.luminance_error; if (ldr_rgbs_error < lum_alpha_error) { @@ -652,8 +658,8 @@ static void compute_color_error_for_every_integer_count_and_quant_level( // 2 integers can encode as L+L float luminance_error = quant_error_rgb + rgb_range_error - + eci->alpha_drop_error - + eci->luminance_error; + + eci.alpha_drop_error + + eci.luminance_error; best_error[i][0] = luminance_error; format_of_choice[i][0] = FMT_LUMINANCE; @@ -661,14 +667,23 @@ static void compute_color_error_for_every_integer_count_and_quant_level( } } -// for 1 partition, find the best combination (one format + a quantization level) for a given bitcount +/** + * @brief For one partition compute the best format and quantization for a given bit count. + * + * @param best_combined_error The best error for each quant level and integer count. + * @param best_combined_format The best format for each quant level and integer count. + * @param bits_available The number of bits available for encoding. + * @param[out] best_quant_level The output best color quant level. + * @param[out] best_format The output best color format. + * @param[out] best_error The output error for the best pairing. + */ static void one_partition_find_best_combination_for_bitcount( - float combined_best_error[21][4], - int formats_of_choice[21][4], + const float best_combined_error[21][4], + const int best_combined_format[21][4], int bits_available, - int* best_quant_level, - int* best_formats, - float* error_of_best_combination + int& best_quant_level, + int& best_format, + float& best_error ) { int best_integer_count = -1; float best_integer_count_error = 1e20f; @@ -682,39 +697,44 @@ static void one_partition_find_best_combination_for_bitcount( continue; // used to indicate the case where we don't have enough bits to represent a given endpoint format at all. } - if (combined_best_error[quant_level][i] < best_integer_count_error) + if (best_combined_error[quant_level][i] < best_integer_count_error) { - best_integer_count_error = combined_best_error[quant_level][i]; + best_integer_count_error = best_combined_error[quant_level][i]; best_integer_count = i; } } int ql = quant_mode_table[best_integer_count + 1][bits_available]; - *best_quant_level = ql; - *error_of_best_combination = best_integer_count_error; + best_quant_level = ql; + best_format = FMT_LUMINANCE; + best_error = best_integer_count_error; + if (ql >= 0) { - *best_formats = formats_of_choice[ql][best_integer_count]; - } - else - { - *best_formats = FMT_LUMINANCE; + best_format = best_combined_format[ql][best_integer_count]; } } -// for 2 partitions, find the best format combinations for every (quantization-mode, integer-count) combination +/** + * @brief For 2 partitions compute the best format combinations for every pair of quant mode and integer count. + * + * @param best_error The best error for a single endpoint quant level and integer count. + * @param best_format The best format for a single endpoint quant level and integer count. + * @param[out] best_combined_error The best combined error pairings for the 2 partitions. + * @param[out] best_combined_format The best combined format pairings for the 2 partitions. + */ static void two_partitions_find_best_combination_for_every_quantization_and_integer_count( - float best_error[2][21][4], // indexed by (partition, quant-level, integer-pair-count-minus-1) - int format_of_choice[2][21][4], - float combined_best_error[21][7], // indexed by (quant-level, integer-pair-count-minus-2) - int formats_of_choice[21][7][2] + const float best_error[2][21][4], // indexed by (partition, quant-level, integer-pair-count-minus-1) + const int best_format[2][21][4], + float best_combined_error[21][7], // indexed by (quant-level, integer-pair-count-minus-2) + int best_combined_format[21][7][2] ) { for (int i = 0; i < 21; i++) { for (int j = 0; j < 7; j++) { - combined_best_error[i][j] = 1e30f; + best_combined_error[i][j] = 1e30f; } } @@ -733,26 +753,36 @@ static void two_partitions_find_best_combination_for_every_quantization_and_inte int intcnt = i + j; float errorterm = astc::min(best_error[0][quant][i] + best_error[1][quant][j], 1e10f); - if (errorterm <= combined_best_error[quant][intcnt]) + if (errorterm <= best_combined_error[quant][intcnt]) { - combined_best_error[quant][intcnt] = errorterm; - formats_of_choice[quant][intcnt][0] = format_of_choice[0][quant][i]; - formats_of_choice[quant][intcnt][1] = format_of_choice[1][quant][j]; + best_combined_error[quant][intcnt] = errorterm; + best_combined_format[quant][intcnt][0] = best_format[0][quant][i]; + best_combined_format[quant][intcnt][1] = best_format[1][quant][j]; } } } } } -// for 2 partitions, find the best combination (two formats + a quantization level) for a given bitcount +/** + * @brief For 2 partitions compute the best format and quantization for a given bit count. + * + * @param best_combined_error The best error for each quant level and integer count. + * @param best_combined_format The best format for each quant level and integer count. + * @param bits_available The number of bits available for encoding. + * @param[out] best_quant_level The output best color quant level. + * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available. + * @param[out] best_formats The output best color formats. + * @param[out] best_error The output error for the best pairing. + */ static void two_partitions_find_best_combination_for_bitcount( - float combined_best_error[21][7], - int formats_of_choice[21][7][2], + float best_combined_error[21][7], + int best_combined_format[21][7][2], int bits_available, - int* best_quant_level, - int* best_quant_level_mod, + int& best_quant_level, + int& best_quant_level_mod, int* best_formats, - float* error_of_best_combination + float& best_error ) { int best_integer_count = 0; float best_integer_count_error = 1e20f; @@ -767,7 +797,7 @@ static void two_partitions_find_best_combination_for_bitcount( break; // used to indicate the case where we don't have enough bits to represent a given endpoint format at all. } - float integer_count_error = combined_best_error[quant_level][integer_count - 2]; + float integer_count_error = best_combined_error[quant_level][integer_count - 2]; if (integer_count_error < best_integer_count_error) { @@ -779,14 +809,14 @@ static void two_partitions_find_best_combination_for_bitcount( int ql = quant_mode_table[best_integer_count][bits_available]; int ql_mod = quant_mode_table[best_integer_count][bits_available + 2]; - *best_quant_level = ql; - *best_quant_level_mod = ql_mod; - *error_of_best_combination = best_integer_count_error; + best_quant_level = ql; + best_quant_level_mod = ql_mod; + best_error = best_integer_count_error; if (ql >= 0) { for (int i = 0; i < 2; i++) { - best_formats[i] = formats_of_choice[ql][best_integer_count - 2][i]; + best_formats[i] = best_combined_format[ql][best_integer_count - 2][i]; } } else @@ -798,18 +828,25 @@ static void two_partitions_find_best_combination_for_bitcount( } } -// for 3 partitions, find the best format combinations for every (quantization-mode, integer-count) combination +/** + * @brief For 3 partitions compute the best format combinations for every pair of quant mode and integer count. + * + * @param best_error The best error for a single endpoint quant level and integer count. + * @param best_format The best format for a single endpoint quant level and integer count. + * @param[out] best_combined_error The best combined error pairings for the 3 partitions. + * @param[out] best_combined_format The best combined format pairings for the 3 partitions. + */ static void three_partitions_find_best_combination_for_every_quantization_and_integer_count( - float best_error[3][21][4], // indexed by (partition, quant-level, integer-count) - int format_of_choice[3][21][4], - float combined_best_error[21][10], - int formats_of_choice[21][10][3] + const float best_error[3][21][4], // indexed by (partition, quant-level, integer-count) + const int best_format[3][21][4], + float best_combined_error[21][10], + int best_combined_format[21][10][3] ) { for (int i = 0; i < 21; i++) { for (int j = 0; j < 10; j++) { - combined_best_error[i][j] = 1e30f; + best_combined_error[i][j] = 1e30f; } } @@ -837,12 +874,12 @@ static void three_partitions_find_best_combination_for_every_quantization_and_in int intcnt = i + j + k; float errorterm = astc::min(best_error[0][quant][i] + best_error[1][quant][j] + best_error[2][quant][k], 1e10f); - if (errorterm <= combined_best_error[quant][intcnt]) + if (errorterm <= best_combined_error[quant][intcnt]) { - combined_best_error[quant][intcnt] = errorterm; - formats_of_choice[quant][intcnt][0] = format_of_choice[0][quant][i]; - formats_of_choice[quant][intcnt][1] = format_of_choice[1][quant][j]; - formats_of_choice[quant][intcnt][2] = format_of_choice[2][quant][k]; + best_combined_error[quant][intcnt] = errorterm; + best_combined_format[quant][intcnt][0] = best_format[0][quant][i]; + best_combined_format[quant][intcnt][1] = best_format[1][quant][j]; + best_combined_format[quant][intcnt][2] = best_format[2][quant][k]; } } } @@ -850,15 +887,25 @@ static void three_partitions_find_best_combination_for_every_quantization_and_in } } -// for 3 partitions, find the best combination (three formats + a quantization level) for a given bitcount +/** + * @brief For 3 partitions compute the best format and quantization for a given bit count. + * + * @param best_combined_error The best error for each quant level and integer count. + * @param best_combined_format The best format for each quant level and integer count. + * @param bits_available The number of bits available for encoding. + * @param[out] best_quant_level The output best color quant level. + * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available. + * @param[out] best_formats The output best color formats. + * @param[out] best_error The output error for the best pairing. + */ static void three_partitions_find_best_combination_for_bitcount( - float combined_best_error[21][10], - int formats_of_choice[21][10][3], + const float best_combined_error[21][10], + const int best_combined_format[21][10][3], int bits_available, - int* best_quant_level, - int* best_quant_level_mod, + int& best_quant_level, + int& best_quant_level_mod, int* best_formats, - float* error_of_best_combination + float& best_error ) { int best_integer_count = 0; float best_integer_count_error = 1e20f; @@ -873,7 +920,7 @@ static void three_partitions_find_best_combination_for_bitcount( break; // used to indicate the case where we don't have enough bits to represent a given endpoint format at all. } - float integer_count_error = combined_best_error[quant_level][integer_count - 3]; + float integer_count_error = best_combined_error[quant_level][integer_count - 3]; if (integer_count_error < best_integer_count_error) { @@ -885,14 +932,14 @@ static void three_partitions_find_best_combination_for_bitcount( int ql = quant_mode_table[best_integer_count][bits_available]; int ql_mod = quant_mode_table[best_integer_count][bits_available + 5]; - *best_quant_level = ql; - *best_quant_level_mod = ql_mod; - *error_of_best_combination = best_integer_count_error; + best_quant_level = ql; + best_quant_level_mod = ql_mod; + best_error = best_integer_count_error; if (ql >= 0) { for (int i = 0; i < 3; i++) { - best_formats[i] = formats_of_choice[ql][best_integer_count - 3][i]; + best_formats[i] = best_combined_format[ql][best_integer_count - 3][i]; } } else @@ -904,18 +951,25 @@ static void three_partitions_find_best_combination_for_bitcount( } } -// for 4 partitions, find the best format combinations for every (quantization-mode, integer-count) combination +/** + * @brief For 4 partitions compute the best format combinations for every pair of quant mode and integer count. + * + * @param best_error The best error for a single endpoint quant level and integer count. + * @param best_format The best format for a single endpoint quant level and integer count. + * @param[out] best_combined_error The best combined error pairings for the 4 partitions. + * @param[out] best_combined_format The best combined format pairings for the 4 partitions. + */ static void four_partitions_find_best_combination_for_every_quantization_and_integer_count( - float best_error[4][21][4], // indexed by (partition, quant-level, integer-count) - int format_of_choice[4][21][4], - float combined_best_error[21][13], - int formats_of_choice[21][13][4] + const float best_error[4][21][4], // indexed by (partition, quant-level, integer-count) + const int best_format[4][21][4], + float best_combined_error[21][13], + int best_combined_format[21][13][4] ) { for (int i = 0; i < 21; i++) { for (int j = 0; j < 13; j++) { - combined_best_error[i][j] = 1e30f; + best_combined_error[i][j] = 1e30f; } } @@ -952,13 +1006,13 @@ static void four_partitions_find_best_combination_for_every_quantization_and_int int intcnt = i + j + k + l; float errorterm = astc::min(best_error[0][quant][i] + best_error[1][quant][j] + best_error[2][quant][k] + best_error[3][quant][l], 1e10f); - if (errorterm <= combined_best_error[quant][intcnt]) + if (errorterm <= best_combined_error[quant][intcnt]) { - combined_best_error[quant][intcnt] = errorterm; - formats_of_choice[quant][intcnt][0] = format_of_choice[0][quant][i]; - formats_of_choice[quant][intcnt][1] = format_of_choice[1][quant][j]; - formats_of_choice[quant][intcnt][2] = format_of_choice[2][quant][k]; - formats_of_choice[quant][intcnt][3] = format_of_choice[3][quant][l]; + best_combined_error[quant][intcnt] = errorterm; + best_combined_format[quant][intcnt][0] = best_format[0][quant][i]; + best_combined_format[quant][intcnt][1] = best_format[1][quant][j]; + best_combined_format[quant][intcnt][2] = best_format[2][quant][k]; + best_combined_format[quant][intcnt][3] = best_format[3][quant][l]; } } } @@ -967,15 +1021,25 @@ static void four_partitions_find_best_combination_for_every_quantization_and_int } } -// for 4 partitions, find the best combination (four formats + a quantization level) for a given bitcount +/** + * @brief For 4 partitions compute the best format and quantization for a given bit count. + * + * @param best_combined_error The best error for each quant level and integer count. + * @param best_combined_format The best format for each quant level and integer count. + * @param bits_available The number of bits available for encoding. + * @param[out] best_quant_level The output best color quant level. + * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available. + * @param[out] best_formats The output best color formats. + * @param[out] best_error The output error for the best pairing. + */ static void four_partitions_find_best_combination_for_bitcount( - float combined_best_error[21][13], - int formats_of_choice[21][13][4], + const float best_combined_error[21][13], + const int best_combined_format[21][13][4], int bits_available, - int* best_quant_level, - int* best_quant_level_mod, + int& best_quant_level, + int& best_quant_level_mod, int* best_formats, - float* error_of_best_combination + float& best_error ) { int best_integer_count = 0; float best_integer_count_error = 1e20f; @@ -990,7 +1054,7 @@ static void four_partitions_find_best_combination_for_bitcount( break; // used to indicate the case where we don't have enough bits to represent a given endpoint format at all. } - float integer_count_error = combined_best_error[quant_level][integer_count - 4]; + float integer_count_error = best_combined_error[quant_level][integer_count - 4]; if (integer_count_error < best_integer_count_error) { @@ -1002,14 +1066,14 @@ static void four_partitions_find_best_combination_for_bitcount( int ql = quant_mode_table[best_integer_count][bits_available]; int ql_mod = quant_mode_table[best_integer_count][bits_available + 8]; - *best_quant_level = ql; - *best_quant_level_mod = ql_mod; - *error_of_best_combination = best_integer_count_error; + best_quant_level = ql; + best_quant_level_mod = ql_mod; + best_error = best_integer_count_error; if (ql >= 0) { for (int i = 0; i < 4; i++) { - best_formats[i] = formats_of_choice[ql][best_integer_count - 4][i]; + best_formats[i] = best_combined_format[ql][best_integer_count - 4][i]; } } else @@ -1021,61 +1085,41 @@ static void four_partitions_find_best_combination_for_bitcount( } } -/* - The determine_optimal_set_of_endpoint_formats_to_use() function. - - It identifies, for each mode, which set of color endpoint encodings - produces the best overall result. It then reports back which - tune_candidate_limit, modes look best, along with the ideal color encoding - combination for each. - - It takes as input: - a partitioning an imageblock, - a set of color endpoints. - for each mode, the number of bits available for color encoding and the error incurred by quantization. - in case of 2 plane of weights, a specifier for which color component to use for the second plane of weights. - - It delivers as output for each of the tune_candidate_limit selected modes: - format specifier - for each partition - quantization level to use - modified quantization level to use - (when all format specifiers are equal) -*/ +/* See header for documentation. */ void determine_optimal_set_of_endpoint_formats_to_use( - const block_size_descriptor* bsd, - const partition_info* pt, - const imageblock* blk, - const error_weight_block* ewb, - const endpoints* ep, + const block_size_descriptor& bsd, + const partition_info& pi, + const imageblock& blk, + const error_weight_block& ewb, + const endpoints& ep, // bitcounts and errors computed for the various quantization methods const int* qwt_bitcounts, const float* qwt_errors, int tune_candidate_limit, // output data int partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][4], - int quantized_weight[TUNE_MAX_TRIAL_CANDIDATES], + int block_mode[TUNE_MAX_TRIAL_CANDIDATES], int quant_level[TUNE_MAX_TRIAL_CANDIDATES], int quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES] ) { - int partition_count = pt->partition_count; + int partition_count = pi.partition_count; promise(partition_count > 0); - promise(bsd->block_mode_count > 0); + promise(bsd.block_mode_count > 0); - int encode_hdr_rgb = blk->rgb_lns[0]; - int encode_hdr_alpha = blk->alpha_lns[0]; + int encode_hdr_rgb = blk.rgb_lns[0]; + int encode_hdr_alpha = blk.alpha_lns[0]; // call a helper function to compute the errors that result from various // encoding choices (such as using luminance instead of RGB, discarding Alpha, // using RGB-scale in place of two separate RGB endpoints and so on) encoding_choice_errors eci[4]; - compute_encoding_choice_errors(*bsd, *blk, *pt, *ewb, *ep, eci); + compute_encoding_choice_errors(bsd, blk, pi, ewb, ep, eci); // for each partition, compute the error weights to apply for that partition. partition_metrics pms[4]; - compute_partition_error_color_weightings(*ewb, *pt, pms); + compute_partition_error_color_weightings(ewb, pi, pms); float best_error[4][21][4]; int format_of_choice[4][21][4]; @@ -1083,7 +1127,7 @@ void determine_optimal_set_of_endpoint_formats_to_use( { compute_color_error_for_every_integer_count_and_quant_level( encode_hdr_rgb, encode_hdr_alpha, i, - pt, &(eci[i]), ep, pms[i].error_weight, best_error[i], + pi, eci[i], ep, pms[i].error_weight, best_error[i], format_of_choice[i]); } @@ -1094,7 +1138,7 @@ void determine_optimal_set_of_endpoint_formats_to_use( // have to ensure that the "overstep" of the last iteration in the vectorized // loop will contain data that will never be picked as best candidate - const int packed_mode_count = bsd->block_mode_count; + const int packed_mode_count = bsd.block_mode_count; const int packed_mode_count_simd_up = round_up_to_simd_multiple_vla(packed_mode_count); for (int i = packed_mode_count; i < packed_mode_count_simd_up; ++i) { @@ -1107,7 +1151,7 @@ void determine_optimal_set_of_endpoint_formats_to_use( if (partition_count == 1) { float error_of_best_combination; - for (int i = 0; i < bsd->block_mode_count; ++i) + for (int i = 0; i < bsd.block_mode_count; ++i) { if (qwt_errors[i] >= 1e29f) { @@ -1117,7 +1161,7 @@ void determine_optimal_set_of_endpoint_formats_to_use( one_partition_find_best_combination_for_bitcount( best_error[0], format_of_choice[0], qwt_bitcounts[i], - best_quant_levels + i, best_ep_formats[i], &error_of_best_combination); + best_quant_levels[i], best_ep_formats[i][0], error_of_best_combination); error_of_best_combination += qwt_errors[i]; errors_of_best_combination[i] = error_of_best_combination; @@ -1134,7 +1178,7 @@ void determine_optimal_set_of_endpoint_formats_to_use( best_error, format_of_choice, combined_best_error, formats_of_choice); - for (int i = 0; i < bsd->block_mode_count; ++i) + for (int i = 0; i < bsd.block_mode_count; ++i) { if (qwt_errors[i] >= 1e29f) { @@ -1145,8 +1189,8 @@ void determine_optimal_set_of_endpoint_formats_to_use( float error_of_best_combination; two_partitions_find_best_combination_for_bitcount( combined_best_error, formats_of_choice, qwt_bitcounts[i], - best_quant_levels + i, best_quant_levels_mod + i, - best_ep_formats[i], &error_of_best_combination); + best_quant_levels[i], best_quant_levels_mod[i], + best_ep_formats[i], error_of_best_combination); errors_of_best_combination[i] = error_of_best_combination + qwt_errors[i]; } @@ -1160,7 +1204,7 @@ void determine_optimal_set_of_endpoint_formats_to_use( three_partitions_find_best_combination_for_every_quantization_and_integer_count( best_error, format_of_choice, combined_best_error, formats_of_choice); - for (int i = 0; i < bsd->block_mode_count; ++i) + for (int i = 0; i < bsd.block_mode_count; ++i) { if (qwt_errors[i] >= 1e29f) { @@ -1171,8 +1215,8 @@ void determine_optimal_set_of_endpoint_formats_to_use( float error_of_best_combination; three_partitions_find_best_combination_for_bitcount( combined_best_error, formats_of_choice, qwt_bitcounts[i], - best_quant_levels + i, best_quant_levels_mod + i, - best_ep_formats[i], &error_of_best_combination); + best_quant_levels[i], best_quant_levels_mod[i], + best_ep_formats[i], error_of_best_combination); errors_of_best_combination[i] = error_of_best_combination + qwt_errors[i]; } @@ -1186,7 +1230,7 @@ void determine_optimal_set_of_endpoint_formats_to_use( four_partitions_find_best_combination_for_every_quantization_and_integer_count( best_error, format_of_choice, combined_best_error, formats_of_choice); - for (int i = 0; i < bsd->block_mode_count; ++i) + for (int i = 0; i < bsd.block_mode_count; ++i) { if (qwt_errors[i] >= 1e29f) { @@ -1197,8 +1241,8 @@ void determine_optimal_set_of_endpoint_formats_to_use( float error_of_best_combination; four_partitions_find_best_combination_for_bitcount( combined_best_error, formats_of_choice, qwt_bitcounts[i], - best_quant_levels + i, best_quant_levels_mod + i, - best_ep_formats[i], &error_of_best_combination); + best_quant_levels[i], best_quant_levels_mod[i], + best_ep_formats[i], error_of_best_combination); errors_of_best_combination[i] = error_of_best_combination + qwt_errors[i]; } @@ -1211,7 +1255,7 @@ void determine_optimal_set_of_endpoint_formats_to_use( vint vbest_error_index(-1); vfloat vbest_ep_error(1e30f); vint lane_ids = vint::lane_id(); - for (int j = 0; j < bsd->block_mode_count; j += ASTCENC_SIMD_WIDTH) + for (int j = 0; j < bsd.block_mode_count; j += ASTCENC_SIMD_WIDTH) { vfloat err = vfloat(&errors_of_best_combination[j]); vmask mask1 = err < vbest_ep_error; @@ -1240,8 +1284,8 @@ void determine_optimal_set_of_endpoint_formats_to_use( for (int i = 0; i < tune_candidate_limit; i++) { - quantized_weight[i] = best_error_weights[i]; - if (quantized_weight[i] >= 0) + block_mode[i] = best_error_weights[i]; + if (block_mode[i] >= 0) { quant_level[i] = best_quant_levels[best_error_weights[i]]; assert(quant_level[i] >= 0 && quant_level[i] < 21); diff --git a/Source/astcenc_quantization.cpp b/Source/astcenc_quantization.cpp index afc1016..6fda471 100644 --- a/Source/astcenc_quantization.cpp +++ b/Source/astcenc_quantization.cpp @@ -535,9 +535,10 @@ const uint8_t color_unquant_tables[21][256] = { // The quant_mode_table[integercount/2][bits] gives us the quantization // level for a given integer count and number of bits that the integer may fit -// into. This is needed for color decoding, and for the color encoding. +// into. This is needed for color encoding and decoding. int8_t quant_mode_table[17][128]; +/* See header for documentation. */ void build_quant_mode_table() { for (int i = 0; i <= 16; i++)