1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2011-2020 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 /**
19 * @brief Functions to generate block size descriptor and decimation tables.
20 */
21
22 #include "astc_codec_internals.h"
23 #include <memory>
24
25 struct TexelWeight
26 {
27 int weightcount_of_texel[MAX_TEXELS_PER_BLOCK];
28 int grid_weights_of_texel[MAX_TEXELS_PER_BLOCK][4];
29 int weights_of_texel[MAX_TEXELS_PER_BLOCK][4];
30
31 int texelcount_of_weight[MAX_WEIGHTS_PER_BLOCK];
32 int texels_of_weight[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK];
33 int texelweights_of_weight[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK];
34 };
35
36 // return 0 on invalid mode, 1 on valid mode.
decode_block_mode_2d(int blockmode,int * Nval,int * Mval,int * dual_weight_plane,int * quant_mode)37 static int decode_block_mode_2d(
38 int blockmode,
39 int* Nval,
40 int* Mval,
41 int* dual_weight_plane,
42 int* quant_mode
43 ) {
44 int base_quant_mode = (blockmode >> 4) & 1;
45 int H = (blockmode >> 9) & 1;
46 int D = (blockmode >> 10) & 1;
47
48 int A = (blockmode >> 5) & 0x3;
49
50 int N = 0, M = 0;
51
52 if ((blockmode & 3) != 0)
53 {
54 base_quant_mode |= (blockmode & 3) << 1;
55 int B = (blockmode >> 7) & 3;
56 switch ((blockmode >> 2) & 3)
57 {
58 case 0:
59 N = B + 4;
60 M = A + 2;
61 break;
62 case 1:
63 N = B + 8;
64 M = A + 2;
65 break;
66 case 2:
67 N = A + 2;
68 M = B + 8;
69 break;
70 case 3:
71 B &= 1;
72 if (blockmode & 0x100)
73 {
74 N = B + 2;
75 M = A + 2;
76 }
77 else
78 {
79 N = A + 2;
80 M = B + 6;
81 }
82 break;
83 }
84 }
85 else
86 {
87 base_quant_mode |= ((blockmode >> 2) & 3) << 1;
88 if (((blockmode >> 2) & 3) == 0)
89 return 0;
90 int B = (blockmode >> 9) & 3;
91 switch ((blockmode >> 7) & 3)
92 {
93 case 0:
94 N = 12;
95 M = A + 2;
96 break;
97 case 1:
98 N = A + 2;
99 M = 12;
100 break;
101 case 2:
102 N = A + 6;
103 M = B + 6;
104 D = 0;
105 H = 0;
106 break;
107 case 3:
108 switch ((blockmode >> 5) & 3)
109 {
110 case 0:
111 N = 6;
112 M = 10;
113 break;
114 case 1:
115 N = 10;
116 M = 6;
117 break;
118 case 2:
119 case 3:
120 return 0;
121 }
122 break;
123 }
124 }
125
126 int weight_count = N * M * (D + 1);
127 int qmode = (base_quant_mode - 2) + 6 * H;
128
129 int weightbits = compute_ise_bitcount(weight_count, (quantization_method) qmode);
130 if (weight_count > MAX_WEIGHTS_PER_BLOCK || weightbits < MIN_WEIGHT_BITS_PER_BLOCK || weightbits > MAX_WEIGHT_BITS_PER_BLOCK)
131 return 0;
132
133 *Nval = N;
134 *Mval = M;
135 *dual_weight_plane = D;
136 *quant_mode = qmode;
137 return 1;
138 }
139
decode_block_mode_3d(int blockmode,int * Nval,int * Mval,int * Qval,int * dual_weight_plane,int * quant_mode)140 static int decode_block_mode_3d(
141 int blockmode,
142 int* Nval,
143 int* Mval,
144 int* Qval,
145 int* dual_weight_plane,
146 int* quant_mode
147 ) {
148 int base_quant_mode = (blockmode >> 4) & 1;
149 int H = (blockmode >> 9) & 1;
150 int D = (blockmode >> 10) & 1;
151
152 int A = (blockmode >> 5) & 0x3;
153
154 int N = 0, M = 0, Q = 0;
155
156 if ((blockmode & 3) != 0)
157 {
158 base_quant_mode |= (blockmode & 3) << 1;
159 int B = (blockmode >> 7) & 3;
160 int C = (blockmode >> 2) & 0x3;
161 N = A + 2;
162 M = B + 2;
163 Q = C + 2;
164 }
165 else
166 {
167 base_quant_mode |= ((blockmode >> 2) & 3) << 1;
168 if (((blockmode >> 2) & 3) == 0)
169 return 0;
170 int B = (blockmode >> 9) & 3;
171 if (((blockmode >> 7) & 3) != 3)
172 {
173 D = 0;
174 H = 0;
175 }
176 switch ((blockmode >> 7) & 3)
177 {
178 case 0:
179 N = 6;
180 M = B + 2;
181 Q = A + 2;
182 break;
183 case 1:
184 N = A + 2;
185 M = 6;
186 Q = B + 2;
187 break;
188 case 2:
189 N = A + 2;
190 M = B + 2;
191 Q = 6;
192 break;
193 case 3:
194 N = 2;
195 M = 2;
196 Q = 2;
197 switch ((blockmode >> 5) & 3)
198 {
199 case 0:
200 N = 6;
201 break;
202 case 1:
203 M = 6;
204 break;
205 case 2:
206 Q = 6;
207 break;
208 case 3:
209 return 0;
210 }
211 break;
212 }
213 }
214
215 int weight_count = N * M * Q * (D + 1);
216 int qmode = (base_quant_mode - 2) + 6 * H;
217
218 int weightbits = compute_ise_bitcount(weight_count, (quantization_method) qmode);
219 if (weight_count > MAX_WEIGHTS_PER_BLOCK ||
220 weightbits < MIN_WEIGHT_BITS_PER_BLOCK ||
221 weightbits > MAX_WEIGHT_BITS_PER_BLOCK)
222 return 0;
223
224 *Nval = N;
225 *Mval = M;
226 *Qval = Q;
227 *dual_weight_plane = D;
228 *quant_mode = qmode;
229 return 1;
230 }
231
initialize_decimation_table_2d(int xdim,int ydim,int x_weights,int y_weights,decimation_table * dt)232 static void initialize_decimation_table_2d(
233 int xdim,
234 int ydim,
235 int x_weights,
236 int y_weights,
237 decimation_table* dt
238 ) {
239 int i, j;
240 int x, y;
241
242 int texels_per_block = xdim * ydim;
243 int weights_per_block = x_weights * y_weights;
244
245 std::unique_ptr<TexelWeight> tw(new TexelWeight);
246
247 for (i = 0; i < weights_per_block; i++)
248 tw->texelcount_of_weight[i] = 0;
249 for (i = 0; i < texels_per_block; i++)
250 tw->weightcount_of_texel[i] = 0;
251
252 for (y = 0; y < ydim; y++)
253 for (x = 0; x < xdim; x++)
254 {
255 int texel = y * xdim + x;
256
257 int x_weight = (((1024 + xdim / 2) / (xdim - 1)) * x * (x_weights - 1) + 32) >> 6;
258 int y_weight = (((1024 + ydim / 2) / (ydim - 1)) * y * (y_weights - 1) + 32) >> 6;
259
260 int x_weight_frac = x_weight & 0xF;
261 int y_weight_frac = y_weight & 0xF;
262 int x_weight_int = x_weight >> 4;
263 int y_weight_int = y_weight >> 4;
264 int qweight[4];
265 int weight[4];
266 qweight[0] = x_weight_int + y_weight_int * x_weights;
267 qweight[1] = qweight[0] + 1;
268 qweight[2] = qweight[0] + x_weights;
269 qweight[3] = qweight[2] + 1;
270
271 // truncated-precision bilinear interpolation.
272 int prod = x_weight_frac * y_weight_frac;
273
274 weight[3] = (prod + 8) >> 4;
275 weight[1] = x_weight_frac - weight[3];
276 weight[2] = y_weight_frac - weight[3];
277 weight[0] = 16 - x_weight_frac - y_weight_frac + weight[3];
278
279 for (i = 0; i < 4; i++)
280 if (weight[i] != 0)
281 {
282 tw->grid_weights_of_texel[texel][tw->weightcount_of_texel[texel]] = qweight[i];
283 tw->weights_of_texel[texel][tw->weightcount_of_texel[texel]] = weight[i];
284 tw->weightcount_of_texel[texel]++;
285 tw->texels_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = texel;
286 tw->texelweights_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = weight[i];
287 tw->texelcount_of_weight[qweight[i]]++;
288 }
289 }
290
291 for (i = 0; i < texels_per_block; i++)
292 {
293 dt->texel_num_weights[i] = tw->weightcount_of_texel[i];
294
295 // ensure that all 4 entries are actually initialized.
296 // This allows a branch-free implementation of compute_value_of_texel_flt()
297 for (j = 0; j < 4; j++)
298 {
299 dt->texel_weights_int[i][j] = 0;
300 dt->texel_weights_float[i][j] = 0.0f;
301 dt->texel_weights[i][j] = 0;
302 }
303
304 for (j = 0; j < tw->weightcount_of_texel[i]; j++)
305 {
306 dt->texel_weights_int[i][j] = (uint8_t)(tw->weights_of_texel[i][j]);
307 dt->texel_weights_float[i][j] = ((float)(tw->weights_of_texel[i][j])) * (1.0f / TEXEL_WEIGHT_SUM);
308 dt->texel_weights[i][j] = (uint8_t)(tw->grid_weights_of_texel[i][j]);
309 }
310 }
311
312 for (i = 0; i < weights_per_block; i++)
313 {
314 dt->weight_num_texels[i] = tw->texelcount_of_weight[i];
315
316 for (j = 0; j < tw->texelcount_of_weight[i]; j++)
317 {
318 int texel = tw->texels_of_weight[i][j];
319 dt->weight_texel[i][j] = (uint8_t)texel;
320 dt->weights_int[i][j] = (uint8_t)(tw->texelweights_of_weight[i][j]);
321 dt->weights_flt[i][j] = (float)(tw->texelweights_of_weight[i][j]);
322
323 // perform a layer of array unrolling. An aspect of this unrolling is that
324 // one of the texel-weight indexes is an identity-mapped index; we will use this
325 // fact to reorder the indexes so that the first one is the identity index.
326 int swap_idx = -1;
327 for (int k = 0; k < 4; k++)
328 {
329 int dttw = dt->texel_weights[texel][k];
330 float dttwf = dt->texel_weights_float[texel][k];
331 if (dttw == i && dttwf != 0.0f)
332 swap_idx = k;
333 dt->texel_weights_texel[i][j][k] = (uint8_t)dttw;
334 dt->texel_weights_float_texel[i][j][k] = dttwf;
335 }
336
337 if (swap_idx != 0)
338 {
339 int vi = dt->texel_weights_texel[i][j][0];
340 float vf = dt->texel_weights_float_texel[i][j][0];
341 dt->texel_weights_texel[i][j][0] = dt->texel_weights_texel[i][j][swap_idx];
342 dt->texel_weights_float_texel[i][j][0] = dt->texel_weights_float_texel[i][j][swap_idx];
343 dt->texel_weights_texel[i][j][swap_idx] = (uint8_t)vi;
344 dt->texel_weights_float_texel[i][j][swap_idx] = vf;
345 }
346 }
347 }
348
349 dt->num_texels = texels_per_block;
350 dt->num_weights = weights_per_block;
351 }
352
initialize_decimation_table_3d(int xdim,int ydim,int zdim,int x_weights,int y_weights,int z_weights,decimation_table * dt)353 static void initialize_decimation_table_3d(
354 int xdim,
355 int ydim,
356 int zdim,
357 int x_weights,
358 int y_weights,
359 int z_weights,
360 decimation_table* dt
361 ) {
362 int i, j;
363 int x, y, z;
364
365 int texels_per_block = xdim * ydim * zdim;
366 int weights_per_block = x_weights * y_weights * z_weights;
367
368 std::unique_ptr<TexelWeight> tw(new TexelWeight);
369
370 for (i = 0; i < weights_per_block; i++)
371 tw->texelcount_of_weight[i] = 0;
372 for (i = 0; i < texels_per_block; i++)
373 tw->weightcount_of_texel[i] = 0;
374
375 for (z = 0; z < zdim; z++)
376 {
377 for (y = 0; y < ydim; y++)
378 {
379 for (x = 0; x < xdim; x++)
380 {
381 int texel = (z * ydim + y) * xdim + x;
382
383 int x_weight = (((1024 + xdim / 2) / (xdim - 1)) * x * (x_weights - 1) + 32) >> 6;
384 int y_weight = (((1024 + ydim / 2) / (ydim - 1)) * y * (y_weights - 1) + 32) >> 6;
385 int z_weight = (((1024 + zdim / 2) / (zdim - 1)) * z * (z_weights - 1) + 32) >> 6;
386
387 int x_weight_frac = x_weight & 0xF;
388 int y_weight_frac = y_weight & 0xF;
389 int z_weight_frac = z_weight & 0xF;
390 int x_weight_int = x_weight >> 4;
391 int y_weight_int = y_weight >> 4;
392 int z_weight_int = z_weight >> 4;
393 int qweight[4];
394 int weight[4];
395 qweight[0] = (z_weight_int * y_weights + y_weight_int) * x_weights + x_weight_int;
396 qweight[3] = ((z_weight_int + 1) * y_weights + (y_weight_int + 1)) * x_weights + (x_weight_int + 1);
397
398 // simplex interpolation
399 int fs = x_weight_frac;
400 int ft = y_weight_frac;
401 int fp = z_weight_frac;
402
403 int cas = ((fs > ft) << 2) + ((ft > fp) << 1) + ((fs > fp));
404 int N = x_weights;
405 int NM = x_weights * y_weights;
406
407 int s1, s2, w0, w1, w2, w3;
408 switch (cas)
409 {
410 case 7:
411 s1 = 1;
412 s2 = N;
413 w0 = 16 - fs;
414 w1 = fs - ft;
415 w2 = ft - fp;
416 w3 = fp;
417 break;
418 case 3:
419 s1 = N;
420 s2 = 1;
421 w0 = 16 - ft;
422 w1 = ft - fs;
423 w2 = fs - fp;
424 w3 = fp;
425 break;
426 case 5:
427 s1 = 1;
428 s2 = NM;
429 w0 = 16 - fs;
430 w1 = fs - fp;
431 w2 = fp - ft;
432 w3 = ft;
433 break;
434 case 4:
435 s1 = NM;
436 s2 = 1;
437 w0 = 16 - fp;
438 w1 = fp - fs;
439 w2 = fs - ft;
440 w3 = ft;
441 break;
442 case 2:
443 s1 = N;
444 s2 = NM;
445 w0 = 16 - ft;
446 w1 = ft - fp;
447 w2 = fp - fs;
448 w3 = fs;
449 break;
450 case 0:
451 s1 = NM;
452 s2 = N;
453 w0 = 16 - fp;
454 w1 = fp - ft;
455 w2 = ft - fs;
456 w3 = fs;
457 break;
458
459 default:
460 s1 = NM;
461 s2 = N;
462 w0 = 16 - fp;
463 w1 = fp - ft;
464 w2 = ft - fs;
465 w3 = fs;
466 break;
467 }
468
469 qweight[1] = qweight[0] + s1;
470 qweight[2] = qweight[1] + s2;
471 weight[0] = w0;
472 weight[1] = w1;
473 weight[2] = w2;
474 weight[3] = w3;
475
476 for (i = 0; i < 4; i++)
477 {
478 if (weight[i] != 0)
479 {
480 tw->grid_weights_of_texel[texel][tw->weightcount_of_texel[texel]] = qweight[i];
481 tw->weights_of_texel[texel][tw->weightcount_of_texel[texel]] = weight[i];
482 tw->weightcount_of_texel[texel]++;
483 tw->texels_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = texel;
484 tw->texelweights_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = weight[i];
485 tw->texelcount_of_weight[qweight[i]]++;
486 }
487 }
488 }
489 }
490 }
491
492 for (i = 0; i < texels_per_block; i++)
493 {
494 dt->texel_num_weights[i] = tw->weightcount_of_texel[i];
495
496 // ensure that all 4 entries are actually initialized.
497 // This allows a branch-free implementation of compute_value_of_texel_flt()
498 for (j = 0; j < 4; j++)
499 {
500 dt->texel_weights_int[i][j] = 0;
501 dt->texel_weights_float[i][j] = 0.0f;
502 dt->texel_weights[i][j] = 0;
503 }
504
505 for (j = 0; j < tw->weightcount_of_texel[i]; j++)
506 {
507 dt->texel_weights_int[i][j] = (uint8_t)(tw->weights_of_texel[i][j]);
508 dt->texel_weights_float[i][j] = ((float)(tw->weights_of_texel[i][j])) * (1.0f / TEXEL_WEIGHT_SUM);
509 dt->texel_weights[i][j] = (uint8_t)(tw->grid_weights_of_texel[i][j]);
510 }
511 }
512
513 for (i = 0; i < weights_per_block; i++)
514 {
515 dt->weight_num_texels[i] = tw->texelcount_of_weight[i];
516 for (j = 0; j < tw->texelcount_of_weight[i]; j++)
517 {
518 int texel = tw->texels_of_weight[i][j];
519 dt->weight_texel[i][j] = (uint8_t)texel;
520 dt->weights_int[i][j] = (uint8_t)(tw->texelweights_of_weight[i][j]);
521 dt->weights_flt[i][j] = (float)(tw->texelweights_of_weight[i][j]);
522
523 // perform a layer of array unrolling. An aspect of this unrolling is that
524 // one of the texel-weight indexes is an identity-mapped index; we will use this
525 // fact to reorder the indexes so that the first one is the identity index.
526 int swap_idx = -1;
527 for (int k = 0; k < 4; k++)
528 {
529 int dttw = dt->texel_weights[texel][k];
530 float dttwf = dt->texel_weights_float[texel][k];
531 if (dttw == i && dttwf != 0.0f)
532 swap_idx = k;
533 dt->texel_weights_texel[i][j][k] = (uint8_t)dttw;
534 dt->texel_weights_float_texel[i][j][k] = dttwf;
535 }
536
537 if (swap_idx != 0)
538 {
539 int vi = dt->texel_weights_texel[i][j][0];
540 float vf = dt->texel_weights_float_texel[i][j][0];
541 dt->texel_weights_texel[i][j][0] = dt->texel_weights_texel[i][j][swap_idx];
542 dt->texel_weights_float_texel[i][j][0] = dt->texel_weights_float_texel[i][j][swap_idx];
543 dt->texel_weights_texel[i][j][swap_idx] = (uint8_t)vi;
544 dt->texel_weights_float_texel[i][j][swap_idx] = vf;
545 }
546 }
547 }
548
549 dt->num_texels = texels_per_block;
550 dt->num_weights = weights_per_block;
551 }
552
construct_block_size_descriptor_2d(int xdim,int ydim,block_size_descriptor * bsd)553 static void construct_block_size_descriptor_2d(
554 int xdim,
555 int ydim,
556 block_size_descriptor* bsd
557 ) {
558 int decimation_mode_index[256]; // for each of the 256 entries in the decim_table_array, its index
559 int decimation_mode_count = 0;
560
561 bsd->xdim = xdim;
562 bsd->ydim = ydim;
563 bsd->zdim = 1;
564 bsd->texel_count = xdim * ydim;
565
566 for (int i = 0; i < 256; i++)
567 {
568 decimation_mode_index[i] = -1;
569 }
570
571 // gather all the infill-modes that can be used with the current block size
572 for (int x_weights = 2; x_weights <= 12; x_weights++)
573 {
574 for (int y_weights = 2; y_weights <= 12; y_weights++)
575 {
576 if (x_weights * y_weights > MAX_WEIGHTS_PER_BLOCK)
577 {
578 continue;
579 }
580
581 decimation_table *dt = new decimation_table;
582 decimation_mode_index[y_weights * 16 + x_weights] = decimation_mode_count;
583 initialize_decimation_table_2d(xdim, ydim, x_weights, y_weights, dt);
584
585 int weight_count = x_weights * y_weights;
586
587 int maxprec_1plane = -1;
588 int maxprec_2planes = -1;
589 for (int i = 0; i < 12; i++)
590 {
591 int bits_1plane = compute_ise_bitcount(weight_count, (quantization_method) i);
592 int bits_2planes = compute_ise_bitcount(2 * weight_count, (quantization_method) i);
593 if (bits_1plane >= MIN_WEIGHT_BITS_PER_BLOCK && bits_1plane <= MAX_WEIGHT_BITS_PER_BLOCK)
594 maxprec_1plane = i;
595 if (bits_2planes >= MIN_WEIGHT_BITS_PER_BLOCK && bits_2planes <= MAX_WEIGHT_BITS_PER_BLOCK)
596 maxprec_2planes = i;
597 }
598
599 if (2 * x_weights * y_weights > MAX_WEIGHTS_PER_BLOCK)
600 {
601 maxprec_2planes = -1;
602 }
603
604 bsd->permit_encode[decimation_mode_count] = (x_weights <= xdim && y_weights <= ydim);
605
606 bsd->decimation_mode_samples[decimation_mode_count] = weight_count;
607 bsd->decimation_mode_maxprec_1plane[decimation_mode_count] = maxprec_1plane;
608 bsd->decimation_mode_maxprec_2planes[decimation_mode_count] = maxprec_2planes;
609 bsd->decimation_tables[decimation_mode_count] = dt;
610
611 decimation_mode_count++;
612 }
613 }
614
615 for (int i = 0; i < MAX_DECIMATION_MODES; i++)
616 {
617 bsd->decimation_mode_percentile[i] = 1.0f;
618 }
619
620 for (int i = decimation_mode_count; i < MAX_DECIMATION_MODES; i++)
621 {
622 bsd->permit_encode[i] = 0;
623 bsd->decimation_mode_samples[i] = 0;
624 bsd->decimation_mode_maxprec_1plane[i] = -1;
625 bsd->decimation_mode_maxprec_2planes[i] = -1;
626 }
627
628 bsd->decimation_mode_count = decimation_mode_count;
629
630 const float *percentiles = get_2d_percentile_table(xdim, ydim);
631
632 // then construct the list of block formats
633 for (int i = 0; i < 2048; i++)
634 {
635 int x_weights, y_weights;
636 int is_dual_plane;
637 int quantization_mode;
638 int fail = 0;
639 int permit_encode = 1;
640
641 if (decode_block_mode_2d(i, &x_weights, &y_weights, &is_dual_plane, &quantization_mode))
642 {
643 if (x_weights > xdim || y_weights > ydim)
644 permit_encode = 0;
645 }
646 else
647 {
648 fail = 1;
649 permit_encode = 0;
650 }
651
652 if (fail)
653 {
654 bsd->block_modes[i].decimation_mode = -1;
655 bsd->block_modes[i].quantization_mode = -1;
656 bsd->block_modes[i].is_dual_plane = -1;
657 bsd->block_modes[i].permit_encode = 0;
658 bsd->block_modes[i].permit_decode = 0;
659 bsd->block_modes[i].percentile = 1.0f;
660 }
661 else
662 {
663 int decimation_mode = decimation_mode_index[y_weights * 16 + x_weights];
664 bsd->block_modes[i].decimation_mode = decimation_mode;
665 bsd->block_modes[i].quantization_mode = quantization_mode;
666 bsd->block_modes[i].is_dual_plane = is_dual_plane;
667 bsd->block_modes[i].permit_encode = permit_encode;
668 bsd->block_modes[i].permit_decode = permit_encode; // disallow decode of grid size larger than block size.
669 bsd->block_modes[i].percentile = percentiles[i];
670
671 if (bsd->decimation_mode_percentile[decimation_mode] > percentiles[i])
672 bsd->decimation_mode_percentile[decimation_mode] = percentiles[i];
673 }
674 }
675
676 delete[] percentiles;
677
678 if (xdim * ydim <= 64)
679 {
680 bsd->texelcount_for_bitmap_partitioning = xdim * ydim;
681 for (int i = 0; i < xdim * ydim; i++)
682 {
683 bsd->texels_for_bitmap_partitioning[i] = i;
684 }
685 }
686 else
687 {
688 uint64_t rng_state[2];
689 astc::rand_init(rng_state);
690
691 // pick 64 random texels for use with bitmap partitioning.
692 int arr[MAX_TEXELS_PER_BLOCK];
693 for (int i = 0; i < xdim * ydim; i++)
694 {
695 arr[i] = 0;
696 }
697
698 int arr_elements_set = 0;
699 while (arr_elements_set < 64)
700 {
701 unsigned int idx = (unsigned int)astc::rand(rng_state);
702 idx %= xdim * ydim;
703 if (arr[idx] == 0)
704 {
705 arr_elements_set++;
706 arr[idx] = 1;
707 }
708 }
709
710 int texel_weights_written = 0;
711 int idx = 0;
712 while (texel_weights_written < 64)
713 {
714 if (arr[idx])
715 {
716 bsd->texels_for_bitmap_partitioning[texel_weights_written++] = idx;
717 }
718 idx++;
719 }
720
721 bsd->texelcount_for_bitmap_partitioning = 64;
722 }
723 }
724
construct_block_size_descriptor_3d(int xdim,int ydim,int zdim,block_size_descriptor * bsd)725 static void construct_block_size_descriptor_3d(
726 int xdim,
727 int ydim,
728 int zdim,
729 block_size_descriptor * bsd
730 ) {
731 int decimation_mode_index[512]; // for each of the 512 entries in the decim_table_array, its index
732 int decimation_mode_count = 0;
733
734 bsd->xdim = xdim;
735 bsd->ydim = ydim;
736 bsd->zdim = zdim;
737 bsd->texel_count = xdim * ydim * zdim;
738
739 for (int i = 0; i < 512; i++)
740 {
741 decimation_mode_index[i] = -1;
742 }
743
744 // gather all the infill-modes that can be used with the current block size
745 for (int x_weights = 2; x_weights <= 6; x_weights++)
746 {
747 for (int y_weights = 2; y_weights <= 6; y_weights++)
748 {
749 for (int z_weights = 2; z_weights <= 6; z_weights++)
750 {
751 if ((x_weights * y_weights * z_weights) > MAX_WEIGHTS_PER_BLOCK)
752 continue;
753 decimation_table *dt = new decimation_table;
754 decimation_mode_index[z_weights * 64 + y_weights * 8 + x_weights] = decimation_mode_count;
755 initialize_decimation_table_3d(xdim, ydim, zdim, x_weights, y_weights, z_weights, dt);
756
757 int weight_count = x_weights * y_weights * z_weights;
758
759 int maxprec_1plane = -1;
760 int maxprec_2planes = -1;
761 for (int i = 0; i < 12; i++)
762 {
763 int bits_1plane = compute_ise_bitcount(weight_count, (quantization_method) i);
764 int bits_2planes = compute_ise_bitcount(2 * weight_count, (quantization_method) i);
765 if (bits_1plane >= MIN_WEIGHT_BITS_PER_BLOCK && bits_1plane <= MAX_WEIGHT_BITS_PER_BLOCK)
766 maxprec_1plane = i;
767 if (bits_2planes >= MIN_WEIGHT_BITS_PER_BLOCK && bits_2planes <= MAX_WEIGHT_BITS_PER_BLOCK)
768 maxprec_2planes = i;
769 }
770
771 if ((2 * x_weights * y_weights * z_weights) > MAX_WEIGHTS_PER_BLOCK)
772 maxprec_2planes = -1;
773
774 bsd->permit_encode[decimation_mode_count] = (x_weights <= xdim && y_weights <= ydim && z_weights <= zdim);
775
776 bsd->decimation_mode_samples[decimation_mode_count] = weight_count;
777 bsd->decimation_mode_maxprec_1plane[decimation_mode_count] = maxprec_1plane;
778 bsd->decimation_mode_maxprec_2planes[decimation_mode_count] = maxprec_2planes;
779 bsd->decimation_tables[decimation_mode_count] = dt;
780
781 decimation_mode_count++;
782 }
783 }
784 }
785
786 for (int i = 0; i < MAX_DECIMATION_MODES; i++)
787 {
788 bsd->decimation_mode_percentile[i] = 1.0f;
789 }
790
791 for (int i = decimation_mode_count; i < MAX_DECIMATION_MODES; i++)
792 {
793 bsd->permit_encode[i] = 0;
794 bsd->decimation_mode_samples[i] = 0;
795 bsd->decimation_mode_maxprec_1plane[i] = -1;
796 bsd->decimation_mode_maxprec_2planes[i] = -1;
797 }
798
799 bsd->decimation_mode_count = decimation_mode_count;
800
801 // then construct the list of block formats
802 for (int i = 0; i < 2048; i++)
803 {
804 int x_weights, y_weights, z_weights;
805 int is_dual_plane;
806 int quantization_mode;
807 int fail = 0;
808 int permit_encode = 1;
809
810 if (decode_block_mode_3d(i, &x_weights, &y_weights, &z_weights, &is_dual_plane, &quantization_mode))
811 {
812 if (x_weights > xdim || y_weights > ydim || z_weights > zdim)
813 permit_encode = 0;
814 }
815 else
816 {
817 fail = 1;
818 permit_encode = 0;
819 }
820 if (fail)
821 {
822 bsd->block_modes[i].decimation_mode = -1;
823 bsd->block_modes[i].quantization_mode = -1;
824 bsd->block_modes[i].is_dual_plane = -1;
825 bsd->block_modes[i].permit_encode = 0;
826 bsd->block_modes[i].permit_decode = 0;
827 bsd->block_modes[i].percentile = 1.0f;
828 }
829 else
830 {
831 int decimation_mode = decimation_mode_index[z_weights * 64 + y_weights * 8 + x_weights];
832 bsd->block_modes[i].decimation_mode = decimation_mode;
833 bsd->block_modes[i].quantization_mode = quantization_mode;
834 bsd->block_modes[i].is_dual_plane = is_dual_plane;
835 bsd->block_modes[i].permit_encode = permit_encode;
836 bsd->block_modes[i].permit_decode = permit_encode;
837
838 bsd->block_modes[i].percentile = 0.0f; // No percentile table
839 if (bsd->decimation_mode_percentile[decimation_mode] > 0.0f)
840 bsd->decimation_mode_percentile[decimation_mode] = 0.0f;
841 }
842 }
843
844 if (xdim * ydim * zdim <= 64)
845 {
846 bsd->texelcount_for_bitmap_partitioning = xdim * ydim * zdim;
847 for (int i = 0; i < xdim * ydim * zdim; i++)
848 {
849 bsd->texels_for_bitmap_partitioning[i] = i;
850 }
851 }
852 else
853 {
854 uint64_t rng_state[2];
855 astc::rand_init(rng_state);
856
857 // pick 64 random texels for use with bitmap partitioning.
858 int arr[MAX_TEXELS_PER_BLOCK];
859 for (int i = 0; i < xdim * ydim * zdim; i++)
860 {
861 arr[i] = 0;
862 }
863
864 int arr_elements_set = 0;
865 while (arr_elements_set < 64)
866 {
867 unsigned int idx = (unsigned int)astc::rand(rng_state);
868 idx %= xdim * ydim * zdim;
869 if (arr[idx] == 0)
870 {
871 arr_elements_set++;
872 arr[idx] = 1;
873 }
874 }
875
876 int texel_weights_written = 0;
877 int idx = 0;
878 while (texel_weights_written < 64)
879 {
880 if (arr[idx])
881 bsd->texels_for_bitmap_partitioning[texel_weights_written++] = idx;
882 idx++;
883 }
884 bsd->texelcount_for_bitmap_partitioning = 64;
885 }
886 }
887
888 /* Public function, see header file for detailed documentation */
init_block_size_descriptor(int xdim,int ydim,int zdim,block_size_descriptor * bsd)889 void init_block_size_descriptor(
890 int xdim,
891 int ydim,
892 int zdim,
893 block_size_descriptor* bsd
894 ) {
895 if (zdim > 1)
896 construct_block_size_descriptor_3d(xdim, ydim, zdim, bsd);
897 else
898 construct_block_size_descriptor_2d(xdim, ydim, bsd);
899
900 init_partition_tables(bsd);
901 }
902
term_block_size_descriptor(block_size_descriptor * bsd)903 void term_block_size_descriptor(
904 block_size_descriptor* bsd)
905 {
906 for(int i = 0; i < bsd->decimation_mode_count; i++)
907 {
908 delete bsd->decimation_tables[i];
909 }
910 }
911