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#include "Common.comp" 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) { return int(clamp(x, 0, 255)); } 100 101ivec3 _clamp(ivec3 x) { return ivec3(clamp(x, 0, 255)); } 102 103ivec4[16] etc2_T_H_index(ivec3[4] clrTable, uint low, bool isPunchthroughAlpha, bool opaque) { 104 ivec4 ret[16]; 105 for (uint y = 0; y < 4; y++) { 106 for (uint x = 0; x < 4; x++) { 107 uint k = y + x * 4; 108 uint msb = (low >> (k + 15)) & 2; 109 uint lsb = (low >> k) & 1; 110 if (isPunchthroughAlpha && (!opaque) && (msb != 0) && (lsb == 0)) { 111 // rgba all 0 112 ret[y * 4 + x] = ivec4(0, 0, 0, 0); 113 } else { 114 uint offset = lsb | msb; 115 ret[y * 4 + x] = ivec4(clrTable[offset], 255); 116 } 117 } 118 } 119 return ret; 120} 121 122ivec4[16] etc2_decode_block_T(uint high, uint low, bool isPunchthroughAlpha, bool opaque) { 123 const int LUT[] = {3, 6, 11, 16, 23, 32, 41, 64}; 124 int r1, r2, g1, g2, b1, b2; 125 r1 = int(convert4To8((((high >> 27) & 3) << 2) | ((high >> 24) & 3))); 126 g1 = int(convert4To8(high >> 20)); 127 b1 = int(convert4To8(high >> 16)); 128 r2 = int(convert4To8(high >> 12)); 129 g2 = int(convert4To8(high >> 8)); 130 b2 = int(convert4To8(high >> 4)); 131 // 3 bits intense modifier 132 int intenseIdx = int((((high >> 2) & 3) << 1) | (high & 1)); 133 int intenseMod = LUT[intenseIdx]; 134 ivec3 clrTable[4]; 135 clrTable[0] = ivec3(r1, g1, b1); 136 clrTable[1] = ivec3(_clamp(int(r2) + intenseMod), _clamp(int(g2) + intenseMod), 137 _clamp(int(b2) + intenseMod)); 138 clrTable[2] = ivec3(r2, g2, b2); 139 clrTable[3] = ivec3(_clamp(int(r2) - intenseMod), _clamp(int(g2) - intenseMod), 140 _clamp(int(b2) - intenseMod)); 141 return etc2_T_H_index(clrTable, low, isPunchthroughAlpha, opaque); 142} 143 144ivec4[16] etc2_decode_block_H(uint high, uint low, bool isPunchthroughAlpha, bool opaque) { 145 const int LUT[] = {3, 6, 11, 16, 23, 32, 41, 64}; 146 ivec3 rgb1, rgb2; 147 rgb1.r = int(convert4To8(high >> 27)); 148 rgb1.g = int(convert4To8(((high >> 24) << 1) | ((high >> 20) & 1))); 149 rgb1.b = int(convert4To8(((high >> 19) << 3) | ((high >> 15) & 7))); 150 rgb2.r = int(convert4To8(high >> 11)); 151 rgb2.g = int(convert4To8(high >> 7)); 152 rgb2.b = int(convert4To8(high >> 3)); 153 // 3 bits intense modifier 154 uint intenseIdx = high & 4; 155 intenseIdx |= (high & 1) << 1; 156 intenseIdx |= uint(((rgb1.r << 16) | (rgb1.g << 8) | rgb1.b) >= 157 ((rgb2.r << 16) | (rgb2.g << 8) | rgb2.b)); 158 int intenseMod = LUT[intenseIdx]; 159 ivec3 clrTable[4]; 160 clrTable[0] = _clamp(ivec3(rgb1) + intenseMod); 161 clrTable[1] = _clamp(ivec3(rgb1) - intenseMod); 162 clrTable[2] = _clamp(ivec3(rgb2) + intenseMod); 163 clrTable[3] = _clamp(ivec3(rgb2) - intenseMod); 164 return etc2_T_H_index(clrTable, low, isPunchthroughAlpha, opaque); 165} 166 167ivec4[16] etc2_decode_block_P(uint high, uint low, bool isPunchthroughAlpha) { 168 ivec3 rgbo, rgbh, rgbv; 169 rgbo.r = int(convert6To8(high >> 25)); 170 rgbo.g = int(convert7To8(((high >> 24) << 6) | ((high >> 17) & 63))); 171 rgbo.b = int(convert6To8(((high >> 16) << 5) | (((high >> 11) & 3) << 3) | ((high >> 7) & 7))); 172 rgbh.r = int(convert6To8(((high >> 2) << 1) | (high & 1))); 173 rgbh.g = int(convert7To8(low >> 25)); 174 rgbh.b = int(convert6To8(low >> 19)); 175 rgbv.r = int(convert6To8(low >> 13)); 176 rgbv.g = int(convert7To8(low >> 6)); 177 rgbv.b = int(convert6To8(low)); 178 ivec4 ret[16]; 179 for (int i = 0; i < 16; i++) { 180 int y = i >> 2; 181 int x = i & 3; 182 ret[i] = ivec4(_clamp((x * (rgbh - rgbo) + y * (rgbv - rgbo) + 4 * rgbo + 2) >> 2), 255); 183 ret[i].a = 255; 184 } 185 return ret; 186} 187 188void decode_subblock(inout ivec4 pOut[16], int r, int g, int b, ivec4 table, uint low, bool second, 189 bool flipped, bool isPunchthroughAlpha, bool opaque) { 190 uint baseX = 0; 191 uint baseY = 0; 192 if (second) { 193 if (flipped) { 194 baseY = 2; 195 } else { 196 baseX = 2; 197 } 198 } 199 for (int i = 0; i < 8; i++) { 200 uint x, y; 201 if (flipped) { 202 x = baseX + (i >> 1); 203 y = baseY + (i & 1); 204 } else { 205 x = baseX + (i >> 2); 206 y = baseY + (i & 3); 207 } 208 uint k = y + (x * 4); 209 uint msb = ((low >> (k + 15)) & 2); 210 uint lsb = ((low >> k) & 1); 211 uint q = x + 4 * y; 212 if (isPunchthroughAlpha && (!opaque) && (msb != 0) && (lsb == 0)) { 213 // rgba all 0 214 pOut[q] = ivec4(0, 0, 0, 0); 215 } else { 216 uint offset = lsb | msb; 217 int delta = table[offset]; 218 pOut[q] = 219 ivec4(_clamp(int(r) + delta), _clamp(int(g) + delta), _clamp(int(b) + delta), 255); 220 } 221 } 222} 223 224ivec4[16] allZeros() { 225 ivec4[16] ret; 226 for (int i = 0; i < 16; i++) { 227 ret[i] = ivec4(0); 228 } 229 return ret; 230} 231 232ivec4[16] etc2_decode_rgb_block(uint high, uint low, bool isPunchthroughAlpha) { 233 bool opaque = (((high >> 1) & 1) != 0); 234 int r1, r2, g1, g2, b1, b2; 235 if (isPunchthroughAlpha || ((high & 2) != 0)) { 236 // differntial 237 uint rBase = high >> 27; 238 uint gBase = high >> 19; 239 uint bBase = high >> 11; 240 if (isOverflowed(rBase, high >> 24)) { 241 return etc2_decode_block_T(high, low, isPunchthroughAlpha, opaque); 242 } 243 if (isOverflowed(gBase, high >> 16)) { 244 return etc2_decode_block_H(high, low, isPunchthroughAlpha, opaque); 245 } 246 if (isOverflowed(bBase, high >> 8)) { 247 return etc2_decode_block_P(high, low, isPunchthroughAlpha); 248 } 249 r1 = int(convert5To8(rBase)); 250 r2 = int(convertDiff(rBase, high >> 24)); 251 g1 = int(convert5To8(gBase)); 252 g2 = int(convertDiff(gBase, high >> 16)); 253 b1 = int(convert5To8(bBase)); 254 b2 = int(convertDiff(bBase, high >> 8)); 255 } else { 256 // not differential 257 r1 = int(convert4To8(high >> 28)); 258 r2 = int(convert4To8(high >> 24)); 259 g1 = int(convert4To8(high >> 20)); 260 g2 = int(convert4To8(high >> 16)); 261 b1 = int(convert4To8(high >> 12)); 262 b2 = int(convert4To8(high >> 8)); 263 } 264 uint tableIndexA = 7 & (high >> 5); 265 uint tableIndexB = 7 & (high >> 2); 266 ivec4 tableA; 267 ivec4 tableB; 268 if (opaque || !isPunchthroughAlpha) { 269 tableA = kRGBModifierTable[tableIndexA]; 270 tableB = kRGBModifierTable[tableIndexB]; 271 } else { 272 tableA = kRGBOpaqueModifierTable[tableIndexA]; 273 tableB = kRGBOpaqueModifierTable[tableIndexB]; 274 } 275 bool flipped = ((high & 1) != 0); 276 ivec4[16] ret; 277 decode_subblock(ret, r1, g1, b1, tableA, low, false, flipped, isPunchthroughAlpha, opaque); 278 decode_subblock(ret, r2, g2, b2, tableB, low, true, flipped, isPunchthroughAlpha, opaque); 279 return ret; 280} 281 282uint[16] eac_decode_single_channel_block(uint high, uint low, bool isSigned) { 283 int base_codeword = int(high >> 24); 284 base_codeword &= 255; 285 int multiplier = int(high >> 20); 286 multiplier &= 15; 287 288 uint tblIdx = ((high >> 16) & 15); 289 const ivec4 table0 = kAlphaModifierTable[tblIdx * 2]; 290 const ivec4 table1 = kAlphaModifierTable[tblIdx * 2 + 1]; 291 const uint p[16] = { 292 high >> 13, high >> 10, high >> 7, high >> 4, high >> 1, (high << 2) | (low >> 30), 293 low >> 27, low >> 24, low >> 21, low >> 18, low >> 15, low >> 12, 294 low >> 9, low >> 6, low >> 3, low}; 295 uint result[16]; 296 for (uint i = 0; i < 16; i++) { 297 // flip x, y in output 298 uint outIdx = (i % 4) * 4 + i / 4; 299 300 uint modifier = (p[i] & 7); 301 int modifierValue = ((modifier >= 4) ? table1[modifier - 4] : table0[modifier]); 302 int decoded = base_codeword + modifierValue * multiplier; 303 result[outIdx] = uint(_clamp(decoded)); 304 } 305 return result; 306} 307 308float[16] eac_decode_single_channel_block_float(uint high, uint low, bool isSigned) { 309 int base_codeword = int(high >> 24); 310 if (isSigned) { 311 if (base_codeword >= 128) { 312 base_codeword -= 256; 313 } 314 if (base_codeword == -128) { 315 base_codeword = -127; 316 } 317 } 318 int multiplier = int(high >> 20); 319 multiplier &= 15; 320 321 uint tblIdx = ((high >> 16) & 15); 322 const ivec4 table0 = kAlphaModifierTable[tblIdx * 2]; 323 const ivec4 table1 = kAlphaModifierTable[tblIdx * 2 + 1]; 324 const uint p[16] = { 325 high >> 13, high >> 10, high >> 7, high >> 4, high >> 1, (high << 2) | (low >> 30), 326 low >> 27, low >> 24, low >> 21, low >> 18, low >> 15, low >> 12, 327 low >> 9, low >> 6, low >> 3, low}; 328 float result[16]; 329 for (uint i = 0; i < 16; i++) { 330 // flip x, y in output 331 uint outIdx = (i % 4) * 4 + i / 4; 332 333 uint modifier = (p[i] & 7); 334 int modifierValue = ((modifier >= 4) ? table1[modifier - 4] : table0[modifier]); 335 int decoded = base_codeword + modifierValue * multiplier; 336 decoded *= 8; 337 if (multiplier == 0) { 338 decoded += modifierValue; 339 } 340 if (isSigned) { 341 decoded = clamp(decoded, -1023, 1023); 342 result[outIdx] = float(decoded) / 1023.0; 343 } else { 344 decoded += 4; 345 decoded = clamp(decoded, 0, 2047); 346 result[outIdx] = float(decoded) / 2047.0; 347 } 348 } 349 return result; 350} 351 352uint constructUint32(uint a16, uint b16) { 353 uint a2 = (a16 & 0xff) << 8; 354 a2 |= (a16 >> 8) & 0xff; 355 uint b2 = (b16 & 0xff) << 8; 356 b2 |= (b16 >> 8) & 0xff; 357 return (a2 << 16) | b2; 358} 359 360uint flip32(uint a) { 361 return ((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) | 362 ((a & 0xff000000) >> 24); 363} 364 365#define BLOCK_Y_SIZE_1DArray 1 366#define BLOCK_Y_SIZE_2DArray 4 367#define BLOCK_Y_SIZE_3D 4 368