• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#version 450
16
17precision highp int;
18
19const uint VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147;
20const uint VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148;
21const uint VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149;
22const uint VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150;
23const uint VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151;
24const uint VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152;
25const uint VK_FORMAT_EAC_R11_UNORM_BLOCK = 153;
26const uint VK_FORMAT_EAC_R11_SNORM_BLOCK = 154;
27const uint VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155;
28const uint VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156;
29
30const int kLookup[8] = {0, 1, 2, 3, -4, -3, -2, -1};
31
32const ivec4 kRGBModifierTable[] = {
33        /* 0 */ {2, 8, -2, -8},
34        /* 1 */ {5, 17, -5, -17},
35        /* 2 */ {9, 29, -9, -29},
36        /* 3 */ {13, 42, -13, -42},
37        /* 4 */ {18, 60, -18, -60},
38        /* 5 */ {24, 80, -24, -80},
39        /* 6 */ {33, 106, -33, -106},
40        /* 7 */ {47, 183, -47, -183}};
41
42const ivec4 kRGBOpaqueModifierTable[] = {
43        /* 0 */ {0, 8, 0, -8},
44        /* 1 */ {0, 17, 0, -17},
45        /* 2 */ {0, 29, 0, -29},
46        /* 3 */ {0, 42, 0, -42},
47        /* 4 */ {0, 60, 0, -60},
48        /* 5 */ {0, 80, 0, -80},
49        /* 6 */ {0, 106, 0, -106},
50        /* 7 */ {0, 183, 0, -183}};
51
52const ivec4 kAlphaModifierTable[] = {
53        /* 0 */ {-3, -6, -9, -15},  {2, 5, 8, 14},
54        /* 1 */ {-3, -7, -10, -13}, {2, 6, 9, 12},
55        /* 2 */ {-2, -5, -8, -13},  {1, 4, 7, 12},
56        /* 3 */ {-2, -4, -6, -13},  {1, 3, 5, 12},
57        /* 4 */ {-3, -6, -8, -12},  {2, 5, 7, 11},
58        /* 5 */ {-3, -7, -9, -11},  {2, 6, 8, 10},
59        /* 6 */ {-4, -7, -8, -11},  {3, 6, 7, 10},
60        /* 7 */ {-3, -5, -8, -11},  {2, 4, 7, 10},
61        /* 8 */ {-2, -6, -8, -10},  {1, 5, 7, 9},
62        /* 9 */ {-2, -5, -8, -10},  {1, 4, 7, 9},
63        /* 10 */ {-2, -4, -8, -10}, {1, 3, 7, 9},
64        /* 11 */ {-2, -5, -7, -10}, {1, 4, 6, 9},
65        /* 12 */ {-3, -4, -7, -10}, {2, 3, 6, 9},
66        /* 13 */ {-1, -2, -3, -10}, {0, 1, 2, 9},
67        /* 14 */ {-4, -6, -8, -9},  {3, 5, 7, 8},
68        /* 15 */ {-3, -5, -7, -9},  {2, 4, 6, 8}};
69
70bool isOverflowed(uint base, uint diff) {
71    int val = int(0x1f & base) + kLookup[0x7 & diff];
72    return (val < 0) || (val >= 32);
73}
74
75uint convert4To8(uint b) {
76    uint c = b & 0xf;
77    return (c << 4) | c;
78}
79
80uint convert5To8(uint b) {
81    uint c = b & 0x1f;
82    return (c << 3) | (c >> 2);
83}
84
85uint convert6To8(uint b) {
86    uint c = b & 0x3f;
87    return (c << 2) | (c >> 4);
88}
89
90uint convert7To8(uint b) {
91    uint c = b & 0x7f;
92    return (c << 1) | (c >> 6);
93}
94
95uint convertDiff(uint base, uint diff) {
96    return convert5To8(uint(int(0x1f & base) + kLookup[0x7 & diff]));
97}
98
99int _clamp(int x) {
100    return int(clamp(x, 0, 255));
101}
102
103ivec3 _clamp(ivec3 x) {
104    return ivec3(clamp(x, 0, 255));
105}
106
107ivec4[16] etc2_T_H_index(ivec3[4] clrTable,
108                         uint low,
109                         bool isPunchthroughAlpha,
110                         bool opaque) {
111    ivec4 ret[16];
112    for (uint y = 0; y < 4; y++) {
113        for (uint x = 0; x < 4; x++) {
114            uint k = y + x * 4;
115            uint msb = (low >> (k + 15)) & 2;
116            uint lsb = (low >> k) & 1;
117            if (isPunchthroughAlpha && (!opaque) && (msb != 0) && (lsb == 0)) {
118                // rgba all 0
119                ret[y * 4 + x] = ivec4(0, 0, 0, 0);
120            } else {
121                uint offset = lsb | msb;
122                ret[y * 4 + x] = ivec4(clrTable[offset], 255);
123            }
124        }
125    }
126    return ret;
127}
128
129ivec4[16] etc2_decode_block_T(uint high,
130                              uint low,
131                              bool isPunchthroughAlpha,
132                              bool opaque) {
133    const int LUT[] = {3, 6, 11, 16, 23, 32, 41, 64};
134    int r1, r2, g1, g2, b1, b2;
135    r1 = int(convert4To8((((high >> 27) & 3) << 2) | ((high >> 24) & 3)));
136    g1 = int(convert4To8(high >> 20));
137    b1 = int(convert4To8(high >> 16));
138    r2 = int(convert4To8(high >> 12));
139    g2 = int(convert4To8(high >> 8));
140    b2 = int(convert4To8(high >> 4));
141    // 3 bits intense modifier
142    int intenseIdx = int((((high >> 2) & 3) << 1) | (high & 1));
143    int intenseMod = LUT[intenseIdx];
144    ivec3 clrTable[4];
145    clrTable[0] = ivec3(r1, g1, b1);
146    clrTable[1] =
147            ivec3(_clamp(int(r2) + intenseMod), _clamp(int(g2) + intenseMod),
148                  _clamp(int(b2) + intenseMod));
149    clrTable[2] = ivec3(r2, g2, b2);
150    clrTable[3] =
151            ivec3(_clamp(int(r2) - intenseMod), _clamp(int(g2) - intenseMod),
152                  _clamp(int(b2) - intenseMod));
153    return etc2_T_H_index(clrTable, low, isPunchthroughAlpha, opaque);
154}
155
156ivec4[16] etc2_decode_block_H(uint high,
157                              uint low,
158                              bool isPunchthroughAlpha,
159                              bool opaque) {
160    const int LUT[] = {3, 6, 11, 16, 23, 32, 41, 64};
161    ivec3 rgb1, rgb2;
162    rgb1.r = int(convert4To8(high >> 27));
163    rgb1.g = int(convert4To8(((high >> 24) << 1) | ((high >> 20) & 1)));
164    rgb1.b = int(convert4To8(((high >> 19) << 3) | ((high >> 15) & 7)));
165    rgb2.r = int(convert4To8(high >> 11));
166    rgb2.g = int(convert4To8(high >> 7));
167    rgb2.b = int(convert4To8(high >> 3));
168    // 3 bits intense modifier
169    uint intenseIdx = high & 4;
170    intenseIdx |= (high & 1) << 1;
171    intenseIdx |= uint(((rgb1.r << 16) | (rgb1.g << 8) | rgb1.b) >=
172                      ((rgb2.r << 16) | (rgb2.g << 8) | rgb2.b));
173    int intenseMod = LUT[intenseIdx];
174    ivec3 clrTable[4];
175    clrTable[0] = _clamp(ivec3(rgb1) + intenseMod);
176    clrTable[1] = _clamp(ivec3(rgb1) - intenseMod);
177    clrTable[2] = _clamp(ivec3(rgb2) + intenseMod);
178    clrTable[3] = _clamp(ivec3(rgb2) - intenseMod);
179    return etc2_T_H_index(clrTable, low, isPunchthroughAlpha, opaque);
180}
181
182ivec4[16] etc2_decode_block_P(uint high, uint low, bool isPunchthroughAlpha) {
183    ivec3 rgbo, rgbh, rgbv;
184    rgbo.r = int(convert6To8(high >> 25));
185    rgbo.g = int(convert7To8(((high >> 24) << 6) | ((high >> 17) & 63)));
186    rgbo.b = int(convert6To8(((high >> 16) << 5) | (((high >> 11) & 3) << 3) |
187                             ((high >> 7) & 7)));
188    rgbh.r = int(convert6To8(((high >> 2) << 1) | (high & 1)));
189    rgbh.g = int(convert7To8(low >> 25));
190    rgbh.b = int(convert6To8(low >> 19));
191    rgbv.r = int(convert6To8(low >> 13));
192    rgbv.g = int(convert7To8(low >> 6));
193    rgbv.b = int(convert6To8(low));
194    ivec4 ret[16];
195    for (int i = 0; i < 16; i++) {
196        int y = i >> 2;
197        int x = i & 3;
198        ret[i] = ivec4(
199                _clamp((x * (rgbh - rgbo) + y * (rgbv - rgbo) + 4 * rgbo + 2) >>
200                       2),
201                255);
202        ret[i].a = 255;
203    }
204    return ret;
205}
206
207void decode_subblock(inout ivec4 pOut[16],
208                     int r,
209                     int g,
210                     int b,
211                     ivec4 table,
212                     uint low,
213                     bool second,
214                     bool flipped,
215                     bool isPunchthroughAlpha,
216                     bool opaque) {
217    uint baseX = 0;
218    uint baseY = 0;
219    if (second) {
220        if (flipped) {
221            baseY = 2;
222        } else {
223            baseX = 2;
224        }
225    }
226    for (int i = 0; i < 8; i++) {
227        uint x, y;
228        if (flipped) {
229            x = baseX + (i >> 1);
230            y = baseY + (i & 1);
231        } else {
232            x = baseX + (i >> 2);
233            y = baseY + (i & 3);
234        }
235        uint k = y + (x * 4);
236        uint msb = ((low >> (k + 15)) & 2);
237        uint lsb = ((low >> k) & 1);
238        uint q = x + 4 * y;
239        if (isPunchthroughAlpha && (!opaque) && (msb != 0) && (lsb == 0)) {
240            // rgba all 0
241            pOut[q] = ivec4(0, 0, 0, 0);
242        } else {
243            uint offset = lsb | msb;
244            int delta = table[offset];
245            pOut[q] = ivec4(_clamp(int(r) + delta), _clamp(int(g) + delta),
246                            _clamp(int(b) + delta), 255);
247        }
248    }
249}
250
251ivec4[16] allZeros() {
252    ivec4[16] ret;
253    for (int i = 0; i < 16; i++) {
254        ret[i] = ivec4(0);
255    }
256    return ret;
257}
258
259ivec4[16] etc2_decode_rgb_block(uint high, uint low, bool isPunchthroughAlpha) {
260    bool opaque = (((high >> 1) & 1) != 0);
261    int r1, r2, g1, g2, b1, b2;
262    if (isPunchthroughAlpha || ((high & 2) != 0)) {
263        // differntial
264        uint rBase = high >> 27;
265        uint gBase = high >> 19;
266        uint bBase = high >> 11;
267        if (isOverflowed(rBase, high >> 24)) {
268            return etc2_decode_block_T(high, low, isPunchthroughAlpha, opaque);
269        }
270        if (isOverflowed(gBase, high >> 16)) {
271            return etc2_decode_block_H(high, low, isPunchthroughAlpha, opaque);
272        }
273        if (isOverflowed(bBase, high >> 8)) {
274            return etc2_decode_block_P(high, low, isPunchthroughAlpha);
275        }
276        r1 = int(convert5To8(rBase));
277        r2 = int(convertDiff(rBase, high >> 24));
278        g1 = int(convert5To8(gBase));
279        g2 = int(convertDiff(gBase, high >> 16));
280        b1 = int(convert5To8(bBase));
281        b2 = int(convertDiff(bBase, high >> 8));
282    } else {
283        // not differential
284        r1 = int(convert4To8(high >> 28));
285        r2 = int(convert4To8(high >> 24));
286        g1 = int(convert4To8(high >> 20));
287        g2 = int(convert4To8(high >> 16));
288        b1 = int(convert4To8(high >> 12));
289        b2 = int(convert4To8(high >> 8));
290    }
291    uint tableIndexA = 7 & (high >> 5);
292    uint tableIndexB = 7 & (high >> 2);
293    ivec4 tableA;
294    ivec4 tableB;
295    if (opaque || !isPunchthroughAlpha) {
296        tableA = kRGBModifierTable[tableIndexA];
297        tableB = kRGBModifierTable[tableIndexB];
298    } else {
299        tableA = kRGBOpaqueModifierTable[tableIndexA];
300        tableB = kRGBOpaqueModifierTable[tableIndexB];
301    }
302    bool flipped = ((high & 1) != 0);
303    ivec4[16] ret;
304    decode_subblock(ret, r1, g1, b1, tableA, low, false, flipped,
305                    isPunchthroughAlpha, opaque);
306    decode_subblock(ret, r2, g2, b2, tableB, low, true, flipped,
307                    isPunchthroughAlpha, opaque);
308    return ret;
309}
310
311uint[16] eac_decode_single_channel_block(uint high, uint low, bool isSigned) {
312    int base_codeword = int(high >> 24);
313    base_codeword &= 255;
314    int multiplier = int(high >> 20);
315    multiplier &= 15;
316
317    uint tblIdx = ((high >> 16) & 15);
318    const ivec4 table0 = kAlphaModifierTable[tblIdx * 2];
319    const ivec4 table1 = kAlphaModifierTable[tblIdx * 2 + 1];
320    const uint p[16] = {high >> 13, high >> 10, high >> 7,
321                        high >> 4,  high >> 1,  (high << 2) | (low >> 30),
322                        low >> 27,  low >> 24,  low >> 21,
323                        low >> 18,  low >> 15,  low >> 12,
324                        low >> 9,   low >> 6,   low >> 3,
325                        low};
326    uint result[16];
327    for (uint i = 0; i < 16; i++) {
328        // flip x, y in output
329        uint outIdx = (i % 4) * 4 + i / 4;
330
331        uint modifier = (p[i] & 7);
332        int modifierValue =
333                ((modifier >= 4) ? table1[modifier - 4] : table0[modifier]);
334        int decoded = base_codeword + modifierValue * multiplier;
335        result[outIdx] = uint(_clamp(decoded));
336    }
337    return result;
338}
339
340float[16] eac_decode_single_channel_block_float(uint high,
341                                                uint low,
342                                                bool isSigned) {
343    int base_codeword = int(high >> 24);
344    if (isSigned) {
345        if (base_codeword >= 128) {
346            base_codeword -= 256;
347        }
348        if (base_codeword == -128) {
349            base_codeword = -127;
350        }
351    }
352    int multiplier = int(high >> 20);
353    multiplier &= 15;
354
355    uint tblIdx = ((high >> 16) & 15);
356    const ivec4 table0 = kAlphaModifierTable[tblIdx * 2];
357    const ivec4 table1 = kAlphaModifierTable[tblIdx * 2 + 1];
358    const uint p[16] = {high >> 13, high >> 10, high >> 7,
359                        high >> 4,  high >> 1,  (high << 2) | (low >> 30),
360                        low >> 27,  low >> 24,  low >> 21,
361                        low >> 18,  low >> 15,  low >> 12,
362                        low >> 9,   low >> 6,   low >> 3,
363                        low};
364    float result[16];
365    for (uint i = 0; i < 16; i++) {
366        // flip x, y in output
367        uint outIdx = (i % 4) * 4 + i / 4;
368
369        uint modifier = (p[i] & 7);
370        int modifierValue =
371                ((modifier >= 4) ? table1[modifier - 4] : table0[modifier]);
372        int decoded = base_codeword + modifierValue * multiplier;
373        decoded *= 8;
374        if (multiplier == 0) {
375            decoded += modifierValue;
376        }
377        if (isSigned) {
378            decoded = clamp(decoded, -1023, 1023);
379            result[outIdx] = float(decoded) / 1023.0;
380        } else {
381            decoded += 4;
382            decoded = clamp(decoded, 0, 2047);
383            result[outIdx] = float(decoded) / 2047.0;
384        }
385    }
386    return result;
387}
388
389uint constructUint32(uint a16, uint b16) {
390    uint a2 = (a16 & 0xff) << 8;
391    a2 |= (a16 >> 8) & 0xff;
392    uint b2 = (b16 & 0xff) << 8;
393    b2 |= (b16 >> 8) & 0xff;
394    return (a2 << 16) | b2;
395}
396
397uint flip32(uint a) {
398    return ((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) |
399           ((a & 0xff000000) >> 24);
400}
401
402ivec2 getPos1DArray(ivec3 pos) {
403    return ivec2(pos.x, pos.z);
404}
405
406ivec3 getPos2DArray(ivec3 pos) {
407    return pos;
408}
409
410ivec3 getPos3D(ivec3 pos) {
411    return pos;
412}
413
414#define BLOCK_Y_SIZE_1DArray 1
415#define BLOCK_Y_SIZE_2DArray 4
416#define BLOCK_Y_SIZE_3D 4
417