1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2023 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 // astcenc doesn't use the top 8 integer bits directly for sRGB RGB components
19 // or when using the decode_unorm8 decode mode. An alterantive is used which
20 // allows a common code path to be used. This test program shows that the two
21 // produce equivalent output once rounded to a decode_unorm8 output.
22 
23 // Compile with e.g. clang++ astcenc_u8_test_bench.cpp -o astcenc_u8_test_bench -mavx2 -mf16c
24 
25 #define ASTCENC_AVX 2
26 #define ASTCENC_F16C 1
27 #define ASTCENC_SSE 41
28 
29 #include "../Source/astcenc_mathlib.cpp"
30 #include "../Source/astcenc_color_unquantize.cpp"
31 #include "../Source/astcenc_decompress_symbolic.cpp"
32 
main()33 int main()
34 {
35     printf("Decode mode test bench\n");
36 
37     for (int ep0 = 0; ep0 < 256; ep0++)
38     {
39         for (int ep1 = 0; ep1 < 256; ep1++)
40         {
41             for (int wt1 = 0; wt1 < 65; wt1++)
42             {
43                 // Validate linear data with decode_unorm8 mode
44                 {
45                     // Expand 8 bit to 16 bit
46                     vint4 weights(wt1);
47                     int ep0_v0 = ep0 * 257;
48                     int ep1_v0 = ep1 * 257;
49 
50                     // Linear with decode_u8 handling
51                     vmask4 decode_u8_v0(true, true, true, true);
52                     vint4 ep0v0(ep0_v0, ep0_v0, ep0_v0, ep0_v0);
53                     vint4 ep1v0(ep1_v0, ep1_v0, ep1_v0, ep1_v0);
54 
55                     // Linear without decode_u8 handling
56                     vmask4 decode_u8_v1(false, false, false, false);
57                     vint4 ep0v1(ep0_v0, ep0_v0, ep0_v0, ep0_v0);
58                     vint4 ep1v1(ep1_v0, ep1_v0, ep1_v0, ep1_v0);
59 
60                     // Lerp both styles
61                     vint4 colorv0 = lerp_color_int(decode_u8_v0, ep0v0, ep1v0, weights);
62                     vint4 colorv1 = lerp_color_int(decode_u8_v1, ep0v1, ep1v1, weights);
63 
64                     // Validate top 8 integer bits match in both cases
65                     //  - Shows that astcenc-style U8 doesn't differ from Khronos-style U8
66                     vint4 cs0 = lsr<8>(colorv0);
67                     vint4 cs1 = lsr<8>(colorv1);
68                     assert(cs0.lane<0>() == cs1.lane<0>());
69                     assert(cs0.lane<3>() == cs1.lane<3>());
70 
71                     // Validate that astcenc output matches the top 8 integer bits
72                     vfloat4 colorv0f = decode_texel(colorv0, vmask4(false));
73                     vint4 colorv0_out = float_to_int_rtn(colorv0f * 255.0f);
74                     assert(colorv0_out.lane<0>() == cs0.lane<0>());
75                 }
76 
77                 // Validate sRGB data with decode_unorm8 mode
78                 {
79                     // Expand 8 bit to 16 bit
80                     vint4 weights(wt1);
81                     int ep0_v0s = (ep0 << 8) | 0x80;
82                     int ep1_v0s = (ep1 << 8) | 0x80;
83                     int ep0_v0 = ep0 * 257;
84                     int ep1_v0 = ep1 * 257;
85 
86                     // sRGB RGB and linear A with decode_u8 handling
87                     vmask4 decode_u8_v0(true, true, true, true);
88                     vint4 ep0v0(ep0_v0s, ep0_v0s, ep0_v0s, ep0_v0);
89                     vint4 ep1v0(ep1_v0s, ep1_v0s, ep1_v0s, ep1_v0);
90 
91                     // sRGB RGB and linear A without decode_u8 handling
92                     vmask4 decode_u8_v1(false, false, false, false);
93                     vint4 ep0v1(ep0_v0s, ep0_v0s, ep0_v0s, ep0_v0);
94                     vint4 ep1v1(ep1_v0s, ep1_v0s, ep1_v0s, ep1_v0);
95 
96                     // Lerp both styles
97                     vint4 colorv0 = lerp_color_int(decode_u8_v0, ep0v0, ep1v0, weights);
98                     vint4 colorv1 = lerp_color_int(decode_u8_v1, ep0v1, ep1v1, weights);
99 
100                     // Validate top 8 integer bits match in both cases
101                     //  - Shows that astcenc-style U8 doesn't differ from Khronos-style U8
102                     vint4 cs0 = lsr<8>(colorv0);
103                     vint4 cs1 = lsr<8>(colorv1);
104                     assert(cs0.lane<0>() == cs1.lane<0>());
105                     assert(cs0.lane<3>() == cs1.lane<3>());
106 
107                     // Validate that astcenc output matches the top 8 integer bits
108                     vfloat4 colorv0f = decode_texel(colorv0, vmask4(false));
109                     vint4 colorv0_out = float_to_int_rtn(colorv0f * 255.0f);
110                     assert(colorv0_out.lane<0>() == cs0.lane<0>());
111                 }
112             }
113         }
114     }
115 
116     return 0;
117 }
118