1*61046927SAndroid Build Coastguard Worker#version 320 es 2*61046927SAndroid Build Coastguard Workerprecision highp float; 3*61046927SAndroid Build Coastguard Workerprecision highp int; 4*61046927SAndroid Build Coastguard Workerprecision highp usamplerBuffer; 5*61046927SAndroid Build Coastguard Workerprecision highp usampler2D; 6*61046927SAndroid Build Coastguard Workerprecision highp image2D; 7*61046927SAndroid Build Coastguard Workerprecision highp uimage2D; 8*61046927SAndroid Build Coastguard Worker 9*61046927SAndroid Build Coastguard Worker/* Copyright (c) 2020-2022 Hans-Kristian Arntzen 10*61046927SAndroid Build Coastguard Worker * Copyright (c) 2022 Intel Corporation 11*61046927SAndroid Build Coastguard Worker * 12*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining 13*61046927SAndroid Build Coastguard Worker * a copy of this software and associated documentation files (the 14*61046927SAndroid Build Coastguard Worker * "Software"), to deal in the Software without restriction, including 15*61046927SAndroid Build Coastguard Worker * without limitation the rights to use, copy, modify, merge, publish, 16*61046927SAndroid Build Coastguard Worker * distribute, sublicense, and/or sell copies of the Software, and to 17*61046927SAndroid Build Coastguard Worker * permit persons to whom the Software is furnished to do so, subject to 18*61046927SAndroid Build Coastguard Worker * the following conditions: 19*61046927SAndroid Build Coastguard Worker * 20*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be 21*61046927SAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software. 22*61046927SAndroid Build Coastguard Worker * 23*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24*61046927SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25*61046927SAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 26*61046927SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 27*61046927SAndroid Build Coastguard Worker * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 28*61046927SAndroid Build Coastguard Worker * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 29*61046927SAndroid Build Coastguard Worker * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30*61046927SAndroid Build Coastguard Worker */ 31*61046927SAndroid Build Coastguard Worker 32*61046927SAndroid Build Coastguard Worker#ifdef VULKAN 33*61046927SAndroid Build Coastguard Worker 34*61046927SAndroid Build Coastguard Workerprecision highp utextureBuffer; 35*61046927SAndroid Build Coastguard Workerprecision highp utexture2DArray; 36*61046927SAndroid Build Coastguard Workerprecision highp uimage2DArray; 37*61046927SAndroid Build Coastguard Workerprecision highp uimage3D; 38*61046927SAndroid Build Coastguard Workerprecision highp utexture3D; 39*61046927SAndroid Build Coastguard Worker 40*61046927SAndroid Build Coastguard Worker#extension GL_EXT_samplerless_texture_functions : require 41*61046927SAndroid Build Coastguard Workerlayout(local_size_x_id = 0, local_size_y_id = 1, local_size_z = 4) in; 42*61046927SAndroid Build Coastguard Worker 43*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 0) writeonly uniform uimage2DArray OutputImage2Darray; 44*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 0) writeonly uniform uimage3D OutputImage3D; 45*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 1) uniform utexture2DArray PayloadInput2Darray; 46*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 1) uniform utexture3D PayloadInput3D; 47*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 2) uniform utextureBuffer LUTRemainingBitsToEndpointQuantizer; 48*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 3) uniform utextureBuffer LUTEndpointUnquantize; 49*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 4) uniform utextureBuffer LUTWeightQuantizer; 50*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 5) uniform utextureBuffer LUTWeightUnquantize; 51*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 6) uniform utextureBuffer LUTTritQuintDecode; 52*61046927SAndroid Build Coastguard Workerlayout(set = 0, binding = 7) uniform utextureBuffer LUTPartitionTable; 53*61046927SAndroid Build Coastguard Worker 54*61046927SAndroid Build Coastguard Workerlayout(constant_id = 2) const bool DECODE_8BIT = false; 55*61046927SAndroid Build Coastguard Worker 56*61046927SAndroid Build Coastguard Workerlayout(push_constant, std430) uniform pc { 57*61046927SAndroid Build Coastguard Worker ivec2 texel_blk_start; 58*61046927SAndroid Build Coastguard Worker ivec2 texel_end; 59*61046927SAndroid Build Coastguard Worker bool is_3Dimage; 60*61046927SAndroid Build Coastguard Worker}; 61*61046927SAndroid Build Coastguard Worker 62*61046927SAndroid Build Coastguard Worker#else /* VULKAN */ 63*61046927SAndroid Build Coastguard Worker 64*61046927SAndroid Build Coastguard Workerlayout(local_size_x = %u, local_size_y = %u, local_size_z = 4) in; 65*61046927SAndroid Build Coastguard Worker 66*61046927SAndroid Build Coastguard Worker#define utextureBuffer usamplerBuffer 67*61046927SAndroid Build Coastguard Worker#define utexture2D usampler2D 68*61046927SAndroid Build Coastguard Worker 69*61046927SAndroid Build Coastguard Workerlayout(binding = 0) uniform utextureBuffer LUTRemainingBitsToEndpointQuantizer; 70*61046927SAndroid Build Coastguard Workerlayout(binding = 1) uniform utextureBuffer LUTEndpointUnquantize; 71*61046927SAndroid Build Coastguard Workerlayout(binding = 2) uniform utextureBuffer LUTWeightQuantizer; 72*61046927SAndroid Build Coastguard Workerlayout(binding = 3) uniform utextureBuffer LUTWeightUnquantize; 73*61046927SAndroid Build Coastguard Workerlayout(binding = 4) uniform utextureBuffer LUTTritQuintDecode; 74*61046927SAndroid Build Coastguard Workerlayout(binding = 5) uniform utexture2D LUTPartitionTable; 75*61046927SAndroid Build Coastguard Workerlayout(binding = 6) uniform utexture2D PayloadInput; 76*61046927SAndroid Build Coastguard Worker 77*61046927SAndroid Build Coastguard Workerlayout(rgba8ui, binding = 7) writeonly uniform uimage2D OutputImage; 78*61046927SAndroid Build Coastguard Workerconst bool DECODE_8BIT = true; 79*61046927SAndroid Build Coastguard Worker 80*61046927SAndroid Build Coastguard Worker#endif /* VULKAN */ 81*61046927SAndroid Build Coastguard Worker 82*61046927SAndroid Build Coastguard Workerconst int MODE_LDR = 0; 83*61046927SAndroid Build Coastguard Workerconst int MODE_HDR = 1; 84*61046927SAndroid Build Coastguard Workerconst int MODE_HDR_LDR_ALPHA = 2; 85*61046927SAndroid Build Coastguard Worker 86*61046927SAndroid Build Coastguard Workerconst uvec4 error_color = uvec4(255, 0, 255, 255); 87*61046927SAndroid Build Coastguard Worker 88*61046927SAndroid Build Coastguard Worker/* bitextract.h */ 89*61046927SAndroid Build Coastguard Workerint extract_bits(uvec4 payload, int offset, int bits) 90*61046927SAndroid Build Coastguard Worker{ 91*61046927SAndroid Build Coastguard Worker int last_offset = offset + bits - 1; 92*61046927SAndroid Build Coastguard Worker int result; 93*61046927SAndroid Build Coastguard Worker 94*61046927SAndroid Build Coastguard Worker if (bits <= 0) 95*61046927SAndroid Build Coastguard Worker result = 0; 96*61046927SAndroid Build Coastguard Worker else if ((last_offset >> 5) == (offset >> 5)) 97*61046927SAndroid Build Coastguard Worker result = int(bitfieldExtract(payload[offset >> 5], offset & 31, bits)); 98*61046927SAndroid Build Coastguard Worker else 99*61046927SAndroid Build Coastguard Worker { 100*61046927SAndroid Build Coastguard Worker int first_bits = 32 - (offset & 31); 101*61046927SAndroid Build Coastguard Worker int result_first = int(bitfieldExtract(payload[offset >> 5], offset & 31, first_bits)); 102*61046927SAndroid Build Coastguard Worker int result_second = int(bitfieldExtract(payload[(offset >> 5) + 1], 0, bits - first_bits)); 103*61046927SAndroid Build Coastguard Worker result = result_first | (result_second << first_bits); 104*61046927SAndroid Build Coastguard Worker } 105*61046927SAndroid Build Coastguard Worker return result; 106*61046927SAndroid Build Coastguard Worker} 107*61046927SAndroid Build Coastguard Worker 108*61046927SAndroid Build Coastguard Worker/* bitextract.h */ 109*61046927SAndroid Build Coastguard Workerint extract_bits_sign(uvec4 payload, int offset, int bits) 110*61046927SAndroid Build Coastguard Worker{ 111*61046927SAndroid Build Coastguard Worker int last_offset = offset + bits - 1; 112*61046927SAndroid Build Coastguard Worker int result; 113*61046927SAndroid Build Coastguard Worker 114*61046927SAndroid Build Coastguard Worker if (bits <= 0) 115*61046927SAndroid Build Coastguard Worker result = 0; 116*61046927SAndroid Build Coastguard Worker else if ((last_offset >> 5) == (offset >> 5)) 117*61046927SAndroid Build Coastguard Worker result = bitfieldExtract(int(payload[offset >> 5]), offset & 31, bits); 118*61046927SAndroid Build Coastguard Worker else 119*61046927SAndroid Build Coastguard Worker { 120*61046927SAndroid Build Coastguard Worker int first_bits = 32 - (offset & 31); 121*61046927SAndroid Build Coastguard Worker int result_first = int(bitfieldExtract(payload[offset >> 5], offset & 31, first_bits)); 122*61046927SAndroid Build Coastguard Worker int result_second = bitfieldExtract(int(payload[(offset >> 5) + 1]), 0, bits - first_bits); 123*61046927SAndroid Build Coastguard Worker result = result_first | (result_second << first_bits); 124*61046927SAndroid Build Coastguard Worker } 125*61046927SAndroid Build Coastguard Worker return result; 126*61046927SAndroid Build Coastguard Worker} 127*61046927SAndroid Build Coastguard Worker 128*61046927SAndroid Build Coastguard Worker/* bitextract.h */ 129*61046927SAndroid Build Coastguard Workerint extract_bits_reverse(uvec4 payload, int offset, int bits) 130*61046927SAndroid Build Coastguard Worker{ 131*61046927SAndroid Build Coastguard Worker int last_offset = offset + bits - 1; 132*61046927SAndroid Build Coastguard Worker int result; 133*61046927SAndroid Build Coastguard Worker 134*61046927SAndroid Build Coastguard Worker if (bits <= 0) 135*61046927SAndroid Build Coastguard Worker result = 0; 136*61046927SAndroid Build Coastguard Worker else if ((last_offset >> 5) == (offset >> 5)) 137*61046927SAndroid Build Coastguard Worker result = int(bitfieldReverse(bitfieldExtract(payload[offset >> 5], offset & 31, bits)) >> (32 - bits)); 138*61046927SAndroid Build Coastguard Worker else 139*61046927SAndroid Build Coastguard Worker { 140*61046927SAndroid Build Coastguard Worker int first_bits = 32 - (offset & 31); 141*61046927SAndroid Build Coastguard Worker uint result_first = bitfieldExtract(payload[offset >> 5], offset & 31, first_bits); 142*61046927SAndroid Build Coastguard Worker uint result_second = bitfieldExtract(payload[(offset >> 5) + 1], 0, bits - first_bits); 143*61046927SAndroid Build Coastguard Worker result = int(bitfieldReverse(result_first | (result_second << first_bits)) >> (32 - bits)); 144*61046927SAndroid Build Coastguard Worker } 145*61046927SAndroid Build Coastguard Worker return result; 146*61046927SAndroid Build Coastguard Worker} 147*61046927SAndroid Build Coastguard Worker 148*61046927SAndroid Build Coastguard Workervoid swap(inout int a, inout int b) 149*61046927SAndroid Build Coastguard Worker{ 150*61046927SAndroid Build Coastguard Worker int tmp = a; 151*61046927SAndroid Build Coastguard Worker a = b; 152*61046927SAndroid Build Coastguard Worker b = tmp; 153*61046927SAndroid Build Coastguard Worker} 154*61046927SAndroid Build Coastguard Worker 155*61046927SAndroid Build Coastguard Workerivec4 build_coord() 156*61046927SAndroid Build Coastguard Worker{ 157*61046927SAndroid Build Coastguard Worker ivec2 payload_coord = ivec2(gl_WorkGroupID.xy) * 2; 158*61046927SAndroid Build Coastguard Worker payload_coord.x += int(gl_LocalInvocationID.z) & 1; 159*61046927SAndroid Build Coastguard Worker payload_coord.y += (int(gl_LocalInvocationID.z) >> 1) & 1; 160*61046927SAndroid Build Coastguard Worker#ifdef VULKAN 161*61046927SAndroid Build Coastguard Worker payload_coord += texel_blk_start; 162*61046927SAndroid Build Coastguard Worker#endif /* VULKAN */ 163*61046927SAndroid Build Coastguard Worker ivec2 coord = payload_coord * ivec2(gl_WorkGroupSize.xy); 164*61046927SAndroid Build Coastguard Worker coord += ivec2(gl_LocalInvocationID.xy); 165*61046927SAndroid Build Coastguard Worker return ivec4(coord, payload_coord); 166*61046927SAndroid Build Coastguard Worker} 167*61046927SAndroid Build Coastguard Worker 168*61046927SAndroid Build Coastguard Workerivec4 interpolate_endpoint(ivec4 ep0, ivec4 ep1, ivec4 weight, int decode_mode) 169*61046927SAndroid Build Coastguard Worker{ 170*61046927SAndroid Build Coastguard Worker if (decode_mode == MODE_HDR) 171*61046927SAndroid Build Coastguard Worker { 172*61046927SAndroid Build Coastguard Worker ep0 <<= 4; 173*61046927SAndroid Build Coastguard Worker ep1 <<= 4; 174*61046927SAndroid Build Coastguard Worker } 175*61046927SAndroid Build Coastguard Worker else if (decode_mode == MODE_HDR_LDR_ALPHA) 176*61046927SAndroid Build Coastguard Worker { 177*61046927SAndroid Build Coastguard Worker ep0.rgb <<= 4; 178*61046927SAndroid Build Coastguard Worker ep1.rgb <<= 4; 179*61046927SAndroid Build Coastguard Worker ep0.a *= 0x101; 180*61046927SAndroid Build Coastguard Worker ep1.a *= 0x101; 181*61046927SAndroid Build Coastguard Worker } 182*61046927SAndroid Build Coastguard Worker else if (DECODE_8BIT) 183*61046927SAndroid Build Coastguard Worker { 184*61046927SAndroid Build Coastguard Worker // This isn't quite right in all cases. 185*61046927SAndroid Build Coastguard Worker // In normal ASTC with sRGB, the alpha channel is supposed to 186*61046927SAndroid Build Coastguard Worker // be decoded as FP16, 187*61046927SAndroid Build Coastguard Worker // even when color components are SRGB 8-bit (?!?!?!?!). 188*61046927SAndroid Build Coastguard Worker // This is correct if decode_unorm8 mode is used though, 189*61046927SAndroid Build Coastguard Worker // for sanity, we're going to assume unorm8 decoding mode 190*61046927SAndroid Build Coastguard Worker // is implied when using sRGB. 191*61046927SAndroid Build Coastguard Worker ep0 = (ep0 << 8) | ivec4(0x80); 192*61046927SAndroid Build Coastguard Worker ep1 = (ep1 << 8) | ivec4(0x80); 193*61046927SAndroid Build Coastguard Worker } 194*61046927SAndroid Build Coastguard Worker else 195*61046927SAndroid Build Coastguard Worker { 196*61046927SAndroid Build Coastguard Worker ep0 *= 0x101; 197*61046927SAndroid Build Coastguard Worker ep1 *= 0x101; 198*61046927SAndroid Build Coastguard Worker } 199*61046927SAndroid Build Coastguard Worker 200*61046927SAndroid Build Coastguard Worker ivec4 color = (ep0 * (64 - weight) + ep1 * weight + 32) >> 6; 201*61046927SAndroid Build Coastguard Worker return color; 202*61046927SAndroid Build Coastguard Worker} 203*61046927SAndroid Build Coastguard Worker 204*61046927SAndroid Build Coastguard Workerbvec4 bvec_or(bvec4 a, bvec4 b) 205*61046927SAndroid Build Coastguard Worker{ 206*61046927SAndroid Build Coastguard Worker return bvec4(ivec4(a) | ivec4(b)); 207*61046927SAndroid Build Coastguard Worker} 208*61046927SAndroid Build Coastguard Worker 209*61046927SAndroid Build Coastguard Workeruint round_down_quantize_fp16(int color) 210*61046927SAndroid Build Coastguard Worker{ 211*61046927SAndroid Build Coastguard Worker // ASTC has a very peculiar way of converting the decoded result to FP16. 212*61046927SAndroid Build Coastguard Worker // 0xffff -> 1.0, and for everything else we get roundDownQuantizeFP16(vec4(c) / vec4(0x10000)). 213*61046927SAndroid Build Coastguard Worker int msb = findMSB(color); 214*61046927SAndroid Build Coastguard Worker int shamt = msb; 215*61046927SAndroid Build Coastguard Worker int m = ((color << 10) >> shamt) & 0x3ff; 216*61046927SAndroid Build Coastguard Worker int e = msb - 1; 217*61046927SAndroid Build Coastguard Worker uint decoded = color == 0xffff ? 0x3c00u : uint(e < 1 ? (color << 8) : (m | (e << 10))); 218*61046927SAndroid Build Coastguard Worker return decoded; 219*61046927SAndroid Build Coastguard Worker} 220*61046927SAndroid Build Coastguard Worker 221*61046927SAndroid Build Coastguard Workeruvec4 round_down_quantize_fp16(ivec4 color) 222*61046927SAndroid Build Coastguard Worker{ 223*61046927SAndroid Build Coastguard Worker // ASTC has a very peculiar way of converting the decoded result to FP16. 224*61046927SAndroid Build Coastguard Worker // 0xffff -> 1.0, and for everything else we get roundDownQuantizeFP16(vec4(c) / vec4(0x10000)). 225*61046927SAndroid Build Coastguard Worker ivec4 msb = findMSB(color); 226*61046927SAndroid Build Coastguard Worker ivec4 shamt = msb; 227*61046927SAndroid Build Coastguard Worker ivec4 m = ((color << 10) >> shamt) & 0x3ff; 228*61046927SAndroid Build Coastguard Worker ivec4 e = msb - 1; 229*61046927SAndroid Build Coastguard Worker uvec4 decoded = uvec4(m | (e << 10)); 230*61046927SAndroid Build Coastguard Worker uvec4 denorm_decode = uvec4(color << 8); 231*61046927SAndroid Build Coastguard Worker decoded = mix(decoded, uvec4(denorm_decode), lessThan(e, ivec4(1))); 232*61046927SAndroid Build Coastguard Worker decoded = mix(decoded, uvec4(0x3c00), equal(color, ivec4(0xffff))); 233*61046927SAndroid Build Coastguard Worker return decoded; 234*61046927SAndroid Build Coastguard Worker} 235*61046927SAndroid Build Coastguard Worker 236*61046927SAndroid Build Coastguard Workeruvec4 decode_fp16(ivec4 color, int decode_mode) 237*61046927SAndroid Build Coastguard Worker{ 238*61046927SAndroid Build Coastguard Worker if (decode_mode != MODE_LDR) 239*61046927SAndroid Build Coastguard Worker { 240*61046927SAndroid Build Coastguard Worker // Interpret the value as FP16, but with some extra fixups along the way to make the interpolation more 241*61046927SAndroid Build Coastguard Worker // logarithmic (apparently). From spec: 242*61046927SAndroid Build Coastguard Worker ivec4 e = color >> 11; 243*61046927SAndroid Build Coastguard Worker ivec4 m = color & 0x7ff; 244*61046927SAndroid Build Coastguard Worker ivec4 mt = 4 * m - 512; 245*61046927SAndroid Build Coastguard Worker mt = mix(mt, ivec4(3 * m), lessThan(m, ivec4(512))); 246*61046927SAndroid Build Coastguard Worker mt = mix(mt, ivec4(5 * m - 2048), greaterThanEqual(m, ivec4(1536))); 247*61046927SAndroid Build Coastguard Worker 248*61046927SAndroid Build Coastguard Worker ivec4 decoded = (e << 10) + (mt >> 3); 249*61046927SAndroid Build Coastguard Worker // +Inf or NaN are decoded to 0x7bff (max finite value). 250*61046927SAndroid Build Coastguard Worker decoded = mix(decoded, ivec4(0x7bff), bvec_or(greaterThan(decoded & 0x7fff, ivec4(0x7c00)), equal(decoded, ivec4(0x7c00)))); 251*61046927SAndroid Build Coastguard Worker 252*61046927SAndroid Build Coastguard Worker if (decode_mode == MODE_HDR_LDR_ALPHA) 253*61046927SAndroid Build Coastguard Worker decoded.a = int(round_down_quantize_fp16(color.a)); 254*61046927SAndroid Build Coastguard Worker 255*61046927SAndroid Build Coastguard Worker return uvec4(decoded); 256*61046927SAndroid Build Coastguard Worker } 257*61046927SAndroid Build Coastguard Worker else 258*61046927SAndroid Build Coastguard Worker { 259*61046927SAndroid Build Coastguard Worker return round_down_quantize_fp16(color); 260*61046927SAndroid Build Coastguard Worker } 261*61046927SAndroid Build Coastguard Worker} 262*61046927SAndroid Build Coastguard Worker 263*61046927SAndroid Build Coastguard Workerstruct BlockMode 264*61046927SAndroid Build Coastguard Worker{ 265*61046927SAndroid Build Coastguard Worker ivec2 weight_grid_size; 266*61046927SAndroid Build Coastguard Worker int weight_mode_index; 267*61046927SAndroid Build Coastguard Worker int num_partitions; 268*61046927SAndroid Build Coastguard Worker int seed; 269*61046927SAndroid Build Coastguard Worker int cem; 270*61046927SAndroid Build Coastguard Worker int config_bits; 271*61046927SAndroid Build Coastguard Worker int primary_config_bits; 272*61046927SAndroid Build Coastguard Worker bool dual_plane; 273*61046927SAndroid Build Coastguard Worker bool void_extent; 274*61046927SAndroid Build Coastguard Worker}; 275*61046927SAndroid Build Coastguard Worker 276*61046927SAndroid Build Coastguard Workerbool decode_error = false; 277*61046927SAndroid Build Coastguard Worker 278*61046927SAndroid Build Coastguard WorkerBlockMode decode_block_mode(uvec4 payload) 279*61046927SAndroid Build Coastguard Worker{ 280*61046927SAndroid Build Coastguard Worker BlockMode mode; 281*61046927SAndroid Build Coastguard Worker mode.void_extent = (payload.x & 0x1ffu) == 0x1fcu; 282*61046927SAndroid Build Coastguard Worker if (mode.void_extent) 283*61046927SAndroid Build Coastguard Worker return mode; 284*61046927SAndroid Build Coastguard Worker 285*61046927SAndroid Build Coastguard Worker mode.dual_plane = (payload.x & (1u << 10u)) != 0u; 286*61046927SAndroid Build Coastguard Worker 287*61046927SAndroid Build Coastguard Worker uint higher = (payload.x >> 2u) & 3u; 288*61046927SAndroid Build Coastguard Worker uint lower = payload.x & 3u; 289*61046927SAndroid Build Coastguard Worker 290*61046927SAndroid Build Coastguard Worker if (lower != 0u) 291*61046927SAndroid Build Coastguard Worker { 292*61046927SAndroid Build Coastguard Worker mode.weight_mode_index = int((payload.x >> 4u) & 1u); 293*61046927SAndroid Build Coastguard Worker mode.weight_mode_index |= int((payload.x << 1u) & 6u); 294*61046927SAndroid Build Coastguard Worker mode.weight_mode_index |= int((payload.x >> 6u) & 8u); 295*61046927SAndroid Build Coastguard Worker 296*61046927SAndroid Build Coastguard Worker if (higher < 2u) 297*61046927SAndroid Build Coastguard Worker { 298*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.x = int(bitfieldExtract(payload.x, 7, 2) + 4u + 4u * higher); 299*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.y = int(bitfieldExtract(payload.x, 5, 2) + 2u); 300*61046927SAndroid Build Coastguard Worker } 301*61046927SAndroid Build Coastguard Worker else if (higher == 2u) 302*61046927SAndroid Build Coastguard Worker { 303*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.x = int(bitfieldExtract(payload.x, 5, 2) + 2u); 304*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.y = int(bitfieldExtract(payload.x, 7, 2) + 8u); 305*61046927SAndroid Build Coastguard Worker } 306*61046927SAndroid Build Coastguard Worker else 307*61046927SAndroid Build Coastguard Worker { 308*61046927SAndroid Build Coastguard Worker if ((payload.x & (1u << 8u)) != 0u) 309*61046927SAndroid Build Coastguard Worker { 310*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.x = int(bitfieldExtract(payload.x, 7, 1) + 2u); 311*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.y = int(bitfieldExtract(payload.x, 5, 2) + 2u); 312*61046927SAndroid Build Coastguard Worker } 313*61046927SAndroid Build Coastguard Worker else 314*61046927SAndroid Build Coastguard Worker { 315*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.x = int(bitfieldExtract(payload.x, 5, 2) + 2u); 316*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.y = int(bitfieldExtract(payload.x, 7, 1) + 6u); 317*61046927SAndroid Build Coastguard Worker } 318*61046927SAndroid Build Coastguard Worker } 319*61046927SAndroid Build Coastguard Worker } 320*61046927SAndroid Build Coastguard Worker else 321*61046927SAndroid Build Coastguard Worker { 322*61046927SAndroid Build Coastguard Worker int p3 = int(bitfieldExtract(payload.x, 9, 1)); 323*61046927SAndroid Build Coastguard Worker int hi = int(bitfieldExtract(payload.x, 7, 2)); 324*61046927SAndroid Build Coastguard Worker int lo = int(bitfieldExtract(payload.x, 5, 2)); 325*61046927SAndroid Build Coastguard Worker if (hi == 0) 326*61046927SAndroid Build Coastguard Worker { 327*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.x = 12; 328*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.y = lo + 2; 329*61046927SAndroid Build Coastguard Worker } 330*61046927SAndroid Build Coastguard Worker else if (hi == 1) 331*61046927SAndroid Build Coastguard Worker { 332*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.x = lo + 2; 333*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.y = 12; 334*61046927SAndroid Build Coastguard Worker } 335*61046927SAndroid Build Coastguard Worker else if (hi == 2) 336*61046927SAndroid Build Coastguard Worker { 337*61046927SAndroid Build Coastguard Worker mode.dual_plane = false; 338*61046927SAndroid Build Coastguard Worker p3 = 0; 339*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.x = lo + 6; 340*61046927SAndroid Build Coastguard Worker mode.weight_grid_size.y = int(bitfieldExtract(payload.x, 9, 2) + 6u); 341*61046927SAndroid Build Coastguard Worker } 342*61046927SAndroid Build Coastguard Worker else 343*61046927SAndroid Build Coastguard Worker { 344*61046927SAndroid Build Coastguard Worker if (lo == 0) 345*61046927SAndroid Build Coastguard Worker mode.weight_grid_size = ivec2(6, 10); 346*61046927SAndroid Build Coastguard Worker else if (lo == 1) 347*61046927SAndroid Build Coastguard Worker mode.weight_grid_size = ivec2(10, 6); 348*61046927SAndroid Build Coastguard Worker else 349*61046927SAndroid Build Coastguard Worker decode_error = true; 350*61046927SAndroid Build Coastguard Worker } 351*61046927SAndroid Build Coastguard Worker 352*61046927SAndroid Build Coastguard Worker int p0 = int(bitfieldExtract(payload.x, 4, 1)); 353*61046927SAndroid Build Coastguard Worker int p1 = int(bitfieldExtract(payload.x, 2, 1)); 354*61046927SAndroid Build Coastguard Worker int p2 = int(bitfieldExtract(payload.x, 3, 1)); 355*61046927SAndroid Build Coastguard Worker mode.weight_mode_index = p0 + (p1 << 1) + (p2 << 2) + (p3 << 3); 356*61046927SAndroid Build Coastguard Worker } 357*61046927SAndroid Build Coastguard Worker 358*61046927SAndroid Build Coastguard Worker // 11 bits for block mode. 359*61046927SAndroid Build Coastguard Worker // 2 bits for partition select 360*61046927SAndroid Build Coastguard Worker // If partitions > 1: 361*61046927SAndroid Build Coastguard Worker // 4 bits CEM selector 362*61046927SAndroid Build Coastguard Worker // If dual_plane: 363*61046927SAndroid Build Coastguard Worker // 2 bits of CCS 364*61046927SAndroid Build Coastguard Worker // else: 365*61046927SAndroid Build Coastguard Worker // 10 for partition seed 366*61046927SAndroid Build Coastguard Worker // 2 bits for CEM main selector 367*61046927SAndroid Build Coastguard Worker // If CEM[1:0] = 00: 368*61046927SAndroid Build Coastguard Worker // 4 bits for CEM extra selector if all same type. 369*61046927SAndroid Build Coastguard Worker // else: 370*61046927SAndroid Build Coastguard Worker // (1 + 2) * num_partitions if different types. 371*61046927SAndroid Build Coastguard Worker // First 4 bits are encoded next to CEM[1:0], otherwise, packed before weights. 372*61046927SAndroid Build Coastguard Worker // If dual_plane: 373*61046927SAndroid Build Coastguard Worker // 2 bits of CCS before extra CEM bits. 374*61046927SAndroid Build Coastguard Worker const int CONFIG_BITS_BLOCK = 11; 375*61046927SAndroid Build Coastguard Worker const int CONFIG_BITS_PARTITION_MODE = 2; 376*61046927SAndroid Build Coastguard Worker const int CONFIG_BITS_SEED = 10; 377*61046927SAndroid Build Coastguard Worker const int CONFIG_BITS_PRIMARY_MULTI_CEM = 2; 378*61046927SAndroid Build Coastguard Worker const int CONFIG_BITS_CEM = 4; 379*61046927SAndroid Build Coastguard Worker const int CONFIG_BITS_EXTRA_CEM_PER_PARTITION = 3; 380*61046927SAndroid Build Coastguard Worker const int CONFIG_BITS_CCS = 2; 381*61046927SAndroid Build Coastguard Worker 382*61046927SAndroid Build Coastguard Worker mode.num_partitions = int(bitfieldExtract(payload.x, CONFIG_BITS_BLOCK, CONFIG_BITS_PARTITION_MODE)) + 1; 383*61046927SAndroid Build Coastguard Worker 384*61046927SAndroid Build Coastguard Worker if (mode.num_partitions > 1) 385*61046927SAndroid Build Coastguard Worker { 386*61046927SAndroid Build Coastguard Worker mode.seed = int(bitfieldExtract(payload.x, CONFIG_BITS_BLOCK + CONFIG_BITS_PARTITION_MODE, CONFIG_BITS_SEED)); 387*61046927SAndroid Build Coastguard Worker mode.cem = int(bitfieldExtract(payload.x, CONFIG_BITS_BLOCK + CONFIG_BITS_PARTITION_MODE + CONFIG_BITS_SEED, 388*61046927SAndroid Build Coastguard Worker CONFIG_BITS_PRIMARY_MULTI_CEM + CONFIG_BITS_CEM)); 389*61046927SAndroid Build Coastguard Worker } 390*61046927SAndroid Build Coastguard Worker else 391*61046927SAndroid Build Coastguard Worker mode.cem = int(bitfieldExtract(payload.x, CONFIG_BITS_BLOCK + CONFIG_BITS_PARTITION_MODE, CONFIG_BITS_CEM)); 392*61046927SAndroid Build Coastguard Worker 393*61046927SAndroid Build Coastguard Worker int config_bits; 394*61046927SAndroid Build Coastguard Worker if (mode.num_partitions > 1) 395*61046927SAndroid Build Coastguard Worker { 396*61046927SAndroid Build Coastguard Worker bool single_cem = (mode.cem & 3) == 0; 397*61046927SAndroid Build Coastguard Worker if (single_cem) 398*61046927SAndroid Build Coastguard Worker { 399*61046927SAndroid Build Coastguard Worker config_bits = CONFIG_BITS_BLOCK + CONFIG_BITS_PARTITION_MODE + 400*61046927SAndroid Build Coastguard Worker CONFIG_BITS_SEED + CONFIG_BITS_PRIMARY_MULTI_CEM + CONFIG_BITS_CEM; 401*61046927SAndroid Build Coastguard Worker } 402*61046927SAndroid Build Coastguard Worker else 403*61046927SAndroid Build Coastguard Worker { 404*61046927SAndroid Build Coastguard Worker config_bits = CONFIG_BITS_BLOCK + CONFIG_BITS_PARTITION_MODE + 405*61046927SAndroid Build Coastguard Worker CONFIG_BITS_SEED + CONFIG_BITS_PRIMARY_MULTI_CEM + 406*61046927SAndroid Build Coastguard Worker CONFIG_BITS_EXTRA_CEM_PER_PARTITION * mode.num_partitions; 407*61046927SAndroid Build Coastguard Worker } 408*61046927SAndroid Build Coastguard Worker } 409*61046927SAndroid Build Coastguard Worker else 410*61046927SAndroid Build Coastguard Worker { 411*61046927SAndroid Build Coastguard Worker config_bits = CONFIG_BITS_BLOCK + CONFIG_BITS_PARTITION_MODE + CONFIG_BITS_CEM; 412*61046927SAndroid Build Coastguard Worker } 413*61046927SAndroid Build Coastguard Worker 414*61046927SAndroid Build Coastguard Worker // Other config bits are packed before the weights. 415*61046927SAndroid Build Coastguard Worker int primary_config_bits; 416*61046927SAndroid Build Coastguard Worker if (mode.num_partitions > 1) 417*61046927SAndroid Build Coastguard Worker { 418*61046927SAndroid Build Coastguard Worker primary_config_bits = CONFIG_BITS_BLOCK + CONFIG_BITS_PARTITION_MODE + CONFIG_BITS_SEED + 419*61046927SAndroid Build Coastguard Worker CONFIG_BITS_PRIMARY_MULTI_CEM + CONFIG_BITS_CEM; 420*61046927SAndroid Build Coastguard Worker } 421*61046927SAndroid Build Coastguard Worker else 422*61046927SAndroid Build Coastguard Worker primary_config_bits = config_bits; 423*61046927SAndroid Build Coastguard Worker 424*61046927SAndroid Build Coastguard Worker if (mode.dual_plane) 425*61046927SAndroid Build Coastguard Worker config_bits += CONFIG_BITS_CCS; 426*61046927SAndroid Build Coastguard Worker 427*61046927SAndroid Build Coastguard Worker // This is not allowed. 428*61046927SAndroid Build Coastguard Worker if (any(greaterThan(mode.weight_grid_size, ivec2(gl_WorkGroupSize.xy)))) 429*61046927SAndroid Build Coastguard Worker decode_error = true; 430*61046927SAndroid Build Coastguard Worker if (mode.dual_plane && mode.num_partitions > 3) 431*61046927SAndroid Build Coastguard Worker decode_error = true; 432*61046927SAndroid Build Coastguard Worker 433*61046927SAndroid Build Coastguard Worker mode.config_bits = config_bits; 434*61046927SAndroid Build Coastguard Worker mode.primary_config_bits = primary_config_bits; 435*61046927SAndroid Build Coastguard Worker return mode; 436*61046927SAndroid Build Coastguard Worker} 437*61046927SAndroid Build Coastguard Worker 438*61046927SAndroid Build Coastguard Workerint idiv3_floor(int v) 439*61046927SAndroid Build Coastguard Worker{ 440*61046927SAndroid Build Coastguard Worker return (v * 0x5556) >> 16; 441*61046927SAndroid Build Coastguard Worker} 442*61046927SAndroid Build Coastguard Worker 443*61046927SAndroid Build Coastguard Workerint idiv3_ceil(int v) 444*61046927SAndroid Build Coastguard Worker{ 445*61046927SAndroid Build Coastguard Worker return idiv3_floor(v + 2); 446*61046927SAndroid Build Coastguard Worker} 447*61046927SAndroid Build Coastguard Worker 448*61046927SAndroid Build Coastguard Workerint idiv5_floor(int v) 449*61046927SAndroid Build Coastguard Worker{ 450*61046927SAndroid Build Coastguard Worker return (v * 0x3334) >> 16; 451*61046927SAndroid Build Coastguard Worker} 452*61046927SAndroid Build Coastguard Worker 453*61046927SAndroid Build Coastguard Workerint idiv5_ceil(int v) 454*61046927SAndroid Build Coastguard Worker{ 455*61046927SAndroid Build Coastguard Worker return idiv5_floor(v + 4); 456*61046927SAndroid Build Coastguard Worker} 457*61046927SAndroid Build Coastguard Worker 458*61046927SAndroid Build Coastguard Workeruvec4 build_bitmask(int bits) 459*61046927SAndroid Build Coastguard Worker{ 460*61046927SAndroid Build Coastguard Worker ivec4 num_bits = ivec4(bits, bits - 32, bits - 64, bits - 96); 461*61046927SAndroid Build Coastguard Worker uvec4 mask = uvec4(1) << clamp(num_bits, ivec4(0), ivec4(31)); 462*61046927SAndroid Build Coastguard Worker mask--; 463*61046927SAndroid Build Coastguard Worker mask = mix(mask, uvec4(0xffffffffu), greaterThanEqual(uvec4(bits), uvec4(32, 64, 96, 128))); 464*61046927SAndroid Build Coastguard Worker return mask; 465*61046927SAndroid Build Coastguard Worker} 466*61046927SAndroid Build Coastguard Worker 467*61046927SAndroid Build Coastguard Workerint decode_integer_sequence(uvec4 payload, int start_bit, int index, ivec3 quant) 468*61046927SAndroid Build Coastguard Worker{ 469*61046927SAndroid Build Coastguard Worker int ret; 470*61046927SAndroid Build Coastguard Worker if (quant.y != 0) 471*61046927SAndroid Build Coastguard Worker { 472*61046927SAndroid Build Coastguard Worker // Trit-decoding. 473*61046927SAndroid Build Coastguard Worker int block = idiv5_floor(index); 474*61046927SAndroid Build Coastguard Worker int offset = index - block * 5; 475*61046927SAndroid Build Coastguard Worker start_bit += block * (5 * quant.x + 8); 476*61046927SAndroid Build Coastguard Worker 477*61046927SAndroid Build Coastguard Worker int t0_t1_offset = start_bit + (quant.x * 1 + 0); 478*61046927SAndroid Build Coastguard Worker int t2_t3_offset = start_bit + (quant.x * 2 + 2); 479*61046927SAndroid Build Coastguard Worker int t4_offset = start_bit + (quant.x * 3 + 4); 480*61046927SAndroid Build Coastguard Worker int t5_t6_offset = start_bit + (quant.x * 4 + 5); 481*61046927SAndroid Build Coastguard Worker int t7_offset = start_bit + (quant.x * 5 + 7); 482*61046927SAndroid Build Coastguard Worker 483*61046927SAndroid Build Coastguard Worker int t = (extract_bits(payload, t0_t1_offset, 2) << 0) | 484*61046927SAndroid Build Coastguard Worker (extract_bits(payload, t2_t3_offset, 2) << 2) | 485*61046927SAndroid Build Coastguard Worker (extract_bits(payload, t4_offset, 1) << 4) | 486*61046927SAndroid Build Coastguard Worker (extract_bits(payload, t5_t6_offset, 2) << 5) | 487*61046927SAndroid Build Coastguard Worker (extract_bits(payload, t7_offset, 1) << 7); 488*61046927SAndroid Build Coastguard Worker 489*61046927SAndroid Build Coastguard Worker t = int(texelFetch(LUTTritQuintDecode, t).x); 490*61046927SAndroid Build Coastguard Worker t = (t >> (3 * offset)) & 7; 491*61046927SAndroid Build Coastguard Worker 492*61046927SAndroid Build Coastguard Worker int m_offset = offset * quant.x; 493*61046927SAndroid Build Coastguard Worker m_offset += idiv5_ceil(offset * 8); 494*61046927SAndroid Build Coastguard Worker 495*61046927SAndroid Build Coastguard Worker if (quant.x != 0) 496*61046927SAndroid Build Coastguard Worker { 497*61046927SAndroid Build Coastguard Worker int m = extract_bits(payload, m_offset + start_bit, quant.x); 498*61046927SAndroid Build Coastguard Worker ret = (t << quant.x) | m; 499*61046927SAndroid Build Coastguard Worker } 500*61046927SAndroid Build Coastguard Worker else 501*61046927SAndroid Build Coastguard Worker ret = t; 502*61046927SAndroid Build Coastguard Worker } 503*61046927SAndroid Build Coastguard Worker else if (quant.z != 0) 504*61046927SAndroid Build Coastguard Worker { 505*61046927SAndroid Build Coastguard Worker // Quint-decoding 506*61046927SAndroid Build Coastguard Worker int block = idiv3_floor(index); 507*61046927SAndroid Build Coastguard Worker int offset = index - block * 3; 508*61046927SAndroid Build Coastguard Worker start_bit += block * (3 * quant.x + 7); 509*61046927SAndroid Build Coastguard Worker 510*61046927SAndroid Build Coastguard Worker int q0_q1_q2_offset = start_bit + (quant.x * 1 + 0); 511*61046927SAndroid Build Coastguard Worker int q3_q4_offset = start_bit + (quant.x * 2 + 3); 512*61046927SAndroid Build Coastguard Worker int q5_q6_offset = start_bit + (quant.x * 3 + 5); 513*61046927SAndroid Build Coastguard Worker 514*61046927SAndroid Build Coastguard Worker int q = (extract_bits(payload, q0_q1_q2_offset, 3) << 0) | 515*61046927SAndroid Build Coastguard Worker (extract_bits(payload, q3_q4_offset, 2) << 3) | 516*61046927SAndroid Build Coastguard Worker (extract_bits(payload, q5_q6_offset, 2) << 5); 517*61046927SAndroid Build Coastguard Worker 518*61046927SAndroid Build Coastguard Worker q = int(texelFetch(LUTTritQuintDecode, 256 + q).x); 519*61046927SAndroid Build Coastguard Worker q = (q >> (3 * offset)) & 7; 520*61046927SAndroid Build Coastguard Worker 521*61046927SAndroid Build Coastguard Worker int m_offset = offset * quant.x; 522*61046927SAndroid Build Coastguard Worker m_offset += idiv3_ceil(offset * 7); 523*61046927SAndroid Build Coastguard Worker 524*61046927SAndroid Build Coastguard Worker if (quant.x != 0) 525*61046927SAndroid Build Coastguard Worker { 526*61046927SAndroid Build Coastguard Worker int m = extract_bits(payload, m_offset + start_bit, quant.x); 527*61046927SAndroid Build Coastguard Worker ret = (q << quant.x) | m; 528*61046927SAndroid Build Coastguard Worker } 529*61046927SAndroid Build Coastguard Worker else 530*61046927SAndroid Build Coastguard Worker ret = q; 531*61046927SAndroid Build Coastguard Worker } 532*61046927SAndroid Build Coastguard Worker else 533*61046927SAndroid Build Coastguard Worker { 534*61046927SAndroid Build Coastguard Worker int bit = index * quant.x; 535*61046927SAndroid Build Coastguard Worker ret = extract_bits(payload, start_bit + bit, quant.x); 536*61046927SAndroid Build Coastguard Worker } 537*61046927SAndroid Build Coastguard Worker return ret; 538*61046927SAndroid Build Coastguard Worker} 539*61046927SAndroid Build Coastguard Worker 540*61046927SAndroid Build Coastguard Workerivec2 normalize_coord(ivec2 pixel_coord) 541*61046927SAndroid Build Coastguard Worker{ 542*61046927SAndroid Build Coastguard Worker ivec2 D = ivec2((vec2((1024 + ivec2(gl_WorkGroupSize.xy >> 1u))) + 0.5) / vec2(gl_WorkGroupSize.xy - 1u)); 543*61046927SAndroid Build Coastguard Worker ivec2 c = D * pixel_coord; 544*61046927SAndroid Build Coastguard Worker return c; 545*61046927SAndroid Build Coastguard Worker} 546*61046927SAndroid Build Coastguard Worker 547*61046927SAndroid Build Coastguard Workerint decode_weight(uvec4 payload, int weight_index, ivec4 quant) 548*61046927SAndroid Build Coastguard Worker{ 549*61046927SAndroid Build Coastguard Worker int primary_weight = decode_integer_sequence(payload, 0, weight_index, quant.xyz); 550*61046927SAndroid Build Coastguard Worker primary_weight = int(texelFetch(LUTWeightUnquantize, primary_weight + quant.w).x); 551*61046927SAndroid Build Coastguard Worker return primary_weight; 552*61046927SAndroid Build Coastguard Worker} 553*61046927SAndroid Build Coastguard Worker 554*61046927SAndroid Build Coastguard Workerint decode_weight_bilinear(uvec4 payload, ivec2 coord, int weight_resolution, 555*61046927SAndroid Build Coastguard Worker int stride, int offset, ivec2 fractional, ivec4 quant) 556*61046927SAndroid Build Coastguard Worker{ 557*61046927SAndroid Build Coastguard Worker int index = coord.y * weight_resolution + coord.x; 558*61046927SAndroid Build Coastguard Worker int p00 = decode_weight(payload, stride * index + offset, quant); 559*61046927SAndroid Build Coastguard Worker int p10, p01, p11; 560*61046927SAndroid Build Coastguard Worker 561*61046927SAndroid Build Coastguard Worker if (fractional.x != 0) 562*61046927SAndroid Build Coastguard Worker p10 = decode_weight(payload, stride * (index + 1) + offset, quant); 563*61046927SAndroid Build Coastguard Worker else 564*61046927SAndroid Build Coastguard Worker p10 = p00; 565*61046927SAndroid Build Coastguard Worker 566*61046927SAndroid Build Coastguard Worker if (fractional.y != 0) 567*61046927SAndroid Build Coastguard Worker { 568*61046927SAndroid Build Coastguard Worker p01 = decode_weight(payload, stride * (index + weight_resolution) + offset, quant); 569*61046927SAndroid Build Coastguard Worker if (fractional.x != 0) 570*61046927SAndroid Build Coastguard Worker p11 = decode_weight(payload, stride * (index + weight_resolution + 1) + offset, quant); 571*61046927SAndroid Build Coastguard Worker else 572*61046927SAndroid Build Coastguard Worker p11 = p01; 573*61046927SAndroid Build Coastguard Worker } 574*61046927SAndroid Build Coastguard Worker else 575*61046927SAndroid Build Coastguard Worker { 576*61046927SAndroid Build Coastguard Worker p01 = p00; 577*61046927SAndroid Build Coastguard Worker p11 = p10; 578*61046927SAndroid Build Coastguard Worker } 579*61046927SAndroid Build Coastguard Worker 580*61046927SAndroid Build Coastguard Worker int w11 = (fractional.x * fractional.y + 8) >> 4; 581*61046927SAndroid Build Coastguard Worker int w10 = fractional.x - w11; 582*61046927SAndroid Build Coastguard Worker int w01 = fractional.y - w11; 583*61046927SAndroid Build Coastguard Worker int w00 = 16 - fractional.x - fractional.y + w11; 584*61046927SAndroid Build Coastguard Worker return (p00 * w00 + p10 * w10 + p01 * w01 + p11 * w11 + 8) >> 4; 585*61046927SAndroid Build Coastguard Worker} 586*61046927SAndroid Build Coastguard Worker 587*61046927SAndroid Build Coastguard Workerivec4 decode_weights(uvec4 payload, BlockMode mode, ivec2 normalized_pixel, out int weight_cost_bits) 588*61046927SAndroid Build Coastguard Worker{ 589*61046927SAndroid Build Coastguard Worker ivec4 quant = ivec4(texelFetch(LUTWeightQuantizer, mode.weight_mode_index)); 590*61046927SAndroid Build Coastguard Worker int num_weights = mode.weight_grid_size.x * mode.weight_grid_size.y; 591*61046927SAndroid Build Coastguard Worker num_weights <<= int(mode.dual_plane); 592*61046927SAndroid Build Coastguard Worker weight_cost_bits = 593*61046927SAndroid Build Coastguard Worker quant.x * num_weights + 594*61046927SAndroid Build Coastguard Worker idiv5_ceil(num_weights * 8 * quant.y) + 595*61046927SAndroid Build Coastguard Worker idiv3_ceil(num_weights * 7 * quant.z); 596*61046927SAndroid Build Coastguard Worker 597*61046927SAndroid Build Coastguard Worker // Decoders must deal with error conditions and return the correct error color. 598*61046927SAndroid Build Coastguard Worker if (weight_cost_bits < 24 || weight_cost_bits > 96 || num_weights > 64) 599*61046927SAndroid Build Coastguard Worker { 600*61046927SAndroid Build Coastguard Worker decode_error = true; 601*61046927SAndroid Build Coastguard Worker return ivec4(0); 602*61046927SAndroid Build Coastguard Worker } 603*61046927SAndroid Build Coastguard Worker 604*61046927SAndroid Build Coastguard Worker int ccs; 605*61046927SAndroid Build Coastguard Worker if (mode.dual_plane) 606*61046927SAndroid Build Coastguard Worker { 607*61046927SAndroid Build Coastguard Worker int extra_cem_bits = 0; 608*61046927SAndroid Build Coastguard Worker if ((mode.cem & 3) != 0) 609*61046927SAndroid Build Coastguard Worker extra_cem_bits = max(mode.num_partitions * 3 - 4, 0); 610*61046927SAndroid Build Coastguard Worker ccs = extract_bits(payload, 126 - weight_cost_bits - extra_cem_bits, 2); 611*61046927SAndroid Build Coastguard Worker } 612*61046927SAndroid Build Coastguard Worker 613*61046927SAndroid Build Coastguard Worker payload = bitfieldReverse(payload); 614*61046927SAndroid Build Coastguard Worker payload = payload.wzyx; 615*61046927SAndroid Build Coastguard Worker payload &= build_bitmask(weight_cost_bits); 616*61046927SAndroid Build Coastguard Worker 617*61046927SAndroid Build Coastguard Worker // Scale the normalized coordinate to weight grid. 618*61046927SAndroid Build Coastguard Worker ivec2 weight_pixel_fixed_point = (normalized_pixel * (mode.weight_grid_size - 1) + 32) >> 6; 619*61046927SAndroid Build Coastguard Worker ivec2 weight_pixel = weight_pixel_fixed_point >> 4; 620*61046927SAndroid Build Coastguard Worker ivec2 weight_pixel_fractional = weight_pixel_fixed_point & 0xf; 621*61046927SAndroid Build Coastguard Worker 622*61046927SAndroid Build Coastguard Worker ivec4 ret; 623*61046927SAndroid Build Coastguard Worker int primary_weight = decode_weight_bilinear(payload, weight_pixel, mode.weight_grid_size.x, 624*61046927SAndroid Build Coastguard Worker 1 << int(mode.dual_plane), 0, 625*61046927SAndroid Build Coastguard Worker weight_pixel_fractional, quant); 626*61046927SAndroid Build Coastguard Worker if (mode.dual_plane) 627*61046927SAndroid Build Coastguard Worker { 628*61046927SAndroid Build Coastguard Worker int secondary_weight = decode_weight_bilinear(payload, weight_pixel, mode.weight_grid_size.x, 629*61046927SAndroid Build Coastguard Worker 2, 1, 630*61046927SAndroid Build Coastguard Worker weight_pixel_fractional, quant); 631*61046927SAndroid Build Coastguard Worker ret = mix(ivec4(primary_weight), ivec4(secondary_weight), equal(ivec4(ccs), ivec4(0, 1, 2, 3))); 632*61046927SAndroid Build Coastguard Worker } 633*61046927SAndroid Build Coastguard Worker else 634*61046927SAndroid Build Coastguard Worker ret = ivec4(primary_weight); 635*61046927SAndroid Build Coastguard Worker 636*61046927SAndroid Build Coastguard Worker return ret; 637*61046927SAndroid Build Coastguard Worker} 638*61046927SAndroid Build Coastguard Worker 639*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_luma_direct(out ivec4 ep0, out ivec4 ep1, 640*61046927SAndroid Build Coastguard Worker int v0, int v1) 641*61046927SAndroid Build Coastguard Worker{ 642*61046927SAndroid Build Coastguard Worker ep0 = ivec4(ivec3(v0), 0xff); 643*61046927SAndroid Build Coastguard Worker ep1 = ivec4(ivec3(v1), 0xff); 644*61046927SAndroid Build Coastguard Worker} 645*61046927SAndroid Build Coastguard Worker 646*61046927SAndroid Build Coastguard Workervoid decode_endpoint_hdr_luma_direct(out ivec4 ep0, out ivec4 ep1, 647*61046927SAndroid Build Coastguard Worker int v0, int v1) 648*61046927SAndroid Build Coastguard Worker{ 649*61046927SAndroid Build Coastguard Worker int y0, y1; 650*61046927SAndroid Build Coastguard Worker if (v1 >= v0) 651*61046927SAndroid Build Coastguard Worker { 652*61046927SAndroid Build Coastguard Worker y0 = v0 << 4; 653*61046927SAndroid Build Coastguard Worker y1 = v1 << 4; 654*61046927SAndroid Build Coastguard Worker } 655*61046927SAndroid Build Coastguard Worker else 656*61046927SAndroid Build Coastguard Worker { 657*61046927SAndroid Build Coastguard Worker y0 = (v1 << 4) + 8; 658*61046927SAndroid Build Coastguard Worker y1 = (v0 << 4) - 8; 659*61046927SAndroid Build Coastguard Worker } 660*61046927SAndroid Build Coastguard Worker 661*61046927SAndroid Build Coastguard Worker ep0 = ivec4(ivec3(y0), 0x780); 662*61046927SAndroid Build Coastguard Worker ep1 = ivec4(ivec3(y1), 0x780); 663*61046927SAndroid Build Coastguard Worker} 664*61046927SAndroid Build Coastguard Worker 665*61046927SAndroid Build Coastguard Workervoid decode_endpoint_hdr_luma_direct_small_range(out ivec4 ep0, out ivec4 ep1, 666*61046927SAndroid Build Coastguard Worker int v0, int v1) 667*61046927SAndroid Build Coastguard Worker{ 668*61046927SAndroid Build Coastguard Worker int y0, y1, d; 669*61046927SAndroid Build Coastguard Worker 670*61046927SAndroid Build Coastguard Worker if ((v0 & 0x80) != 0) 671*61046927SAndroid Build Coastguard Worker { 672*61046927SAndroid Build Coastguard Worker y0 = ((v1 & 0xe0) << 4) | ((v0 & 0x7f) << 2); 673*61046927SAndroid Build Coastguard Worker d = (v1 & 0x1f) << 2; 674*61046927SAndroid Build Coastguard Worker } 675*61046927SAndroid Build Coastguard Worker else 676*61046927SAndroid Build Coastguard Worker { 677*61046927SAndroid Build Coastguard Worker y0 = ((v1 & 0xf0) << 4) | ((v0 & 0x7f) << 1); 678*61046927SAndroid Build Coastguard Worker d = (v1 & 0x0f) << 1; 679*61046927SAndroid Build Coastguard Worker } 680*61046927SAndroid Build Coastguard Worker 681*61046927SAndroid Build Coastguard Worker y1 = min(y0 + d, 0xfff); 682*61046927SAndroid Build Coastguard Worker 683*61046927SAndroid Build Coastguard Worker ep0 = ivec4(ivec3(y0), 0x780); 684*61046927SAndroid Build Coastguard Worker ep1 = ivec4(ivec3(y1), 0x780); 685*61046927SAndroid Build Coastguard Worker} 686*61046927SAndroid Build Coastguard Worker 687*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_luma_base_offset(out ivec4 ep0, out ivec4 ep1, 688*61046927SAndroid Build Coastguard Worker int v0, int v1) 689*61046927SAndroid Build Coastguard Worker{ 690*61046927SAndroid Build Coastguard Worker int l0 = (v0 >> 2) | (v1 & 0xc0); 691*61046927SAndroid Build Coastguard Worker int l1 = l0 + (v1 & 0x3f); 692*61046927SAndroid Build Coastguard Worker l1 = min(l1, 0xff); 693*61046927SAndroid Build Coastguard Worker ep0 = ivec4(ivec3(l0), 0xff); 694*61046927SAndroid Build Coastguard Worker ep1 = ivec4(ivec3(l1), 0xff); 695*61046927SAndroid Build Coastguard Worker} 696*61046927SAndroid Build Coastguard Worker 697*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_luma_alpha_direct(out ivec4 ep0, out ivec4 ep1, 698*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3) 699*61046927SAndroid Build Coastguard Worker{ 700*61046927SAndroid Build Coastguard Worker ep0 = ivec4(ivec3(v0), v2); 701*61046927SAndroid Build Coastguard Worker ep1 = ivec4(ivec3(v1), v3); 702*61046927SAndroid Build Coastguard Worker} 703*61046927SAndroid Build Coastguard Worker 704*61046927SAndroid Build Coastguard Workerivec4 blue_contract(int r, int g, int b, int a) 705*61046927SAndroid Build Coastguard Worker{ 706*61046927SAndroid Build Coastguard Worker ivec4 ret; 707*61046927SAndroid Build Coastguard Worker ret.r = (r + b) >> 1; 708*61046927SAndroid Build Coastguard Worker ret.g = (g + b) >> 1; 709*61046927SAndroid Build Coastguard Worker ret.b = b; 710*61046927SAndroid Build Coastguard Worker ret.a = a; 711*61046927SAndroid Build Coastguard Worker return ret; 712*61046927SAndroid Build Coastguard Worker} 713*61046927SAndroid Build Coastguard Worker 714*61046927SAndroid Build Coastguard Workervoid bit_transfer_signed(inout int a, inout int b) 715*61046927SAndroid Build Coastguard Worker{ 716*61046927SAndroid Build Coastguard Worker b >>= 1; 717*61046927SAndroid Build Coastguard Worker b |= a & 0x80; 718*61046927SAndroid Build Coastguard Worker a >>= 1; 719*61046927SAndroid Build Coastguard Worker a &= 0x3f; 720*61046927SAndroid Build Coastguard Worker a = bitfieldExtract(a, 0, 6); 721*61046927SAndroid Build Coastguard Worker} 722*61046927SAndroid Build Coastguard Worker 723*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_luma_alpha_base_offset(out ivec4 ep0, out ivec4 ep1, 724*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3) 725*61046927SAndroid Build Coastguard Worker{ 726*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v1, v0); 727*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v3, v2); 728*61046927SAndroid Build Coastguard Worker int v0_v1 = clamp(v0 + v1, 0, 0xff); 729*61046927SAndroid Build Coastguard Worker int v2_v3 = clamp(v2 + v3, 0, 0xff); 730*61046927SAndroid Build Coastguard Worker v0 = clamp(v0, 0, 0xff); 731*61046927SAndroid Build Coastguard Worker v2 = clamp(v2, 0, 0xff); 732*61046927SAndroid Build Coastguard Worker ep0 = ivec4(ivec3(v0), v2); 733*61046927SAndroid Build Coastguard Worker ep1 = ivec4(ivec3(v0_v1), v2_v3); 734*61046927SAndroid Build Coastguard Worker} 735*61046927SAndroid Build Coastguard Worker 736*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_rgb_base_scale(out ivec4 ep0, out ivec4 ep1, 737*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3) 738*61046927SAndroid Build Coastguard Worker{ 739*61046927SAndroid Build Coastguard Worker ep0 = ivec4((ivec3(v0, v1, v2) * v3) >> 8, 0xff); 740*61046927SAndroid Build Coastguard Worker ep1 = ivec4(v0, v1, v2, 0xff); 741*61046927SAndroid Build Coastguard Worker} 742*61046927SAndroid Build Coastguard Worker 743*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_rgb_base_scale_two_a(out ivec4 ep0, out ivec4 ep1, 744*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3, int v4, int v5) 745*61046927SAndroid Build Coastguard Worker{ 746*61046927SAndroid Build Coastguard Worker ep0 = ivec4((ivec3(v0, v1, v2) * v3) >> 8, v4); 747*61046927SAndroid Build Coastguard Worker ep1 = ivec4(v0, v1, v2, v5); 748*61046927SAndroid Build Coastguard Worker} 749*61046927SAndroid Build Coastguard Worker 750*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_rgb_direct(out ivec4 ep0, out ivec4 ep1, 751*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3, int v4, int v5) 752*61046927SAndroid Build Coastguard Worker{ 753*61046927SAndroid Build Coastguard Worker int s0 = v0 + v2 + v4; 754*61046927SAndroid Build Coastguard Worker int s1 = v1 + v3 + v5; 755*61046927SAndroid Build Coastguard Worker if (s1 >= s0) 756*61046927SAndroid Build Coastguard Worker { 757*61046927SAndroid Build Coastguard Worker ep0 = ivec4(v0, v2, v4, 0xff); 758*61046927SAndroid Build Coastguard Worker ep1 = ivec4(v1, v3, v5, 0xff); 759*61046927SAndroid Build Coastguard Worker } 760*61046927SAndroid Build Coastguard Worker else 761*61046927SAndroid Build Coastguard Worker { 762*61046927SAndroid Build Coastguard Worker ep0 = blue_contract(v1, v3, v5, 0xff); 763*61046927SAndroid Build Coastguard Worker ep1 = blue_contract(v0, v2, v4, 0xff); 764*61046927SAndroid Build Coastguard Worker } 765*61046927SAndroid Build Coastguard Worker} 766*61046927SAndroid Build Coastguard Worker 767*61046927SAndroid Build Coastguard Workervoid decode_endpoint_hdr_rgb_scale(out ivec4 ep0, out ivec4 ep1, 768*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3) 769*61046927SAndroid Build Coastguard Worker{ 770*61046927SAndroid Build Coastguard Worker // Mind-numbing weird format, just copy from spec ... 771*61046927SAndroid Build Coastguard Worker int mode_value = ((v0 & 0xc0) >> 6) | ((v1 & 0x80) >> 5) | ((v2 & 0x80) >> 4); 772*61046927SAndroid Build Coastguard Worker int major_component; 773*61046927SAndroid Build Coastguard Worker int mode; 774*61046927SAndroid Build Coastguard Worker 775*61046927SAndroid Build Coastguard Worker if ((mode_value & 0xc) != 0xc) 776*61046927SAndroid Build Coastguard Worker { 777*61046927SAndroid Build Coastguard Worker major_component = mode_value >> 2; 778*61046927SAndroid Build Coastguard Worker mode = mode_value & 3; 779*61046927SAndroid Build Coastguard Worker } 780*61046927SAndroid Build Coastguard Worker else if (mode_value != 0xf) 781*61046927SAndroid Build Coastguard Worker { 782*61046927SAndroid Build Coastguard Worker major_component = mode_value & 3; 783*61046927SAndroid Build Coastguard Worker mode = 4; 784*61046927SAndroid Build Coastguard Worker } 785*61046927SAndroid Build Coastguard Worker else 786*61046927SAndroid Build Coastguard Worker { 787*61046927SAndroid Build Coastguard Worker major_component = 0; 788*61046927SAndroid Build Coastguard Worker mode = 5; 789*61046927SAndroid Build Coastguard Worker } 790*61046927SAndroid Build Coastguard Worker 791*61046927SAndroid Build Coastguard Worker int red = v0 & 0x3f; 792*61046927SAndroid Build Coastguard Worker int green = v1 & 0x1f; 793*61046927SAndroid Build Coastguard Worker int blue = v2 & 0x1f; 794*61046927SAndroid Build Coastguard Worker int scale = v3 & 0x1f; 795*61046927SAndroid Build Coastguard Worker 796*61046927SAndroid Build Coastguard Worker int x0 = (v1 >> 6) & 1; 797*61046927SAndroid Build Coastguard Worker int x1 = (v1 >> 5) & 1; 798*61046927SAndroid Build Coastguard Worker int x2 = (v2 >> 6) & 1; 799*61046927SAndroid Build Coastguard Worker int x3 = (v2 >> 5) & 1; 800*61046927SAndroid Build Coastguard Worker int x4 = (v3 >> 7) & 1; 801*61046927SAndroid Build Coastguard Worker int x5 = (v3 >> 6) & 1; 802*61046927SAndroid Build Coastguard Worker int x6 = (v3 >> 5) & 1; 803*61046927SAndroid Build Coastguard Worker 804*61046927SAndroid Build Coastguard Worker int ohm = 1 << mode; 805*61046927SAndroid Build Coastguard Worker if ((ohm & 0x30) != 0) green |= x0 << 6; 806*61046927SAndroid Build Coastguard Worker if ((ohm & 0x3a) != 0) green |= x1 << 5; 807*61046927SAndroid Build Coastguard Worker if ((ohm & 0x30) != 0) blue |= x2 << 6; 808*61046927SAndroid Build Coastguard Worker if ((ohm & 0x3a) != 0) blue |= x3 << 5; 809*61046927SAndroid Build Coastguard Worker if ((ohm & 0x3d) != 0) scale |= x6 << 5; 810*61046927SAndroid Build Coastguard Worker if ((ohm & 0x2d) != 0) scale |= x5 << 6; 811*61046927SAndroid Build Coastguard Worker if ((ohm & 0x04) != 0) scale |= x4 << 7; 812*61046927SAndroid Build Coastguard Worker if ((ohm & 0x3b) != 0) red |= x4 << 6; 813*61046927SAndroid Build Coastguard Worker if ((ohm & 0x04) != 0) red |= x3 << 6; 814*61046927SAndroid Build Coastguard Worker if ((ohm & 0x10) != 0) red |= x5 << 7; 815*61046927SAndroid Build Coastguard Worker if ((ohm & 0x0f) != 0) red |= x2 << 7; 816*61046927SAndroid Build Coastguard Worker if ((ohm & 0x05) != 0) red |= x1 << 8; 817*61046927SAndroid Build Coastguard Worker if ((ohm & 0x0a) != 0) red |= x0 << 8; 818*61046927SAndroid Build Coastguard Worker if ((ohm & 0x05) != 0) red |= x0 << 9; 819*61046927SAndroid Build Coastguard Worker if ((ohm & 0x02) != 0) red |= x6 << 9; 820*61046927SAndroid Build Coastguard Worker if ((ohm & 0x01) != 0) red |= x3 << 10; 821*61046927SAndroid Build Coastguard Worker if ((ohm & 0x02) != 0) red |= x5 << 10; 822*61046927SAndroid Build Coastguard Worker 823*61046927SAndroid Build Coastguard Worker int shamt = max(mode, 1); 824*61046927SAndroid Build Coastguard Worker red <<= shamt; 825*61046927SAndroid Build Coastguard Worker green <<= shamt; 826*61046927SAndroid Build Coastguard Worker blue <<= shamt; 827*61046927SAndroid Build Coastguard Worker scale <<= shamt; 828*61046927SAndroid Build Coastguard Worker 829*61046927SAndroid Build Coastguard Worker if (mode != 5) 830*61046927SAndroid Build Coastguard Worker { 831*61046927SAndroid Build Coastguard Worker green = red - green; 832*61046927SAndroid Build Coastguard Worker blue = red - blue; 833*61046927SAndroid Build Coastguard Worker } 834*61046927SAndroid Build Coastguard Worker 835*61046927SAndroid Build Coastguard Worker if (major_component == 1) 836*61046927SAndroid Build Coastguard Worker swap(red, green); 837*61046927SAndroid Build Coastguard Worker else if (major_component == 2) 838*61046927SAndroid Build Coastguard Worker swap(red, blue); 839*61046927SAndroid Build Coastguard Worker 840*61046927SAndroid Build Coastguard Worker ep1 = ivec4(clamp(ivec3(red, green, blue), ivec3(0), ivec3(0xfff)), 0x780); 841*61046927SAndroid Build Coastguard Worker ep0 = ivec4(clamp(ivec3(red, green, blue) - scale, ivec3(0), ivec3(0xfff)), 0x780); 842*61046927SAndroid Build Coastguard Worker} 843*61046927SAndroid Build Coastguard Worker 844*61046927SAndroid Build Coastguard Workervoid decode_endpoint_hdr_rgb_direct(out ivec4 ep0, out ivec4 ep1, 845*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3, int v4, int v5) 846*61046927SAndroid Build Coastguard Worker{ 847*61046927SAndroid Build Coastguard Worker int major_component = ((v4 & 0x80) >> 7) | ((v5 & 0x80) >> 6); 848*61046927SAndroid Build Coastguard Worker 849*61046927SAndroid Build Coastguard Worker if (major_component == 3) 850*61046927SAndroid Build Coastguard Worker { 851*61046927SAndroid Build Coastguard Worker ep0 = ivec4(v0 << 4, v2 << 4, (v4 & 0x7f) << 5, 0x780); 852*61046927SAndroid Build Coastguard Worker ep1 = ivec4(v1 << 4, v3 << 4, (v5 & 0x7f) << 5, 0x780); 853*61046927SAndroid Build Coastguard Worker return; 854*61046927SAndroid Build Coastguard Worker } 855*61046927SAndroid Build Coastguard Worker 856*61046927SAndroid Build Coastguard Worker int mode = ((v1 & 0x80) >> 7) | ((v2 & 0x80) >> 6) | ((v3 & 0x80) >> 5); 857*61046927SAndroid Build Coastguard Worker int va = v0 | ((v1 & 0x40) << 2); 858*61046927SAndroid Build Coastguard Worker int vb0 = v2 & 0x3f; 859*61046927SAndroid Build Coastguard Worker int vb1 = v3 & 0x3f; 860*61046927SAndroid Build Coastguard Worker int vc = v1 & 0x3f; 861*61046927SAndroid Build Coastguard Worker int vd0 = v4 & 0x7f; 862*61046927SAndroid Build Coastguard Worker int vd1 = v5 & 0x7f; 863*61046927SAndroid Build Coastguard Worker 864*61046927SAndroid Build Coastguard Worker int d_bits = 7 - (mode & 1); 865*61046927SAndroid Build Coastguard Worker if ((mode & 5) == 4) 866*61046927SAndroid Build Coastguard Worker d_bits -= 2; 867*61046927SAndroid Build Coastguard Worker 868*61046927SAndroid Build Coastguard Worker vd0 = bitfieldExtract(vd0, 0, d_bits); 869*61046927SAndroid Build Coastguard Worker vd1 = bitfieldExtract(vd1, 0, d_bits); 870*61046927SAndroid Build Coastguard Worker 871*61046927SAndroid Build Coastguard Worker int x0 = (v2 >> 6) & 1; 872*61046927SAndroid Build Coastguard Worker int x1 = (v3 >> 6) & 1; 873*61046927SAndroid Build Coastguard Worker int x2 = (v4 >> 6) & 1; 874*61046927SAndroid Build Coastguard Worker int x3 = (v5 >> 6) & 1; 875*61046927SAndroid Build Coastguard Worker int x4 = (v4 >> 5) & 1; 876*61046927SAndroid Build Coastguard Worker int x5 = (v5 >> 5) & 1; 877*61046927SAndroid Build Coastguard Worker 878*61046927SAndroid Build Coastguard Worker int ohm = 1 << mode; 879*61046927SAndroid Build Coastguard Worker if ((ohm & 0xa4) != 0) va |= x0 << 9; 880*61046927SAndroid Build Coastguard Worker if ((ohm & 0x08) != 0) va |= x2 << 9; 881*61046927SAndroid Build Coastguard Worker if ((ohm & 0x50) != 0) va |= x4 << 9; 882*61046927SAndroid Build Coastguard Worker if ((ohm & 0x50) != 0) va |= x5 << 10; 883*61046927SAndroid Build Coastguard Worker if ((ohm & 0xa0) != 0) va |= x1 << 10; 884*61046927SAndroid Build Coastguard Worker if ((ohm & 0xc0) != 0) va |= x2 << 11; 885*61046927SAndroid Build Coastguard Worker 886*61046927SAndroid Build Coastguard Worker if ((ohm & 0x04) != 0) vc |= x1 << 6; 887*61046927SAndroid Build Coastguard Worker if ((ohm & 0xe8) != 0) vc |= x3 << 6; 888*61046927SAndroid Build Coastguard Worker if ((ohm & 0x20) != 0) vc |= x2 << 7; 889*61046927SAndroid Build Coastguard Worker 890*61046927SAndroid Build Coastguard Worker if ((ohm & 0x5b) != 0) vb0 |= x0 << 6; 891*61046927SAndroid Build Coastguard Worker if ((ohm & 0x5b) != 0) vb1 |= x1 << 6; 892*61046927SAndroid Build Coastguard Worker if ((ohm & 0x12) != 0) vb0 |= x2 << 7; 893*61046927SAndroid Build Coastguard Worker if ((ohm & 0x12) != 0) vb1 |= x3 << 7; 894*61046927SAndroid Build Coastguard Worker 895*61046927SAndroid Build Coastguard Worker int shamt = (mode >> 1) ^ 3; 896*61046927SAndroid Build Coastguard Worker va <<= shamt; 897*61046927SAndroid Build Coastguard Worker vb0 <<= shamt; 898*61046927SAndroid Build Coastguard Worker vb1 <<= shamt; 899*61046927SAndroid Build Coastguard Worker vc <<= shamt; 900*61046927SAndroid Build Coastguard Worker vd0 <<= shamt; 901*61046927SAndroid Build Coastguard Worker vd1 <<= shamt; 902*61046927SAndroid Build Coastguard Worker 903*61046927SAndroid Build Coastguard Worker ep1 = ivec4(clamp(ivec3(va, va - vb0, va - vb1), ivec3(0), ivec3(0xfff)), 0x780); 904*61046927SAndroid Build Coastguard Worker ep0 = ivec4(clamp(ivec3(va - vc, va - vb0 - vc - vd0, va - vb1 - vc - vd1), ivec3(0), ivec3(0xfff)), 0x780); 905*61046927SAndroid Build Coastguard Worker 906*61046927SAndroid Build Coastguard Worker if (major_component == 1) 907*61046927SAndroid Build Coastguard Worker { 908*61046927SAndroid Build Coastguard Worker swap(ep0.r, ep0.g); 909*61046927SAndroid Build Coastguard Worker swap(ep1.r, ep1.g); 910*61046927SAndroid Build Coastguard Worker } 911*61046927SAndroid Build Coastguard Worker else if (major_component == 2) 912*61046927SAndroid Build Coastguard Worker { 913*61046927SAndroid Build Coastguard Worker swap(ep0.r, ep0.b); 914*61046927SAndroid Build Coastguard Worker swap(ep1.r, ep1.b); 915*61046927SAndroid Build Coastguard Worker } 916*61046927SAndroid Build Coastguard Worker} 917*61046927SAndroid Build Coastguard Worker 918*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_rgb_base_offset(out ivec4 ep0, out ivec4 ep1, 919*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3, int v4, int v5) 920*61046927SAndroid Build Coastguard Worker{ 921*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v1, v0); 922*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v3, v2); 923*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v5, v4); 924*61046927SAndroid Build Coastguard Worker if (v1 + v3 + v5 >= 0) 925*61046927SAndroid Build Coastguard Worker { 926*61046927SAndroid Build Coastguard Worker ep0 = ivec4(v0, v2, v4, 0xff); 927*61046927SAndroid Build Coastguard Worker ep1 = ivec4(v0 + v1, v2 + v3, v4 + v5, 0xff); 928*61046927SAndroid Build Coastguard Worker } 929*61046927SAndroid Build Coastguard Worker else 930*61046927SAndroid Build Coastguard Worker { 931*61046927SAndroid Build Coastguard Worker ep0 = blue_contract(v0 + v1, v2 + v3, v4 + v5, 0xff); 932*61046927SAndroid Build Coastguard Worker ep1 = blue_contract(v0, v2, v4, 0xff); 933*61046927SAndroid Build Coastguard Worker } 934*61046927SAndroid Build Coastguard Worker 935*61046927SAndroid Build Coastguard Worker ep0.rgb = clamp(ep0.rgb, ivec3(0), ivec3(0xff)); 936*61046927SAndroid Build Coastguard Worker ep1.rgb = clamp(ep1.rgb, ivec3(0), ivec3(0xff)); 937*61046927SAndroid Build Coastguard Worker} 938*61046927SAndroid Build Coastguard Worker 939*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_rgba_direct(out ivec4 ep0, out ivec4 ep1, 940*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3, 941*61046927SAndroid Build Coastguard Worker int v4, int v5, int v6, int v7) 942*61046927SAndroid Build Coastguard Worker{ 943*61046927SAndroid Build Coastguard Worker int s0 = v0 + v2 + v4; 944*61046927SAndroid Build Coastguard Worker int s1 = v1 + v3 + v5; 945*61046927SAndroid Build Coastguard Worker if (s1 >= s0) 946*61046927SAndroid Build Coastguard Worker { 947*61046927SAndroid Build Coastguard Worker ep0 = ivec4(v0, v2, v4, v6); 948*61046927SAndroid Build Coastguard Worker ep1 = ivec4(v1, v3, v5, v7); 949*61046927SAndroid Build Coastguard Worker } 950*61046927SAndroid Build Coastguard Worker else 951*61046927SAndroid Build Coastguard Worker { 952*61046927SAndroid Build Coastguard Worker ep0 = blue_contract(v1, v3, v5, v7); 953*61046927SAndroid Build Coastguard Worker ep1 = blue_contract(v0, v2, v4, v6); 954*61046927SAndroid Build Coastguard Worker } 955*61046927SAndroid Build Coastguard Worker} 956*61046927SAndroid Build Coastguard Worker 957*61046927SAndroid Build Coastguard Workervoid decode_endpoint_ldr_rgba_base_offset(out ivec4 ep0, out ivec4 ep1, 958*61046927SAndroid Build Coastguard Worker int v0, int v1, int v2, int v3, int v4, int v5, int v6, int v7) 959*61046927SAndroid Build Coastguard Worker{ 960*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v1, v0); 961*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v3, v2); 962*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v5, v4); 963*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v7, v6); 964*61046927SAndroid Build Coastguard Worker 965*61046927SAndroid Build Coastguard Worker if (v1 + v3 + v5 >= 0) 966*61046927SAndroid Build Coastguard Worker { 967*61046927SAndroid Build Coastguard Worker ep0 = ivec4(v0, v2, v4, v6); 968*61046927SAndroid Build Coastguard Worker ep1 = ivec4(v0 + v1, v2 + v3, v4 + v5, v6 + v7); 969*61046927SAndroid Build Coastguard Worker } 970*61046927SAndroid Build Coastguard Worker else 971*61046927SAndroid Build Coastguard Worker { 972*61046927SAndroid Build Coastguard Worker ep0 = blue_contract(v0 + v1, v2 + v3, v4 + v5, v6 + v7); 973*61046927SAndroid Build Coastguard Worker ep1 = blue_contract(v0, v2, v4, v6); 974*61046927SAndroid Build Coastguard Worker } 975*61046927SAndroid Build Coastguard Worker 976*61046927SAndroid Build Coastguard Worker ep0 = clamp(ep0, ivec4(0), ivec4(0xff)); 977*61046927SAndroid Build Coastguard Worker ep1 = clamp(ep1, ivec4(0), ivec4(0xff)); 978*61046927SAndroid Build Coastguard Worker} 979*61046927SAndroid Build Coastguard Worker 980*61046927SAndroid Build Coastguard Workervoid decode_endpoint_hdr_alpha(out int ep0, out int ep1, int v6, int v7) 981*61046927SAndroid Build Coastguard Worker{ 982*61046927SAndroid Build Coastguard Worker int mode = ((v6 >> 7) & 1) | ((v7 >> 6) & 2); 983*61046927SAndroid Build Coastguard Worker v6 &= 0x7f; 984*61046927SAndroid Build Coastguard Worker v7 &= 0x7f; 985*61046927SAndroid Build Coastguard Worker 986*61046927SAndroid Build Coastguard Worker if (mode == 3) 987*61046927SAndroid Build Coastguard Worker { 988*61046927SAndroid Build Coastguard Worker ep0 = v6 << 5; 989*61046927SAndroid Build Coastguard Worker ep1 = v7 << 5; 990*61046927SAndroid Build Coastguard Worker } 991*61046927SAndroid Build Coastguard Worker else 992*61046927SAndroid Build Coastguard Worker { 993*61046927SAndroid Build Coastguard Worker v6 |= (v7 << (mode + 1)) & 0x780; 994*61046927SAndroid Build Coastguard Worker v7 &= 0x3f >> mode; 995*61046927SAndroid Build Coastguard Worker v7 ^= 0x20 >> mode; 996*61046927SAndroid Build Coastguard Worker v7 -= 0x20 >> mode; 997*61046927SAndroid Build Coastguard Worker v6 <<= 4 - mode; 998*61046927SAndroid Build Coastguard Worker v7 <<= 4 - mode; 999*61046927SAndroid Build Coastguard Worker v7 += v6; 1000*61046927SAndroid Build Coastguard Worker v7 = clamp(v7, 0, 0xfff); 1001*61046927SAndroid Build Coastguard Worker ep0 = v6; 1002*61046927SAndroid Build Coastguard Worker ep1 = v7; 1003*61046927SAndroid Build Coastguard Worker } 1004*61046927SAndroid Build Coastguard Worker} 1005*61046927SAndroid Build Coastguard Worker 1006*61046927SAndroid Build Coastguard Workervoid decode_endpoint(out ivec4 ep0, out ivec4 ep1, out int decode_mode, 1007*61046927SAndroid Build Coastguard Worker uvec4 payload, int bit_offset, ivec4 quant, int ep_mode, 1008*61046927SAndroid Build Coastguard Worker int base_endpoint_index, int num_endpoint_bits) 1009*61046927SAndroid Build Coastguard Worker{ 1010*61046927SAndroid Build Coastguard Worker num_endpoint_bits += bit_offset; 1011*61046927SAndroid Build Coastguard Worker payload &= build_bitmask(num_endpoint_bits); 1012*61046927SAndroid Build Coastguard Worker 1013*61046927SAndroid Build Coastguard Worker // Could of course use an array, but that doesn't lower nicely to indexed registers on all GPUs. 1014*61046927SAndroid Build Coastguard Worker int v0, v1, v2, v3, v4, v5, v6, v7; 1015*61046927SAndroid Build Coastguard Worker int num_values = 2 * ((ep_mode >> 2) + 1); 1016*61046927SAndroid Build Coastguard Worker 1017*61046927SAndroid Build Coastguard Worker#define DECODE_EP(i) \ 1018*61046927SAndroid Build Coastguard Worker int(texelFetch(LUTEndpointUnquantize, quant.w + decode_integer_sequence(payload, bit_offset, i + base_endpoint_index, quant.xyz)).x) 1019*61046927SAndroid Build Coastguard Worker 1020*61046927SAndroid Build Coastguard Worker int hi_bits = ep_mode >> 2; 1021*61046927SAndroid Build Coastguard Worker v0 = DECODE_EP(0); 1022*61046927SAndroid Build Coastguard Worker v1 = DECODE_EP(1); 1023*61046927SAndroid Build Coastguard Worker 1024*61046927SAndroid Build Coastguard Worker if (hi_bits >= 1) 1025*61046927SAndroid Build Coastguard Worker { 1026*61046927SAndroid Build Coastguard Worker v2 = DECODE_EP(2); 1027*61046927SAndroid Build Coastguard Worker v3 = DECODE_EP(3); 1028*61046927SAndroid Build Coastguard Worker } 1029*61046927SAndroid Build Coastguard Worker 1030*61046927SAndroid Build Coastguard Worker if (hi_bits >= 2) 1031*61046927SAndroid Build Coastguard Worker { 1032*61046927SAndroid Build Coastguard Worker v4 = DECODE_EP(4); 1033*61046927SAndroid Build Coastguard Worker v5 = DECODE_EP(5); 1034*61046927SAndroid Build Coastguard Worker } 1035*61046927SAndroid Build Coastguard Worker 1036*61046927SAndroid Build Coastguard Worker if (hi_bits >= 3) 1037*61046927SAndroid Build Coastguard Worker { 1038*61046927SAndroid Build Coastguard Worker v6 = DECODE_EP(6); 1039*61046927SAndroid Build Coastguard Worker v7 = DECODE_EP(7); 1040*61046927SAndroid Build Coastguard Worker } 1041*61046927SAndroid Build Coastguard Worker 1042*61046927SAndroid Build Coastguard Worker switch (ep_mode) 1043*61046927SAndroid Build Coastguard Worker { 1044*61046927SAndroid Build Coastguard Worker case 0: 1045*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_luma_direct(ep0, ep1, 1046*61046927SAndroid Build Coastguard Worker v0, v1); 1047*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1048*61046927SAndroid Build Coastguard Worker break; 1049*61046927SAndroid Build Coastguard Worker 1050*61046927SAndroid Build Coastguard Worker case 1: 1051*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_luma_base_offset(ep0, ep1, 1052*61046927SAndroid Build Coastguard Worker v0, v1); 1053*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1054*61046927SAndroid Build Coastguard Worker break; 1055*61046927SAndroid Build Coastguard Worker 1056*61046927SAndroid Build Coastguard Worker case 2: 1057*61046927SAndroid Build Coastguard Worker decode_endpoint_hdr_luma_direct(ep0, ep1, 1058*61046927SAndroid Build Coastguard Worker v0, v1); 1059*61046927SAndroid Build Coastguard Worker decode_mode = MODE_HDR; 1060*61046927SAndroid Build Coastguard Worker break; 1061*61046927SAndroid Build Coastguard Worker 1062*61046927SAndroid Build Coastguard Worker case 3: 1063*61046927SAndroid Build Coastguard Worker decode_endpoint_hdr_luma_direct_small_range(ep0, ep1, 1064*61046927SAndroid Build Coastguard Worker v0, v1); 1065*61046927SAndroid Build Coastguard Worker decode_mode = MODE_HDR; 1066*61046927SAndroid Build Coastguard Worker break; 1067*61046927SAndroid Build Coastguard Worker 1068*61046927SAndroid Build Coastguard Worker case 4: 1069*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_luma_alpha_direct(ep0, ep1, 1070*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3); 1071*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1072*61046927SAndroid Build Coastguard Worker break; 1073*61046927SAndroid Build Coastguard Worker 1074*61046927SAndroid Build Coastguard Worker case 5: 1075*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_luma_alpha_base_offset(ep0, ep1, 1076*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3); 1077*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1078*61046927SAndroid Build Coastguard Worker break; 1079*61046927SAndroid Build Coastguard Worker 1080*61046927SAndroid Build Coastguard Worker case 6: 1081*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_rgb_base_scale(ep0, ep1, 1082*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3); 1083*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1084*61046927SAndroid Build Coastguard Worker break; 1085*61046927SAndroid Build Coastguard Worker 1086*61046927SAndroid Build Coastguard Worker case 7: 1087*61046927SAndroid Build Coastguard Worker decode_endpoint_hdr_rgb_scale(ep0, ep1, 1088*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3); 1089*61046927SAndroid Build Coastguard Worker decode_mode = MODE_HDR; 1090*61046927SAndroid Build Coastguard Worker break; 1091*61046927SAndroid Build Coastguard Worker 1092*61046927SAndroid Build Coastguard Worker case 8: 1093*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_rgb_direct(ep0, ep1, 1094*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3, v4, v5); 1095*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1096*61046927SAndroid Build Coastguard Worker break; 1097*61046927SAndroid Build Coastguard Worker 1098*61046927SAndroid Build Coastguard Worker case 9: 1099*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_rgb_base_offset(ep0, ep1, 1100*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3, v4, v5); 1101*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1102*61046927SAndroid Build Coastguard Worker break; 1103*61046927SAndroid Build Coastguard Worker 1104*61046927SAndroid Build Coastguard Worker case 10: 1105*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_rgb_base_scale_two_a(ep0, ep1, 1106*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3, v4, v5); 1107*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1108*61046927SAndroid Build Coastguard Worker break; 1109*61046927SAndroid Build Coastguard Worker 1110*61046927SAndroid Build Coastguard Worker case 11: 1111*61046927SAndroid Build Coastguard Worker case 14: 1112*61046927SAndroid Build Coastguard Worker case 15: 1113*61046927SAndroid Build Coastguard Worker decode_endpoint_hdr_rgb_direct(ep0, ep1, 1114*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3, v4, v5); 1115*61046927SAndroid Build Coastguard Worker if (ep_mode == 14) 1116*61046927SAndroid Build Coastguard Worker { 1117*61046927SAndroid Build Coastguard Worker ep0.a = v6; 1118*61046927SAndroid Build Coastguard Worker ep1.a = v7; 1119*61046927SAndroid Build Coastguard Worker decode_mode = MODE_HDR_LDR_ALPHA; 1120*61046927SAndroid Build Coastguard Worker } 1121*61046927SAndroid Build Coastguard Worker else if (ep_mode == 15) 1122*61046927SAndroid Build Coastguard Worker { 1123*61046927SAndroid Build Coastguard Worker decode_endpoint_hdr_alpha(ep0.a, ep1.a, v6, v7); 1124*61046927SAndroid Build Coastguard Worker decode_mode = MODE_HDR; 1125*61046927SAndroid Build Coastguard Worker } 1126*61046927SAndroid Build Coastguard Worker else 1127*61046927SAndroid Build Coastguard Worker decode_mode = MODE_HDR; 1128*61046927SAndroid Build Coastguard Worker break; 1129*61046927SAndroid Build Coastguard Worker 1130*61046927SAndroid Build Coastguard Worker case 12: 1131*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_rgba_direct(ep0, ep1, 1132*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3, v4, v5, v6, v7); 1133*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1134*61046927SAndroid Build Coastguard Worker break; 1135*61046927SAndroid Build Coastguard Worker 1136*61046927SAndroid Build Coastguard Worker case 13: 1137*61046927SAndroid Build Coastguard Worker decode_endpoint_ldr_rgba_base_offset(ep0, ep1, 1138*61046927SAndroid Build Coastguard Worker v0, v1, v2, v3, v4, v5, v6, v7); 1139*61046927SAndroid Build Coastguard Worker decode_mode = MODE_LDR; 1140*61046927SAndroid Build Coastguard Worker break; 1141*61046927SAndroid Build Coastguard Worker } 1142*61046927SAndroid Build Coastguard Worker 1143*61046927SAndroid Build Coastguard Worker if (DECODE_8BIT && decode_mode != MODE_LDR) 1144*61046927SAndroid Build Coastguard Worker decode_error = true; 1145*61046927SAndroid Build Coastguard Worker} 1146*61046927SAndroid Build Coastguard Worker 1147*61046927SAndroid Build Coastguard Worker#define CHECK_DECODE_ERROR() do { \ 1148*61046927SAndroid Build Coastguard Worker if (decode_error) \ 1149*61046927SAndroid Build Coastguard Worker { \ 1150*61046927SAndroid Build Coastguard Worker emit_decode_error(coord.xy); \ 1151*61046927SAndroid Build Coastguard Worker return; \ 1152*61046927SAndroid Build Coastguard Worker } \ 1153*61046927SAndroid Build Coastguard Worker} while(false) 1154*61046927SAndroid Build Coastguard Worker 1155*61046927SAndroid Build Coastguard Workervoid emit_decode_error(ivec2 coord) 1156*61046927SAndroid Build Coastguard Worker{ 1157*61046927SAndroid Build Coastguard Worker#ifdef VULKAN 1158*61046927SAndroid Build Coastguard Worker if (is_3Dimage) 1159*61046927SAndroid Build Coastguard Worker imageStore(OutputImage3D, ivec3(coord, gl_WorkGroupID.z), error_color); 1160*61046927SAndroid Build Coastguard Worker else 1161*61046927SAndroid Build Coastguard Worker imageStore(OutputImage2Darray, ivec3(coord, gl_WorkGroupID.z), error_color); 1162*61046927SAndroid Build Coastguard Worker#else /* VULKAN */ 1163*61046927SAndroid Build Coastguard Worker imageStore(OutputImage, coord, error_color); 1164*61046927SAndroid Build Coastguard Worker#endif /* VULKAN */ 1165*61046927SAndroid Build Coastguard Worker} 1166*61046927SAndroid Build Coastguard Worker 1167*61046927SAndroid Build Coastguard Workerint compute_num_endpoint_pairs(int num_partitions, int cem) 1168*61046927SAndroid Build Coastguard Worker{ 1169*61046927SAndroid Build Coastguard Worker int ret; 1170*61046927SAndroid Build Coastguard Worker if (num_partitions > 1) 1171*61046927SAndroid Build Coastguard Worker { 1172*61046927SAndroid Build Coastguard Worker bool single_cem = (cem & 3) == 0; 1173*61046927SAndroid Build Coastguard Worker if (single_cem) 1174*61046927SAndroid Build Coastguard Worker ret = ((cem >> 4) + 1) * num_partitions; 1175*61046927SAndroid Build Coastguard Worker else 1176*61046927SAndroid Build Coastguard Worker ret = (cem & 3) * num_partitions + bitCount(bitfieldExtract(uint(cem), 2, num_partitions)); 1177*61046927SAndroid Build Coastguard Worker } 1178*61046927SAndroid Build Coastguard Worker else 1179*61046927SAndroid Build Coastguard Worker { 1180*61046927SAndroid Build Coastguard Worker ret = (cem >> 2) + 1; 1181*61046927SAndroid Build Coastguard Worker } 1182*61046927SAndroid Build Coastguard Worker return ret; 1183*61046927SAndroid Build Coastguard Worker} 1184*61046927SAndroid Build Coastguard Worker 1185*61046927SAndroid Build Coastguard Workervoid decode_cem_base_endpoint(uvec4 payload, int weight_cost_bits, inout int cem, out int base_endpoint_index, 1186*61046927SAndroid Build Coastguard Worker int num_partitions, int partition_index) 1187*61046927SAndroid Build Coastguard Worker{ 1188*61046927SAndroid Build Coastguard Worker if (num_partitions > 1) 1189*61046927SAndroid Build Coastguard Worker { 1190*61046927SAndroid Build Coastguard Worker bool single_cem = (cem & 3) == 0; 1191*61046927SAndroid Build Coastguard Worker if (single_cem) 1192*61046927SAndroid Build Coastguard Worker { 1193*61046927SAndroid Build Coastguard Worker cem >>= 2; 1194*61046927SAndroid Build Coastguard Worker base_endpoint_index = ((cem >> 2) + 1) * partition_index; 1195*61046927SAndroid Build Coastguard Worker } 1196*61046927SAndroid Build Coastguard Worker else 1197*61046927SAndroid Build Coastguard Worker { 1198*61046927SAndroid Build Coastguard Worker if (partition_index != 0) 1199*61046927SAndroid Build Coastguard Worker base_endpoint_index = (cem & 3) * partition_index + bitCount(bitfieldExtract(uint(cem), 2, partition_index)); 1200*61046927SAndroid Build Coastguard Worker else 1201*61046927SAndroid Build Coastguard Worker base_endpoint_index = 0; 1202*61046927SAndroid Build Coastguard Worker 1203*61046927SAndroid Build Coastguard Worker int base_class = (cem & 3) - 1; 1204*61046927SAndroid Build Coastguard Worker int extra_cem_bits = num_partitions * 3 - 4; 1205*61046927SAndroid Build Coastguard Worker int extra_bits = extract_bits(payload, 128 - weight_cost_bits - extra_cem_bits, extra_cem_bits); 1206*61046927SAndroid Build Coastguard Worker cem = (extra_bits << 4) | (cem >> 2); 1207*61046927SAndroid Build Coastguard Worker 1208*61046927SAndroid Build Coastguard Worker int class_offset_bit = (cem >> partition_index) & 1; 1209*61046927SAndroid Build Coastguard Worker int ep_bits = (cem >> (num_partitions + 2 * partition_index)) & 3; 1210*61046927SAndroid Build Coastguard Worker 1211*61046927SAndroid Build Coastguard Worker cem = 4 * (base_class + class_offset_bit) + ep_bits; 1212*61046927SAndroid Build Coastguard Worker } 1213*61046927SAndroid Build Coastguard Worker base_endpoint_index *= 2; 1214*61046927SAndroid Build Coastguard Worker } 1215*61046927SAndroid Build Coastguard Worker else 1216*61046927SAndroid Build Coastguard Worker { 1217*61046927SAndroid Build Coastguard Worker base_endpoint_index = 0; 1218*61046927SAndroid Build Coastguard Worker } 1219*61046927SAndroid Build Coastguard Worker} 1220*61046927SAndroid Build Coastguard Worker 1221*61046927SAndroid Build Coastguard Workerivec4 void_extent_color(uvec4 payload, out int decode_mode) 1222*61046927SAndroid Build Coastguard Worker{ 1223*61046927SAndroid Build Coastguard Worker int min_s = extract_bits(payload, 12, 13); 1224*61046927SAndroid Build Coastguard Worker int max_s = extract_bits(payload, 12 + 13, 13); 1225*61046927SAndroid Build Coastguard Worker int min_t = extract_bits(payload, 12 + 2 * 13, 13); 1226*61046927SAndroid Build Coastguard Worker int max_t = extract_bits(payload, 12 + 3 * 13, 13); 1227*61046927SAndroid Build Coastguard Worker 1228*61046927SAndroid Build Coastguard Worker int reserved = extract_bits(payload, 10, 2); 1229*61046927SAndroid Build Coastguard Worker if (reserved != 3) 1230*61046927SAndroid Build Coastguard Worker { 1231*61046927SAndroid Build Coastguard Worker decode_error = true; 1232*61046927SAndroid Build Coastguard Worker return ivec4(0); 1233*61046927SAndroid Build Coastguard Worker } 1234*61046927SAndroid Build Coastguard Worker 1235*61046927SAndroid Build Coastguard Worker if (!all(equal(ivec4(min_s, max_s, min_t, max_t), ivec4((1 << 13) - 1)))) 1236*61046927SAndroid Build Coastguard Worker { 1237*61046927SAndroid Build Coastguard Worker if (any(greaterThanEqual(ivec2(min_s, min_t), ivec2(max_s, max_t)))) 1238*61046927SAndroid Build Coastguard Worker { 1239*61046927SAndroid Build Coastguard Worker decode_error = true; 1240*61046927SAndroid Build Coastguard Worker return ivec4(0); 1241*61046927SAndroid Build Coastguard Worker } 1242*61046927SAndroid Build Coastguard Worker } 1243*61046927SAndroid Build Coastguard Worker 1244*61046927SAndroid Build Coastguard Worker decode_mode = (payload.x & (1u << 9)) != 0u ? MODE_HDR : MODE_LDR; 1245*61046927SAndroid Build Coastguard Worker 1246*61046927SAndroid Build Coastguard Worker int r = extract_bits(payload, 64, 16); 1247*61046927SAndroid Build Coastguard Worker int g = extract_bits(payload, 64 + 16, 16); 1248*61046927SAndroid Build Coastguard Worker int b = extract_bits(payload, 64 + 32, 16); 1249*61046927SAndroid Build Coastguard Worker int a = extract_bits(payload, 64 + 48, 16); 1250*61046927SAndroid Build Coastguard Worker 1251*61046927SAndroid Build Coastguard Worker return ivec4(r, g, b, a); 1252*61046927SAndroid Build Coastguard Worker} 1253*61046927SAndroid Build Coastguard Worker 1254*61046927SAndroid Build Coastguard Workervoid main() 1255*61046927SAndroid Build Coastguard Worker{ 1256*61046927SAndroid Build Coastguard Worker ivec4 coord = build_coord(); 1257*61046927SAndroid Build Coastguard Worker#ifdef VULKAN 1258*61046927SAndroid Build Coastguard Worker if (any(greaterThanEqual(coord.xy, texel_end.xy))) 1259*61046927SAndroid Build Coastguard Worker return; 1260*61046927SAndroid Build Coastguard Worker#else /* VULKAN */ 1261*61046927SAndroid Build Coastguard Worker if (any(greaterThanEqual(coord.xy, imageSize(OutputImage)))) 1262*61046927SAndroid Build Coastguard Worker return; 1263*61046927SAndroid Build Coastguard Worker#endif /* VULKAN */ 1264*61046927SAndroid Build Coastguard Worker 1265*61046927SAndroid Build Coastguard Worker ivec2 pixel_coord = ivec2(gl_LocalInvocationID.xy); 1266*61046927SAndroid Build Coastguard Worker int linear_pixel = int(gl_WorkGroupSize.x) * pixel_coord.y + pixel_coord.x; 1267*61046927SAndroid Build Coastguard Worker uvec4 payload; 1268*61046927SAndroid Build Coastguard Worker#ifdef VULKAN 1269*61046927SAndroid Build Coastguard Worker if (is_3Dimage) 1270*61046927SAndroid Build Coastguard Worker payload = texelFetch(PayloadInput3D, ivec3(coord.zw, gl_WorkGroupID.z), 0); 1271*61046927SAndroid Build Coastguard Worker else 1272*61046927SAndroid Build Coastguard Worker payload = texelFetch(PayloadInput2Darray,ivec3(coord.zw, gl_WorkGroupID.z), 0); 1273*61046927SAndroid Build Coastguard Worker#else /* VULKAN */ 1274*61046927SAndroid Build Coastguard Worker payload = texelFetch(PayloadInput, coord.zw, 0); 1275*61046927SAndroid Build Coastguard Worker#endif /* VULKAN */ 1276*61046927SAndroid Build Coastguard Worker 1277*61046927SAndroid Build Coastguard Worker BlockMode block_mode = decode_block_mode(payload); 1278*61046927SAndroid Build Coastguard Worker CHECK_DECODE_ERROR(); 1279*61046927SAndroid Build Coastguard Worker 1280*61046927SAndroid Build Coastguard Worker ivec4 final_color; 1281*61046927SAndroid Build Coastguard Worker int decode_mode; 1282*61046927SAndroid Build Coastguard Worker if (block_mode.void_extent) 1283*61046927SAndroid Build Coastguard Worker { 1284*61046927SAndroid Build Coastguard Worker final_color = void_extent_color(payload, decode_mode); 1285*61046927SAndroid Build Coastguard Worker CHECK_DECODE_ERROR(); 1286*61046927SAndroid Build Coastguard Worker } 1287*61046927SAndroid Build Coastguard Worker else 1288*61046927SAndroid Build Coastguard Worker { 1289*61046927SAndroid Build Coastguard Worker int weight_cost_bits; 1290*61046927SAndroid Build Coastguard Worker ivec4 weights = decode_weights(payload, block_mode, normalize_coord(pixel_coord), weight_cost_bits); 1291*61046927SAndroid Build Coastguard Worker 1292*61046927SAndroid Build Coastguard Worker int partition_index = 0; 1293*61046927SAndroid Build Coastguard Worker if (block_mode.num_partitions > 1) 1294*61046927SAndroid Build Coastguard Worker { 1295*61046927SAndroid Build Coastguard Worker int lut_x = pixel_coord.x + int(gl_WorkGroupSize.x) * (block_mode.seed & 31); 1296*61046927SAndroid Build Coastguard Worker int lut_y = pixel_coord.y + int(gl_WorkGroupSize.y) * (block_mode.seed >> 5); 1297*61046927SAndroid Build Coastguard Worker#ifdef VULKAN 1298*61046927SAndroid Build Coastguard Worker int lut_width = int(gl_WorkGroupSize.x) * 32; 1299*61046927SAndroid Build Coastguard Worker partition_index = int(texelFetch(LUTPartitionTable, lut_y * lut_width + lut_x).x); 1300*61046927SAndroid Build Coastguard Worker#else /* VULKAN */ 1301*61046927SAndroid Build Coastguard Worker partition_index = int(texelFetch(LUTPartitionTable, ivec2(lut_x, lut_y), 0).x); 1302*61046927SAndroid Build Coastguard Worker#endif /* VULKAN */ 1303*61046927SAndroid Build Coastguard Worker partition_index = (partition_index >> (2 * block_mode.num_partitions - 4)) & 3; 1304*61046927SAndroid Build Coastguard Worker } 1305*61046927SAndroid Build Coastguard Worker 1306*61046927SAndroid Build Coastguard Worker int available_endpoint_bits = max(128 - block_mode.config_bits - weight_cost_bits, 0); 1307*61046927SAndroid Build Coastguard Worker 1308*61046927SAndroid Build Coastguard Worker // In multi-partition mode, the 6-bit CEM field is encoded as 1309*61046927SAndroid Build Coastguard Worker // First two bits tell if all CEM field are the same, if not we specify a class offset, and N bits 1310*61046927SAndroid Build Coastguard Worker // after that will offset the class by 1. 1311*61046927SAndroid Build Coastguard Worker int num_endpoint_pairs = compute_num_endpoint_pairs(block_mode.num_partitions, block_mode.cem); 1312*61046927SAndroid Build Coastguard Worker 1313*61046927SAndroid Build Coastguard Worker // Error color must be emitted if we need more than 18 integer sequence encoded values of color. 1314*61046927SAndroid Build Coastguard Worker if (num_endpoint_pairs > 9) 1315*61046927SAndroid Build Coastguard Worker { 1316*61046927SAndroid Build Coastguard Worker decode_error = true; 1317*61046927SAndroid Build Coastguard Worker emit_decode_error(coord.xy); 1318*61046927SAndroid Build Coastguard Worker return; 1319*61046927SAndroid Build Coastguard Worker } 1320*61046927SAndroid Build Coastguard Worker 1321*61046927SAndroid Build Coastguard Worker ivec4 endpoint_quant = ivec4(texelFetch(LUTRemainingBitsToEndpointQuantizer, 1322*61046927SAndroid Build Coastguard Worker 128 * (num_endpoint_pairs - 1) + available_endpoint_bits)); 1323*61046927SAndroid Build Coastguard Worker 1324*61046927SAndroid Build Coastguard Worker // Only read the bits we need for endpoints. 1325*61046927SAndroid Build Coastguard Worker int num_endpoint_values = num_endpoint_pairs * 2; 1326*61046927SAndroid Build Coastguard Worker available_endpoint_bits = 1327*61046927SAndroid Build Coastguard Worker endpoint_quant.x * num_endpoint_values + 1328*61046927SAndroid Build Coastguard Worker idiv5_ceil(endpoint_quant.y * 8 * num_endpoint_values) + 1329*61046927SAndroid Build Coastguard Worker idiv3_ceil(endpoint_quant.z * 7 * num_endpoint_values); 1330*61046927SAndroid Build Coastguard Worker 1331*61046927SAndroid Build Coastguard Worker // No space left for color endpoints. 1332*61046927SAndroid Build Coastguard Worker if (all(equal(endpoint_quant.xyz, ivec3(0)))) 1333*61046927SAndroid Build Coastguard Worker { 1334*61046927SAndroid Build Coastguard Worker decode_error = true; 1335*61046927SAndroid Build Coastguard Worker emit_decode_error(coord.xy); 1336*61046927SAndroid Build Coastguard Worker return; 1337*61046927SAndroid Build Coastguard Worker } 1338*61046927SAndroid Build Coastguard Worker 1339*61046927SAndroid Build Coastguard Worker int endpoint_bit_offset = block_mode.primary_config_bits; 1340*61046927SAndroid Build Coastguard Worker ivec4 ep0, ep1; 1341*61046927SAndroid Build Coastguard Worker 1342*61046927SAndroid Build Coastguard Worker // Decode CEM for multi-partition schemes. 1343*61046927SAndroid Build Coastguard Worker int cem = block_mode.cem; 1344*61046927SAndroid Build Coastguard Worker int base_endpoint_index; 1345*61046927SAndroid Build Coastguard Worker decode_cem_base_endpoint(payload, weight_cost_bits, cem, base_endpoint_index, 1346*61046927SAndroid Build Coastguard Worker block_mode.num_partitions, partition_index); 1347*61046927SAndroid Build Coastguard Worker 1348*61046927SAndroid Build Coastguard Worker decode_endpoint(ep0, ep1, decode_mode, payload, endpoint_bit_offset, endpoint_quant, 1349*61046927SAndroid Build Coastguard Worker cem, base_endpoint_index, available_endpoint_bits); 1350*61046927SAndroid Build Coastguard Worker CHECK_DECODE_ERROR(); 1351*61046927SAndroid Build Coastguard Worker 1352*61046927SAndroid Build Coastguard Worker final_color = interpolate_endpoint(ep0, ep1, weights, decode_mode); 1353*61046927SAndroid Build Coastguard Worker } 1354*61046927SAndroid Build Coastguard Worker 1355*61046927SAndroid Build Coastguard Worker if (DECODE_8BIT) 1356*61046927SAndroid Build Coastguard Worker { 1357*61046927SAndroid Build Coastguard Worker#ifdef VULKAN 1358*61046927SAndroid Build Coastguard Worker if (is_3Dimage) 1359*61046927SAndroid Build Coastguard Worker imageStore(OutputImage3D, ivec3(coord.xy, gl_WorkGroupID.z), uvec4(final_color >> 8)); 1360*61046927SAndroid Build Coastguard Worker else 1361*61046927SAndroid Build Coastguard Worker imageStore(OutputImage2Darray, ivec3(coord.xy, gl_WorkGroupID.z), uvec4(final_color >> 8)); 1362*61046927SAndroid Build Coastguard Worker#else /* VULKAN */ 1363*61046927SAndroid Build Coastguard Worker imageStore(OutputImage, coord.xy, uvec4(final_color >> 8)); 1364*61046927SAndroid Build Coastguard Worker#endif /* VULKAN */ 1365*61046927SAndroid Build Coastguard Worker } 1366*61046927SAndroid Build Coastguard Worker else 1367*61046927SAndroid Build Coastguard Worker { 1368*61046927SAndroid Build Coastguard Worker uvec4 encoded; 1369*61046927SAndroid Build Coastguard Worker if (block_mode.void_extent && decode_mode == MODE_HDR) 1370*61046927SAndroid Build Coastguard Worker encoded = uvec4(final_color); 1371*61046927SAndroid Build Coastguard Worker else 1372*61046927SAndroid Build Coastguard Worker encoded = decode_fp16(final_color, decode_mode); 1373*61046927SAndroid Build Coastguard Worker#ifdef VULKAN 1374*61046927SAndroid Build Coastguard Worker if (is_3Dimage) 1375*61046927SAndroid Build Coastguard Worker imageStore(OutputImage3D, ivec3(coord.xy, gl_WorkGroupID.z), encoded); 1376*61046927SAndroid Build Coastguard Worker else 1377*61046927SAndroid Build Coastguard Worker imageStore(OutputImage2Darray, ivec3(coord.xy, gl_WorkGroupID.z), encoded); 1378*61046927SAndroid Build Coastguard Worker#else /* VULKAN */ 1379*61046927SAndroid Build Coastguard Worker imageStore(OutputImage, coord.xy, encoded); 1380*61046927SAndroid Build Coastguard Worker#endif /* VULKAN */ 1381*61046927SAndroid Build Coastguard Worker } 1382*61046927SAndroid Build Coastguard Worker} 1383