Add existing to tracked
This commit is contained in:
+69
@@ -0,0 +1,69 @@
|
||||
export class BufferReader {
|
||||
private _dataView: DataView;
|
||||
private _littleEndian: boolean;
|
||||
public _offset: number;
|
||||
|
||||
constructor(data: Uint8Array, byteOffset: number, byteLength: number, littleEndian: boolean) {
|
||||
this._dataView = new DataView(data.buffer, data.byteOffset + byteOffset, byteLength);
|
||||
this._littleEndian = littleEndian;
|
||||
this._offset = 0;
|
||||
}
|
||||
|
||||
_nextUint8(): number {
|
||||
const value = this._dataView.getUint8(this._offset);
|
||||
this._offset += 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
_nextUint16(): number {
|
||||
const value = this._dataView.getUint16(this._offset, this._littleEndian);
|
||||
this._offset += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
_nextUint32(): number {
|
||||
const value = this._dataView.getUint32(this._offset, this._littleEndian);
|
||||
this._offset += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
_nextUint64(): number {
|
||||
const left = this._dataView.getUint32(this._offset, this._littleEndian);
|
||||
const right = this._dataView.getUint32(this._offset + 4, this._littleEndian);
|
||||
// TODO(cleanup): Just test this...
|
||||
// const value = this._littleEndian ? left + (2 ** 32 * right) : (2 ** 32 * left) + right;
|
||||
const value = left + 2 ** 32 * right;
|
||||
this._offset += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
_nextInt32(): number {
|
||||
const value = this._dataView.getInt32(this._offset, this._littleEndian);
|
||||
this._offset += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
_nextUint8Array(len: number): Uint8Array {
|
||||
const value = new Uint8Array(this._dataView.buffer, this._dataView.byteOffset + this._offset, len);
|
||||
this._offset += len;
|
||||
return value;
|
||||
}
|
||||
|
||||
_skip(bytes: number): this {
|
||||
this._offset += bytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
_scan(maxByteLength: number, term = 0x00): Uint8Array {
|
||||
const byteOffset = this._offset;
|
||||
let byteLength = 0;
|
||||
while (this._dataView.getUint8(this._offset) !== term && byteLength < maxByteLength) {
|
||||
byteLength++;
|
||||
this._offset++;
|
||||
}
|
||||
|
||||
if (byteLength < maxByteLength) this._offset++;
|
||||
|
||||
return new Uint8Array(this._dataView.buffer, this._dataView.byteOffset + byteOffset, byteLength);
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
///////////////////////////////////////////////////
|
||||
// Common.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
// Injected at compile time, from $npm_package_version.
|
||||
declare const PACKAGE_VERSION: string;
|
||||
|
||||
export const KTX_WRITER: string = `KTX-Parse v${PACKAGE_VERSION}`;
|
||||
|
||||
export const NUL: Uint8Array = new Uint8Array([0x00]);
|
||||
|
||||
export type vec3 = [number, number, number];
|
||||
export type vec2 = [number, number, number];
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// KTX2 Header.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
export const KTX2_ID: number[] = [
|
||||
// '´', 'K', 'T', 'X', '2', '0', 'ª', '\r', '\n', '\x1A', '\n'
|
||||
0xab, 0x4b, 0x54, 0x58, 0x20, 0x32, 0x30, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a,
|
||||
];
|
||||
|
||||
export const HEADER_BYTE_LENGTH = 68; // 13 * 4 + 2 * 8
|
||||
+511
@@ -0,0 +1,511 @@
|
||||
///////////////////////////////////////////////////
|
||||
// KTX2 Header.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
export const KHR_SUPERCOMPRESSION_NONE = 0;
|
||||
export const KHR_SUPERCOMPRESSION_BASISLZ = 1;
|
||||
export const KHR_SUPERCOMPRESSION_ZSTD = 2;
|
||||
export const KHR_SUPERCOMPRESSION_ZLIB = 3;
|
||||
|
||||
export type Supercompression =
|
||||
| typeof KHR_SUPERCOMPRESSION_NONE
|
||||
| typeof KHR_SUPERCOMPRESSION_BASISLZ
|
||||
| typeof KHR_SUPERCOMPRESSION_ZSTD
|
||||
| typeof KHR_SUPERCOMPRESSION_ZLIB;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Data Format Descriptor (DFD).
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
export const KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT = 0;
|
||||
export const KHR_DF_VENDORID_KHRONOS = 0;
|
||||
export const KHR_DF_VERSION = 2;
|
||||
|
||||
export const KHR_DF_MODEL_UNSPECIFIED = 0;
|
||||
export const KHR_DF_MODEL_RGBSDA = 1;
|
||||
// ...
|
||||
export const KHR_DF_MODEL_ETC1 = 160;
|
||||
export const KHR_DF_MODEL_ETC2 = 161;
|
||||
export const KHR_DF_MODEL_ASTC = 162;
|
||||
export const KHR_DF_MODEL_ETC1S = 163;
|
||||
export const KHR_DF_MODEL_UASTC = 166;
|
||||
|
||||
export const KHR_DF_FLAG_ALPHA_STRAIGHT = 0;
|
||||
export const KHR_DF_FLAG_ALPHA_PREMULTIPLIED = 1;
|
||||
|
||||
export const KHR_DF_TRANSFER_UNSPECIFIED = 0;
|
||||
export const KHR_DF_TRANSFER_LINEAR = 1;
|
||||
export const KHR_DF_TRANSFER_SRGB = 2;
|
||||
export const KHR_DF_TRANSFER_ITU = 3;
|
||||
export const KHR_DF_TRANSFER_NTSC = 4;
|
||||
export const KHR_DF_TRANSFER_SLOG = 5;
|
||||
export const KHR_DF_TRANSFER_SLOG2 = 6;
|
||||
export const KHR_DF_TRANSFER_BT1886 = 7;
|
||||
export const KHR_DF_TRANSFER_HLG_OETF = 8;
|
||||
export const KHR_DF_TRANSFER_HLG_EOTF = 9;
|
||||
export const KHR_DF_TRANSFER_PQ_EOTF = 10;
|
||||
export const KHR_DF_TRANSFER_PQ_OETF = 11;
|
||||
export const KHR_DF_TRANSFER_DCIP3 = 12;
|
||||
export const KHR_DF_TRANSFER_PAL_OETF = 13;
|
||||
export const KHR_DF_TRANSFER_PAL625_EOTF = 14;
|
||||
export const KHR_DF_TRANSFER_ST240 = 15;
|
||||
export const KHR_DF_TRANSFER_ACESCC = 16;
|
||||
export const KHR_DF_TRANSFER_ACESCCT = 17;
|
||||
export const KHR_DF_TRANSFER_ADOBERGB = 18;
|
||||
|
||||
export type Transfer =
|
||||
| typeof KHR_DF_TRANSFER_UNSPECIFIED
|
||||
| typeof KHR_DF_TRANSFER_LINEAR
|
||||
| typeof KHR_DF_TRANSFER_SRGB
|
||||
| typeof KHR_DF_TRANSFER_ITU
|
||||
| typeof KHR_DF_TRANSFER_NTSC
|
||||
| typeof KHR_DF_TRANSFER_SLOG
|
||||
| typeof KHR_DF_TRANSFER_SLOG2
|
||||
| typeof KHR_DF_TRANSFER_BT1886
|
||||
| typeof KHR_DF_TRANSFER_HLG_OETF
|
||||
| typeof KHR_DF_TRANSFER_HLG_EOTF
|
||||
| typeof KHR_DF_TRANSFER_PQ_EOTF
|
||||
| typeof KHR_DF_TRANSFER_PQ_OETF
|
||||
| typeof KHR_DF_TRANSFER_DCIP3
|
||||
| typeof KHR_DF_TRANSFER_PAL_OETF
|
||||
| typeof KHR_DF_TRANSFER_PAL625_EOTF
|
||||
| typeof KHR_DF_TRANSFER_ST240
|
||||
| typeof KHR_DF_TRANSFER_ACESCC
|
||||
| typeof KHR_DF_TRANSFER_ACESCCT
|
||||
| typeof KHR_DF_TRANSFER_ADOBERGB;
|
||||
|
||||
export const KHR_DF_PRIMARIES_UNSPECIFIED = 0;
|
||||
export const KHR_DF_PRIMARIES_BT709 = 1;
|
||||
export const KHR_DF_PRIMARIES_BT601_EBU = 2;
|
||||
export const KHR_DF_PRIMARIES_BT601_SMPTE = 3;
|
||||
export const KHR_DF_PRIMARIES_BT2020 = 4;
|
||||
export const KHR_DF_PRIMARIES_CIEXYZ = 5;
|
||||
export const KHR_DF_PRIMARIES_ACES = 6;
|
||||
export const KHR_DF_PRIMARIES_ACESCC = 7;
|
||||
export const KHR_DF_PRIMARIES_NTSC1953 = 8;
|
||||
export const KHR_DF_PRIMARIES_PAL525 = 9;
|
||||
export const KHR_DF_PRIMARIES_DISPLAYP3 = 10;
|
||||
export const KHR_DF_PRIMARIES_ADOBERGB = 11;
|
||||
|
||||
export type Primaries =
|
||||
| typeof KHR_DF_PRIMARIES_UNSPECIFIED
|
||||
| typeof KHR_DF_PRIMARIES_BT709
|
||||
| typeof KHR_DF_PRIMARIES_BT601_EBU
|
||||
| typeof KHR_DF_PRIMARIES_BT601_SMPTE
|
||||
| typeof KHR_DF_PRIMARIES_BT2020
|
||||
| typeof KHR_DF_PRIMARIES_CIEXYZ
|
||||
| typeof KHR_DF_PRIMARIES_ACES
|
||||
| typeof KHR_DF_PRIMARIES_ACESCC
|
||||
| typeof KHR_DF_PRIMARIES_NTSC1953
|
||||
| typeof KHR_DF_PRIMARIES_PAL525
|
||||
| typeof KHR_DF_PRIMARIES_DISPLAYP3
|
||||
| typeof KHR_DF_PRIMARIES_ADOBERGB;
|
||||
|
||||
export const KHR_DF_CHANNEL_RGBSDA_RED = 0;
|
||||
export const KHR_DF_CHANNEL_RGBSDA_GREEN = 1;
|
||||
export const KHR_DF_CHANNEL_RGBSDA_BLUE = 2;
|
||||
export const KHR_DF_CHANNEL_RGBSDA_STENCIL = 13;
|
||||
export const KHR_DF_CHANNEL_RGBSDA_DEPTH = 14;
|
||||
export const KHR_DF_CHANNEL_RGBSDA_ALPHA = 15;
|
||||
|
||||
export type Channel =
|
||||
| typeof KHR_DF_CHANNEL_RGBSDA_RED
|
||||
| typeof KHR_DF_CHANNEL_RGBSDA_GREEN
|
||||
| typeof KHR_DF_CHANNEL_RGBSDA_BLUE
|
||||
| typeof KHR_DF_CHANNEL_RGBSDA_STENCIL
|
||||
| typeof KHR_DF_CHANNEL_RGBSDA_DEPTH
|
||||
| typeof KHR_DF_CHANNEL_RGBSDA_ALPHA;
|
||||
|
||||
export const KHR_DF_SAMPLE_DATATYPE_FLOAT = 0x80;
|
||||
export const KHR_DF_SAMPLE_DATATYPE_SIGNED = 0x40;
|
||||
export const KHR_DF_SAMPLE_DATATYPE_EXPONENT = 0x20;
|
||||
export const KHR_DF_SAMPLE_DATATYPE_LINEAR = 0x10;
|
||||
|
||||
export type SampleDatatype =
|
||||
| typeof KHR_DF_SAMPLE_DATATYPE_FLOAT
|
||||
| typeof KHR_DF_SAMPLE_DATATYPE_SIGNED
|
||||
| typeof KHR_DF_SAMPLE_DATATYPE_EXPONENT
|
||||
| typeof KHR_DF_SAMPLE_DATATYPE_LINEAR;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// VK FORMAT.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
export const VK_FORMAT_UNDEFINED = 0;
|
||||
export const VK_FORMAT_R4G4_UNORM_PACK8 = 1;
|
||||
export const VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2;
|
||||
export const VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3;
|
||||
export const VK_FORMAT_R5G6B5_UNORM_PACK16 = 4;
|
||||
export const VK_FORMAT_B5G6R5_UNORM_PACK16 = 5;
|
||||
export const VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6;
|
||||
export const VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7;
|
||||
export const VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8;
|
||||
export const VK_FORMAT_R8_UNORM = 9;
|
||||
export const VK_FORMAT_R8_SNORM = 10;
|
||||
export const VK_FORMAT_R8_UINT = 13;
|
||||
export const VK_FORMAT_R8_SINT = 14;
|
||||
export const VK_FORMAT_R8_SRGB = 15;
|
||||
export const VK_FORMAT_R8G8_UNORM = 16;
|
||||
export const VK_FORMAT_R8G8_SNORM = 17;
|
||||
export const VK_FORMAT_R8G8_UINT = 20;
|
||||
export const VK_FORMAT_R8G8_SINT = 21;
|
||||
export const VK_FORMAT_R8G8_SRGB = 22;
|
||||
export const VK_FORMAT_R8G8B8_UNORM = 23;
|
||||
export const VK_FORMAT_R8G8B8_SNORM = 24;
|
||||
export const VK_FORMAT_R8G8B8_UINT = 27;
|
||||
export const VK_FORMAT_R8G8B8_SINT = 28;
|
||||
export const VK_FORMAT_R8G8B8_SRGB = 29;
|
||||
export const VK_FORMAT_B8G8R8_UNORM = 30;
|
||||
export const VK_FORMAT_B8G8R8_SNORM = 31;
|
||||
export const VK_FORMAT_B8G8R8_UINT = 34;
|
||||
export const VK_FORMAT_B8G8R8_SINT = 35;
|
||||
export const VK_FORMAT_B8G8R8_SRGB = 36;
|
||||
export const VK_FORMAT_R8G8B8A8_UNORM = 37;
|
||||
export const VK_FORMAT_R8G8B8A8_SNORM = 38;
|
||||
export const VK_FORMAT_R8G8B8A8_UINT = 41;
|
||||
export const VK_FORMAT_R8G8B8A8_SINT = 42;
|
||||
export const VK_FORMAT_R8G8B8A8_SRGB = 43;
|
||||
export const VK_FORMAT_B8G8R8A8_UNORM = 44;
|
||||
export const VK_FORMAT_B8G8R8A8_SNORM = 45;
|
||||
export const VK_FORMAT_B8G8R8A8_UINT = 48;
|
||||
export const VK_FORMAT_B8G8R8A8_SINT = 49;
|
||||
export const VK_FORMAT_B8G8R8A8_SRGB = 50;
|
||||
export const VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58;
|
||||
export const VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59;
|
||||
export const VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62;
|
||||
export const VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63;
|
||||
export const VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64;
|
||||
export const VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65;
|
||||
export const VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68;
|
||||
export const VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69;
|
||||
export const VK_FORMAT_R16_UNORM = 70;
|
||||
export const VK_FORMAT_R16_SNORM = 71;
|
||||
export const VK_FORMAT_R16_UINT = 74;
|
||||
export const VK_FORMAT_R16_SINT = 75;
|
||||
export const VK_FORMAT_R16_SFLOAT = 76;
|
||||
export const VK_FORMAT_R16G16_UNORM = 77;
|
||||
export const VK_FORMAT_R16G16_SNORM = 78;
|
||||
export const VK_FORMAT_R16G16_UINT = 81;
|
||||
export const VK_FORMAT_R16G16_SINT = 82;
|
||||
export const VK_FORMAT_R16G16_SFLOAT = 83;
|
||||
export const VK_FORMAT_R16G16B16_UNORM = 84;
|
||||
export const VK_FORMAT_R16G16B16_SNORM = 85;
|
||||
export const VK_FORMAT_R16G16B16_UINT = 88;
|
||||
export const VK_FORMAT_R16G16B16_SINT = 89;
|
||||
export const VK_FORMAT_R16G16B16_SFLOAT = 90;
|
||||
export const VK_FORMAT_R16G16B16A16_UNORM = 91;
|
||||
export const VK_FORMAT_R16G16B16A16_SNORM = 92;
|
||||
export const VK_FORMAT_R16G16B16A16_UINT = 95;
|
||||
export const VK_FORMAT_R16G16B16A16_SINT = 96;
|
||||
export const VK_FORMAT_R16G16B16A16_SFLOAT = 97;
|
||||
export const VK_FORMAT_R32_UINT = 98;
|
||||
export const VK_FORMAT_R32_SINT = 99;
|
||||
export const VK_FORMAT_R32_SFLOAT = 100;
|
||||
export const VK_FORMAT_R32G32_UINT = 101;
|
||||
export const VK_FORMAT_R32G32_SINT = 102;
|
||||
export const VK_FORMAT_R32G32_SFLOAT = 103;
|
||||
export const VK_FORMAT_R32G32B32_UINT = 104;
|
||||
export const VK_FORMAT_R32G32B32_SINT = 105;
|
||||
export const VK_FORMAT_R32G32B32_SFLOAT = 106;
|
||||
export const VK_FORMAT_R32G32B32A32_UINT = 107;
|
||||
export const VK_FORMAT_R32G32B32A32_SINT = 108;
|
||||
export const VK_FORMAT_R32G32B32A32_SFLOAT = 109;
|
||||
export const VK_FORMAT_R64_UINT = 110;
|
||||
export const VK_FORMAT_R64_SINT = 111;
|
||||
export const VK_FORMAT_R64_SFLOAT = 112;
|
||||
export const VK_FORMAT_R64G64_UINT = 113;
|
||||
export const VK_FORMAT_R64G64_SINT = 114;
|
||||
export const VK_FORMAT_R64G64_SFLOAT = 115;
|
||||
export const VK_FORMAT_R64G64B64_UINT = 116;
|
||||
export const VK_FORMAT_R64G64B64_SINT = 117;
|
||||
export const VK_FORMAT_R64G64B64_SFLOAT = 118;
|
||||
export const VK_FORMAT_R64G64B64A64_UINT = 119;
|
||||
export const VK_FORMAT_R64G64B64A64_SINT = 120;
|
||||
export const VK_FORMAT_R64G64B64A64_SFLOAT = 121;
|
||||
export const VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122;
|
||||
export const VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123;
|
||||
export const VK_FORMAT_D16_UNORM = 124;
|
||||
export const VK_FORMAT_X8_D24_UNORM_PACK32 = 125;
|
||||
export const VK_FORMAT_D32_SFLOAT = 126;
|
||||
export const VK_FORMAT_S8_UINT = 127;
|
||||
export const VK_FORMAT_D16_UNORM_S8_UINT = 128;
|
||||
export const VK_FORMAT_D24_UNORM_S8_UINT = 129;
|
||||
export const VK_FORMAT_D32_SFLOAT_S8_UINT = 130;
|
||||
export const VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131;
|
||||
export const VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132;
|
||||
export const VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133;
|
||||
export const VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134;
|
||||
export const VK_FORMAT_BC2_UNORM_BLOCK = 135;
|
||||
export const VK_FORMAT_BC2_SRGB_BLOCK = 136;
|
||||
export const VK_FORMAT_BC3_UNORM_BLOCK = 137;
|
||||
export const VK_FORMAT_BC3_SRGB_BLOCK = 138;
|
||||
export const VK_FORMAT_BC4_UNORM_BLOCK = 139;
|
||||
export const VK_FORMAT_BC4_SNORM_BLOCK = 140;
|
||||
export const VK_FORMAT_BC5_UNORM_BLOCK = 141;
|
||||
export const VK_FORMAT_BC5_SNORM_BLOCK = 142;
|
||||
export const VK_FORMAT_BC6H_UFLOAT_BLOCK = 143;
|
||||
export const VK_FORMAT_BC6H_SFLOAT_BLOCK = 144;
|
||||
export const VK_FORMAT_BC7_UNORM_BLOCK = 145;
|
||||
export const VK_FORMAT_BC7_SRGB_BLOCK = 146;
|
||||
export const VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147;
|
||||
export const VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148;
|
||||
export const VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149;
|
||||
export const VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150;
|
||||
export const VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151;
|
||||
export const VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152;
|
||||
export const VK_FORMAT_EAC_R11_UNORM_BLOCK = 153;
|
||||
export const VK_FORMAT_EAC_R11_SNORM_BLOCK = 154;
|
||||
export const VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155;
|
||||
export const VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156;
|
||||
export const VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157;
|
||||
export const VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158;
|
||||
export const VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159;
|
||||
export const VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160;
|
||||
export const VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161;
|
||||
export const VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162;
|
||||
export const VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163;
|
||||
export const VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164;
|
||||
export const VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165;
|
||||
export const VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166;
|
||||
export const VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167;
|
||||
export const VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168;
|
||||
export const VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169;
|
||||
export const VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170;
|
||||
export const VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171;
|
||||
export const VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172;
|
||||
export const VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173;
|
||||
export const VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174;
|
||||
export const VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175;
|
||||
export const VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176;
|
||||
export const VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177;
|
||||
export const VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178;
|
||||
export const VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179;
|
||||
export const VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180;
|
||||
export const VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181;
|
||||
export const VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182;
|
||||
export const VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183;
|
||||
export const VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184;
|
||||
export const VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007;
|
||||
export const VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008;
|
||||
export const VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009;
|
||||
export const VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010;
|
||||
export const VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011;
|
||||
export const VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017;
|
||||
export const VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018;
|
||||
export const VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019;
|
||||
export const VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020;
|
||||
export const VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021;
|
||||
export const VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000;
|
||||
export const VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001;
|
||||
export const VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002;
|
||||
export const VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003;
|
||||
export const VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004;
|
||||
export const VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005;
|
||||
export const VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006;
|
||||
export const VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007;
|
||||
export const VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = 1000066000;
|
||||
export const VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = 1000066001;
|
||||
export const VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = 1000066002;
|
||||
export const VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT = 1000066003;
|
||||
export const VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT = 1000066004;
|
||||
export const VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT = 1000066005;
|
||||
export const VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT = 1000066006;
|
||||
export const VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT = 1000066007;
|
||||
export const VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT = 1000066008;
|
||||
export const VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT = 1000066009;
|
||||
export const VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT = 1000066010;
|
||||
export const VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = 1000066011;
|
||||
export const VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = 1000066012;
|
||||
export const VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = 1000066013;
|
||||
export const VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = 1000340000;
|
||||
export const VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = 1000340001;
|
||||
|
||||
export type VKFormat =
|
||||
| typeof VK_FORMAT_UNDEFINED
|
||||
| typeof VK_FORMAT_R4G4_UNORM_PACK8
|
||||
| typeof VK_FORMAT_R4G4B4A4_UNORM_PACK16
|
||||
| typeof VK_FORMAT_B4G4R4A4_UNORM_PACK16
|
||||
| typeof VK_FORMAT_R5G6B5_UNORM_PACK16
|
||||
| typeof VK_FORMAT_B5G6R5_UNORM_PACK16
|
||||
| typeof VK_FORMAT_R5G5B5A1_UNORM_PACK16
|
||||
| typeof VK_FORMAT_B5G5R5A1_UNORM_PACK16
|
||||
| typeof VK_FORMAT_A1R5G5B5_UNORM_PACK16
|
||||
| typeof VK_FORMAT_R8_UNORM
|
||||
| typeof VK_FORMAT_R8_SNORM
|
||||
| typeof VK_FORMAT_R8_UINT
|
||||
| typeof VK_FORMAT_R8_SINT
|
||||
| typeof VK_FORMAT_R8_SRGB
|
||||
| typeof VK_FORMAT_R8G8_UNORM
|
||||
| typeof VK_FORMAT_R8G8_SNORM
|
||||
| typeof VK_FORMAT_R8G8_UINT
|
||||
| typeof VK_FORMAT_R8G8_SINT
|
||||
| typeof VK_FORMAT_R8G8_SRGB
|
||||
| typeof VK_FORMAT_R8G8B8_UNORM
|
||||
| typeof VK_FORMAT_R8G8B8_SNORM
|
||||
| typeof VK_FORMAT_R8G8B8_UINT
|
||||
| typeof VK_FORMAT_R8G8B8_SINT
|
||||
| typeof VK_FORMAT_R8G8B8_SRGB
|
||||
| typeof VK_FORMAT_B8G8R8_UNORM
|
||||
| typeof VK_FORMAT_B8G8R8_SNORM
|
||||
| typeof VK_FORMAT_B8G8R8_UINT
|
||||
| typeof VK_FORMAT_B8G8R8_SINT
|
||||
| typeof VK_FORMAT_B8G8R8_SRGB
|
||||
| typeof VK_FORMAT_R8G8B8A8_UNORM
|
||||
| typeof VK_FORMAT_R8G8B8A8_SNORM
|
||||
| typeof VK_FORMAT_R8G8B8A8_UINT
|
||||
| typeof VK_FORMAT_R8G8B8A8_SINT
|
||||
| typeof VK_FORMAT_R8G8B8A8_SRGB
|
||||
| typeof VK_FORMAT_B8G8R8A8_UNORM
|
||||
| typeof VK_FORMAT_B8G8R8A8_SNORM
|
||||
| typeof VK_FORMAT_B8G8R8A8_UINT
|
||||
| typeof VK_FORMAT_B8G8R8A8_SINT
|
||||
| typeof VK_FORMAT_B8G8R8A8_SRGB
|
||||
| typeof VK_FORMAT_A2R10G10B10_UNORM_PACK32
|
||||
| typeof VK_FORMAT_A2R10G10B10_SNORM_PACK32
|
||||
| typeof VK_FORMAT_A2R10G10B10_UINT_PACK32
|
||||
| typeof VK_FORMAT_A2R10G10B10_SINT_PACK32
|
||||
| typeof VK_FORMAT_A2B10G10R10_UNORM_PACK32
|
||||
| typeof VK_FORMAT_A2B10G10R10_SNORM_PACK32
|
||||
| typeof VK_FORMAT_A2B10G10R10_UINT_PACK32
|
||||
| typeof VK_FORMAT_A2B10G10R10_SINT_PACK32
|
||||
| typeof VK_FORMAT_R16_UNORM
|
||||
| typeof VK_FORMAT_R16_SNORM
|
||||
| typeof VK_FORMAT_R16_UINT
|
||||
| typeof VK_FORMAT_R16_SINT
|
||||
| typeof VK_FORMAT_R16_SFLOAT
|
||||
| typeof VK_FORMAT_R16G16_UNORM
|
||||
| typeof VK_FORMAT_R16G16_SNORM
|
||||
| typeof VK_FORMAT_R16G16_UINT
|
||||
| typeof VK_FORMAT_R16G16_SINT
|
||||
| typeof VK_FORMAT_R16G16_SFLOAT
|
||||
| typeof VK_FORMAT_R16G16B16_UNORM
|
||||
| typeof VK_FORMAT_R16G16B16_SNORM
|
||||
| typeof VK_FORMAT_R16G16B16_UINT
|
||||
| typeof VK_FORMAT_R16G16B16_SINT
|
||||
| typeof VK_FORMAT_R16G16B16_SFLOAT
|
||||
| typeof VK_FORMAT_R16G16B16A16_UNORM
|
||||
| typeof VK_FORMAT_R16G16B16A16_SNORM
|
||||
| typeof VK_FORMAT_R16G16B16A16_UINT
|
||||
| typeof VK_FORMAT_R16G16B16A16_SINT
|
||||
| typeof VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
| typeof VK_FORMAT_R32_UINT
|
||||
| typeof VK_FORMAT_R32_SINT
|
||||
| typeof VK_FORMAT_R32_SFLOAT
|
||||
| typeof VK_FORMAT_R32G32_UINT
|
||||
| typeof VK_FORMAT_R32G32_SINT
|
||||
| typeof VK_FORMAT_R32G32_SFLOAT
|
||||
| typeof VK_FORMAT_R32G32B32_UINT
|
||||
| typeof VK_FORMAT_R32G32B32_SINT
|
||||
| typeof VK_FORMAT_R32G32B32_SFLOAT
|
||||
| typeof VK_FORMAT_R32G32B32A32_UINT
|
||||
| typeof VK_FORMAT_R32G32B32A32_SINT
|
||||
| typeof VK_FORMAT_R32G32B32A32_SFLOAT
|
||||
| typeof VK_FORMAT_R64_UINT
|
||||
| typeof VK_FORMAT_R64_SINT
|
||||
| typeof VK_FORMAT_R64_SFLOAT
|
||||
| typeof VK_FORMAT_R64G64_UINT
|
||||
| typeof VK_FORMAT_R64G64_SINT
|
||||
| typeof VK_FORMAT_R64G64_SFLOAT
|
||||
| typeof VK_FORMAT_R64G64B64_UINT
|
||||
| typeof VK_FORMAT_R64G64B64_SINT
|
||||
| typeof VK_FORMAT_R64G64B64_SFLOAT
|
||||
| typeof VK_FORMAT_R64G64B64A64_UINT
|
||||
| typeof VK_FORMAT_R64G64B64A64_SINT
|
||||
| typeof VK_FORMAT_R64G64B64A64_SFLOAT
|
||||
| typeof VK_FORMAT_B10G11R11_UFLOAT_PACK32
|
||||
| typeof VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
|
||||
| typeof VK_FORMAT_D16_UNORM
|
||||
| typeof VK_FORMAT_X8_D24_UNORM_PACK32
|
||||
| typeof VK_FORMAT_D32_SFLOAT
|
||||
| typeof VK_FORMAT_S8_UINT
|
||||
| typeof VK_FORMAT_D16_UNORM_S8_UINT
|
||||
| typeof VK_FORMAT_D24_UNORM_S8_UINT
|
||||
| typeof VK_FORMAT_D32_SFLOAT_S8_UINT
|
||||
| typeof VK_FORMAT_BC1_RGB_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC1_RGB_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_BC1_RGBA_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC1_RGBA_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_BC2_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC2_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_BC3_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC3_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_BC4_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC4_SNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC5_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC5_SNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC6H_UFLOAT_BLOCK
|
||||
| typeof VK_FORMAT_BC6H_SFLOAT_BLOCK
|
||||
| typeof VK_FORMAT_BC7_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_BC7_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_EAC_R11_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_EAC_R11_SNORM_BLOCK
|
||||
| typeof VK_FORMAT_EAC_R11G11_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_EAC_R11G11_SNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_4x4_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_4x4_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_5x4_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_5x4_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_5x5_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_5x5_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_6x5_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_6x5_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_6x6_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_6x6_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_8x5_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_8x5_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_8x6_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_8x6_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_8x8_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_8x8_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_10x5_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_10x5_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_10x6_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_10x6_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_10x8_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_10x8_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_10x10_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_10x10_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_12x10_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_12x10_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_12x12_UNORM_BLOCK
|
||||
| typeof VK_FORMAT_ASTC_12x12_SRGB_BLOCK
|
||||
| typeof VK_FORMAT_R10X6_UNORM_PACK16
|
||||
| typeof VK_FORMAT_R10X6G10X6_UNORM_2PACK16
|
||||
| typeof VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16
|
||||
| typeof VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16
|
||||
| typeof VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16
|
||||
| typeof VK_FORMAT_R12X4_UNORM_PACK16
|
||||
| typeof VK_FORMAT_R12X4G12X4_UNORM_2PACK16
|
||||
| typeof VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16
|
||||
| typeof VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16
|
||||
| typeof VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16
|
||||
| typeof VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG
|
||||
| typeof VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG
|
||||
| typeof VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG
|
||||
| typeof VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG
|
||||
| typeof VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG
|
||||
| typeof VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG
|
||||
| typeof VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG
|
||||
| typeof VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG
|
||||
| typeof VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT
|
||||
| typeof VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT
|
||||
| typeof VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT;
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
import type { Supercompression, VKFormat } from './constants.js';
|
||||
|
||||
/**
|
||||
* Represents an unpacked KTX 2.0 texture container. Data for individual mip levels are stored in
|
||||
* the `.levels` array, typically compressed in Basis Universal formats. Additional properties
|
||||
* provide metadata required to process, transcode, and upload these textures.
|
||||
*/
|
||||
export interface KTX2Container {
|
||||
/**
|
||||
* Specifies the image format using Vulkan VkFormat enum values. When using Basis Universal
|
||||
* texture formats, `vkFormat` must be VK_FORMAT_UNDEFINED.
|
||||
*/
|
||||
vkFormat: VKFormat;
|
||||
|
||||
/**
|
||||
* Size of the data type in bytes used to upload the data to a graphics API. When `vkFormat` is
|
||||
* VK_FORMAT_UNDEFINED, `typeSize` must be 1.
|
||||
*/
|
||||
typeSize: number;
|
||||
|
||||
/** Width of the texture image for level 0, in pixels. */
|
||||
pixelWidth: number;
|
||||
|
||||
/** Height of the texture image for level 0, in pixels. */
|
||||
pixelHeight: number;
|
||||
|
||||
/** Depth of the texture image for level 0, in pixels (3D textures only). */
|
||||
pixelDepth: number;
|
||||
|
||||
/** Number of array elements (array textures only). */
|
||||
layerCount: number;
|
||||
|
||||
/**
|
||||
* Number of cubemap faces. For cubemaps and cubemap arrays, `faceCount` must be 6. For all
|
||||
* other textures, `faceCount` must be 1. Cubemap faces are stored in +X, -X, +Y, -Y, +Z, -Z
|
||||
* order.
|
||||
*/
|
||||
faceCount: number;
|
||||
|
||||
/**
|
||||
* Number of levels in the mipmap level array. Mipmap pyramid may not necessarily be complete.
|
||||
* `levelCount = 1` implies that the file contains only the base level, and is not meant to have
|
||||
* other levels. `levelCount = 0` implies that the file contains only the base level, and that
|
||||
* other levels should be generated by the loader at runtime. For block-compressed formats,
|
||||
* `levelCount = 0` is disallowed.
|
||||
*/
|
||||
levelCount: number;
|
||||
|
||||
/** Indicates which supercompression scheme has been applied to mip level images, if any. */
|
||||
supercompressionScheme: Supercompression;
|
||||
|
||||
/** Mip levels, ordered largest (original) to smallest (~1px). */
|
||||
levels: KTX2Level[];
|
||||
|
||||
/** Data Format Descriptor. */
|
||||
dataFormatDescriptor: KTX2DataFormatDescriptorBasicFormat[];
|
||||
|
||||
/** Key/Value Data. */
|
||||
keyValue: { [key: string]: string | Uint8Array };
|
||||
|
||||
/** Supercompression Global Data. */
|
||||
globalData: KTX2GlobalDataBasisLZ | null;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Mip Levels.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
export interface KTX2Level {
|
||||
/** Compressed data of the mip level. */
|
||||
levelData: Uint8Array;
|
||||
|
||||
/**
|
||||
* Size of the mip level after reflation from supercompression, if applicable. When
|
||||
* `supercompressionType` is BASISLZ, `uncompressedByteLength` must be 0. When
|
||||
* `supercompressionType` is `NONE`, `uncompressedByteLength` must match the `levelData` byte
|
||||
* length.
|
||||
*
|
||||
* _**NOTICE:** this implies that for formats such as UASTC, `uncompressedByteLength` may
|
||||
* indicate size after ZSTD reflation (and of transcoded ASTC data), but does _not_ indicate
|
||||
* size of decoded RGBA32 pixels._
|
||||
*/
|
||||
uncompressedByteLength: number;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Data Format Descriptor (DFD).
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
export interface KTX2DataFormatDescriptorBasicFormat {
|
||||
vendorId: number;
|
||||
descriptorType: number;
|
||||
versionNumber: number;
|
||||
colorModel: number;
|
||||
colorPrimaries: number;
|
||||
transferFunction: number;
|
||||
flags: number;
|
||||
texelBlockDimension: [number, number, number, number];
|
||||
bytesPlane: [number, number, number, number, number, number, number, number];
|
||||
samples: KTX2BasicFormatSample[];
|
||||
}
|
||||
|
||||
export interface KTX2BasicFormatSample {
|
||||
bitOffset: number;
|
||||
bitLength: number;
|
||||
channelType: number;
|
||||
samplePosition: number[];
|
||||
sampleLower: number;
|
||||
sampleUpper: number;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Supercompression Global Data.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
export interface KTX2GlobalDataBasisLZ {
|
||||
endpointCount: number;
|
||||
selectorCount: number;
|
||||
imageDescs: KTX2GlobalDataBasisLZImageDesc[];
|
||||
endpointsData: Uint8Array;
|
||||
selectorsData: Uint8Array;
|
||||
tablesData: Uint8Array;
|
||||
extendedData: Uint8Array;
|
||||
}
|
||||
|
||||
interface KTX2GlobalDataBasisLZImageDesc {
|
||||
imageFlags: number;
|
||||
rgbSliceByteOffset: number;
|
||||
rgbSliceByteLength: number;
|
||||
alphaSliceByteOffset: number;
|
||||
alphaSliceByteLength: number;
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
KHR_DF_FLAG_ALPHA_STRAIGHT,
|
||||
KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,
|
||||
KHR_DF_MODEL_UNSPECIFIED,
|
||||
KHR_DF_PRIMARIES_BT709,
|
||||
KHR_DF_TRANSFER_SRGB,
|
||||
KHR_DF_VENDORID_KHRONOS,
|
||||
KHR_DF_VERSION,
|
||||
KHR_SUPERCOMPRESSION_NONE,
|
||||
VK_FORMAT_UNDEFINED,
|
||||
} from './constants.js';
|
||||
import type { KTX2Container } from './container.js';
|
||||
|
||||
/**
|
||||
* Creates a 'default' {@link KTX2Container} object, initialized with common
|
||||
* configuration wfor BT709 primaries and sRGB transfer, without pixel data.
|
||||
* There's nothing particularly special about the 'default' container; creating
|
||||
* the KTX2Container object explicitly is also fine.
|
||||
*/
|
||||
export function createDefaultContainer(): KTX2Container {
|
||||
return {
|
||||
vkFormat: VK_FORMAT_UNDEFINED,
|
||||
typeSize: 1,
|
||||
pixelWidth: 0,
|
||||
pixelHeight: 0,
|
||||
pixelDepth: 0,
|
||||
layerCount: 0,
|
||||
faceCount: 1,
|
||||
levelCount: 0,
|
||||
supercompressionScheme: KHR_SUPERCOMPRESSION_NONE,
|
||||
levels: [],
|
||||
dataFormatDescriptor: [
|
||||
{
|
||||
vendorId: KHR_DF_VENDORID_KHRONOS,
|
||||
descriptorType: KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,
|
||||
versionNumber: KHR_DF_VERSION,
|
||||
colorModel: KHR_DF_MODEL_UNSPECIFIED,
|
||||
colorPrimaries: KHR_DF_PRIMARIES_BT709,
|
||||
transferFunction: KHR_DF_TRANSFER_SRGB,
|
||||
flags: KHR_DF_FLAG_ALPHA_STRAIGHT,
|
||||
texelBlockDimension: [0, 0, 0, 0],
|
||||
bytesPlane: [0, 0, 0, 0, 0, 0, 0, 0],
|
||||
samples: [],
|
||||
},
|
||||
],
|
||||
keyValue: {},
|
||||
globalData: null,
|
||||
};
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
export * from './create-default-container.js';
|
||||
export * from './container.js';
|
||||
export * from './constants.js';
|
||||
export * from './read.js';
|
||||
export * from './write.js';
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
import { BufferReader } from './buffer-reader.js';
|
||||
import { KTX2_ID } from './constants-internal.js';
|
||||
import { KHR_DF_SAMPLE_DATATYPE_SIGNED, type Supercompression, type VKFormat } from './constants.js';
|
||||
import type { KTX2BasicFormatSample, KTX2Container, KTX2DataFormatDescriptorBasicFormat } from './container.js';
|
||||
import { createDefaultContainer } from './create-default-container.js';
|
||||
import { decodeText } from './util.js';
|
||||
|
||||
/**
|
||||
* Parses a KTX 2.0 file, returning an unpacked {@link KTX2Container} instance with all associated
|
||||
* data. The container's mip levels and other binary data are pointers into the original file, not
|
||||
* copies, so the original file should not be overwritten after reading.
|
||||
*
|
||||
* @param data Bytes of KTX 2.0 file, as Uint8Array or Buffer.
|
||||
*/
|
||||
export function read(data: Uint8Array): KTX2Container {
|
||||
///////////////////////////////////////////////////
|
||||
// KTX 2.0 Identifier.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const id = new Uint8Array(data.buffer, data.byteOffset, KTX2_ID.length);
|
||||
if (
|
||||
id[0] !== KTX2_ID[0] || // '´'
|
||||
id[1] !== KTX2_ID[1] || // 'K'
|
||||
id[2] !== KTX2_ID[2] || // 'T'
|
||||
id[3] !== KTX2_ID[3] || // 'X'
|
||||
id[4] !== KTX2_ID[4] || // ' '
|
||||
id[5] !== KTX2_ID[5] || // '2'
|
||||
id[6] !== KTX2_ID[6] || // '0'
|
||||
id[7] !== KTX2_ID[7] || // 'ª'
|
||||
id[8] !== KTX2_ID[8] || // '\r'
|
||||
id[9] !== KTX2_ID[9] || // '\n'
|
||||
id[10] !== KTX2_ID[10] || // '\x1A'
|
||||
id[11] !== KTX2_ID[11] // '\n'
|
||||
) {
|
||||
throw new Error('Missing KTX 2.0 identifier.');
|
||||
}
|
||||
|
||||
const container = createDefaultContainer();
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Header.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const headerByteLength = 17 * Uint32Array.BYTES_PER_ELEMENT;
|
||||
const headerReader = new BufferReader(data, KTX2_ID.length, headerByteLength, true);
|
||||
|
||||
container.vkFormat = headerReader._nextUint32() as VKFormat;
|
||||
container.typeSize = headerReader._nextUint32();
|
||||
container.pixelWidth = headerReader._nextUint32();
|
||||
container.pixelHeight = headerReader._nextUint32();
|
||||
container.pixelDepth = headerReader._nextUint32();
|
||||
container.layerCount = headerReader._nextUint32();
|
||||
container.faceCount = headerReader._nextUint32();
|
||||
container.levelCount = headerReader._nextUint32();
|
||||
|
||||
container.supercompressionScheme = headerReader._nextUint32() as Supercompression;
|
||||
|
||||
const dfdByteOffset = headerReader._nextUint32();
|
||||
const dfdByteLength = headerReader._nextUint32();
|
||||
const kvdByteOffset = headerReader._nextUint32();
|
||||
const kvdByteLength = headerReader._nextUint32();
|
||||
const sgdByteOffset = headerReader._nextUint64();
|
||||
const sgdByteLength = headerReader._nextUint64();
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Level Index.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const levelByteLength = Math.max(container.levelCount, 1) * 3 * 8;
|
||||
const levelReader = new BufferReader(data, KTX2_ID.length + headerByteLength, levelByteLength, true);
|
||||
|
||||
for (let i = 0, il = Math.max(container.levelCount, 1); i < il; i++) {
|
||||
container.levels.push({
|
||||
levelData: new Uint8Array(data.buffer, data.byteOffset + levelReader._nextUint64(), levelReader._nextUint64()),
|
||||
uncompressedByteLength: levelReader._nextUint64(),
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Data Format Descriptor (DFD).
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const dfdReader = new BufferReader(data, dfdByteOffset, dfdByteLength, true);
|
||||
|
||||
dfdReader._skip(4); // totalSize
|
||||
const vendorId = dfdReader._nextUint16();
|
||||
const descriptorType = dfdReader._nextUint16();
|
||||
const versionNumber = dfdReader._nextUint16();
|
||||
const descriptorBlockSize = dfdReader._nextUint16();
|
||||
const colorModel = dfdReader._nextUint8();
|
||||
const colorPrimaries = dfdReader._nextUint8();
|
||||
const transferFunction = dfdReader._nextUint8();
|
||||
const flags = dfdReader._nextUint8();
|
||||
|
||||
const texelBlockDimension = [
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
] as KTX2DataFormatDescriptorBasicFormat['texelBlockDimension'];
|
||||
|
||||
const bytesPlane = [
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
dfdReader._nextUint8(),
|
||||
] as KTX2DataFormatDescriptorBasicFormat['bytesPlane'];
|
||||
|
||||
const samples = [] as KTX2BasicFormatSample[];
|
||||
|
||||
const dfd: KTX2DataFormatDescriptorBasicFormat = {
|
||||
vendorId,
|
||||
descriptorType,
|
||||
versionNumber,
|
||||
colorModel,
|
||||
colorPrimaries,
|
||||
transferFunction,
|
||||
flags,
|
||||
texelBlockDimension,
|
||||
bytesPlane,
|
||||
samples,
|
||||
};
|
||||
|
||||
const sampleStart = 6;
|
||||
const sampleWords = 4;
|
||||
const numSamples = (descriptorBlockSize / 4 - sampleStart) / sampleWords;
|
||||
|
||||
for (let i = 0; i < numSamples; i++) {
|
||||
const sample = {
|
||||
bitOffset: dfdReader._nextUint16(),
|
||||
bitLength: dfdReader._nextUint8(),
|
||||
channelType: dfdReader._nextUint8(),
|
||||
samplePosition: [dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8()],
|
||||
sampleLower: Number.NEGATIVE_INFINITY,
|
||||
sampleUpper: Number.POSITIVE_INFINITY,
|
||||
};
|
||||
|
||||
if (sample.channelType & KHR_DF_SAMPLE_DATATYPE_SIGNED) {
|
||||
sample.sampleLower = dfdReader._nextInt32();
|
||||
sample.sampleUpper = dfdReader._nextInt32();
|
||||
} else {
|
||||
sample.sampleLower = dfdReader._nextUint32();
|
||||
sample.sampleUpper = dfdReader._nextUint32();
|
||||
}
|
||||
|
||||
dfd.samples[i] = sample;
|
||||
}
|
||||
|
||||
container.dataFormatDescriptor.length = 0;
|
||||
container.dataFormatDescriptor.push(dfd);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Key/Value Data (KVD).
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const kvdReader = new BufferReader(data, kvdByteOffset, kvdByteLength, true);
|
||||
|
||||
while (kvdReader._offset < kvdByteLength) {
|
||||
const keyValueByteLength = kvdReader._nextUint32();
|
||||
const keyData = kvdReader._scan(keyValueByteLength);
|
||||
const key = decodeText(keyData);
|
||||
|
||||
container.keyValue[key] = kvdReader._nextUint8Array(keyValueByteLength - keyData.byteLength - 1);
|
||||
|
||||
if (key.match(/^ktx/i)) {
|
||||
const text = decodeText(container.keyValue[key] as Uint8Array);
|
||||
container.keyValue[key] = text.substring(0, text.lastIndexOf('\x00'));
|
||||
}
|
||||
|
||||
const kvPadding = keyValueByteLength % 4 ? 4 - (keyValueByteLength % 4) : 0; // align(4)
|
||||
// 4-byte alignment.
|
||||
kvdReader._skip(kvPadding);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Supercompression Global Data (SGD).
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
if (sgdByteLength <= 0) return container;
|
||||
|
||||
const sgdReader = new BufferReader(data, sgdByteOffset, sgdByteLength, true);
|
||||
|
||||
const endpointCount = sgdReader._nextUint16();
|
||||
const selectorCount = sgdReader._nextUint16();
|
||||
const endpointsByteLength = sgdReader._nextUint32();
|
||||
const selectorsByteLength = sgdReader._nextUint32();
|
||||
const tablesByteLength = sgdReader._nextUint32();
|
||||
const extendedByteLength = sgdReader._nextUint32();
|
||||
|
||||
const imageDescs = [];
|
||||
for (let i = 0, il = Math.max(container.levelCount, 1); i < il; i++) {
|
||||
imageDescs.push({
|
||||
imageFlags: sgdReader._nextUint32(),
|
||||
rgbSliceByteOffset: sgdReader._nextUint32(),
|
||||
rgbSliceByteLength: sgdReader._nextUint32(),
|
||||
alphaSliceByteOffset: sgdReader._nextUint32(),
|
||||
alphaSliceByteLength: sgdReader._nextUint32(),
|
||||
});
|
||||
}
|
||||
|
||||
const endpointsByteOffset = sgdByteOffset + sgdReader._offset;
|
||||
const selectorsByteOffset = endpointsByteOffset + endpointsByteLength;
|
||||
const tablesByteOffset = selectorsByteOffset + selectorsByteLength;
|
||||
const extendedByteOffset = tablesByteOffset + tablesByteLength;
|
||||
|
||||
const endpointsData = new Uint8Array(data.buffer, data.byteOffset + endpointsByteOffset, endpointsByteLength);
|
||||
const selectorsData = new Uint8Array(data.buffer, data.byteOffset + selectorsByteOffset, selectorsByteLength);
|
||||
const tablesData = new Uint8Array(data.buffer, data.byteOffset + tablesByteOffset, tablesByteLength);
|
||||
const extendedData = new Uint8Array(data.buffer, data.byteOffset + extendedByteOffset, extendedByteLength);
|
||||
|
||||
container.globalData = {
|
||||
endpointCount,
|
||||
selectorCount,
|
||||
imageDescs,
|
||||
endpointsData,
|
||||
selectorsData,
|
||||
tablesData,
|
||||
extendedData,
|
||||
};
|
||||
|
||||
return container;
|
||||
}
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
import type { vec3 } from './constants-internal.js';
|
||||
import {
|
||||
type VKFormat,
|
||||
VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
|
||||
VK_FORMAT_BC1_RGB_UNORM_BLOCK,
|
||||
VK_FORMAT_BC7_SRGB_BLOCK,
|
||||
VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
|
||||
VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
|
||||
VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
|
||||
VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
|
||||
VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
|
||||
VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
|
||||
VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
|
||||
VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
|
||||
VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,
|
||||
VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
|
||||
VK_FORMAT_UNDEFINED,
|
||||
} from './constants.js';
|
||||
import type { KTX2Container } from './container.js';
|
||||
|
||||
/** Encodes text to an ArrayBuffer. */
|
||||
export function encodeText(text: string): Uint8Array {
|
||||
return new TextEncoder().encode(text);
|
||||
}
|
||||
|
||||
/** Decodes an ArrayBuffer to text. */
|
||||
export function decodeText(buffer: Uint8Array): string {
|
||||
return new TextDecoder().decode(buffer);
|
||||
}
|
||||
|
||||
/** Concatenates N ArrayBuffers. */
|
||||
export function concat(buffers: (ArrayBuffer | Uint8Array)[]): Uint8Array {
|
||||
let totalByteLength = 0;
|
||||
for (const buffer of buffers) {
|
||||
totalByteLength += buffer.byteLength;
|
||||
}
|
||||
|
||||
const result = new Uint8Array(totalByteLength);
|
||||
let byteOffset = 0;
|
||||
|
||||
for (const buffer of buffers) {
|
||||
result.set(new Uint8Array(buffer), byteOffset);
|
||||
byteOffset += buffer.byteLength;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Returns the least common multiple (LCM) for two positive integers. */
|
||||
export function leastCommonMultiple(a: number, b: number): number {
|
||||
const max = Math.max(a, b);
|
||||
const min = Math.min(a, b);
|
||||
let lcm = max;
|
||||
|
||||
while (lcm % min !== 0) {
|
||||
lcm += max;
|
||||
}
|
||||
|
||||
return lcm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns amount of padding, in bytes, required to pad a value V to N-byte
|
||||
* boundaries. Both V and N must be positive integers.
|
||||
*/
|
||||
export function getPadding(v: number, n = 4): number {
|
||||
return Math.ceil(v / n) * n - v;
|
||||
}
|
||||
|
||||
/** Returns byte length per texel block. */
|
||||
export function getBlockByteLength(container: KTX2Container): number {
|
||||
return container.levels[0].levelData.byteLength / getBlockCount(container, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns total number of blocks for given level. For VK_FORMAT_UNDEFINED, DFD is required.
|
||||
*
|
||||
* References:
|
||||
* - https://github.khronos.org/KTX-Specification/ktxspec.v2.html#levelImages
|
||||
*/
|
||||
export function getBlockCount(container: KTX2Container, levelIndex: number): number {
|
||||
let blockCount = 1;
|
||||
|
||||
const pixelDimensions = [container.pixelWidth, container.pixelHeight, container.pixelDepth];
|
||||
const blockDimensions = getBlockDimensions(container);
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (pixelDimensions[i] > 0) {
|
||||
const dimBlockCount = Math.ceil(Math.floor(pixelDimensions[i] * 2 ** -levelIndex) / blockDimensions[i]);
|
||||
blockCount *= Math.max(1, dimBlockCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (container.layerCount > 0) {
|
||||
blockCount *= container.layerCount;
|
||||
}
|
||||
|
||||
if (container.faceCount > 0) {
|
||||
blockCount *= container.faceCount;
|
||||
}
|
||||
|
||||
return blockCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a KTX2 container, returns block dimensions as [width, height, depth]. Requires valid DFD.
|
||||
*/
|
||||
export function getBlockDimensions(container: KTX2Container): vec3 {
|
||||
const [x, y, z] = container.dataFormatDescriptor[0].texelBlockDimension;
|
||||
return [x + 1, y + 1, z + 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Given `vkFormat`, returns block dimensions as [width, height, depth]. Does not support
|
||||
* VK_FORMAT_UNDEFINED.
|
||||
*
|
||||
* References:
|
||||
* - https://github.khronos.org/KTX-Specification/ktxspec.v2.html#_mippadding
|
||||
* - https://registry.khronos.org/vulkan/specs/1.2-extensions/html/vkspec.html#formats-compatibility
|
||||
*/
|
||||
export function getBlockDimensionsByVKFormat(vkFormat: VKFormat): vec3 {
|
||||
if (vkFormat === VK_FORMAT_UNDEFINED) {
|
||||
throw new Error('Unknown block dimensions for VK_FORMAT_UNDEFINED.');
|
||||
}
|
||||
if (vkFormat >= VK_FORMAT_BC1_RGB_UNORM_BLOCK && vkFormat <= VK_FORMAT_BC7_SRGB_BLOCK) {
|
||||
return [4, 4, 1];
|
||||
}
|
||||
if (vkFormat >= VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK && vkFormat <= VK_FORMAT_EAC_R11G11_SNORM_BLOCK) {
|
||||
return [4, 4, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_4x4_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_4x4_SRGB_BLOCK) {
|
||||
return [4, 4, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_5x4_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_5x4_SRGB_BLOCK) {
|
||||
return [5, 4, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_5x5_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_5x5_SRGB_BLOCK) {
|
||||
return [5, 5, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_6x5_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_6x5_SRGB_BLOCK) {
|
||||
return [6, 5, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_6x6_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_6x6_SRGB_BLOCK) {
|
||||
return [6, 6, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_8x5_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_8x5_SRGB_BLOCK) {
|
||||
return [8, 5, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_8x6_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_8x6_SRGB_BLOCK) {
|
||||
return [8, 6, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_8x8_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_8x8_SRGB_BLOCK) {
|
||||
return [8, 8, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_10x5_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_10x5_SRGB_BLOCK) {
|
||||
return [10, 5, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_10x6_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_10x6_SRGB_BLOCK) {
|
||||
return [10, 6, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_10x8_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_10x8_SRGB_BLOCK) {
|
||||
return [10, 8, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_10x10_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_10x10_SRGB_BLOCK) {
|
||||
return [10, 10, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_12x10_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_12x10_SRGB_BLOCK) {
|
||||
return [12, 10, 1];
|
||||
}
|
||||
if (vkFormat === VK_FORMAT_ASTC_12x12_UNORM_BLOCK || vkFormat === VK_FORMAT_ASTC_12x12_SRGB_BLOCK) {
|
||||
return [12, 12, 1];
|
||||
}
|
||||
if (
|
||||
vkFormat === VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG ||
|
||||
vkFormat === VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG ||
|
||||
vkFormat === VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG ||
|
||||
vkFormat === VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG
|
||||
) {
|
||||
return [8, 4, 1];
|
||||
}
|
||||
if (
|
||||
vkFormat === VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG ||
|
||||
vkFormat === VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG ||
|
||||
vkFormat === VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG ||
|
||||
vkFormat === VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG
|
||||
) {
|
||||
return [4, 4, 1];
|
||||
}
|
||||
return [1, 1, 1];
|
||||
}
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
import { HEADER_BYTE_LENGTH, KTX2_ID, KTX_WRITER, NUL } from './constants-internal.js';
|
||||
import {
|
||||
KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,
|
||||
KHR_DF_SAMPLE_DATATYPE_SIGNED,
|
||||
KHR_SUPERCOMPRESSION_NONE,
|
||||
} from './constants.js';
|
||||
import type { KTX2Container } from './container.js';
|
||||
import { concat, encodeText, getBlockByteLength, getPadding, leastCommonMultiple } from './util.js';
|
||||
|
||||
interface WriteOptions {
|
||||
keepWriter?: boolean;
|
||||
}
|
||||
const DEFAULT_OPTIONS: WriteOptions = { keepWriter: false };
|
||||
|
||||
/**
|
||||
* Serializes a {@link KTX2Container} instance to a KTX 2.0 file. Mip levels and other binary data
|
||||
* are copied into the resulting Uint8Array, so the original container can safely be edited or
|
||||
* destroyed after it is serialized.
|
||||
*
|
||||
* Options:
|
||||
* - keepWriter: If true, 'KTXWriter' key/value field is written as provided by the container.
|
||||
* Otherwise, a string for the current ktx-parse version is generated. Default: false.
|
||||
*
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
export function write(container: KTX2Container, options: WriteOptions = {}): Uint8Array {
|
||||
// biome-ignore lint/style/noParameterAssign: Merging defaults only.
|
||||
options = { ...DEFAULT_OPTIONS, ...options };
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Supercompression Global Data (SGD).
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
let sgdBuffer = new ArrayBuffer(0);
|
||||
if (container.globalData) {
|
||||
const sgdHeaderBuffer = new ArrayBuffer(20 + container.globalData.imageDescs.length * 5 * 4);
|
||||
const sgdHeaderView = new DataView(sgdHeaderBuffer);
|
||||
sgdHeaderView.setUint16(0, container.globalData.endpointCount, true);
|
||||
sgdHeaderView.setUint16(2, container.globalData.selectorCount, true);
|
||||
sgdHeaderView.setUint32(4, container.globalData.endpointsData.byteLength, true);
|
||||
sgdHeaderView.setUint32(8, container.globalData.selectorsData.byteLength, true);
|
||||
sgdHeaderView.setUint32(12, container.globalData.tablesData.byteLength, true);
|
||||
sgdHeaderView.setUint32(16, container.globalData.extendedData.byteLength, true);
|
||||
|
||||
for (let i = 0; i < container.globalData.imageDescs.length; i++) {
|
||||
const imageDesc = container.globalData.imageDescs[i];
|
||||
sgdHeaderView.setUint32(20 + i * 5 * 4 + 0, imageDesc.imageFlags, true);
|
||||
sgdHeaderView.setUint32(20 + i * 5 * 4 + 4, imageDesc.rgbSliceByteOffset, true);
|
||||
sgdHeaderView.setUint32(20 + i * 5 * 4 + 8, imageDesc.rgbSliceByteLength, true);
|
||||
sgdHeaderView.setUint32(20 + i * 5 * 4 + 12, imageDesc.alphaSliceByteOffset, true);
|
||||
sgdHeaderView.setUint32(20 + i * 5 * 4 + 16, imageDesc.alphaSliceByteLength, true);
|
||||
}
|
||||
|
||||
sgdBuffer = concat([
|
||||
sgdHeaderBuffer,
|
||||
container.globalData.endpointsData,
|
||||
container.globalData.selectorsData,
|
||||
container.globalData.tablesData,
|
||||
container.globalData.extendedData,
|
||||
]);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Key/Value Data (KVD).
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const keyValueData: Uint8Array[] = [];
|
||||
const keyValueList = Object.entries({
|
||||
...container.keyValue,
|
||||
...(!options.keepWriter && { KTXwriter: KTX_WRITER }),
|
||||
});
|
||||
|
||||
keyValueList.sort((a, b) => (a[0] > b[0] ? 1 : -1));
|
||||
|
||||
for (const [key, value] of keyValueList) {
|
||||
const keyData = encodeText(key);
|
||||
const valueData = typeof value === 'string' ? concat([encodeText(value), NUL]) : value;
|
||||
const kvByteLength = keyData.byteLength + 1 + valueData.byteLength;
|
||||
const kvPadding = getPadding(kvByteLength, 4); // align(4)
|
||||
keyValueData.push(
|
||||
concat([
|
||||
new Uint32Array([kvByteLength]),
|
||||
keyData,
|
||||
NUL,
|
||||
valueData,
|
||||
new Uint8Array(kvPadding).fill(0x00), // align(4)
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
const kvdBuffer = concat(keyValueData);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Data Format Descriptor (DFD).
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
if (
|
||||
container.dataFormatDescriptor.length !== 1 ||
|
||||
container.dataFormatDescriptor[0].descriptorType !== KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT
|
||||
) {
|
||||
throw new Error('Only BASICFORMAT Data Format Descriptor output supported.');
|
||||
}
|
||||
|
||||
const dfd = container.dataFormatDescriptor[0];
|
||||
|
||||
const dfdBuffer = new ArrayBuffer(28 + dfd.samples.length * 16);
|
||||
const dfdView = new DataView(dfdBuffer);
|
||||
const descriptorBlockSize = 24 + dfd.samples.length * 16;
|
||||
|
||||
dfdView.setUint32(0, dfdBuffer.byteLength, true);
|
||||
dfdView.setUint16(4, dfd.vendorId, true);
|
||||
dfdView.setUint16(6, dfd.descriptorType, true);
|
||||
dfdView.setUint16(8, dfd.versionNumber, true);
|
||||
dfdView.setUint16(10, descriptorBlockSize, true);
|
||||
|
||||
dfdView.setUint8(12, dfd.colorModel);
|
||||
dfdView.setUint8(13, dfd.colorPrimaries);
|
||||
dfdView.setUint8(14, dfd.transferFunction);
|
||||
dfdView.setUint8(15, dfd.flags);
|
||||
|
||||
if (!Array.isArray(dfd.texelBlockDimension)) {
|
||||
throw new Error('texelBlockDimension is now an array. For dimensionality `d`, set `d - 1`.');
|
||||
}
|
||||
|
||||
dfdView.setUint8(16, dfd.texelBlockDimension[0]);
|
||||
dfdView.setUint8(17, dfd.texelBlockDimension[1]);
|
||||
dfdView.setUint8(18, dfd.texelBlockDimension[2]);
|
||||
dfdView.setUint8(19, dfd.texelBlockDimension[3]);
|
||||
|
||||
for (let i = 0; i < 8; i++) dfdView.setUint8(20 + i, dfd.bytesPlane[i]);
|
||||
|
||||
for (let i = 0; i < dfd.samples.length; i++) {
|
||||
const sample = dfd.samples[i];
|
||||
const sampleByteOffset = 28 + i * 16;
|
||||
|
||||
dfdView.setUint16(sampleByteOffset + 0, sample.bitOffset, true);
|
||||
dfdView.setUint8(sampleByteOffset + 2, sample.bitLength);
|
||||
dfdView.setUint8(sampleByteOffset + 3, sample.channelType);
|
||||
|
||||
dfdView.setUint8(sampleByteOffset + 4, sample.samplePosition[0]);
|
||||
dfdView.setUint8(sampleByteOffset + 5, sample.samplePosition[1]);
|
||||
dfdView.setUint8(sampleByteOffset + 6, sample.samplePosition[2]);
|
||||
dfdView.setUint8(sampleByteOffset + 7, sample.samplePosition[3]);
|
||||
|
||||
if (sample.channelType & KHR_DF_SAMPLE_DATATYPE_SIGNED) {
|
||||
dfdView.setInt32(sampleByteOffset + 8, sample.sampleLower, true);
|
||||
dfdView.setInt32(sampleByteOffset + 12, sample.sampleUpper, true);
|
||||
} else {
|
||||
dfdView.setUint32(sampleByteOffset + 8, sample.sampleLower, true);
|
||||
dfdView.setUint32(sampleByteOffset + 12, sample.sampleUpper, true);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Data alignment.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const dfdByteOffset = KTX2_ID.length + HEADER_BYTE_LENGTH + container.levels.length * 3 * 8;
|
||||
const kvdByteOffset = dfdByteOffset + dfdBuffer.byteLength;
|
||||
let sgdByteOffset = sgdBuffer.byteLength > 0 ? kvdByteOffset + kvdBuffer.byteLength : 0;
|
||||
if (sgdByteOffset % 8) sgdByteOffset += 8 - (sgdByteOffset % 8); // align(8)
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Level Index.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const levelData: Uint8Array[] = [];
|
||||
const levelIndex = new DataView(new ArrayBuffer(container.levels.length * 3 * 8));
|
||||
const levelDataByteOffsets = new Uint32Array(container.levels.length);
|
||||
|
||||
let levelAlign = 0;
|
||||
if (container.supercompressionScheme === KHR_SUPERCOMPRESSION_NONE) {
|
||||
levelAlign = leastCommonMultiple(getBlockByteLength(container), 4);
|
||||
}
|
||||
|
||||
// Level data is ordered small → large.
|
||||
let levelDataByteOffset = (sgdByteOffset || kvdByteOffset + kvdBuffer.byteLength) + sgdBuffer.byteLength;
|
||||
for (let i = container.levels.length - 1; i >= 0; i--) {
|
||||
// Level padding.
|
||||
if (levelDataByteOffset % levelAlign) {
|
||||
const paddingBytes = getPadding(levelDataByteOffset, levelAlign);
|
||||
levelData.push(new Uint8Array(paddingBytes));
|
||||
levelDataByteOffset += paddingBytes;
|
||||
}
|
||||
|
||||
// Level data.
|
||||
const level = container.levels[i];
|
||||
levelData.push(level.levelData);
|
||||
levelDataByteOffsets[i] = levelDataByteOffset;
|
||||
levelDataByteOffset += level.levelData.byteLength;
|
||||
}
|
||||
|
||||
// Level index is ordered large → small.
|
||||
for (let i = 0; i < container.levels.length; i++) {
|
||||
const level = container.levels[i];
|
||||
levelIndex.setBigUint64(i * 24 + 0, BigInt(levelDataByteOffsets[i]), true);
|
||||
levelIndex.setBigUint64(i * 24 + 8, BigInt(level.levelData.byteLength), true);
|
||||
levelIndex.setBigUint64(i * 24 + 16, BigInt(level.uncompressedByteLength), true);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Header.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
const headerBuffer = new ArrayBuffer(HEADER_BYTE_LENGTH);
|
||||
const headerView = new DataView(headerBuffer);
|
||||
headerView.setUint32(0, container.vkFormat, true);
|
||||
headerView.setUint32(4, container.typeSize, true);
|
||||
headerView.setUint32(8, container.pixelWidth, true);
|
||||
headerView.setUint32(12, container.pixelHeight, true);
|
||||
headerView.setUint32(16, container.pixelDepth, true);
|
||||
headerView.setUint32(20, container.layerCount, true);
|
||||
headerView.setUint32(24, container.faceCount, true);
|
||||
headerView.setUint32(28, container.levelCount, true);
|
||||
headerView.setUint32(32, container.supercompressionScheme, true);
|
||||
|
||||
headerView.setUint32(36, dfdByteOffset, true);
|
||||
headerView.setUint32(40, dfdBuffer.byteLength, true);
|
||||
headerView.setUint32(44, kvdByteOffset, true);
|
||||
headerView.setUint32(48, kvdBuffer.byteLength, true);
|
||||
headerView.setBigUint64(52, BigInt(sgdBuffer.byteLength > 0 ? sgdByteOffset : 0), true);
|
||||
headerView.setBigUint64(60, BigInt(sgdBuffer.byteLength), true);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Compose.
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
return new Uint8Array(
|
||||
concat([
|
||||
new Uint8Array(KTX2_ID).buffer,
|
||||
headerBuffer,
|
||||
levelIndex.buffer,
|
||||
dfdBuffer,
|
||||
kvdBuffer,
|
||||
sgdByteOffset > 0
|
||||
? new ArrayBuffer(sgdByteOffset - (kvdByteOffset + kvdBuffer.byteLength)) // align(8)
|
||||
: new ArrayBuffer(0),
|
||||
sgdBuffer,
|
||||
...levelData,
|
||||
]),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user