in src/webgpu/util/texture/texel_data.ts [286:369]
function unpackComponentsBits(
componentOrder: TexelComponent[],
byteView: Uint8Array,
bitLengths: number | PerTexelComponent<number>
): PerTexelComponent<number> {
const components = makePerTexelComponent(componentOrder, 0);
let bitLengthMap;
let totalBitLength;
if (typeof bitLengths === 'number') {
let index = 0;
// Optimized cases for when the bit lengths are all a well aligned value.
switch (bitLengths) {
case 8:
for (const c of componentOrder) {
components[c] = byteView[index++];
}
return components;
case 16: {
const shortView = new Uint16Array(byteView.buffer, byteView.byteOffset);
for (const c of componentOrder) {
components[c] = shortView[index++];
}
return components;
}
case 32: {
const longView = new Uint32Array(byteView.buffer, byteView.byteOffset);
for (const c of componentOrder) {
components[c] = longView[index++];
}
return components;
}
}
bitLengthMap = makePerTexelComponent(componentOrder, bitLengths);
totalBitLength = bitLengths * componentOrder.length;
} else {
bitLengthMap = bitLengths;
totalBitLength = Object.entries(bitLengthMap).reduce((acc, [, value]) => {
assert(value !== undefined);
return acc + value;
}, 0);
}
assert(totalBitLength % 8 === 0);
const dataView = new DataView(byteView.buffer, byteView.byteOffset, byteView.byteLength);
let bitOffset = 0;
for (const c of componentOrder) {
const bitLength = bitLengthMap[c];
assert(bitLength !== undefined);
let value: number;
const byteOffset = Math.floor(bitOffset / 8);
const byteLength = Math.ceil(bitLength / 8);
if (byteOffset === bitOffset / 8 && byteLength === bitLength / 8) {
switch (byteLength) {
case 1:
value = dataView.getUint8(byteOffset);
break;
case 2:
value = dataView.getUint16(byteOffset, true);
break;
case 4:
value = dataView.getUint32(byteOffset, true);
break;
default:
unreachable();
}
} else {
// Packed representations are all 32-bit and use Uint as the data type.
// ex.) rg10b11float, rgb10a2unorm
assert(dataView.byteLength === 4);
const word = dataView.getUint32(0, true);
value = (word >>> bitOffset) & ((1 << bitLength) - 1);
}
bitOffset += bitLength;
components[c] = value;
}
return components;
}