Add existing to tracked
This commit is contained in:
+17
@@ -0,0 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## v0.4
|
||||
|
||||
- Removed UMD builds
|
||||
|
||||
## v0.3
|
||||
|
||||
- Improved support for uncompressed formats and fixed various bugs
|
||||
- Renamed `channelID` to `channelType`
|
||||
- Added and reorganized exported constants and enums
|
||||
- Changed type of `texelBlockDimension` to array
|
||||
- Values now match KTX2 specification, with dimensionality `d` represented as `d - 1`
|
||||
|
||||
## v0.2
|
||||
|
||||
## v0.1
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Don McCurdy
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
# ktx-parse
|
||||
|
||||
[](https://www.npmjs.com/package/ktx-parse)
|
||||
[](https://bundlephobia.com/package/ktx-parse)
|
||||
[](https://github.com/donmccurdy/KTX-Parse/blob/main/LICENSE)
|
||||
[](https://github.com/donmccurdy/KTX-parse/actions?query=workflow%3ACI)
|
||||
[](https://codecov.io/gh/donmccurdy/KTX-Parse)
|
||||
|
||||
_KTX 2.0 (.ktx2) parser and serializer._
|
||||
|
||||
## Quickstart
|
||||
|
||||
Install:
|
||||
|
||||
```
|
||||
npm install --save ktx-parse
|
||||
```
|
||||
|
||||
Import:
|
||||
|
||||
```js
|
||||
import { read, write } from "ktx-parse";
|
||||
```
|
||||
|
||||
Usage:
|
||||
|
||||
```js
|
||||
// Parse texture container from file:
|
||||
const container = read(data /* ← Uint8Array or Buffer */);
|
||||
|
||||
// Write texture container to file:
|
||||
const data = write(container); // → Uint8Array
|
||||
```
|
||||
|
||||
See [API documentation](https://tsdocs.dev/docs/ktx-parse/) for more details.
|
||||
|
||||
## Encoding / Decoding
|
||||
|
||||
KTX-Parse reads/writes KTX 2.0 containers, and provides access to the compressed texture data within the container. To decompress that texture data, or to compress existing texture data into GPU texture formats used by KTX 2.0, you'll need to use additional libraries such as encoders or transcoders.
|
||||
|
||||
**Encoding:**
|
||||
|
||||
Encoding GPU textures is a slow process, and should be completed at development/authoring time so that the compressed texture can be transmitted to the viewing device. GPU textures require much less GPU memory than image formats like PNG or JPEG, and can be uploaded to the GPU quickly with less impact on framerate. GPU textures can also have smaller filesizes in many, but not all, cases. See the [Basis documentation](https://github.com/BinomialLLC/basis_universal/) for details on this process.
|
||||
|
||||
The following tools may be used to produce Basis Universal compressed textures in KTX 2.0 (`.ktx2`) containers, which `ktx-parse` can then read or edit:
|
||||
|
||||
- [BinomialLLC/basis_universal](https://github.com/BinomialLLC/basis_universal/) CLI, C++, and WebAssembly encoders
|
||||
- [KhronosGroup/KTX-Software](https://github.com/KhronosGroup/KTX-Software) CLI, C++, and WebAssembly encoders
|
||||
|
||||
**Transcoding / Decoding:**
|
||||
|
||||
Basis Universal texture formats (ETC1S and UASTC) cannot be directly read by a GPU, but are designed to be very efficiently rewritten into many of the specific GPU texture formats that different GPUs require. This process is called _transcoding_, and typically happens on the viewing device after a target output format (e.g. ETC1, ASTC, BC1, ...) is chosen. These transcoders can also fully _decode_ texture data to uncompressed RGBA formats, if raw pixel data is required.
|
||||
|
||||
- [BinomialLLC/basis_universal](https://github.com/BinomialLLC/basis_universal/) provides official C++ and WebAssembly transcoders, which support all Basis Universal input formats and can transcode to any output format (with appropriate compilation flags). With common settings, a transcoder will likely be > 200kb on web. This transcoder can read KTX 2.0 files directly.
|
||||
- [KhronosGroup/Universal-Texture-Transcoders](https://github.com/KhronosGroup/Universal-Texture-Transcoders) provides very small, fast WebAssembly transcoders each supporting only a single output texture format. Each transcoder is roughly 10-20kb, and the viewing device can choose which transcoder to download, as appropriate. These transcoders cannot read KTX 2.0 files directly. Instead, unpack the KTX 2.0 files with `ktx-parse` first, then transcode the mip levels using a low-level transcoder. _Only UASTC texture formats currently supported._
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
export declare class BufferReader {
|
||||
private _dataView;
|
||||
private _littleEndian;
|
||||
_offset: number;
|
||||
constructor(data: Uint8Array, byteOffset: number, byteLength: number, littleEndian: boolean);
|
||||
_nextUint8(): number;
|
||||
_nextUint16(): number;
|
||||
_nextUint32(): number;
|
||||
_nextUint64(): number;
|
||||
_nextInt32(): number;
|
||||
_nextUint8Array(len: number): Uint8Array;
|
||||
_skip(bytes: number): this;
|
||||
_scan(maxByteLength: number, term?: number): Uint8Array;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export declare const KTX_WRITER: string;
|
||||
export declare const NUL: Uint8Array;
|
||||
export type vec3 = [number, number, number];
|
||||
export type vec2 = [number, number, number];
|
||||
export declare const KTX2_ID: number[];
|
||||
export declare const HEADER_BYTE_LENGTH = 68;
|
||||
+251
File diff suppressed because one or more lines are too long
+104
@@ -0,0 +1,104 @@
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
export {};
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
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 declare function createDefaultContainer(): KTX2Container;
|
||||
+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';
|
||||
+1041
File diff suppressed because it is too large
Load Diff
+1
File diff suppressed because one or more lines are too long
+794
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+798
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+9
@@ -0,0 +1,9 @@
|
||||
import type { KTX2Container } from './container.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 declare function read(data: Uint8Array): KTX2Container;
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import type { vec3 } from './constants-internal.js';
|
||||
import { type VKFormat } from './constants.js';
|
||||
import type { KTX2Container } from './container.js';
|
||||
/** Encodes text to an ArrayBuffer. */
|
||||
export declare function encodeText(text: string): Uint8Array;
|
||||
/** Decodes an ArrayBuffer to text. */
|
||||
export declare function decodeText(buffer: Uint8Array): string;
|
||||
/** Concatenates N ArrayBuffers. */
|
||||
export declare function concat(buffers: (ArrayBuffer | Uint8Array)[]): Uint8Array;
|
||||
/** Returns the least common multiple (LCM) for two positive integers. */
|
||||
export declare function leastCommonMultiple(a: number, b: number): number;
|
||||
/**
|
||||
* 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 declare function getPadding(v: number, n?: number): number;
|
||||
/** Returns byte length per texel block. */
|
||||
export declare function getBlockByteLength(container: KTX2Container): number;
|
||||
/**
|
||||
* 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 declare function getBlockCount(container: KTX2Container, levelIndex: number): number;
|
||||
/**
|
||||
* Given a KTX2 container, returns block dimensions as [width, height, depth]. Requires valid DFD.
|
||||
*/
|
||||
export declare function getBlockDimensions(container: KTX2Container): vec3;
|
||||
/**
|
||||
* 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 declare function getBlockDimensionsByVKFormat(vkFormat: VKFormat): vec3;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import type { KTX2Container } from './container.js';
|
||||
interface WriteOptions {
|
||||
keepWriter?: boolean;
|
||||
}
|
||||
/**
|
||||
* 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 declare function write(container: KTX2Container, options?: WriteOptions): Uint8Array;
|
||||
export {};
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "ktx-parse",
|
||||
"version": "1.1.0",
|
||||
"description": "KTX 2.0 (.ktx2) parser and serializer.",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"source": "./src/index.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"main": "./dist/ktx-parse.cjs",
|
||||
"module": "./dist/ktx-parse.esm.js",
|
||||
"exports": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"require": "./dist/ktx-parse.cjs",
|
||||
"default": "./dist/ktx-parse.modern.js"
|
||||
},
|
||||
"repository": "github:donmccurdy/ktx-parse",
|
||||
"author": "Don McCurdy <dm@donmccurdy.com>",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "microbundle --format cjs,esm,modern --no-compress --define PACKAGE_VERSION=$npm_package_version",
|
||||
"watch": "microbundle watch --format cjs,esm,modern --no-compress --define PACKAGE_VERSION=$npm_package_version",
|
||||
"test": "ava --no-worker-threads test/test.ts",
|
||||
"validate": "ava --no-worker-threads test/validate.ts",
|
||||
"coverage": "c8 --reporter=lcov --reporter=text ava --no-worker-threads test/test.ts --tap",
|
||||
"coverage:report": "c8 report --reporter=text-lcov > coverage/coverage.lcov",
|
||||
"lint": "biome check src test",
|
||||
"lint:ci": "biome ci src test",
|
||||
"clean": "rm -rf dist/* || true",
|
||||
"release": "yarn postversion:commit && yarn npm publish && yarn postversion:push",
|
||||
"prerelease": "yarn postversion:commit && yarn npm publish --tag alpha && yarn postversion:push",
|
||||
"postversion:commit": "git add -u && git commit -m \"chore(release): v$npm_package_version\" && git tag -a v$npm_package_version -m v$npm_package_version",
|
||||
"postversion:push": "git push && git push --tags && yarn coverage:report",
|
||||
"prepublish": "yarn lint && yarn test && yarn validate",
|
||||
"prepack": "yarn clean && yarn build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.9.4",
|
||||
"@types/node": "^24.0.3",
|
||||
"ava": "6.4.0",
|
||||
"c8": "10.1.3",
|
||||
"microbundle": "0.15.1",
|
||||
"typescript": "5.8.3"
|
||||
},
|
||||
"files": [
|
||||
"dist/",
|
||||
"src/",
|
||||
"README.md",
|
||||
"LICENSE",
|
||||
"package.json"
|
||||
],
|
||||
"browserslist": [
|
||||
"defaults",
|
||||
"not IE 11",
|
||||
"node >= 14"
|
||||
],
|
||||
"ava": {
|
||||
"extensions": {
|
||||
"ts": "module"
|
||||
},
|
||||
"nodeArguments": [
|
||||
"--experimental-strip-types"
|
||||
]
|
||||
},
|
||||
"packageManager": "yarn@4.9.2"
|
||||
}
|
||||
+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