You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
14 KiB
417 lines
14 KiB
// Copyright 2019 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#version 450
|
|
|
|
precision highp int;
|
|
|
|
const uint VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147;
|
|
const uint VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148;
|
|
const uint VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149;
|
|
const uint VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150;
|
|
const uint VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151;
|
|
const uint VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152;
|
|
const uint VK_FORMAT_EAC_R11_UNORM_BLOCK = 153;
|
|
const uint VK_FORMAT_EAC_R11_SNORM_BLOCK = 154;
|
|
const uint VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155;
|
|
const uint VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156;
|
|
|
|
const int kLookup[8] = {0, 1, 2, 3, -4, -3, -2, -1};
|
|
|
|
const ivec4 kRGBModifierTable[] = {
|
|
/* 0 */ {2, 8, -2, -8},
|
|
/* 1 */ {5, 17, -5, -17},
|
|
/* 2 */ {9, 29, -9, -29},
|
|
/* 3 */ {13, 42, -13, -42},
|
|
/* 4 */ {18, 60, -18, -60},
|
|
/* 5 */ {24, 80, -24, -80},
|
|
/* 6 */ {33, 106, -33, -106},
|
|
/* 7 */ {47, 183, -47, -183}};
|
|
|
|
const ivec4 kRGBOpaqueModifierTable[] = {
|
|
/* 0 */ {0, 8, 0, -8},
|
|
/* 1 */ {0, 17, 0, -17},
|
|
/* 2 */ {0, 29, 0, -29},
|
|
/* 3 */ {0, 42, 0, -42},
|
|
/* 4 */ {0, 60, 0, -60},
|
|
/* 5 */ {0, 80, 0, -80},
|
|
/* 6 */ {0, 106, 0, -106},
|
|
/* 7 */ {0, 183, 0, -183}};
|
|
|
|
const ivec4 kAlphaModifierTable[] = {
|
|
/* 0 */ {-3, -6, -9, -15}, {2, 5, 8, 14},
|
|
/* 1 */ {-3, -7, -10, -13}, {2, 6, 9, 12},
|
|
/* 2 */ {-2, -5, -8, -13}, {1, 4, 7, 12},
|
|
/* 3 */ {-2, -4, -6, -13}, {1, 3, 5, 12},
|
|
/* 4 */ {-3, -6, -8, -12}, {2, 5, 7, 11},
|
|
/* 5 */ {-3, -7, -9, -11}, {2, 6, 8, 10},
|
|
/* 6 */ {-4, -7, -8, -11}, {3, 6, 7, 10},
|
|
/* 7 */ {-3, -5, -8, -11}, {2, 4, 7, 10},
|
|
/* 8 */ {-2, -6, -8, -10}, {1, 5, 7, 9},
|
|
/* 9 */ {-2, -5, -8, -10}, {1, 4, 7, 9},
|
|
/* 10 */ {-2, -4, -8, -10}, {1, 3, 7, 9},
|
|
/* 11 */ {-2, -5, -7, -10}, {1, 4, 6, 9},
|
|
/* 12 */ {-3, -4, -7, -10}, {2, 3, 6, 9},
|
|
/* 13 */ {-1, -2, -3, -10}, {0, 1, 2, 9},
|
|
/* 14 */ {-4, -6, -8, -9}, {3, 5, 7, 8},
|
|
/* 15 */ {-3, -5, -7, -9}, {2, 4, 6, 8}};
|
|
|
|
bool isOverflowed(uint base, uint diff) {
|
|
int val = int(0x1f & base) + kLookup[0x7 & diff];
|
|
return (val < 0) || (val >= 32);
|
|
}
|
|
|
|
uint convert4To8(uint b) {
|
|
uint c = b & 0xf;
|
|
return (c << 4) | c;
|
|
}
|
|
|
|
uint convert5To8(uint b) {
|
|
uint c = b & 0x1f;
|
|
return (c << 3) | (c >> 2);
|
|
}
|
|
|
|
uint convert6To8(uint b) {
|
|
uint c = b & 0x3f;
|
|
return (c << 2) | (c >> 4);
|
|
}
|
|
|
|
uint convert7To8(uint b) {
|
|
uint c = b & 0x7f;
|
|
return (c << 1) | (c >> 6);
|
|
}
|
|
|
|
uint convertDiff(uint base, uint diff) {
|
|
return convert5To8(uint(int(0x1f & base) + kLookup[0x7 & diff]));
|
|
}
|
|
|
|
int _clamp(int x) {
|
|
return int(clamp(x, 0, 255));
|
|
}
|
|
|
|
ivec3 _clamp(ivec3 x) {
|
|
return ivec3(clamp(x, 0, 255));
|
|
}
|
|
|
|
ivec4[16] etc2_T_H_index(ivec3[4] clrTable,
|
|
uint low,
|
|
bool isPunchthroughAlpha,
|
|
bool opaque) {
|
|
ivec4 ret[16];
|
|
for (uint y = 0; y < 4; y++) {
|
|
for (uint x = 0; x < 4; x++) {
|
|
uint k = y + x * 4;
|
|
uint msb = (low >> (k + 15)) & 2;
|
|
uint lsb = (low >> k) & 1;
|
|
if (isPunchthroughAlpha && (!opaque) && (msb != 0) && (lsb == 0)) {
|
|
// rgba all 0
|
|
ret[y * 4 + x] = ivec4(0, 0, 0, 0);
|
|
} else {
|
|
uint offset = lsb | msb;
|
|
ret[y * 4 + x] = ivec4(clrTable[offset], 255);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ivec4[16] etc2_decode_block_T(uint high,
|
|
uint low,
|
|
bool isPunchthroughAlpha,
|
|
bool opaque) {
|
|
const int LUT[] = {3, 6, 11, 16, 23, 32, 41, 64};
|
|
int r1, r2, g1, g2, b1, b2;
|
|
r1 = int(convert4To8((((high >> 27) & 3) << 2) | ((high >> 24) & 3)));
|
|
g1 = int(convert4To8(high >> 20));
|
|
b1 = int(convert4To8(high >> 16));
|
|
r2 = int(convert4To8(high >> 12));
|
|
g2 = int(convert4To8(high >> 8));
|
|
b2 = int(convert4To8(high >> 4));
|
|
// 3 bits intense modifier
|
|
int intenseIdx = int((((high >> 2) & 3) << 1) | (high & 1));
|
|
int intenseMod = LUT[intenseIdx];
|
|
ivec3 clrTable[4];
|
|
clrTable[0] = ivec3(r1, g1, b1);
|
|
clrTable[1] =
|
|
ivec3(_clamp(int(r2) + intenseMod), _clamp(int(g2) + intenseMod),
|
|
_clamp(int(b2) + intenseMod));
|
|
clrTable[2] = ivec3(r2, g2, b2);
|
|
clrTable[3] =
|
|
ivec3(_clamp(int(r2) - intenseMod), _clamp(int(g2) - intenseMod),
|
|
_clamp(int(b2) - intenseMod));
|
|
return etc2_T_H_index(clrTable, low, isPunchthroughAlpha, opaque);
|
|
}
|
|
|
|
ivec4[16] etc2_decode_block_H(uint high,
|
|
uint low,
|
|
bool isPunchthroughAlpha,
|
|
bool opaque) {
|
|
const int LUT[] = {3, 6, 11, 16, 23, 32, 41, 64};
|
|
ivec3 rgb1, rgb2;
|
|
rgb1.r = int(convert4To8(high >> 27));
|
|
rgb1.g = int(convert4To8(((high >> 24) << 1) | ((high >> 20) & 1)));
|
|
rgb1.b = int(convert4To8(((high >> 19) << 3) | ((high >> 15) & 7)));
|
|
rgb2.r = int(convert4To8(high >> 11));
|
|
rgb2.g = int(convert4To8(high >> 7));
|
|
rgb2.b = int(convert4To8(high >> 3));
|
|
// 3 bits intense modifier
|
|
uint intenseIdx = high & 4;
|
|
intenseIdx |= (high & 1) << 1;
|
|
intenseIdx |= uint(((rgb1.r << 16) | (rgb1.g << 8) | rgb1.b) >=
|
|
((rgb2.r << 16) | (rgb2.g << 8) | rgb2.b));
|
|
int intenseMod = LUT[intenseIdx];
|
|
ivec3 clrTable[4];
|
|
clrTable[0] = _clamp(ivec3(rgb1) + intenseMod);
|
|
clrTable[1] = _clamp(ivec3(rgb1) - intenseMod);
|
|
clrTable[2] = _clamp(ivec3(rgb2) + intenseMod);
|
|
clrTable[3] = _clamp(ivec3(rgb2) - intenseMod);
|
|
return etc2_T_H_index(clrTable, low, isPunchthroughAlpha, opaque);
|
|
}
|
|
|
|
ivec4[16] etc2_decode_block_P(uint high, uint low, bool isPunchthroughAlpha) {
|
|
ivec3 rgbo, rgbh, rgbv;
|
|
rgbo.r = int(convert6To8(high >> 25));
|
|
rgbo.g = int(convert7To8(((high >> 24) << 6) | ((high >> 17) & 63)));
|
|
rgbo.b = int(convert6To8(((high >> 16) << 5) | (((high >> 11) & 3) << 3) |
|
|
((high >> 7) & 7)));
|
|
rgbh.r = int(convert6To8(((high >> 2) << 1) | (high & 1)));
|
|
rgbh.g = int(convert7To8(low >> 25));
|
|
rgbh.b = int(convert6To8(low >> 19));
|
|
rgbv.r = int(convert6To8(low >> 13));
|
|
rgbv.g = int(convert7To8(low >> 6));
|
|
rgbv.b = int(convert6To8(low));
|
|
ivec4 ret[16];
|
|
for (int i = 0; i < 16; i++) {
|
|
int y = i >> 2;
|
|
int x = i & 3;
|
|
ret[i] = ivec4(
|
|
_clamp((x * (rgbh - rgbo) + y * (rgbv - rgbo) + 4 * rgbo + 2) >>
|
|
2),
|
|
255);
|
|
ret[i].a = 255;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void decode_subblock(inout ivec4 pOut[16],
|
|
int r,
|
|
int g,
|
|
int b,
|
|
ivec4 table,
|
|
uint low,
|
|
bool second,
|
|
bool flipped,
|
|
bool isPunchthroughAlpha,
|
|
bool opaque) {
|
|
uint baseX = 0;
|
|
uint baseY = 0;
|
|
if (second) {
|
|
if (flipped) {
|
|
baseY = 2;
|
|
} else {
|
|
baseX = 2;
|
|
}
|
|
}
|
|
for (int i = 0; i < 8; i++) {
|
|
uint x, y;
|
|
if (flipped) {
|
|
x = baseX + (i >> 1);
|
|
y = baseY + (i & 1);
|
|
} else {
|
|
x = baseX + (i >> 2);
|
|
y = baseY + (i & 3);
|
|
}
|
|
uint k = y + (x * 4);
|
|
uint msb = ((low >> (k + 15)) & 2);
|
|
uint lsb = ((low >> k) & 1);
|
|
uint q = x + 4 * y;
|
|
if (isPunchthroughAlpha && (!opaque) && (msb != 0) && (lsb == 0)) {
|
|
// rgba all 0
|
|
pOut[q] = ivec4(0, 0, 0, 0);
|
|
} else {
|
|
uint offset = lsb | msb;
|
|
int delta = table[offset];
|
|
pOut[q] = ivec4(_clamp(int(r) + delta), _clamp(int(g) + delta),
|
|
_clamp(int(b) + delta), 255);
|
|
}
|
|
}
|
|
}
|
|
|
|
ivec4[16] allZeros() {
|
|
ivec4[16] ret;
|
|
for (int i = 0; i < 16; i++) {
|
|
ret[i] = ivec4(0);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ivec4[16] etc2_decode_rgb_block(uint high, uint low, bool isPunchthroughAlpha) {
|
|
bool opaque = (((high >> 1) & 1) != 0);
|
|
int r1, r2, g1, g2, b1, b2;
|
|
if (isPunchthroughAlpha || ((high & 2) != 0)) {
|
|
// differntial
|
|
uint rBase = high >> 27;
|
|
uint gBase = high >> 19;
|
|
uint bBase = high >> 11;
|
|
if (isOverflowed(rBase, high >> 24)) {
|
|
return etc2_decode_block_T(high, low, isPunchthroughAlpha, opaque);
|
|
}
|
|
if (isOverflowed(gBase, high >> 16)) {
|
|
return etc2_decode_block_H(high, low, isPunchthroughAlpha, opaque);
|
|
}
|
|
if (isOverflowed(bBase, high >> 8)) {
|
|
return etc2_decode_block_P(high, low, isPunchthroughAlpha);
|
|
}
|
|
r1 = int(convert5To8(rBase));
|
|
r2 = int(convertDiff(rBase, high >> 24));
|
|
g1 = int(convert5To8(gBase));
|
|
g2 = int(convertDiff(gBase, high >> 16));
|
|
b1 = int(convert5To8(bBase));
|
|
b2 = int(convertDiff(bBase, high >> 8));
|
|
} else {
|
|
// not differential
|
|
r1 = int(convert4To8(high >> 28));
|
|
r2 = int(convert4To8(high >> 24));
|
|
g1 = int(convert4To8(high >> 20));
|
|
g2 = int(convert4To8(high >> 16));
|
|
b1 = int(convert4To8(high >> 12));
|
|
b2 = int(convert4To8(high >> 8));
|
|
}
|
|
uint tableIndexA = 7 & (high >> 5);
|
|
uint tableIndexB = 7 & (high >> 2);
|
|
ivec4 tableA;
|
|
ivec4 tableB;
|
|
if (opaque || !isPunchthroughAlpha) {
|
|
tableA = kRGBModifierTable[tableIndexA];
|
|
tableB = kRGBModifierTable[tableIndexB];
|
|
} else {
|
|
tableA = kRGBOpaqueModifierTable[tableIndexA];
|
|
tableB = kRGBOpaqueModifierTable[tableIndexB];
|
|
}
|
|
bool flipped = ((high & 1) != 0);
|
|
ivec4[16] ret;
|
|
decode_subblock(ret, r1, g1, b1, tableA, low, false, flipped,
|
|
isPunchthroughAlpha, opaque);
|
|
decode_subblock(ret, r2, g2, b2, tableB, low, true, flipped,
|
|
isPunchthroughAlpha, opaque);
|
|
return ret;
|
|
}
|
|
|
|
uint[16] eac_decode_single_channel_block(uint high, uint low, bool isSigned) {
|
|
int base_codeword = int(high >> 24);
|
|
base_codeword &= 255;
|
|
int multiplier = int(high >> 20);
|
|
multiplier &= 15;
|
|
|
|
uint tblIdx = ((high >> 16) & 15);
|
|
const ivec4 table0 = kAlphaModifierTable[tblIdx * 2];
|
|
const ivec4 table1 = kAlphaModifierTable[tblIdx * 2 + 1];
|
|
const uint p[16] = {high >> 13, high >> 10, high >> 7,
|
|
high >> 4, high >> 1, (high << 2) | (low >> 30),
|
|
low >> 27, low >> 24, low >> 21,
|
|
low >> 18, low >> 15, low >> 12,
|
|
low >> 9, low >> 6, low >> 3,
|
|
low};
|
|
uint result[16];
|
|
for (uint i = 0; i < 16; i++) {
|
|
// flip x, y in output
|
|
uint outIdx = (i % 4) * 4 + i / 4;
|
|
|
|
uint modifier = (p[i] & 7);
|
|
int modifierValue =
|
|
((modifier >= 4) ? table1[modifier - 4] : table0[modifier]);
|
|
int decoded = base_codeword + modifierValue * multiplier;
|
|
result[outIdx] = uint(_clamp(decoded));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
float[16] eac_decode_single_channel_block_float(uint high,
|
|
uint low,
|
|
bool isSigned) {
|
|
int base_codeword = int(high >> 24);
|
|
if (isSigned) {
|
|
if (base_codeword >= 128) {
|
|
base_codeword -= 256;
|
|
}
|
|
if (base_codeword == -128) {
|
|
base_codeword = -127;
|
|
}
|
|
}
|
|
int multiplier = int(high >> 20);
|
|
multiplier &= 15;
|
|
|
|
uint tblIdx = ((high >> 16) & 15);
|
|
const ivec4 table0 = kAlphaModifierTable[tblIdx * 2];
|
|
const ivec4 table1 = kAlphaModifierTable[tblIdx * 2 + 1];
|
|
const uint p[16] = {high >> 13, high >> 10, high >> 7,
|
|
high >> 4, high >> 1, (high << 2) | (low >> 30),
|
|
low >> 27, low >> 24, low >> 21,
|
|
low >> 18, low >> 15, low >> 12,
|
|
low >> 9, low >> 6, low >> 3,
|
|
low};
|
|
float result[16];
|
|
for (uint i = 0; i < 16; i++) {
|
|
// flip x, y in output
|
|
uint outIdx = (i % 4) * 4 + i / 4;
|
|
|
|
uint modifier = (p[i] & 7);
|
|
int modifierValue =
|
|
((modifier >= 4) ? table1[modifier - 4] : table0[modifier]);
|
|
int decoded = base_codeword + modifierValue * multiplier;
|
|
decoded *= 8;
|
|
if (multiplier == 0) {
|
|
decoded += modifierValue;
|
|
}
|
|
if (isSigned) {
|
|
decoded = clamp(decoded, -1023, 1023);
|
|
result[outIdx] = float(decoded) / 1023.0;
|
|
} else {
|
|
decoded += 4;
|
|
decoded = clamp(decoded, 0, 2047);
|
|
result[outIdx] = float(decoded) / 2047.0;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
uint constructUint32(uint a16, uint b16) {
|
|
uint a2 = (a16 & 0xff) << 8;
|
|
a2 |= (a16 >> 8) & 0xff;
|
|
uint b2 = (b16 & 0xff) << 8;
|
|
b2 |= (b16 >> 8) & 0xff;
|
|
return (a2 << 16) | b2;
|
|
}
|
|
|
|
uint flip32(uint a) {
|
|
return ((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) |
|
|
((a & 0xff000000) >> 24);
|
|
}
|
|
|
|
ivec2 getPos1DArray(ivec3 pos) {
|
|
return ivec2(pos.x, pos.z);
|
|
}
|
|
|
|
ivec3 getPos2DArray(ivec3 pos) {
|
|
return pos;
|
|
}
|
|
|
|
ivec3 getPos3D(ivec3 pos) {
|
|
return pos;
|
|
}
|
|
|
|
#define BLOCK_Y_SIZE_1DArray 1
|
|
#define BLOCK_Y_SIZE_2DArray 4
|
|
#define BLOCK_Y_SIZE_3D 4
|