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] {
329 (65536.0f * 65536.0f / 18.0f), // 2 values, 1 step
330 (65536.0f * 65536.0f / 18.0f) / (2 * 2), // 3 values, 2 steps
331 (65536.0f * 65536.0f / 18.0f) / (3 * 3), // 4 values, 3 steps
332 (65536.0f * 65536.0f / 18.0f) / (4 * 4), // 5 values
333 (65536.0f * 65536.0f / 18.0f) / (5 * 5),
334 (65536.0f * 65536.0f / 18.0f) / (7 * 7),
335 (65536.0f * 65536.0f / 18.0f) / (9 * 9),
336 (65536.0f * 65536.0f / 18.0f) / (11 * 11),
337 (65536.0f * 65536.0f / 18.0f) / (15 * 15),
338 (65536.0f * 65536.0f / 18.0f) / (19 * 19),
339 (65536.0f * 65536.0f / 18.0f) / (23 * 23),
340 (65536.0f * 65536.0f / 18.0f) / (31 * 31),
341 (65536.0f * 65536.0f / 18.0f) / (39 * 39),
342 (65536.0f * 65536.0f / 18.0f) / (47 * 47),
343 (65536.0f * 65536.0f / 18.0f) / (63 * 63),
344 (65536.0f * 65536.0f / 18.0f) / (79 * 79),
345 (65536.0f * 65536.0f / 18.0f) / (95 * 95),
346 (65536.0f * 65536.0f / 18.0f) / (127 * 127),
347 (65536.0f * 65536.0f / 18.0f) / (159 * 159),
348 (65536.0f * 65536.0f / 18.0f) / (191 * 191),
349 (65536.0f * 65536.0f / 18.0f) / (255 * 255)
350 };
351
352 vfloat4 ep0 = ep.endpt0[partition_index];
353 vfloat4 ep1 = ep.endpt1[partition_index];
354
355 float ep1_min = hmin_rgb_s(ep1);
356 ep1_min = astc::max(ep1_min, 0.0f);
357
358 float error_weight_rgbsum = hadd_rgb_s(error_weight);
359
360 float range_upper_limit_rgb = encode_hdr_rgb ? 61440.0f : 65535.0f;
361 float range_upper_limit_alpha = encode_hdr_alpha ? 61440.0f : 65535.0f;
362
363 // It is possible to get endpoint colors significantly outside [0,upper-limit] even if the
364 // input data are safely contained in [0,upper-limit]; we need to add an error term for this
365 vfloat4 offset(range_upper_limit_rgb, range_upper_limit_rgb, range_upper_limit_rgb, range_upper_limit_alpha);
366 vfloat4 ep0_range_error_high = max(ep0 - offset, 0.0f);
367 vfloat4 ep1_range_error_high = max(ep1 - offset, 0.0f);
368
369 vfloat4 ep0_range_error_low = min(ep0, 0.0f);
370 vfloat4 ep1_range_error_low = min(ep1, 0.0f);
371
372 vfloat4 sum_range_error =
373 (ep0_range_error_low * ep0_range_error_low) +
374 (ep1_range_error_low * ep1_range_error_low) +
375 (ep0_range_error_high * ep0_range_error_high) +
376 (ep1_range_error_high * ep1_range_error_high);
377
378 float rgb_range_error = dot3_s(sum_range_error, error_weight)
379 * 0.5f * static_cast<float>(partition_size);
380 float alpha_range_error = sum_range_error.lane<3>() * error_weight.lane<3>()
381 * 0.5f * static_cast<float>(partition_size);
382
383 if (encode_hdr_rgb)
384 {
385
386 // Collect some statistics
387 float af, cf;
388 if (ep1.lane<0>() > ep1.lane<1>() && ep1.lane<0>() > ep1.lane<2>())
389 {
390 af = ep1.lane<0>();
391 cf = ep1.lane<0>() - ep0.lane<0>();
392 }
393 else if (ep1.lane<1>() > ep1.lane<2>())
394 {
395 af = ep1.lane<1>();
396 cf = ep1.lane<1>() - ep0.lane<1>();
397 }
398 else
399 {
400 af = ep1.lane<2>();
401 cf = ep1.lane<2>() - ep0.lane<2>();
402 }
403
404 // Estimate of color-component spread in high endpoint color
405 float bf = af - ep1_min;
406 vfloat4 prd = (ep1 - vfloat4(cf)).swz<0, 1, 2>();
407 vfloat4 pdif = prd - ep0.swz<0, 1, 2>();
408 // Estimate of color-component spread in low endpoint color
409 float df = hmax_s(abs(pdif));
410
411 int b = static_cast<int>(bf);
412 int c = static_cast<int>(cf);
413 int d = static_cast<int>(df);
414
415 // Determine which one of the 6 submodes is likely to be used in case of an RGBO-mode
416 int rgbo_mode = 5; // 7 bits per component
417 // mode 4: 8 7 6
418 if (b < 32768 && c < 16384)
419 {
420 rgbo_mode = 4;
421 }
422
423 // mode 3: 9 6 7
424 if (b < 8192 && c < 16384)
425 {
426 rgbo_mode = 3;
427 }
428
429 // mode 2: 10 5 8
430 if (b < 2048 && c < 16384)
431 {
432 rgbo_mode = 2;
433 }
434
435 // mode 1: 11 6 5
436 if (b < 2048 && c < 1024)
437 {
438 rgbo_mode = 1;
439 }
440
441 // mode 0: 11 5 7
442 if (b < 1024 && c < 4096)
443 {
444 rgbo_mode = 0;
445 }
446
447 // Determine which one of the 9 submodes is likely to be used in case of an RGB-mode.
448 int rgb_mode = 8; // 8 bits per component, except 7 bits for blue
449
450 // mode 0: 9 7 6 7
451 if (b < 16384 && c < 8192 && d < 8192)
452 {
453 rgb_mode = 0;
454 }
455
456 // mode 1: 9 8 6 6
457 if (b < 32768 && c < 8192 && d < 4096)
458 {
459 rgb_mode = 1;
460 }
461
462 // mode 2: 10 6 7 7
463 if (b < 4096 && c < 8192 && d < 4096)
464 {
465 rgb_mode = 2;
466 }
467
468 // mode 3: 10 7 7 6
469 if (b < 8192 && c < 8192 && d < 2048)
470 {
471 rgb_mode = 3;
472 }
473
474 // mode 4: 11 8 6 5
475 if (b < 8192 && c < 2048 && d < 512)
476 {
477 rgb_mode = 4;
478 }
479
480 // mode 5: 11 6 8 6
481 if (b < 2048 && c < 8192 && d < 1024)
482 {
483 rgb_mode = 5;
484 }
485
486 // mode 6: 12 7 7 5
487 if (b < 2048 && c < 2048 && d < 256)
488 {
489 rgb_mode = 6;
490 }
491
492 // mode 7: 12 6 7 6
493 if (b < 1024 && c < 2048 && d < 512)
494 {
495 rgb_mode = 7;
496 }
497
498 static const float rgbo_error_scales[6] { 4.0f, 4.0f, 16.0f, 64.0f, 256.0f, 1024.0f };
499 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 };
500
501 float mode7mult = rgbo_error_scales[rgbo_mode] * 0.0015f; // Empirically determined ....
502 float mode11mult = rgb_error_scales[rgb_mode] * 0.010f; // Empirically determined ....
503
504
505 float lum_high = hadd_rgb_s(ep1) * (1.0f / 3.0f);
506 float lum_low = hadd_rgb_s(ep0) * (1.0f / 3.0f);
507 float lumdif = lum_high - lum_low;
508 float mode23mult = lumdif < 960 ? 4.0f : lumdif < 3968 ? 16.0f : 128.0f;
509
510 mode23mult *= 0.0005f; // Empirically determined ....
511
512 // Pick among the available HDR endpoint modes
513 for (int i = QUANT_2; i < QUANT_16; i++)
514 {
515 best_error[i][3] = ERROR_CALC_DEFAULT;
516 best_error[i][2] = ERROR_CALC_DEFAULT;
517 best_error[i][1] = ERROR_CALC_DEFAULT;
518 best_error[i][0] = ERROR_CALC_DEFAULT;
519
520 format_of_choice[i][3] = static_cast<uint8_t>(encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA);
521 format_of_choice[i][2] = FMT_HDR_RGB;
522 format_of_choice[i][1] = FMT_HDR_RGB_SCALE;
523 format_of_choice[i][0] = FMT_HDR_LUMINANCE_LARGE_RANGE;
524 }
525
526 for (int i = QUANT_16; i <= QUANT_256; i++)
527 {
528 // The base_quant_error should depend on the scale-factor that would be used during
529 // actual encode of the color value
530
531 float base_quant_error = baseline_quant_error[i] * static_cast<float>(partition_size);
532 float rgb_quantization_error = error_weight_rgbsum * base_quant_error * 2.0f;
533 float alpha_quantization_error = error_weight.lane<3>() * base_quant_error * 2.0f;
534 float rgba_quantization_error = rgb_quantization_error + alpha_quantization_error;
535
536 // For 8 integers, we have two encodings: one with HDR A and another one with LDR A
537
538 float full_hdr_rgba_error = rgba_quantization_error + rgb_range_error + alpha_range_error;
539 best_error[i][3] = full_hdr_rgba_error;
540 format_of_choice[i][3] = static_cast<uint8_t>(encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA);
541
542 // For 6 integers, we have one HDR-RGB encoding
543 float full_hdr_rgb_error = (rgb_quantization_error * mode11mult) + rgb_range_error + eci.alpha_drop_error;
544 best_error[i][2] = full_hdr_rgb_error;
545 format_of_choice[i][2] = FMT_HDR_RGB;
546
547 // For 4 integers, we have one HDR-RGB-Scale encoding
548 float hdr_rgb_scale_error = (rgb_quantization_error * mode7mult) + rgb_range_error + eci.alpha_drop_error + eci.rgb_luma_error;
549
550 best_error[i][1] = hdr_rgb_scale_error;
551 format_of_choice[i][1] = FMT_HDR_RGB_SCALE;
552
553 // For 2 integers, we assume luminance-with-large-range
554 float hdr_luminance_error = (rgb_quantization_error * mode23mult) + rgb_range_error + eci.alpha_drop_error + eci.luminance_error;
555 best_error[i][0] = hdr_luminance_error;
556 format_of_choice[i][0] = FMT_HDR_LUMINANCE_LARGE_RANGE;
557 }
558 }
559 else
560 {
561 for (int i = QUANT_2; i < QUANT_6; i++)
562 {
563 best_error[i][3] = ERROR_CALC_DEFAULT;
564 best_error[i][2] = ERROR_CALC_DEFAULT;
565 best_error[i][1] = ERROR_CALC_DEFAULT;
566 best_error[i][0] = ERROR_CALC_DEFAULT;
567
568 format_of_choice[i][3] = FMT_RGBA;
569 format_of_choice[i][2] = FMT_RGB;
570 format_of_choice[i][1] = FMT_RGB_SCALE;
571 format_of_choice[i][0] = FMT_LUMINANCE;
572 }
573
574 float base_quant_error_rgb = error_weight_rgbsum * static_cast<float>(partition_size);
575 float base_quant_error_a = error_weight.lane<3>() * static_cast<float>(partition_size);
576 float base_quant_error_rgba = base_quant_error_rgb + base_quant_error_a;
577
578 float error_scale_bc_rgba = eci.can_blue_contract ? 0.625f : 1.0f;
579 float error_scale_oe_rgba = eci.can_offset_encode ? 0.5f : 1.0f;
580
581 float error_scale_bc_rgb = eci.can_blue_contract ? 0.5f : 1.0f;
582 float error_scale_oe_rgb = eci.can_offset_encode ? 0.25f : 1.0f;
583
584 // Pick among the available LDR endpoint modes
585 for (int i = QUANT_6; i <= QUANT_256; i++)
586 {
587 // Offset encoding not possible at higher quant levels
588 if (i >= QUANT_192)
589 {
590 error_scale_oe_rgba = 1.0f;
591 error_scale_oe_rgb = 1.0f;
592 }
593
594 float base_quant_error = baseline_quant_error[i];
595 float quant_error_rgb = base_quant_error_rgb * base_quant_error;
596 float quant_error_rgba = base_quant_error_rgba * base_quant_error;
597
598 // 8 integers can encode as RGBA+RGBA
599 float full_ldr_rgba_error = quant_error_rgba
600 * error_scale_bc_rgba
601 * error_scale_oe_rgba
602 + rgb_range_error
603 + alpha_range_error;
604
605 best_error[i][3] = full_ldr_rgba_error;
606 format_of_choice[i][3] = FMT_RGBA;
607
608 // 6 integers can encode as RGB+RGB or RGBS+AA
609 float full_ldr_rgb_error = quant_error_rgb
610 * error_scale_bc_rgb
611 * error_scale_oe_rgb
612 + rgb_range_error
613 + eci.alpha_drop_error;
614
615 float rgbs_alpha_error = quant_error_rgba
616 + eci.rgb_scale_error
617 + rgb_range_error
618 + alpha_range_error;
619
620 if (rgbs_alpha_error < full_ldr_rgb_error)
621 {
622 best_error[i][2] = rgbs_alpha_error;
623 format_of_choice[i][2] = FMT_RGB_SCALE_ALPHA;
624 }
625 else
626 {
627 best_error[i][2] = full_ldr_rgb_error;
628 format_of_choice[i][2] = FMT_RGB;
629 }
630
631 // 4 integers can encode as RGBS or LA+LA
632 float ldr_rgbs_error = quant_error_rgb
633 + rgb_range_error
634 + eci.alpha_drop_error
635 + eci.rgb_scale_error;
636
637 float lum_alpha_error = quant_error_rgba
638 + rgb_range_error
639 + alpha_range_error
640 + eci.luminance_error;
641
642 if (ldr_rgbs_error < lum_alpha_error)
643 {
644 best_error[i][1] = ldr_rgbs_error;
645 format_of_choice[i][1] = FMT_RGB_SCALE;
646 }
647 else
648 {
649 best_error[i][1] = lum_alpha_error;
650 format_of_choice[i][1] = FMT_LUMINANCE_ALPHA;
651 }
652
653 // 2 integers can encode as L+L
654 float luminance_error = quant_error_rgb
655 + rgb_range_error
656 + eci.alpha_drop_error
657 + eci.luminance_error;
658
659 best_error[i][0] = luminance_error;
660 format_of_choice[i][0] = FMT_LUMINANCE;
661 }
662 }
663 }
664
665 /**
666 * @brief For one partition compute the best format and quantization for a given bit count.
667 *
668 * @param best_combined_error The best error for each quant level and integer count.
669 * @param best_combined_format The best format for each quant level and integer count.
670 * @param bits_available The number of bits available for encoding.
671 * @param[out] best_quant_level The output best color quant level.
672 * @param[out] best_format The output best color format.
673 *
674 * @return The output error for the best pairing.
675 */
one_partition_find_best_combination_for_bitcount(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)676 static float one_partition_find_best_combination_for_bitcount(
677 const float best_combined_error[21][4],
678 const uint8_t best_combined_format[21][4],
679 int bits_available,
680 uint8_t& best_quant_level,
681 uint8_t& best_format
682 ) {
683 int best_integer_count = 0;
684 float best_integer_count_error = ERROR_CALC_DEFAULT;
685
686 for (int integer_count = 1; integer_count <= 4; integer_count++)
687 {
688 // Compute the quantization level for a given number of integers and a given number of bits
689 int quant_level = quant_mode_table[integer_count][bits_available];
690
691 // Don't have enough bits to represent a given endpoint format at all!
692 if (quant_level < QUANT_6)
693 {
694 continue;
695 }
696
697 float integer_count_error = best_combined_error[quant_level][integer_count - 1];
698 if (integer_count_error < best_integer_count_error)
699 {
700 best_integer_count_error = integer_count_error;
701 best_integer_count = integer_count - 1;
702 }
703 }
704
705 int ql = quant_mode_table[best_integer_count + 1][bits_available];
706
707 best_quant_level = static_cast<uint8_t>(ql);
708 best_format = FMT_LUMINANCE;
709
710 if (ql >= QUANT_6)
711 {
712 best_format = best_combined_format[ql][best_integer_count];
713 }
714
715 return best_integer_count_error;
716 }
717
718 /**
719 * @brief For 2 partitions compute the best format combinations for every pair of quant mode and integer count.
720 *
721 * @param best_error The best error for a single endpoint quant level and integer count.
722 * @param best_format The best format for a single endpoint quant level and integer count.
723 * @param[out] best_combined_error The best combined error pairings for the 2 partitions.
724 * @param[out] best_combined_format The best combined format pairings for the 2 partitions.
725 */
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])726 static void two_partitions_find_best_combination_for_every_quantization_and_integer_count(
727 const float best_error[2][21][4], // indexed by (partition, quant-level, integer-pair-count-minus-1)
728 const uint8_t best_format[2][21][4],
729 float best_combined_error[21][7], // indexed by (quant-level, integer-pair-count-minus-2)
730 uint8_t best_combined_format[21][7][2]
731 ) {
732 for (int i = QUANT_2; i <= QUANT_256; i++)
733 {
734 for (int j = 0; j < 7; j++)
735 {
736 best_combined_error[i][j] = ERROR_CALC_DEFAULT;
737 }
738 }
739
740 for (int quant = QUANT_6; quant <= QUANT_256; quant++)
741 {
742 for (int i = 0; i < 4; i++) // integer-count for first endpoint-pair
743 {
744 for (int j = 0; j < 4; j++) // integer-count for second endpoint-pair
745 {
746 int low2 = astc::min(i, j);
747 int high2 = astc::max(i, j);
748 if ((high2 - low2) > 1)
749 {
750 continue;
751 }
752
753 int intcnt = i + j;
754 float errorterm = astc::min(best_error[0][quant][i] + best_error[1][quant][j], 1e10f);
755 if (errorterm <= best_combined_error[quant][intcnt])
756 {
757 best_combined_error[quant][intcnt] = errorterm;
758 best_combined_format[quant][intcnt][0] = best_format[0][quant][i];
759 best_combined_format[quant][intcnt][1] = best_format[1][quant][j];
760 }
761 }
762 }
763 }
764 }
765
766 /**
767 * @brief For 2 partitions compute the best format and quantization for a given bit count.
768 *
769 * @param best_combined_error The best error for each quant level and integer count.
770 * @param best_combined_format The best format for each quant level and integer count.
771 * @param bits_available The number of bits available for encoding.
772 * @param[out] best_quant_level The output best color quant level.
773 * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available.
774 * @param[out] best_formats The output best color formats.
775 *
776 * @return The output error for the best pairing.
777 */
two_partitions_find_best_combination_for_bitcount(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)778 static float two_partitions_find_best_combination_for_bitcount(
779 float best_combined_error[21][7],
780 uint8_t best_combined_format[21][7][2],
781 int bits_available,
782 uint8_t& best_quant_level,
783 uint8_t& best_quant_level_mod,
784 uint8_t* best_formats
785 ) {
786 int best_integer_count = 0;
787 float best_integer_count_error = ERROR_CALC_DEFAULT;
788
789 for (int integer_count = 2; integer_count <= 8; integer_count++)
790 {
791 // Compute the quantization level for a given number of integers and a given number of bits
792 int quant_level = quant_mode_table[integer_count][bits_available];
793
794 // Don't have enough bits to represent a given endpoint format at all!
795 if (quant_level < QUANT_6)
796 {
797 break;
798 }
799
800 float integer_count_error = best_combined_error[quant_level][integer_count - 2];
801 if (integer_count_error < best_integer_count_error)
802 {
803 best_integer_count_error = integer_count_error;
804 best_integer_count = integer_count;
805 }
806 }
807
808 int ql = quant_mode_table[best_integer_count][bits_available];
809 int ql_mod = quant_mode_table[best_integer_count][bits_available + 2];
810
811 best_quant_level = static_cast<uint8_t>(ql);
812 best_quant_level_mod = static_cast<uint8_t>(ql_mod);
813
814 if (ql >= QUANT_6)
815 {
816 for (int i = 0; i < 2; i++)
817 {
818 best_formats[i] = best_combined_format[ql][best_integer_count - 2][i];
819 }
820 }
821 else
822 {
823 for (int i = 0; i < 2; i++)
824 {
825 best_formats[i] = FMT_LUMINANCE;
826 }
827 }
828
829 return best_integer_count_error;
830 }
831
832 /**
833 * @brief For 3 partitions compute the best format combinations for every pair of quant mode and integer count.
834 *
835 * @param best_error The best error for a single endpoint quant level and integer count.
836 * @param best_format The best format for a single endpoint quant level and integer count.
837 * @param[out] best_combined_error The best combined error pairings for the 3 partitions.
838 * @param[out] best_combined_format The best combined format pairings for the 3 partitions.
839 */
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])840 static void three_partitions_find_best_combination_for_every_quantization_and_integer_count(
841 const float best_error[3][21][4], // indexed by (partition, quant-level, integer-count)
842 const uint8_t best_format[3][21][4],
843 float best_combined_error[21][10],
844 uint8_t best_combined_format[21][10][3]
845 ) {
846 for (int i = QUANT_2; i <= QUANT_256; i++)
847 {
848 for (int j = 0; j < 10; j++)
849 {
850 best_combined_error[i][j] = ERROR_CALC_DEFAULT;
851 }
852 }
853
854 for (int quant = QUANT_6; quant <= QUANT_256; quant++)
855 {
856 for (int i = 0; i < 4; i++) // integer-count for first endpoint-pair
857 {
858 for (int j = 0; j < 4; j++) // integer-count for second endpoint-pair
859 {
860 int low2 = astc::min(i, j);
861 int high2 = astc::max(i, j);
862 if ((high2 - low2) > 1)
863 {
864 continue;
865 }
866
867 for (int k = 0; k < 4; k++) // integer-count for third endpoint-pair
868 {
869 int low3 = astc::min(k, low2);
870 int high3 = astc::max(k, high2);
871 if ((high3 - low3) > 1)
872 {
873 continue;
874 }
875
876 int intcnt = i + j + k;
877 float errorterm = astc::min(best_error[0][quant][i] + best_error[1][quant][j] + best_error[2][quant][k], 1e10f);
878 if (errorterm <= best_combined_error[quant][intcnt])
879 {
880 best_combined_error[quant][intcnt] = errorterm;
881 best_combined_format[quant][intcnt][0] = best_format[0][quant][i];
882 best_combined_format[quant][intcnt][1] = best_format[1][quant][j];
883 best_combined_format[quant][intcnt][2] = best_format[2][quant][k];
884 }
885 }
886 }
887 }
888 }
889 }
890
891 /**
892 * @brief For 3 partitions compute the best format and quantization for a given bit count.
893 *
894 * @param best_combined_error The best error for each quant level and integer count.
895 * @param best_combined_format The best format for each quant level and integer count.
896 * @param bits_available The number of bits available for encoding.
897 * @param[out] best_quant_level The output best color quant level.
898 * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available.
899 * @param[out] best_formats The output best color formats.
900 *
901 * @return The output error for the best pairing.
902 */
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)903 static float three_partitions_find_best_combination_for_bitcount(
904 const float best_combined_error[21][10],
905 const uint8_t best_combined_format[21][10][3],
906 int bits_available,
907 uint8_t& best_quant_level,
908 uint8_t& best_quant_level_mod,
909 uint8_t* best_formats
910 ) {
911 int best_integer_count = 0;
912 float best_integer_count_error = ERROR_CALC_DEFAULT;
913
914 for (int integer_count = 3; integer_count <= 9; integer_count++)
915 {
916 // Compute the quantization level for a given number of integers and a given number of bits
917 int quant_level = quant_mode_table[integer_count][bits_available];
918
919 // Don't have enough bits to represent a given endpoint format at all!
920 if (quant_level < QUANT_6)
921 {
922 break;
923 }
924
925 float integer_count_error = best_combined_error[quant_level][integer_count - 3];
926 if (integer_count_error < best_integer_count_error)
927 {
928 best_integer_count_error = integer_count_error;
929 best_integer_count = integer_count;
930 }
931 }
932
933 int ql = quant_mode_table[best_integer_count][bits_available];
934 int ql_mod = quant_mode_table[best_integer_count][bits_available + 5];
935
936 best_quant_level = static_cast<uint8_t>(ql);
937 best_quant_level_mod = static_cast<uint8_t>(ql_mod);
938
939 if (ql >= QUANT_6)
940 {
941 for (int i = 0; i < 3; i++)
942 {
943 best_formats[i] = best_combined_format[ql][best_integer_count - 3][i];
944 }
945 }
946 else
947 {
948 for (int i = 0; i < 3; i++)
949 {
950 best_formats[i] = FMT_LUMINANCE;
951 }
952 }
953
954 return best_integer_count_error;
955 }
956
957 /**
958 * @brief For 4 partitions compute the best format combinations for every pair of quant mode and integer count.
959 *
960 * @param best_error The best error for a single endpoint quant level and integer count.
961 * @param best_format The best format for a single endpoint quant level and integer count.
962 * @param[out] best_combined_error The best combined error pairings for the 4 partitions.
963 * @param[out] best_combined_format The best combined format pairings for the 4 partitions.
964 */
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])965 static void four_partitions_find_best_combination_for_every_quantization_and_integer_count(
966 const float best_error[4][21][4], // indexed by (partition, quant-level, integer-count)
967 const uint8_t best_format[4][21][4],
968 float best_combined_error[21][13],
969 uint8_t best_combined_format[21][13][4]
970 ) {
971 for (int i = QUANT_2; i <= QUANT_256; i++)
972 {
973 for (int j = 0; j < 13; j++)
974 {
975 best_combined_error[i][j] = ERROR_CALC_DEFAULT;
976 }
977 }
978
979 for (int quant = QUANT_6; quant <= QUANT_256; quant++)
980 {
981 for (int i = 0; i < 4; i++) // integer-count for first endpoint-pair
982 {
983 for (int j = 0; j < 4; j++) // integer-count for second endpoint-pair
984 {
985 int low2 = astc::min(i, j);
986 int high2 = astc::max(i, j);
987 if ((high2 - low2) > 1)
988 {
989 continue;
990 }
991
992 for (int k = 0; k < 4; k++) // integer-count for third endpoint-pair
993 {
994 int low3 = astc::min(k, low2);
995 int high3 = astc::max(k, high2);
996 if ((high3 - low3) > 1)
997 {
998 continue;
999 }
1000
1001 for (int l = 0; l < 4; l++) // integer-count for fourth endpoint-pair
1002 {
1003 int low4 = astc::min(l, low3);
1004 int high4 = astc::max(l, high3);
1005 if ((high4 - low4) > 1)
1006 {
1007 continue;
1008 }
1009
1010 int intcnt = i + j + k + l;
1011 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);
1012 if (errorterm <= best_combined_error[quant][intcnt])
1013 {
1014 best_combined_error[quant][intcnt] = errorterm;
1015 best_combined_format[quant][intcnt][0] = best_format[0][quant][i];
1016 best_combined_format[quant][intcnt][1] = best_format[1][quant][j];
1017 best_combined_format[quant][intcnt][2] = best_format[2][quant][k];
1018 best_combined_format[quant][intcnt][3] = best_format[3][quant][l];
1019 }
1020 }
1021 }
1022 }
1023 }
1024 }
1025 }
1026
1027 /**
1028 * @brief For 4 partitions compute the best format and quantization for a given bit count.
1029 *
1030 * @param best_combined_error The best error for each quant level and integer count.
1031 * @param best_combined_format The best format for each quant level and integer count.
1032 * @param bits_available The number of bits available for encoding.
1033 * @param[out] best_quant_level The output best color quant level.
1034 * @param[out] best_quant_level_mod The output best color quant level assuming two more bits are available.
1035 * @param[out] best_formats The output best color formats.
1036 *
1037 * @return best_error The output error for the best pairing.
1038 */
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)1039 static float four_partitions_find_best_combination_for_bitcount(
1040 const float best_combined_error[21][13],
1041 const uint8_t best_combined_format[21][13][4],
1042 int bits_available,
1043 uint8_t& best_quant_level,
1044 uint8_t& best_quant_level_mod,
1045 uint8_t* best_formats
1046 ) {
1047 int best_integer_count = 0;
1048 float best_integer_count_error = ERROR_CALC_DEFAULT;
1049
1050 for (int integer_count = 4; integer_count <= 9; integer_count++)
1051 {
1052 // Compute the quantization level for a given number of integers and a given number of bits
1053 int quant_level = quant_mode_table[integer_count][bits_available];
1054
1055 // Don't have enough bits to represent a given endpoint format at all!
1056 if (quant_level < QUANT_6)
1057 {
1058 break;
1059 }
1060
1061 float integer_count_error = best_combined_error[quant_level][integer_count - 4];
1062 if (integer_count_error < best_integer_count_error)
1063 {
1064 best_integer_count_error = integer_count_error;
1065 best_integer_count = integer_count;
1066 }
1067 }
1068
1069 int ql = quant_mode_table[best_integer_count][bits_available];
1070 int ql_mod = quant_mode_table[best_integer_count][bits_available + 8];
1071
1072 best_quant_level = static_cast<uint8_t>(ql);
1073 best_quant_level_mod = static_cast<uint8_t>(ql_mod);
1074
1075 if (ql >= QUANT_6)
1076 {
1077 for (int i = 0; i < 4; i++)
1078 {
1079 best_formats[i] = best_combined_format[ql][best_integer_count - 4][i];
1080 }
1081 }
1082 else
1083 {
1084 for (int i = 0; i < 4; i++)
1085 {
1086 best_formats[i] = FMT_LUMINANCE;
1087 }
1088 }
1089
1090 return best_integer_count_error;
1091 }
1092
1093 /* See header for documentation. */
compute_ideal_endpoint_formats(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)1094 unsigned int compute_ideal_endpoint_formats(
1095 const partition_info& pi,
1096 const image_block& blk,
1097 const endpoints& ep,
1098 // bitcounts and errors computed for the various quantization methods
1099 const int8_t* qwt_bitcounts,
1100 const float* qwt_errors,
1101 unsigned int tune_candidate_limit,
1102 unsigned int start_block_mode,
1103 unsigned int end_block_mode,
1104 // output data
1105 uint8_t partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS],
1106 int block_mode[TUNE_MAX_TRIAL_CANDIDATES],
1107 quant_method quant_level[TUNE_MAX_TRIAL_CANDIDATES],
1108 quant_method quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES],
1109 compression_working_buffers& tmpbuf
1110 ) {
1111 int partition_count = pi.partition_count;
1112
1113 promise(partition_count > 0);
1114
1115 bool encode_hdr_rgb = static_cast<bool>(blk.rgb_lns[0]);
1116 bool encode_hdr_alpha = static_cast<bool>(blk.alpha_lns[0]);
1117
1118 // Compute the errors that result from various encoding choices (such as using luminance instead
1119 // of RGB, discarding Alpha, using RGB-scale in place of two separate RGB endpoints and so on)
1120 encoding_choice_errors eci[BLOCK_MAX_PARTITIONS];
1121 compute_encoding_choice_errors(blk, pi, ep, eci);
1122
1123 float best_error[BLOCK_MAX_PARTITIONS][21][4];
1124 uint8_t format_of_choice[BLOCK_MAX_PARTITIONS][21][4];
1125 for (int i = 0; i < partition_count; i++)
1126 {
1127 compute_color_error_for_every_integer_count_and_quant_level(
1128 encode_hdr_rgb, encode_hdr_alpha, i,
1129 pi, eci[i], ep, blk.channel_weight, best_error[i],
1130 format_of_choice[i]);
1131 }
1132
1133 float* errors_of_best_combination = tmpbuf.errors_of_best_combination;
1134 uint8_t* best_quant_levels = tmpbuf.best_quant_levels;
1135 uint8_t* best_quant_levels_mod = tmpbuf.best_quant_levels_mod;
1136 uint8_t (&best_ep_formats)[WEIGHTS_MAX_BLOCK_MODES][BLOCK_MAX_PARTITIONS] = tmpbuf.best_ep_formats;
1137
1138 // Ensure that the first iteration understep contains data that will never be picked
1139 unsigned int packed_start_block_mode = round_down_to_simd_multiple_vla(start_block_mode);
1140 for (unsigned int i = packed_start_block_mode; i < start_block_mode; i++)
1141 {
1142 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1143 best_quant_levels[i] = QUANT_2;
1144 best_quant_levels_mod[i] = QUANT_2;
1145 }
1146
1147 // Ensure that last iteration overstep contains data that will never be picked
1148 const unsigned int packed_end_block_mode = round_up_to_simd_multiple_vla(end_block_mode);
1149 for (unsigned int i = end_block_mode; i < packed_end_block_mode; i++)
1150 {
1151 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1152 best_quant_levels[i] = QUANT_2;
1153 best_quant_levels_mod[i] = QUANT_2;
1154 }
1155
1156 // Track a scalar best to avoid expensive search at least once ...
1157 float error_of_best_combination = ERROR_CALC_DEFAULT;
1158 int index_of_best_combination = -1;
1159
1160 // The block contains 1 partition
1161 if (partition_count == 1)
1162 {
1163 for (unsigned int i = start_block_mode; i < end_block_mode; i++)
1164 {
1165 if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
1166 {
1167 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1168 continue;
1169 }
1170
1171 float error_of_best = one_partition_find_best_combination_for_bitcount(
1172 best_error[0], format_of_choice[0], qwt_bitcounts[i],
1173 best_quant_levels[i], best_ep_formats[i][0]);
1174
1175 float total_error = error_of_best + qwt_errors[i];
1176 errors_of_best_combination[i] = total_error;
1177 best_quant_levels_mod[i] = best_quant_levels[i];
1178
1179 if (total_error < error_of_best_combination)
1180 {
1181 error_of_best_combination = total_error;
1182 index_of_best_combination = i;
1183 }
1184 }
1185 }
1186 // The block contains 2 partitions
1187 else if (partition_count == 2)
1188 {
1189 float combined_best_error[21][7];
1190 uint8_t formats_of_choice[21][7][2];
1191
1192 two_partitions_find_best_combination_for_every_quantization_and_integer_count(
1193 best_error, format_of_choice, combined_best_error, formats_of_choice);
1194
1195 assert(start_block_mode == 0);
1196 for (unsigned int i = 0; i < end_block_mode; i++)
1197 {
1198 if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
1199 {
1200 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1201 continue;
1202 }
1203
1204 float error_of_best = two_partitions_find_best_combination_for_bitcount(
1205 combined_best_error, formats_of_choice, qwt_bitcounts[i],
1206 best_quant_levels[i], best_quant_levels_mod[i],
1207 best_ep_formats[i]);
1208
1209 float total_error = error_of_best + qwt_errors[i];
1210 errors_of_best_combination[i] = total_error;
1211
1212 if (total_error < error_of_best_combination)
1213 {
1214 error_of_best_combination = total_error;
1215 index_of_best_combination = i;
1216 }
1217 }
1218 }
1219 // The block contains 3 partitions
1220 else if (partition_count == 3)
1221 {
1222 float combined_best_error[21][10];
1223 uint8_t formats_of_choice[21][10][3];
1224
1225 three_partitions_find_best_combination_for_every_quantization_and_integer_count(
1226 best_error, format_of_choice, combined_best_error, formats_of_choice);
1227
1228 assert(start_block_mode == 0);
1229 for (unsigned int i = 0; i < end_block_mode; i++)
1230 {
1231 if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
1232 {
1233 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1234 continue;
1235 }
1236
1237 float error_of_best = three_partitions_find_best_combination_for_bitcount(
1238 combined_best_error, formats_of_choice, qwt_bitcounts[i],
1239 best_quant_levels[i], best_quant_levels_mod[i],
1240 best_ep_formats[i]);
1241
1242 float total_error = error_of_best + qwt_errors[i];
1243 errors_of_best_combination[i] = total_error;
1244
1245 if (total_error < error_of_best_combination)
1246 {
1247 error_of_best_combination = total_error;
1248 index_of_best_combination = i;
1249 }
1250 }
1251 }
1252 // The block contains 4 partitions
1253 else // if (partition_count == 4)
1254 {
1255 assert(partition_count == 4);
1256 float combined_best_error[21][13];
1257 uint8_t formats_of_choice[21][13][4];
1258
1259 four_partitions_find_best_combination_for_every_quantization_and_integer_count(
1260 best_error, format_of_choice, combined_best_error, formats_of_choice);
1261
1262 assert(start_block_mode == 0);
1263 for (unsigned int i = 0; i < end_block_mode; i++)
1264 {
1265 if (qwt_errors[i] >= ERROR_CALC_DEFAULT)
1266 {
1267 errors_of_best_combination[i] = ERROR_CALC_DEFAULT;
1268 continue;
1269 }
1270
1271 float error_of_best = four_partitions_find_best_combination_for_bitcount(
1272 combined_best_error, formats_of_choice, qwt_bitcounts[i],
1273 best_quant_levels[i], best_quant_levels_mod[i],
1274 best_ep_formats[i]);
1275
1276 float total_error = error_of_best + qwt_errors[i];
1277 errors_of_best_combination[i] = total_error;
1278
1279 if (total_error < error_of_best_combination)
1280 {
1281 error_of_best_combination = total_error;
1282 index_of_best_combination = i;
1283 }
1284 }
1285 }
1286
1287 int best_error_weights[TUNE_MAX_TRIAL_CANDIDATES];
1288
1289 // Fast path the first result and avoid the list search for trial 0
1290 best_error_weights[0] = index_of_best_combination;
1291 if (index_of_best_combination >= 0)
1292 {
1293 errors_of_best_combination[index_of_best_combination] = ERROR_CALC_DEFAULT;
1294 }
1295
1296 // Search the remaining results and pick the best candidate modes for trial 1+
1297 for (unsigned int i = 1; i < tune_candidate_limit; i++)
1298 {
1299 vint vbest_error_index(-1);
1300 vfloat vbest_ep_error(ERROR_CALC_DEFAULT);
1301
1302 start_block_mode = round_down_to_simd_multiple_vla(start_block_mode);
1303 vint lane_ids = vint::lane_id() + vint(start_block_mode);
1304 for (unsigned int j = start_block_mode; j < end_block_mode; j += ASTCENC_SIMD_WIDTH)
1305 {
1306 vfloat err = vfloat(errors_of_best_combination + j);
1307 vmask mask = err < vbest_ep_error;
1308 vbest_ep_error = select(vbest_ep_error, err, mask);
1309 vbest_error_index = select(vbest_error_index, lane_ids, mask);
1310 lane_ids += vint(ASTCENC_SIMD_WIDTH);
1311 }
1312
1313 // Pick best mode from the SIMD result, using lowest matching index to ensure invariance
1314 vmask lanes_min_error = vbest_ep_error == hmin(vbest_ep_error);
1315 vbest_error_index = select(vint(0x7FFFFFFF), vbest_error_index, lanes_min_error);
1316 vbest_error_index = hmin(vbest_error_index);
1317 int best_error_index = vbest_error_index.lane<0>();
1318
1319 best_error_weights[i] = best_error_index;
1320
1321 // Max the error for this candidate so we don't pick it again
1322 if (best_error_index >= 0)
1323 {
1324 errors_of_best_combination[best_error_index] = ERROR_CALC_DEFAULT;
1325 }
1326 // Early-out if no more candidates are valid
1327 else
1328 {
1329 break;
1330 }
1331 }
1332
1333 for (unsigned int i = 0; i < tune_candidate_limit; i++)
1334 {
1335 if (best_error_weights[i] < 0)
1336 {
1337 return i;
1338 }
1339
1340 block_mode[i] = best_error_weights[i];
1341
1342 quant_level[i] = static_cast<quant_method>(best_quant_levels[best_error_weights[i]]);
1343 quant_level_mod[i] = static_cast<quant_method>(best_quant_levels_mod[best_error_weights[i]]);
1344
1345 assert(quant_level[i] >= QUANT_6 && quant_level[i] <= QUANT_256);
1346 assert(quant_level_mod[i] >= QUANT_6 && quant_level_mod[i] <= QUANT_256);
1347
1348 for (int j = 0; j < partition_count; j++)
1349 {
1350 partition_format_specifiers[i][j] = best_ep_formats[best_error_weights[i]][j];
1351 }
1352 }
1353
1354 return tune_candidate_limit;
1355 }
1356
1357 #endif
1358