UNPKG

xgpu

Version:

XGPU is an extendable library for WebGPU that provides a higher-level, easy-to-use interface for building rendering engines or processing numeric data. It handles automatic data binding, buffer alignment, variable declarations in shaders, and more. XGPU i

238 lines (237 loc) 9.68 kB
// Copyright (c) 2023 Thomas Le Coz. All rights reserved. // This code is governed by an MIT license that can be found in the LICENSE file. export class GPUType { _isVector = false; _isMatrix = false; _isArray = false; _vecType = 1; _arrayLen; _primitive; _matrixColumns = 1; _matrixRows = 1; _alignOf; _sizeOf; _dataType; _rawType; //https://www.w3.org/TR/WGSL/#alignment-and-size constructor(dataType) { this._rawType = dataType; dataType = this.renameDataType(dataType); this._dataType = dataType; //console.log("GPUType dataType = ", dataType) this.getPrimitiveDataType(dataType, 0); } renameDataType(type) { switch (type) { case "float": return "f32"; case "vec2": return "vec2<f32>"; case "vec3": return "vec3<f32>"; case "vec4": return "vec4<f32>"; case "int": return "i32"; case "ivec2": return "vec2<i32>"; case "ivec3": return "vec3<i32>"; case "ivec4": return "vec4<i32>"; case "uint": return "u32"; case "uvec2": return "vec2<u32>"; case "uvec3": return "vec3<u32>"; case "uvec4": return "vec4<u32>"; case "mat4": return "mat4x4<f32>"; case "mat3": return "mat3x3<f32>"; case "mat2": return "mat2x2<f32>"; case "mat2d": return "mat2w3<f32>"; } return type; } get isPrimitive() { return !this._isVector && !this._isArray && !this._isMatrix; } ; get isVector() { return this._isVector && !this._isArray && !this._isMatrix; } ; get isMatrix() { return this._isMatrix && !this._isArray; } get isArray() { return this._isArray; } get isMatrixOfVectors() { return this._isMatrix && this._isVector; } get isArrayOfVectors() { return this._isArray && this._isVector; } get isArrayOfMatrixs() { return this._isArray && this._isMatrix; } get vectorType() { return this._vecType; } get arrayLength() { return this._arrayLen; } get matrixColumns() { return this._matrixColumns; } get matrixRows() { return this._matrixRows; } get primitive() { return this._primitive; } get nbValues() { return this._matrixColumns * this._matrixRows * this._vecType * (this._arrayLen ? this._arrayLen : 1); } get byteSize() { return this._sizeOf; } get byteAlign() { return this._alignOf; } set byteAlign(n) { this._alignOf = n; } get dataType() { return this._dataType; } get rawType() { return this._rawType; } get byteValue() { if (this._primitive === "f16") return 2; return 4; } getMatrixBytesStructure(col, row, primitive) { const type = "mat" + col + "x" + row + "<" + primitive + ">"; //console.log("getMatrixBytesStructure ", type) const dataInfos = { "mat2x2<f32>": [8, 16], "mat2x2<f16>": [4, 8], "mat3x2<f32>": [8, 24], "mat3x2<f16>": [4, 12], "mat4x2<f32>": [8, 32], "mat4x2<f16>": [4, 16], "mat2x3<f32>": [16, 32], "mat2x3<f16>": [8, 16], "mat3x3<f32>": [16, 48], "mat3x3<f16>": [8, 24], "mat4x3<f32>": [16, 64], "mat4x3<f16>": [8, 32], "mat2x4<f32>": [16, 32], "mat2x4<f16>": [8, 16], "mat3x4<f32>": [16, 48], "mat3x4<f16>": [8, 24], "mat4x4<f32>": [16, 64], "mat4x4<f16>": [8, 32] }; const o = dataInfos[type]; //console.log(o) this._alignOf = o[0]; this._sizeOf = o[1]; } getPrimitiveDataType = (dataType, start) => { //console.log("getPrimitiveDataType ", dataType) const first = dataType.substring(start, start + 1); switch (first) { case "u": this._primitive = "u32"; this._alignOf = 4; this._sizeOf = 4; break; case "i": this._primitive = "i32"; this._alignOf = 4; this._sizeOf = 4; break; case "f": const val = dataType.substring(start, start + 3); if (val === "f32" || val == "flo") { //float this._primitive = "f32"; this._alignOf = 4; this._sizeOf = 4; } else if (val === "f16") { this._primitive = val; this._alignOf = 2; this._sizeOf = 2; } else throw new Error("invalid primitive type"); break; case "v": if (dataType.substring(start, start + 3) === "vec") { this._isVector = true; const type = Number(dataType.substring(start + 3, start + 4)); if (type >= 2 && type <= 4) { this._vecType = type; this.getPrimitiveDataType(dataType, start + 5); if (this._primitive === "f16") { this._sizeOf = 2 * type; if (type === 2) this._alignOf = 4; else if (type === 3) this._alignOf = 8; else if (type === 4) this._alignOf = 8; } else { this._sizeOf = 4 * type; if (type === 2) this._alignOf = 8; else if (type === 3) this._alignOf = 16; else if (type === 4) this._alignOf = 16; } } else { throw new Error("invalid vec type"); } } else { throw new Error("invalid primitive type"); } break; case "a": if (dataType.substring(start, start + 5) === "array") { this._isArray = true; let temp = 15; if (dataType.substring(6, 7) === "m") { //array of matrix temp = 17; } else if (dataType.substring(6, 7) === "f" || dataType.substring(6, 7) === "i" || dataType.substring(6, 7) === "u") { //array of f32/i32/u32 temp = 9; } //console.log(start, temp, dataType.substring(start, temp)) //console.log("dataType.substring(start + temp, start + temp + 1) = ", dataType.substring(start + temp, start + temp + 1)) if (dataType.substring(start + temp, start + temp + 1) === ",") { let num; temp++; //console.log("=> ", dataType.substring(temp, temp + 1)) for (let i = 1; i < 16; i++) { let n = dataType.substring(temp, temp + i); if (isNaN(Number(n))) break; num = n; } //console.log("num = ", num) this._arrayLen = Number(num); } this.getPrimitiveDataType(dataType, start + 6); if (this.arrayLength) this._sizeOf *= this._arrayLen; } else { throw new Error("invalid primitive type"); } break; case "m": if (dataType.substring(start, start + 3) === "mat") { this._isMatrix = true; const col = Number(dataType.substring(start + 3, start + 4)); const row = Number(dataType.substring(start + 5, start + 6)); //console.log("matrix ", col, row) if (!isNaN(col) && !isNaN(row)) { this._matrixColumns = col; this._matrixRows = row; this.getPrimitiveDataType(dataType, start + 7); if (this._primitive === "f16" || this._primitive === "f32") { this.getMatrixBytesStructure(col, row, this._primitive); } else { throw new Error("Matrix values must be f32 or f16"); } } else { throw new Error("invalid matrix type"); } } else { throw new Error("invalid primitive type"); } break; } }; }