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