1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2011-2022 Arm Limited
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 // use this file except in compliance with the License. You may obtain a copy
7 // of the License at:
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 // License for the specific language governing permissions and limitations
15 // under the License.
16 // ----------------------------------------------------------------------------
17
18 #if !defined(ASTCENC_DECOMPRESS_ONLY)
19
20 /**
21 * @brief Functions for finding best endpoint format.
22 *
23 * We assume there are two independent sources of error in any given partition:
24 *
25 * - Encoding choice errors
26 * - Quantization errors
27 *
28 * Encoding choice errors are caused by encoder decisions. For example:
29 *
30 * - Using luminance instead of separate RGB components.
31 * - Using a constant 1.0 alpha instead of storing an alpha component.
32 * - Using RGB+scale instead of storing two full RGB endpoints.
33 *
34 * Quantization errors occur due to the limited precision we use for storage. These errors generally
35 * scale with quantization level, but are not actually independent of color encoding. In particular:
36 *
37 * - If we can use offset encoding then quantization error is halved.
38 * - If we can use blue-contraction then quantization error for RG is halved.
39 * - If we use HDR endpoints the quantization error is higher.
40 *
41 * Apart from these effects, we assume the error is proportional to the quantization step size.
42 */
43
44
45 #include "astcenc_internal.h"
46 #include "astcenc_vecmathlib.h"
47
48 #include <assert.h>
49
50 /**
51 * @brief Compute the errors of the endpoint line options for one partition.
52 *
53 * Uncorrelated data assumes storing completely independent RGBA channels for each endpoint. Same
54 * chroma data assumes storing RGBA endpoints which pass though the origin (LDR only). RGBL data
55 * assumes storing RGB + lumashift (HDR only). Luminance error assumes storing RGB channels as a
56 * single value.
57 *
58 *
59 * @param pi The partition info data.
60 * @param partition_index The partition index to compule the error for.
61 * @param blk The image block.
62 * @param uncor_pline The endpoint line assuming uncorrelated endpoints.
63 * @param[out] uncor_err The computed error for the uncorrelated endpoint line.
64 * @param samec_pline The endpoint line assuming the same chroma for both endpoints.
65 * @param[out] samec_err The computed error for the uncorrelated endpoint line.
66 * @param rgbl_pline The endpoint line assuming RGB + lumashift data.
67 * @param[out] rgbl_err The computed error for the RGB + lumashift endpoint line.
68 * @param l_pline The endpoint line assuming luminance data.
69 * @param[out] l_err The computed error for the luminance endpoint line.
70 * @param[out] a_drop_err The computed error for dropping the alpha component.
71 */
compute_error_squared_rgb_single_partition(const partition_info & pi,int partition_index,const image_block & blk,const processed_line3 & uncor_pline,float & uncor_err,const processed_line3 & samec_pline,float & samec_err,const processed_line3 & rgbl_pline,float & rgbl_err,const processed_line3 & l_pline,float & l_err,float & a_drop_err)72 static void compute_error_squared_rgb_single_partition(
73 const partition_info& pi,
74 int partition_index,
75 const image_block& blk,
76 const processed_line3& uncor_pline,
77 float& uncor_err,
78 const processed_line3& samec_pline,
79 float& samec_err,
80 const processed_line3& rgbl_pline,
81 float& rgbl_err,
82 const processed_line3& l_pline,
83 float& l_err,
84 float& a_drop_err
85 ) {
86 vfloat4 ews = blk.channel_weight;
87
88 unsigned int texel_count = pi.partition_texel_count[partition_index];
89 const uint8_t* texel_indexes = pi.texels_of_partition[partition_index];
90 promise(texel_count > 0);
91
92 vfloatacc a_drop_errv = vfloatacc::zero();
93 vfloat default_a(blk.get_default_alpha());
94
95 vfloatacc uncor_errv = vfloatacc::zero();
96 vfloat uncor_bs0(uncor_pline.bs.lane<0>());
97 vfloat uncor_bs1(uncor_pline.bs.lane<1>());
98 vfloat uncor_bs2(uncor_pline.bs.lane<2>());
99
100 vfloat uncor_amod0(uncor_pline.amod.lane<0>());
101 vfloat uncor_amod1(uncor_pline.amod.lane<1>());
102 vfloat uncor_amod2(uncor_pline.amod.lane<2>());
103
104 vfloatacc samec_errv = vfloatacc::zero();
105 vfloat samec_bs0(samec_pline.bs.lane<0>());
106 vfloat samec_bs1(samec_pline.bs.lane<1>());
107 vfloat samec_bs2(samec_pline.bs.lane<2>());
108
109 vfloatacc rgbl_errv = vfloatacc::zero();
110 vfloat rgbl_bs0(rgbl_pline.bs.lane<0>());
111 vfloat rgbl_bs1(rgbl_pline.bs.lane<1>());
112 vfloat rgbl_bs2(rgbl_pline.bs.lane<2>());
113
114 vfloat rgbl_amod0(rgbl_pline.amod.lane<0>());
115 vfloat rgbl_amod1(rgbl_pline.amod.lane<1>());
116 vfloat rgbl_amod2(rgbl_pline.amod.lane<2>());
117
118 vfloatacc l_errv = vfloatacc::zero();
119 vfloat l_bs0(l_pline.bs.lane<0>());
120 vfloat l_bs1(l_pline.bs.lane<1>());
121 vfloat l_bs2(l_pline.bs.lane<2>());
122
123 vint lane_ids = vint::lane_id();
124 for (unsigned int i = 0; i < texel_count; i += ASTCENC_SIMD_WIDTH)
125 {
126 vint tix(texel_indexes + i);
127
128 vmask mask = lane_ids < vint(texel_count);
129 lane_ids += vint(ASTCENC_SIMD_WIDTH);
130
131 // Compute the error that arises from just ditching alpha
132 vfloat data_a = gatherf(blk.data_a, tix);
133 vfloat alpha_diff = data_a - default_a;
134 alpha_diff = alpha_diff * alpha_diff;
135
136 haccumulate(a_drop_errv, alpha_diff, mask);
137
138 vfloat data_r = gatherf(blk.data_r, tix);
139 vfloat data_g = gatherf(blk.data_g, tix);
140 vfloat data_b = gatherf(blk.data_b, tix);
141
142 // Compute uncorrelated error
143 vfloat param = data_r * uncor_bs0
144 + data_g * uncor_bs1
145 + data_b * uncor_bs2;
146
147 vfloat dist0 = (uncor_amod0 + param * uncor_bs0) - data_r;
148 vfloat dist1 = (uncor_amod1 + param * uncor_bs1) - data_g;
149 vfloat dist2 = (uncor_amod2 + param * uncor_bs2) - data_b;
150
151 vfloat error = dist0 * dist0 * ews.lane<0>()
152 + dist1 * dist1 * ews.lane<1>()
153 + dist2 * dist2 * ews.lane<2>();
154
155 haccumulate(uncor_errv, error, mask);
156
157 // Compute same chroma error - no "amod", its always zero
158 param = data_r * samec_bs0
159 + data_g * samec_bs1
160 + data_b * samec_bs2;
161
162 dist0 = (param * samec_bs0) - data_r;
163 dist1 = (param * samec_bs1) - data_g;
164 dist2 = (param * samec_bs2) - data_b;
165
166 error = dist0 * dist0 * ews.lane<0>()
167 + dist1 * dist1 * ews.lane<1>()
168 + dist2 * dist2 * ews.lane<2>();
169
170 haccumulate(samec_errv, error, mask);
171
172 // Compute rgbl error
173 param = data_r * rgbl_bs0
174 + data_g * rgbl_bs1
175 + data_b * rgbl_bs2;
176
177 dist0 = (rgbl_amod0 + param * rgbl_bs0) - data_r;
178 dist1 = (rgbl_amod1 + param * rgbl_bs1) - data_g;
179 dist2 = (rgbl_amod2 + param * rgbl_bs2) - data_b;
180
181 error = dist0 * dist0 * ews.lane<0>()
182 + dist1 * dist1 * ews.lane<1>()
183 + dist2 * dist2 * ews.lane<2>();
184
185 haccumulate(rgbl_errv, error, mask);
186
187 // Compute luma error - no "amod", its always zero
188 param = data_r * l_bs0
189 + data_g * l_bs1
190 + data_b * l_bs2;
191
192 dist0 = (param * l_bs0) - data_r;
193 dist1 = (param * l_bs1) - data_g;
194 dist2 = (param * l_bs2) - data_b;
195
196 error = dist0 * dist0 * ews.lane<0>()
197 + dist1 * dist1 * ews.lane<1>()
198 + dist2 * dist2 * ews.lane<2>();
199
200 haccumulate(l_errv, error, mask);
201 }
202
203 a_drop_err = hadd_s(a_drop_errv) * ews.lane<3>();
204 uncor_err = hadd_s(uncor_errv);
205 samec_err = hadd_s(samec_errv);
206 rgbl_err = hadd_s(rgbl_errv);
207 l_err = hadd_s(l_errv);
208 }
209
210 /**
211 * @brief For a given set of input colors and partitioning determine endpoint encode errors.
212 *
213 * This function determines the color error that results from RGB-scale encoding (LDR only),
214 * RGB-lumashift encoding (HDR only), luminance-encoding, and alpha drop. Also determines whether
215 * the endpoints are eligible for offset encoding or blue-contraction
216 *
217 * @param blk The image block.
218 * @param pi The partition info data.
219 * @param ep The idealized endpoints.
220 * @param[out] eci The resulting encoding choice error metrics.
221 */
compute_encoding_choice_errors(const image_block & blk,const partition_info & pi,const endpoints & ep,encoding_choice_errors eci[BLOCK_MAX_PARTITIONS])222 static void compute_encoding_choice_errors(
223 const image_block& blk,
224 const partition_info& pi,
225 const endpoints& ep,
226 encoding_choice_errors eci[BLOCK_MAX_PARTITIONS])
227 {
228 int partition_count = pi.partition_count;
229 promise(partition_count > 0);
230
231 partition_metrics pms[BLOCK_MAX_PARTITIONS];
232
233 compute_avgs_and_dirs_3_comp_rgb(pi, blk, pms);
234
235 for (int i = 0; i < partition_count; i++)
236 {
237 partition_metrics& pm = pms[i];
238
239 line3 uncor_rgb_lines;
240 line3 samec_rgb_lines; // for LDR-RGB-scale
241 line3 rgb_luma_lines; // for HDR-RGB-scale
242
243 processed_line3 uncor_rgb_plines;
244 processed_line3 samec_rgb_plines;
245 processed_line3 rgb_luma_plines;
246 processed_line3 luminance_plines;
247
248 float uncorr_rgb_error;
249 float samechroma_rgb_error;
250 float rgb_luma_error;
251 float luminance_rgb_error;
252 float alpha_drop_error;
253
254 uncor_rgb_lines.a = pm.avg;
255 uncor_rgb_lines.b = normalize_safe(pm.dir, unit3());
256
257 samec_rgb_lines.a = vfloat4::zero();
258 samec_rgb_lines.b = normalize_safe(pm.avg, unit3());
259
260 rgb_luma_lines.a = pm.avg;
261 rgb_luma_lines.b = unit3();
262
263 uncor_rgb_plines.amod = uncor_rgb_lines.a - uncor_rgb_lines.b * dot3(uncor_rgb_lines.a, uncor_rgb_lines.b);
264 uncor_rgb_plines.bs = uncor_rgb_lines.b;
265
266 // Same chroma always goes though zero, so this is simpler than the others
267 samec_rgb_plines.amod = vfloat4::zero();
268 samec_rgb_plines.bs = samec_rgb_lines.b;
269
270 rgb_luma_plines.amod = rgb_luma_lines.a - rgb_luma_lines.b * dot3(rgb_luma_lines.a, rgb_luma_lines.b);
271 rgb_luma_plines.bs = rgb_luma_lines.b;
272
273 // Luminance always goes though zero, so this is simpler than the others
274 luminance_plines.amod = vfloat4::zero();
275 luminance_plines.bs = unit3();
276
277 compute_error_squared_rgb_single_partition(
278 pi, i, blk,
279 uncor_rgb_plines, uncorr_rgb_error,
280 samec_rgb_plines, samechroma_rgb_error,
281 rgb_luma_plines, rgb_luma_error,
282 luminance_plines, luminance_rgb_error,
283 alpha_drop_error);
284
285 // Determine if we can offset encode RGB lanes
286 vfloat4 endpt0 = ep.endpt0[i];
287 vfloat4 endpt1 = ep.endpt1[i];
288 vfloat4 endpt_diff = abs(endpt1 - endpt0);
289 vmask4 endpt_can_offset = endpt_diff < vfloat4(0.12f * 65535.0f);
290 bool can_offset_encode = (mask(endpt_can_offset) & 0x7) == 0x7;
291
292 // Store out the settings
293 eci[i].rgb_scale_error = (samechroma_rgb_error - uncorr_rgb_error) * 0.7f; // empirical
294 eci[i].rgb_luma_error = (rgb_luma_error - uncorr_rgb_error) * 1.5f; // wild guess
295 eci[i].luminance_error = (luminance_rgb_error - uncorr_rgb_error) * 3.0f; // empirical
296 eci[i].alpha_drop_error = alpha_drop_error * 3.0f;
297 eci[i].can_offset_encode = can_offset_encode;
298 eci[i].can_blue_contract = !blk.is_luminance();
299 }
300 }
301
302 /**
303 * @brief For a given partition compute the error for every endpoint integer count and quant level.
304 *
305 * @param encode_hdr_rgb @c true if using HDR for RGB, @c false for LDR.
306 * @param encode_hdr_alpha @c true if using HDR for alpha, @c false for LDR.
307 * @param partition_index The partition index.
308 * @param pi The partition info.
309 * @param eci The encoding choice error metrics.
310 * @param ep The idealized endpoints.
311 * @param error_weight The resulting encoding choice error metrics.
312 * @param[out] best_error The best error for each integer count and quant level.
313 * @param[out] format_of_choice The preferred endpoint format for each integer count and quant level.
314 */
compute_color_error_for_every_integer_count_and_quant_level(bool encode_hdr_rgb,bool encode_hdr_alpha,int partition_index,const partition_info & pi,const encoding_choice_errors & eci,const endpoints & ep,vfloat4 error_weight,float best_error[21][4],uint8_t format_of_choice[21][4])315 static void compute_color_error_for_every_integer_count_and_quant_level(
316 bool encode_hdr_rgb,
317 bool encode_hdr_alpha,
318 int partition_index,
319 const partition_info& pi,
320 const encoding_choice_errors& eci,
321 const endpoints& ep,
322 vfloat4 error_weight,
323 float best_error[21][4],
324 uint8_t format_of_choice[21][4]
325 ) {
326 int partition_size = pi.partition_texel_count[partition_index];
327
328 static const float baseline_quant_error[21 - QUANT_6] {
329 (65536.0f * 65536.0f / 18.0f) / (5 * 5),
330 (65536.0f * 65536.0f / 18.0f) / (7 * 7),
331 (65536.0f * 65536.0f / 18.0f) / (9 * 9),
332 (65536.0f * 65536.0f / 18.0f) / (11 * 11),
333 (65536.0f * 65536.0f / 18.0f) / (15 * 15),
334 (65536.0f * 65536.0f / 18.0f) / (19 * 19),
335 (65536.0f * 65536.0f / 18.0f) / (23 * 23),
336 (65536.0f * 65536.0f / 18.0f) / (31 * 31),
337 (65536.0f * 65536.0f / 18.0f) / (39 * 39),
338 (65536.0f * 65536.0f / 18.0f) / (47 * 47),
339 (65536.0f * 65536.0f / 18.0f) / (63 * 63),
340 (65536.0f * 65536.0f / 18.0f) / (79 * 79),
341 (65536.0f * 65536.0f / 18.0f) / (95 * 95),
342 (65536.0f * 65536.0f / 18.0f) / (127 * 127),
343 (65536.0f * 65536.0f / 18.0f) / (159 * 159),
344 (65536.0f * 65536.0f / 18.0f) / (191 * 191),
345 (65536.0f * 65536.0f / 18.0f) / (255 * 255)
346 };
347
348 vfloat4 ep0 = ep.endpt0[partition_index];
349 vfloat4 ep1 = ep.endpt1[partition_index];
350
351 float ep1_min = hmin_rgb_s(ep1);
352 ep1_min = astc::max(ep1_min, 0.0f);
353
354 float error_weight_rgbsum = hadd_rgb_s(error_weight);
355
356 float range_upper_limit_rgb = encode_hdr_rgb ? 61440.0f : 65535.0f;
357 float range_upper_limit_alpha = encode_hdr_alpha ? 61440.0f : 65535.0f;
358
359 // It is possible to get endpoint colors significantly outside [0,upper-limit] even if the
360 // input data are safely contained in [0,upper-limit]; we need to add an error term for this
361 vfloat4 offset(range_upper_limit_rgb, range_upper_limit_rgb, range_upper_limit_rgb, range_upper_limit_alpha);
362 vfloat4 ep0_range_error_high = max(ep0 - offset, 0.0f);
363 vfloat4 ep1_range_error_high = max(ep1 - offset, 0.0f);
364
365 vfloat4 ep0_range_error_low = min(ep0, 0.0f);
366 vfloat4 ep1_range_error_low = min(ep1, 0.0f);
367
368 vfloat4 sum_range_error =
369 (ep0_range_error_low * ep0_range_error_low) +
370 (ep1_range_error_low * ep1_range_error_low) +
371 (ep0_range_error_high * ep0_range_error_high) +
372 (ep1_range_error_high * ep1_range_error_high);
373
374 float rgb_range_error = dot3_s(sum_range_error, error_weight)
375 * 0.5f * static_cast<float>(partition_size);
376 float alpha_range_error = sum_range_error.lane<3>() * error_weight.lane<3>()
377 * 0.5f * static_cast<float>(partition_size);
378
379 if (encode_hdr_rgb)
380 {
381
382 // Collect some statistics
383 float af, cf;
384 if (ep1.lane<0>() > ep1.lane<1>() && ep1.lane<0>() > ep1.lane<2>())
385 {
386 af = ep1.lane<0>();
387 cf = ep1.lane<0>() - ep0.lane<0>();
388 }
389 else if (ep1.lane<1>() > ep1.lane<2>())
390 {
391 af = ep1.lane<1>();
392 cf = ep1.lane<1>() - ep0.lane<1>();
393 }
394 else
395 {
396 af = ep1.lane<2>();
397 cf = ep1.lane<2>() - ep0.lane<2>();
398 }
399
400 // Estimate of color-component spread in high endpoint color
401 float bf = af - ep1_min;
402 vfloat4 prd = (ep1 - vfloat4(cf)).swz<0, 1, 2>();
403 vfloat4 pdif = prd - ep0.swz<0, 1, 2>();
404 // Estimate of color-component spread in low endpoint color
405 float df = hmax_s(abs(pdif));
406
407 int b = static_cast<int>(bf);
408 int c = static_cast<int>(cf);
409 int d = static_cast<int>(df);
410
411 // Determine which one of the 6 submodes is likely to be used in case of an RGBO-mode
412 int rgbo_mode = 5; // 7 bits per component
413 // mode 4: 8 7 6
414 if (b < 32768 && c < 16384)
415 {
416 rgbo_mode = 4;
417 }
418
419 // mode 3: 9 6 7
420 if (b < 8192 && c < 16384)
421 {
422 rgbo_mode = 3;
423 }
424
425 // mode 2: 10 5 8
426 if (b < 2048 && c < 16384)
427 {
428 rgbo_mode = 2;
429 }
430
431 // mode 1: 11 6 5
432 if (b < 2048 && c < 1024)
433 {
434 rgbo_mode = 1;
435 }
436
437 // mode 0: 11 5 7
438 if (b < 1024 && c < 4096)
439 {
440 rgbo_mode = 0;
441 }
442
443 // Determine which one of the 9 submodes is likely to be used in case of an RGB-mode.
444 int rgb_mode = 8; // 8 bits per component, except 7 bits for blue
445
446 // mode 0: 9 7 6 7
447 if (b < 16384 && c < 8192 && d < 8192)
448 {
449 rgb_mode = 0;
450 }
451
452 // mode 1: 9 8 6 6
453 if (b < 32768 && c < 8192 && d < 4096)
454 {
455 rgb_mode = 1;
456 }
457
458 // mode 2: 10 6 7 7
459 if (b < 4096 && c < 8192 && d < 4096)
460 {
461 rgb_mode = 2;
462 }
463
464 // mode 3: 10 7 7 6
465 if (b < 8192 && c < 8192 && d < 2048)
466 {
467 rgb_mode = 3;
468 }
469
470 // mode 4: 11 8 6 5
471 if (b < 8192 && c < 2048 && d < 512)
472 {
473 rgb_mode = 4;
474 }
475
476 // mode 5: 11 6 8 6
477 if (b < 2048 && c < 8192 && d < 1024)
478 {
479 rgb_mode = 5;
480 }
481
482 // mode 6: 12 7 7 5
483 if (b < 2048 && c < 2048 && d < 256)
484 {
485 rgb_mode = 6;
486 }
487
488 // mode 7: 12 6 7 6
489 if (b < 1024 && c < 2048 && d < 512)
490 {
491 rgb_mode = 7;
492 }
493
494 static const float rgbo_error_scales[6] { 4.0f, 4.0f, 16.0f, 64.0f, 256.0f, 1024.0f };
495 static const float rgb_error_scales[9] { 64.0f, 64.0f, 16.0f, 16.0f, 4.0f, 4.0f, 1.0f, 1.0f, 384.0f };
496
497 float mode7mult = rgbo_error_scales[rgbo_mode] * 0.0015f; // Empirically determined ....
498 float mode11mult = rgb_error_scales[rgb_mode] * 0.010f; // Empirically determined ....
499
500
501 float lum_high = hadd_rgb_s(ep1) * (1.0f / 3.0f);
502 float lum_low = hadd_rgb_s(ep0) * (1.0f / 3.0f);
503 float lumdif = lum_high - lum_low;
504 float mode23mult = lumdif < 960 ? 4.0f : lumdif < 3968 ? 16.0f : 128.0f;
505
506 mode23mult *= 0.0005f; // Empirically determined ....
507
508 // Pick among the available HDR endpoint modes
509 for (int i = QUANT_2; i < QUANT_16; i++)
510 {
511 best_error[i][3] = ERROR_CALC_DEFAULT;
512 best_error[i][2] = ERROR_CALC_DEFAULT;
513 best_error[i][1] = ERROR_CALC_DEFAULT;
514 best_error[i][0] = ERROR_CALC_DEFAULT;
515
516 format_of_choice[i][3] = static_cast<uint8_t>(encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA);
517 format_of_choice[i][2] = FMT_HDR_RGB;
518 format_of_choice[i][1] = FMT_HDR_RGB_SCALE;
519 format_of_choice[i][0] = FMT_HDR_LUMINANCE_LARGE_RANGE;
520 }
521
522 for (int i = QUANT_16; i <= QUANT_256; i++)
523 {
524 // The base_quant_error should depend on the scale-factor that would be used during
525 // actual encode of the color value
526
527 float base_quant_error = baseline_quant_error[i - QUANT_6] * static_cast<float>(partition_size);
528 float rgb_quantization_error = error_weight_rgbsum * base_quant_error * 2.0f;
529 float alpha_quantization_error = error_weight.lane<3>() * base_quant_error * 2.0f;
530 float rgba_quantization_error = rgb_quantization_error + alpha_quantization_error;
531
532 // For 8 integers, we have two encodings: one with HDR A and another one with LDR A
533
534 float full_hdr_rgba_error = rgba_quantization_error + rgb_range_error + alpha_range_error;
535 best_error[i][3] = full_hdr_rgba_error;
536 format_of_choice[i][3] = static_cast<uint8_t>(encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA);
537
538 // For 6 integers, we have one HDR-RGB encoding
539 float full_hdr_rgb_error = (rgb_quantization_error * mode11mult) + rgb_range_error + eci.alpha_drop_error;
540 best_error[i][2] = full_hdr_rgb_error;
541 format_of_choice[i][2] = FMT_HDR_RGB;
542
543 // For 4 integers, we have one HDR-RGB-Scale encoding
544 float hdr_rgb_scale_error = (rgb_quantization_error * mode7mult) + rgb_range_error + eci.alpha_drop_error + eci.rgb_luma_error;
545
546 best_error[i][1] = hdr_rgb_scale_error;
547 format_of_choice[i][1] = FMT_HDR_RGB_SCALE;
548
549 // For 2 integers, we assume luminance-with-large-range
550 float hdr_luminance_error = (rgb_quantization_error * mode23mult) + rgb_range_error + eci.alpha_drop_error + eci.luminance_error;
551 best_error[i][0] = hdr_luminance_error;
552 format_of_choice[i][0] = FMT_HDR_LUMINANCE_LARGE_RANGE;
553 }
554 }
555 else
556 {
557 for (int i = QUANT_2; i < QUANT_6; i++)
558 {
559 best_error[i][3] = ERROR_CALC_DEFAULT;
560 best_error[i][2] = ERROR_CALC_DEFAULT;
561 best_error[i][1] = ERROR_CALC_DEFAULT;
562 best_error[i][0] = ERROR_CALC_DEFAULT;
563
564 format_of_choice[i][3] = FMT_RGBA;
565 format_of_choice[i][2] = FMT_RGB;
566 format_of_choice[i][1] = FMT_RGB_SCALE;
567 format_of_choice[i][0] = FMT_LUMINANCE;
568 }
569
570 float base_quant_error_rgb = error_weight_rgbsum * static_cast<float>(partition_size);
571 float base_quant_error_a = error_weight.lane<3>() * static_cast<float>(partition_size);
572 float base_quant_error_rgba = base_quant_error_rgb + base_quant_error_a;
573
574 float error_scale_bc_rgba = eci.can_blue_contract ? 0.625f : 1.0f;
575 float error_scale_oe_rgba = eci.can_offset_encode ? 0.5f : 1.0f;
576
577 float error_scale_bc_rgb = eci.can_blue_contract ? 0.5f : 1.0f;
578 float error_scale_oe_rgb = eci.can_offset_encode ? 0.25f : 1.0f;
579
580 // Pick among the available LDR endpoint modes
581 for (int i = QUANT_6; i <= QUANT_256; i++)
582 {
583 // Offset encoding not possible at higher quant levels
584 if (i >= QUANT_192)
585 {
586 error_scale_oe_rgba = 1.0f;
587 error_scale_oe_rgb = 1.0f;
588 }
589
590 float base_quant_error = baseline_quant_error[i - QUANT_6];
591 float quant_error_rgb = base_quant_error_rgb * base_quant_error;
592 float quant_error_rgba = base_quant_error_rgba * base_quant_error;
593
594 // 8 integers can encode as RGBA+RGBA
595 float full_ldr_rgba_error = quant_error_rgba
596 * error_scale_bc_rgba
597 * error_scale_oe_rgba
598 + rgb_range_error
599 + alpha_range_error;
600
601 best_error[i][3] = full_ldr_rgba_error;
602 format_of_choice[i][3] = FMT_RGBA;
603
604 // 6 integers can encode as RGB+RGB or RGBS+AA
605 float full_ldr_rgb_error = quant_error_rgb
606 * error_scale_bc_rgb
607 * error_scale_oe_rgb
608 + rgb_range_error
609 + eci.alpha_drop_error;
610
611 float rgbs_alpha_error = quant_error_rgba
612 + eci.rgb_scale_error
613 + rgb_range_error
614 + alpha_range_error;
615
616 if (rgbs_alpha_error < full_ldr_rgb_error)
617 {
618 best_error[i][2] = rgbs_alpha_error;
619 format_of_choice[i][2] = FMT_RGB_SCALE_ALPHA;
620 }
621 else
622 {
623 best_error[i][2] = full_ldr_rgb_error;
624 format_of_choice[i][2] = FMT_RGB;
625 }
626
627 // 4 integers can encode as RGBS or LA+LA
628 float ldr_rgbs_error = quant_error_rgb
629 + rgb_range_error
630 + eci.alpha_drop_error
631 + eci.rgb_scale_error;
632
633 float lum_alpha_error = quant_error_rgba
634 + rgb_range_error
635 + alpha_range_error
636 + eci.luminance_error;
637
638 if (ldr_rgbs_error < lum_alpha_error)
639 {
640 best_error[i][1] = ldr_rgbs_error;
641 format_of_choice[i][1] = FMT_RGB_SCALE;
642 }
643 else
644 {
645 best_error[i][1] = lum_alpha_error;
646 format_of_choice[i][1] = FMT_LUMINANCE_ALPHA;
647 }
648
649 // 2 integers can encode as L+L
650 float luminance_error = quant_error_rgb
651 + rgb_range_error
652 + eci.alpha_drop_error
653 + eci.luminance_error;
654
655 best_error[i][0] = luminance_error;
656 format_of_choice[i][0] = FMT_LUMINANCE;
657 }
658 }
659 }
660
661 /**
662 * @brief For one partition compute the best format and quantization for a given bit count.
663 *
664 * @param best_combined_error The best error for each quant level and integer count.
665 * @param best_combined_format The best format for each quant level and integer count.
666 * @param bits_available The number of bits available for encoding.
667 * @param[out] best_quant_level The output best color quant level.
668 * @param[out] best_format The output best color format.
669 *
670 * @return The output error for the best pairing.
671 */
one_partition_find_best_combination_for_bitcount(QualityProfile privateProfile,const float best_combined_error[21][4],const uint8_t best_combined_format[21][4],int bits_available,uint8_t & best_quant_level,uint8_t & best_format)672 static float one_partition_find_best_combination_for_bitcount(
673 QualityProfile privateProfile,
674 const float best_combined_error[21][4],
675 const uint8_t best_combined_format[21][4],
676 int bits_available,
677 uint8_t& best_quant_level,
678 uint8_t& best_format
679 ) {
680 int best_integer_count = 0;
681 float best_integer_count_error = ERROR_CALC_DEFAULT;
682
683 for (int integer_count = 1; integer_count <= 4; integer_count++)
684 {
685 if (privateProfile != HIGH_QUALITY_PROFILE)
686 {
687 integer_count = 4; // constant 4 bit count for HIGH_SPEED_PROFILE mode
688 }
689 // Compute the quantization level for a given number of integers and a given number of bits
690 int quant_level = quant_mode_table[integer_count][bits_available];
691
692 // Don't have enough bits to represent a given endpoint format at all!
693 if (quant_level < QUANT_6)
694 {
695 continue;
696 }
697
698 float integer_count_error = best_combined_error[quant_level][integer_count - 1];
699 if (integer_count_error < best_integer_count_error)
700 {
701 best_integer_count_error = integer_count_error;
702 best_integer_count = integer_count - 1;
703 }
704 }
705
706 int ql = quant_mode_table[best_integer_count + 1][bits_available];
707
708 best_quant_level = static_cast<uint8_t>(ql);
709 if (privateProfile != HIGH_QUALITY_PROFILE) // keep openSource code style
710 {
711 best_format = FMT_RGBA;
712 }
713 else
714 {
715 best_format = FMT_LUMINANCE;
716
717 if (ql >= QUANT_6)
718 {
719 best_format = best_combined_format[ql][best_integer_count];
720 }
721 }
722
723 return best_integer_count_error;
724 }
725
726 /**
727 * @brief For 2 partitions compute the best format combinations for every pair of quant mode and integer count.
728 *
729 * @param best_error The best error for a single endpoint quant level and integer count.
730 * @param best_format The best format for a single endpoint quant level and integer count.
731 * @param[out] best_combined_error The best combined error pairings for the 2 partitions.
732 * @param[out] best_combined_format The best combined format pairings for the 2 partitions.
733 */
two_partitions_find_best_combination_for_every_quantization_and_integer_count(const float best_error[2][21][4],const uint8_t best_format[2][21][4],float best_combined_error[21][7],uint8_t best_combined_format[21][7][2])734 static void two_partitions_find_best_combination_for_every_quantization_and_integer_count(
735 const float best_error[2][21][4], // indexed by (partition, quant-level, integer-pair-count-minus-1)
736 const uint8_t best_format[2][21][4],
737 float best_combined_error[21][7], // indexed by (quant-level, integer-pair-count-minus-2)
738 uint8_t best_combined_format[21][7][2]
739 ) {
740 for (int i = QUANT_2; i <= QUANT_256; i++)
741 {
742 for (int j = 0; j < 7; j++)
743 {
744 best_combined_error[i][j] = ERROR_CALC_DEFAULT;
745 }
746 }
747
748 for (int quant = QUANT_6; quant <= QUANT_256; quant++)
749 {
750 for (int i = 0; i < 4; i++) // integer-count for first endpoint-pair
751 {
752 for (int j = 0; j < 4; j++) // integer-count for second endpoint-pair
753 {
754 int low2 = astc::min(i, j);
755 int high2 = astc::max(i, j);
756 if ((high2 - low2) > 1)
757 {
758 continue;
759 }
760
761 int intcnt = i + j;
762 float errorterm = astc::min(best_error[0][quant][i] + best_error[1][quant][j], 1e10f);
763 if (errorterm <= best_combined_error[quant][intcnt])
764 {
765 best_combined_error[quant][intcnt] = errorterm;
766 best_combined_format[quant][intcnt][0] = best_format[0][quant][i];
767 best_combined_format[quant][intcnt][1] = best_format[1][quant][j];
768 }
769 }
770 }
771 }
772 }
773
774 /**
775 * @brief For 2 partitions compute the best format and quantization for a given bit count.
776 *
777 * @param best_combined_error The best error for each quant level and integer count.
778 * @param best_combined_format The best format for each quant level and integer count.
779 * @param bits_available The number of bits available for encoding.
780 * @param[out] best_quant_level The output best color quant level.
781 * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available.
782 * @param[out] best_formats The output best color formats.
783 *
784 * @return The output error for the best pairing.
785 */
two_partitions_find_best_combination_for_bitcount(unsigned int privateProfile,float best_combined_error[21][7],uint8_t best_combined_format[21][7][2],int bits_available,uint8_t & best_quant_level,uint8_t & best_quant_level_mod,uint8_t * best_formats)786 static float two_partitions_find_best_combination_for_bitcount(
787 unsigned int privateProfile,
788 float best_combined_error[21][7],
789 uint8_t best_combined_format[21][7][2],
790 int bits_available,
791 uint8_t& best_quant_level,
792 uint8_t& best_quant_level_mod,
793 uint8_t* best_formats
794 ) {
795 int best_integer_count = 0;
796 float best_integer_count_error = ERROR_CALC_DEFAULT;
797 int integer_count = 2;
798 if (privateProfile != HIGH_QUALITY_PROFILE)
799 {
800 integer_count = 8; // constant 8 bit count
801 }
802
803 for (; integer_count <= 8; integer_count++)
804 {
805 // Compute the quantization level for a given number of integers and a given number of bits
806 int quant_level = quant_mode_table[integer_count][bits_available];
807
808 // Don't have enough bits to represent a given endpoint format at all!
809 if (quant_level < QUANT_6)
810 {
811 break;
812 }
813
814 float integer_count_error = best_combined_error[quant_level][integer_count - 2];
815 if (integer_count_error < best_integer_count_error)
816 {
817 best_integer_count_error = integer_count_error;
818 best_integer_count = integer_count;
819 }
820 }
821
822 int ql = quant_mode_table[best_integer_count][bits_available];
823 int ql_mod = quant_mode_table[best_integer_count][bits_available + 2];
824
825 best_quant_level = static_cast<uint8_t>(ql);
826 best_quant_level_mod = static_cast<uint8_t>(ql_mod);
827
828 if (ql >= QUANT_6)
829 {
830 for (int i = 0; i < 2; i++)
831 {
832 best_formats[i] = best_combined_format[ql][best_integer_count - 2][i];
833 }
834 }
835 else
836 {
837 for (int i = 0; i < 2; i++)
838 {
839 best_formats[i] = FMT_LUMINANCE;
840 }
841 }
842
843 return best_integer_count_error;
844 }
845
846 /**
847 * @brief For 3 partitions compute the best format combinations for every pair of quant mode and integer count.
848 *
849 * @param best_error The best error for a single endpoint quant level and integer count.
850 * @param best_format The best format for a single endpoint quant level and integer count.
851 * @param[out] best_combined_error The best combined error pairings for the 3 partitions.
852 * @param[out] best_combined_format The best combined format pairings for the 3 partitions.
853 */
three_partitions_find_best_combination_for_every_quantization_and_integer_count(const float best_error[3][21][4],const uint8_t best_format[3][21][4],float best_combined_error[21][10],uint8_t best_combined_format[21][10][3])854 static void three_partitions_find_best_combination_for_every_quantization_and_integer_count(
855 const float best_error[3][21][4], // indexed by (partition, quant-level, integer-count)
856 const uint8_t best_format[3][21][4],
857 float best_combined_error[21][10],
858 uint8_t best_combined_format[21][10][3]
859 ) {
860 for (int i = QUANT_2; i <= QUANT_256; i++)
861 {
862 for (int j = 0; j < 10; j++)
863 {
864 best_combined_error[i][j] = ERROR_CALC_DEFAULT;
865 }
866 }
867
868 for (int quant = QUANT_6; quant <= QUANT_256; quant++)
869 {
870 for (int i = 0; i < 4; i++) // integer-count for first endpoint-pair
871 {
872 for (int j = 0; j < 4; j++) // integer-count for second endpoint-pair
873 {
874 int low2 = astc::min(i, j);
875 int high2 = astc::max(i, j);
876 if ((high2 - low2) > 1)
877 {
878 continue;
879 }
880
881 for (int k = 0; k < 4; k++) // integer-count for third endpoint-pair
882 {
883 int low3 = astc::min(k, low2);
884 int high3 = astc::max(k, high2);
885 if ((high3 - low3) > 1)
886 {
887 continue;
888 }
889
890 int intcnt = i + j + k;
891 float errorterm = astc::min(best_error[0][quant][i] + best_error[1][quant][j] + best_error[2][quant][k], 1e10f);
892 if (errorterm <= best_combined_error[quant][intcnt])
893 {
894 best_combined_error[quant][intcnt] = errorterm;
895 best_combined_format[quant][intcnt][0] = best_format[0][quant][i];
896 best_combined_format[quant][intcnt][1] = best_format[1][quant][j];
897 best_combined_format[quant][intcnt][2] = best_format[2][quant][k];
898 }
899 }
900 }
901 }
902 }
903 }
904
905 /**
906 * @brief For 3 partitions compute the best format and quantization for a given bit count.
907 *
908 * @param best_combined_error The best error for each quant level and integer count.
909 * @param best_combined_format The best format for each quant level and integer count.
910 * @param bits_available The number of bits available for encoding.
911 * @param[out] best_quant_level The output best color quant level.
912 * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available.
913 * @param[out] best_formats The output best color formats.
914 *
915 * @return The output error for the best pairing.
916 */
three_partitions_find_best_combination_for_bitcount(const float best_combined_error[21][10],const uint8_t best_combined_format[21][10][3],int bits_available,uint8_t & best_quant_level,uint8_t & best_quant_level_mod,uint8_t * best_formats)917 static float three_partitions_find_best_combination_for_bitcount(
918 const float best_combined_error[21][10],
919 const uint8_t best_combined_format[21][10][3],
920 int bits_available,
921 uint8_t& best_quant_level,
922 uint8_t& best_quant_level_mod,
923 uint8_t* best_formats
924 ) {
925 int best_integer_count = 0;
926 float best_integer_count_error = ERROR_CALC_DEFAULT;
927
928 for (int integer_count = 3; integer_count <= 9; integer_count++)
929 {
930 // Compute the quantization level for a given number of integers and a given number of bits
931 int quant_level = quant_mode_table[integer_count][bits_available];
932
933 // Don't have enough bits to represent a given endpoint format at all!
934 if (quant_level < QUANT_6)
935 {
936 break;
937 }
938
939 float integer_count_error = best_combined_error[quant_level][integer_count - 3];
940 if (integer_count_error < best_integer_count_error)
941 {
942 best_integer_count_error = integer_count_error;
943 best_integer_count = integer_count;
944 }
945 }
946
947 int ql = quant_mode_table[best_integer_count][bits_available];
948 int ql_mod = quant_mode_table[best_integer_count][bits_available + 5];
949
950 best_quant_level = static_cast<uint8_t>(ql);
951 best_quant_level_mod = static_cast<uint8_t>(ql_mod);
952
953 if (ql >= QUANT_6)
954 {
955 for (int i = 0; i < 3; i++)
956 {
957 best_formats[i] = best_combined_format[ql][best_integer_count - 3][i];
958 }
959 }
960 else
961 {
962 for (int i = 0; i < 3; i++)
963 {
964 best_formats[i] = FMT_LUMINANCE;
965 }
966 }
967
968 return best_integer_count_error;
969 }
970
971 /**
972 * @brief For 4 partitions compute the best format combinations for every pair of quant mode and integer count.
973 *
974 * @param best_error The best error for a single endpoint quant level and integer count.
975 * @param best_format The best format for a single endpoint quant level and integer count.
976 * @param[out] best_combined_error The best combined error pairings for the 4 partitions.
977 * @param[out] best_combined_format The best combined format pairings for the 4 partitions.
978 */
four_partitions_find_best_combination_for_every_quantization_and_integer_count(const float best_error[4][21][4],const uint8_t best_format[4][21][4],float best_combined_error[21][13],uint8_t best_combined_format[21][13][4])979 static void four_partitions_find_best_combination_for_every_quantization_and_integer_count(
980 const float best_error[4][21][4], // indexed by (partition, quant-level, integer-count)
981 const uint8_t best_format[4][21][4],
982 float best_combined_error[21][13],
983 uint8_t best_combined_format[21][13][4]
984 ) {
985 for (int i = QUANT_2; i <= QUANT_256; i++)
986 {
987 for (int j = 0; j < 13; j++)
988 {
989 best_combined_error[i][j] = ERROR_CALC_DEFAULT;
990 }
991 }
992
993 for (int quant = QUANT_6; quant <= QUANT_256; quant++)
994 {
995 for (int i = 0; i < 4; i++) // integer-count for first endpoint-pair
996 {
997 for (int j = 0; j < 4; j++) // integer-count for second endpoint-pair
998 {
999 int low2 = astc::min(i, j);
1000 int high2 = astc::max(i, j);
1001 if ((high2 - low2) > 1)
1002 {
1003 continue;
1004 }
1005
1006 for (int k = 0; k < 4; k++) // integer-count for third endpoint-pair
1007 {
1008 int low3 = astc::min(k, low2);
1009 int high3 = astc::max(k, high2);
1010 if ((high3 - low3) > 1)
1011 {
1012 continue;
1013 }
1014
1015 for (int l = 0; l < 4; l++) // integer-count for fourth endpoint-pair
1016 {
1017 int low4 = astc::min(l, low3);
1018 int high4 = astc::max(l, high3);
1019 if ((high4 - low4) > 1)
1020 {
1021 continue;
1022 }
1023
1024 int intcnt = i + j + k + l;
1025 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);
1026 if (errorterm <= best_combined_error[quant][intcnt])
1027 {
1028 best_combined_error[quant][intcnt] = errorterm;
1029 best_combined_format[quant][intcnt][0] = best_format[0][quant][i];
1030 best_combined_format[quant][intcnt][1] = best_format[1][quant][j];
1031 best_combined_format[quant][intcnt][2] = best_format[2][quant][k];
1032 best_combined_format[quant][intcnt][3] = best_format[3][quant][l];
1033 }
1034 }
1035 }
1036 }
1037 }
1038 }
1039 }
1040
1041 /**
1042 * @brief For 4 partitions compute the best format and quantization for a given bit count.
1043 *
1044 * @param best_combined_error The best error for each quant level and integer count.
1045 * @param best_combined_format The best format for each quant level and integer count.
1046 * @param bits_available The number of bits available for encoding.
1047 * @param[out] best_quant_level The output best color quant level.
1048 * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available.
1049 * @param[out] best_formats The output best color formats.
1050 *
1051 * @return best_error The output error for the best pairing.
1052 */
four_partitions_find_best_combination_for_bitcount(const float best_combined_error[21][13],const uint8_t best_combined_format[21][13][4],int bits_available,uint8_t & best_quant_level,uint8_t & best_quant_level_mod,uint8_t * best_formats)1053 static float four_partitions_find_best_combination_for_bitcount(
1054 const float best_combined_error[21][13],
1055 const uint8_t best_combined_format[21][13][4],
1056 int bits_available,
1057 uint8_t& best_quant_level,
1058 uint8_t& best_quant_level_mod,
1059 uint8_t* best_formats
1060 ) {
1061 int best_integer_count = 0;
1062 float best_integer_count_error = ERROR_CALC_DEFAULT;
1063
1064 for (int integer_count = 4; integer_count <= 9; integer_count++)
1065 {
1066 // Compute the quantization level for a given number of integers and a given number of bits
1067 int quant_level = quant_mode_table[integer_count][bits_available];
1068
1069 // Don't have enough bits to represent a given endpoint format at all!
1070 if (quant_level < QUANT_6)
1071 {
1072 break;
1073 }
1074
1075 float integer_count_error = best_combined_error[quant_level][integer_count - 4];
1076 if (integer_count_error < best_integer_count_error)
1077 {
1078 best_integer_count_error = integer_count_error;
1079 best_integer_count = integer_count;
1080 }
1081 }
1082
1083 int ql = quant_mode_table[best_integer_count][bits_available];
1084 int ql_mod = quant_mode_table[best_integer_count][bits_available + 8];
1085
1086 best_quant_level = static_cast<uint8_t>(ql);
1087 best_quant_level_mod = static_cast<uint8_t>(ql_mod);
1088
1089 if (ql >= QUANT_6)
1090 {
1091 for (int i = 0; i < 4; i++)
1092 {
1093 best_formats[i] = best_combined_format[ql][best_integer_count - 4][i];
1094 }
1095 }
1096 else
1097 {
1098 for (int i = 0; i < 4; i++)
1099 {
1100 best_formats[i] = FMT_LUMINANCE;
1101 }
1102 }
1103
1104 return best_integer_count_error;
1105 }
1106
1107 /* See header for documentation. */
compute_ideal_endpoint_formats(QualityProfile privateProfile,const partition_info & pi,const image_block & blk,const endpoints & ep,const int8_t * qwt_bitcounts,const float * qwt_errors,unsigned int tune_candidate_limit,unsigned int start_block_mode,unsigned int end_block_mode,uint8_t partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS],int block_mode[TUNE_MAX_TRIAL_CANDIDATES],quant_method quant_level[TUNE_MAX_TRIAL_CANDIDATES],quant_method quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES],compression_working_buffers & tmpbuf)1108 unsigned int compute_ideal_endpoint_formats(
1109 QualityProfile privateProfile,
1110 const partition_info& pi,
1111 const image_block& blk,
1112 const endpoints& ep,
1113 // bitcounts and errors computed for the various quantization methods
1114 const int8_t* qwt_bitcounts,
1115 const float* qwt_errors,
1116 unsigned int tune_candidate_limit,
1117 unsigned int start_block_mode,
1118 unsigned int end_block_mode,
1119 // output data
1120 uint8_t partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS],
1121 int block_mode[TUNE_MAX_TRIAL_CANDIDATES],
1122 quant_method quant_level[TUNE_MAX_TRIAL_CANDIDATES],
1123 quant_method quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES],
1124 compression_working_buffers& tmpbuf
1125 ) {
1126 int partition_count = pi.partition_count;
1127
1128 promise(partition_count > 0);
1129
1130 bool encode_hdr_rgb = static_cast<bool>(blk.rgb_lns[0]);
1131 bool encode_hdr_alpha = static_cast<bool>(blk.alpha_lns[0]);
1132
1133 // Compute the errors that result from various encoding choices (such as using luminance instead
1134 // of RGB, discarding Alpha, using RGB-scale in place of two separate RGB endpoints and so on)
1135 encoding_choice_errors eci[BLOCK_MAX_PARTITIONS];
1136 compute_encoding_choice_errors(blk, pi, ep, eci);
1137
1138 float best_error[BLOCK_MAX_PARTITIONS][21][4];
1139 uint8_t format_of_choice[BLOCK_MAX_PARTITIONS][21][4];
1140 for (int i = 0; i < partition_count; i++)
1141 {
1142 compute_color_error_for_every_integer_count_and_quant_level(
1143 encode_hdr_rgb, encode_hdr_alpha, i,
1144 pi, eci[i], ep, blk.channel_weight, best_error[i],
1145 format_of_choice[i]);
1146 }
1147
1148 float* errors_of_best_combination = tmpbuf.errors_of_best_combination;
1149 uint8_t* best_quant_levels = tmpbuf.best_quant_levels;
1150 uint8_t* best_quant_levels_mod = tmpbuf.best_quant_levels_mod;
1151 uint8_t (&best_ep_formats)[WEIGHTS_MAX_BLOCK_MODES][BLOCK_MAX_PARTITIONS] = tmpbuf.best_ep_formats;
1152
1153 // Ensure that the first iteration understep contains data that will never be picked
1154 vfloat clear_error(ERROR_CALC_DEFAULT);
1155 vint clear_quant(0);
1156
1157 unsigned int packed_start_block_mode = round_down_to_simd_multiple_vla(start_block_mode);
1158 storea(clear_error, errors_of_best_combination + packed_start_block_mode);
1159 store_nbytes(clear_quant, best_quant_levels + packed_start_block_mode);
1160 store_nbytes(clear_quant, best_quant_levels_mod + packed_start_block_mode);
1161
1162 // Ensure that last iteration overstep contains data that will never be picked
1163 unsigned int packed_end_block_mode = round_down_to_simd_multiple_vla(end_block_mode - 1);
1164 storea(clear_error, errors_of_best_combination + packed_end_block_mode);
1165 store_nbytes(clear_quant, best_quant_levels + packed_end_block_mode);
1166 store_nbytes(clear_quant, best_quant_levels_mod + packed_end_block_mode);
1167
1168 // Track a scalar best to avoid expensive search at least once ...
1169 float error_of_best_combination = ERROR_CALC_DEFAULT;
1170 int index_of_best_combination = -1;
1171
1172 // The block contains 1 partition
1173 if (partition_count == 1)
1174 {
1175 for (unsigned int i = start_block_mode; i < end_block_mode; i++)
1176 {
1177 if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
1178 {
1179 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1180 continue;
1181 }
1182
1183 float error_of_best = one_partition_find_best_combination_for_bitcount(
1184 privateProfile,
1185 best_error[0], format_of_choice[0], qwt_bitcounts[i],
1186 best_quant_levels[i], best_ep_formats[i][0]);
1187
1188 float total_error = error_of_best + qwt_errors[i];
1189 errors_of_best_combination[i] = total_error;
1190 best_quant_levels_mod[i] = best_quant_levels[i];
1191
1192 if (total_error < error_of_best_combination)
1193 {
1194 error_of_best_combination = total_error;
1195 index_of_best_combination = i;
1196 }
1197 }
1198 }
1199 // The block contains 2 partitions
1200 else if (partition_count == 2)
1201 {
1202 float combined_best_error[21][7];
1203 uint8_t formats_of_choice[21][7][2];
1204
1205 two_partitions_find_best_combination_for_every_quantization_and_integer_count(
1206 best_error, format_of_choice, combined_best_error, formats_of_choice);
1207
1208 assert(start_block_mode == 0);
1209 for (unsigned int i = 0; i < end_block_mode; i++)
1210 {
1211 if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
1212 {
1213 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1214 continue;
1215 }
1216
1217 float error_of_best = two_partitions_find_best_combination_for_bitcount(
1218 privateProfile,
1219 combined_best_error, formats_of_choice, qwt_bitcounts[i],
1220 best_quant_levels[i], best_quant_levels_mod[i],
1221 best_ep_formats[i]);
1222
1223 float total_error = error_of_best + qwt_errors[i];
1224 errors_of_best_combination[i] = total_error;
1225
1226 if (total_error < error_of_best_combination)
1227 {
1228 error_of_best_combination = total_error;
1229 index_of_best_combination = i;
1230 }
1231 }
1232 }
1233 // The block contains 3 partitions
1234 else if (partition_count == 3)
1235 {
1236 float combined_best_error[21][10];
1237 uint8_t formats_of_choice[21][10][3];
1238
1239 three_partitions_find_best_combination_for_every_quantization_and_integer_count(
1240 best_error, format_of_choice, combined_best_error, formats_of_choice);
1241
1242 assert(start_block_mode == 0);
1243 for (unsigned int i = 0; i < end_block_mode; i++)
1244 {
1245 if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
1246 {
1247 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1248 continue;
1249 }
1250
1251 float error_of_best = three_partitions_find_best_combination_for_bitcount(
1252 combined_best_error, formats_of_choice, qwt_bitcounts[i],
1253 best_quant_levels[i], best_quant_levels_mod[i],
1254 best_ep_formats[i]);
1255
1256 float total_error = error_of_best + qwt_errors[i];
1257 errors_of_best_combination[i] = total_error;
1258
1259 if (total_error < error_of_best_combination)
1260 {
1261 error_of_best_combination = total_error;
1262 index_of_best_combination = i;
1263 }
1264 }
1265 }
1266 // The block contains 4 partitions
1267 else // if (partition_count == 4)
1268 {
1269 assert(partition_count == 4);
1270 float combined_best_error[21][13];
1271 uint8_t formats_of_choice[21][13][4];
1272
1273 four_partitions_find_best_combination_for_every_quantization_and_integer_count(
1274 best_error, format_of_choice, combined_best_error, formats_of_choice);
1275
1276 assert(start_block_mode == 0);
1277 for (unsigned int i = 0; i < end_block_mode; i++)
1278 {
1279 if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
1280 {
1281 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1282 continue;
1283 }
1284
1285 float error_of_best = four_partitions_find_best_combination_for_bitcount(
1286 combined_best_error, formats_of_choice, qwt_bitcounts[i],
1287 best_quant_levels[i], best_quant_levels_mod[i],
1288 best_ep_formats[i]);
1289
1290 float total_error = error_of_best + qwt_errors[i];
1291 errors_of_best_combination[i] = total_error;
1292
1293 if (total_error < error_of_best_combination)
1294 {
1295 error_of_best_combination = total_error;
1296 index_of_best_combination = i;
1297 }
1298 }
1299 }
1300
1301 int best_error_weights[TUNE_MAX_TRIAL_CANDIDATES];
1302
1303 // Fast path the first result and avoid the list search for trial 0
1304 best_error_weights[0] = index_of_best_combination;
1305 if (index_of_best_combination >= 0)
1306 {
1307 errors_of_best_combination[index_of_best_combination] = ERROR_CALC_DEFAULT;
1308 }
1309
1310 // Search the remaining results and pick the best candidate modes for trial 1+
1311 for (unsigned int i = 1; i < tune_candidate_limit; i++)
1312 {
1313 vint vbest_error_index(-1);
1314 vfloat vbest_ep_error(ERROR_CALC_DEFAULT);
1315
1316 start_block_mode = round_down_to_simd_multiple_vla(start_block_mode);
1317 vint lane_ids = vint::lane_id() + vint(start_block_mode);
1318 for (unsigned int j = start_block_mode; j < end_block_mode; j += ASTCENC_SIMD_WIDTH)
1319 {
1320 vfloat err = vfloat(errors_of_best_combination + j);
1321 vmask mask = err < vbest_ep_error;
1322 vbest_ep_error = select(vbest_ep_error, err, mask);
1323 vbest_error_index = select(vbest_error_index, lane_ids, mask);
1324 lane_ids += vint(ASTCENC_SIMD_WIDTH);
1325 }
1326
1327 // Pick best mode from the SIMD result, using lowest matching index to ensure invariance
1328 vmask lanes_min_error = vbest_ep_error == hmin(vbest_ep_error);
1329 vbest_error_index = select(vint(0x7FFFFFFF), vbest_error_index, lanes_min_error);
1330 vbest_error_index = hmin(vbest_error_index);
1331 int best_error_index = vbest_error_index.lane<0>();
1332
1333 best_error_weights[i] = best_error_index;
1334
1335 // Max the error for this candidate so we don't pick it again
1336 if (best_error_index >= 0)
1337 {
1338 errors_of_best_combination[best_error_index] = ERROR_CALC_DEFAULT;
1339 }
1340 // Early-out if no more candidates are valid
1341 else
1342 {
1343 break;
1344 }
1345 }
1346
1347 for (unsigned int i = 0; i < tune_candidate_limit; i++)
1348 {
1349 if (best_error_weights[i] < 0)
1350 {
1351 return i;
1352 }
1353
1354 block_mode[i] = best_error_weights[i];
1355
1356 quant_level[i] = static_cast<quant_method>(best_quant_levels[best_error_weights[i]]);
1357 quant_level_mod[i] = static_cast<quant_method>(best_quant_levels_mod[best_error_weights[i]]);
1358
1359 assert(quant_level[i] >= QUANT_6 && quant_level[i] <= QUANT_256);
1360 assert(quant_level_mod[i] >= QUANT_6 && quant_level_mod[i] <= QUANT_256);
1361
1362 for (int j = 0; j < partition_count; j++)
1363 {
1364 partition_format_specifiers[i][j] = best_ep_formats[best_error_weights[i]][j];
1365 }
1366 }
1367
1368 return tune_candidate_limit;
1369 }
1370
1371 #endif
1372