@cosmos-js/wgpu-struct 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,112 @@
1
+ export declare enum LENGTH {
2
+ BIT8 = 1,
3
+ BIT16 = 2,
4
+ BIT32 = 4
5
+ }
6
+ export declare const WGPU_DATA_TYPE: {
7
+ /**Represents a U8 (1 byte) */
8
+ readonly U8: {
9
+ readonly type: "uint";
10
+ readonly length: LENGTH.BIT8;
11
+ };
12
+ /**Represents a U16 (2 byte) */
13
+ readonly U16: {
14
+ readonly type: "uint";
15
+ readonly length: LENGTH.BIT16;
16
+ };
17
+ /**Represents a U32 (4 byte) */
18
+ readonly U32: {
19
+ readonly type: "uint";
20
+ readonly length: LENGTH.BIT32;
21
+ };
22
+ /**Represent a I8 (1 byte) */
23
+ readonly I8: {
24
+ readonly type: "int";
25
+ readonly length: LENGTH.BIT8;
26
+ };
27
+ /**Represent a I16 (2 byte) */
28
+ readonly I16: {
29
+ readonly type: "int";
30
+ readonly length: LENGTH.BIT16;
31
+ };
32
+ /**Represent a I32 (4 byte) */
33
+ readonly I32: {
34
+ readonly type: "int";
35
+ readonly length: LENGTH.BIT32;
36
+ };
37
+ /**Represent a F16 (2 byte) */
38
+ readonly F16: {
39
+ readonly type: "float";
40
+ readonly length: LENGTH.BIT16;
41
+ };
42
+ /**Repesent a F32 (4 byte) */
43
+ readonly F32: {
44
+ readonly type: "float";
45
+ readonly length: LENGTH.BIT32;
46
+ };
47
+ };
48
+ export type WGPU_DATA_TYPE = typeof WGPU_DATA_TYPE[keyof typeof WGPU_DATA_TYPE];
49
+ export interface TYPE_METADATA {
50
+ /**
51
+ * Represents the length of the type.
52
+ *
53
+ * e.g. **`length: 4`** meaning it's a **`array<yourType, 4>`**
54
+ */
55
+ length: number;
56
+ /**
57
+ * Represents the webgpu type;
58
+ *
59
+ * e.g. **`WGPU_DATA_TYPE.U8`** represents a **Uint8 [0-256]**
60
+ */
61
+ type: WGPU_DATA_TYPE;
62
+ }
63
+ export type FIELD = ({
64
+ /**Name of the field */
65
+ name: string;
66
+ required: boolean;
67
+ }) & (({
68
+ /**
69
+ * The type of the field;
70
+ *
71
+ * If you want to represent a vec3i; use `{length: 3, type: WGPU_DATA_TYPE.I32}`
72
+ */
73
+ type: TYPE_METADATA;
74
+ }) | ({
75
+ /**
76
+ * Inner struct
77
+ */
78
+ innerStruct: WGPU_STRUCT;
79
+ length: number;
80
+ }));
81
+ export type WGPU_STRUCT = FIELD[];
82
+ export type DIGESTABLE_FIELD = {
83
+ name: string;
84
+ length: number;
85
+ required: boolean;
86
+ } & ({
87
+ struct: DIGESTABLE_STRUCT_LAYOUT;
88
+ } | {
89
+ type: WGPU_DATA_TYPE;
90
+ });
91
+ export interface DIGESTABLE_STRUCT_LAYOUT {
92
+ byteLength: number;
93
+ items: DIGESTABLE_FIELD[];
94
+ }
95
+ export interface DATA_TYPE {
96
+ [x: string]: number[] | DATA_TYPE[];
97
+ }
98
+ export declare namespace StructValidation {
99
+ function validateNames(struct: WGPU_STRUCT): void;
100
+ function validateBytelength(struct: WGPU_STRUCT): void;
101
+ function validateData(data: DATA_TYPE, layout: DIGESTABLE_STRUCT_LAYOUT): void;
102
+ }
103
+ export declare namespace StructConverter {
104
+ function convertToDigestableLayout(struct: WGPU_STRUCT): DIGESTABLE_STRUCT_LAYOUT;
105
+ }
106
+ export declare namespace Packer {
107
+ /** Packs data to {type: "f32"|"i32"|"u32", value: number}[] */
108
+ function packToBit32(data: DATA_TYPE, layout: DIGESTABLE_STRUCT_LAYOUT): {
109
+ type: "f32" | "i32" | "u32";
110
+ value: number;
111
+ }[];
112
+ }
package/dist/index.js ADDED
@@ -0,0 +1,185 @@
1
+ export var LENGTH;
2
+ (function (LENGTH) {
3
+ LENGTH[LENGTH["BIT8"] = 1] = "BIT8";
4
+ LENGTH[LENGTH["BIT16"] = 2] = "BIT16";
5
+ LENGTH[LENGTH["BIT32"] = 4] = "BIT32";
6
+ })(LENGTH || (LENGTH = {}));
7
+ export const WGPU_DATA_TYPE = {
8
+ /**Represents a U8 (1 byte) */
9
+ U8: { type: "uint", length: LENGTH.BIT8 },
10
+ /**Represents a U16 (2 byte) */
11
+ U16: { type: "uint", length: LENGTH.BIT16 },
12
+ /**Represents a U32 (4 byte) */
13
+ U32: { type: "uint", length: LENGTH.BIT32 },
14
+ /**Represent a I8 (1 byte) */
15
+ I8: { type: "int", length: LENGTH.BIT8 },
16
+ /**Represent a I16 (2 byte) */
17
+ I16: { type: "int", length: LENGTH.BIT16 },
18
+ /**Represent a I32 (4 byte) */
19
+ I32: { type: "int", length: LENGTH.BIT32 },
20
+ /**Represent a F16 (2 byte) */
21
+ F16: { type: "float", length: LENGTH.BIT16 },
22
+ /**Repesent a F32 (4 byte) */
23
+ F32: { type: "float", length: LENGTH.BIT32 }
24
+ };
25
+ export var StructValidation;
26
+ (function (StructValidation) {
27
+ function validateNames(struct) {
28
+ const set = {};
29
+ for (const field of struct) {
30
+ if (set[field.name])
31
+ throw new Error("Duplicate field name " + field.name);
32
+ else if (field?.innerStruct)
33
+ validateNames(field.innerStruct);
34
+ set[field.name] = true;
35
+ }
36
+ }
37
+ StructValidation.validateNames = validateNames;
38
+ function getByteLength(struct) {
39
+ let bytes = 0;
40
+ for (const field of struct) {
41
+ const assingleTyped = field;
42
+ if (assingleTyped.type) {
43
+ bytes += assingleTyped.type.type.length * assingleTyped.type.length;
44
+ }
45
+ const asstructTyped = field;
46
+ if (asstructTyped.innerStruct) {
47
+ bytes += asstructTyped.length * getByteLength(asstructTyped.innerStruct);
48
+ }
49
+ }
50
+ return bytes;
51
+ }
52
+ function validateBytelength(struct) {
53
+ const byteLength = getByteLength(struct);
54
+ if (byteLength % 4 !== 0) {
55
+ throw new Error(`Length of the given struct is not divisible by 4.`);
56
+ }
57
+ if (byteLength % 16 !== 0) {
58
+ throw new Error(`Length of the given struct is not divisble by 16`);
59
+ }
60
+ }
61
+ StructValidation.validateBytelength = validateBytelength;
62
+ function validateData(data, layout) {
63
+ for (const field of layout.items) {
64
+ const fieldData = data[field.name];
65
+ if (!fieldData && field.required)
66
+ throw new Error(`Error while validating data: "${field.name}" not given`);
67
+ if (fieldData.length !== field.length)
68
+ throw new Error(`[Field "${field.name}"]: Given data is of ${fieldData.length} where as ${field.length} is required.`);
69
+ const asTyped = field;
70
+ if (asTyped.type) {
71
+ if (fieldData.every(a => typeof a !== "number")) {
72
+ throw new Error(`[Field "${field.name}"]: Array given is not of number[] type`);
73
+ }
74
+ }
75
+ else {
76
+ for (const data of fieldData) {
77
+ validateData(data, field.struct);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ StructValidation.validateData = validateData;
83
+ })(StructValidation || (StructValidation = {}));
84
+ export var StructConverter;
85
+ (function (StructConverter) {
86
+ function convertToDigestableLayout(struct) {
87
+ const layout = { byteLength: 0, items: [] };
88
+ for (const field of struct) {
89
+ const fieldTyped = field;
90
+ const fieldStruct = field;
91
+ if (fieldTyped.type) {
92
+ const byteLength = fieldTyped.type.type.length * fieldTyped.type.length;
93
+ layout.byteLength += byteLength;
94
+ layout.items.push({ "length": fieldTyped.type.length, "name": fieldTyped.name, "type": fieldTyped.type.type, required: fieldTyped.required });
95
+ }
96
+ else if (fieldStruct.innerStruct) {
97
+ const digested = convertToDigestableLayout(fieldStruct.innerStruct);
98
+ const byteLength = fieldStruct.length * digested.byteLength;
99
+ layout.byteLength += byteLength;
100
+ layout.items.push({ length: fieldStruct.length, name: fieldStruct.name, struct: digested, required: fieldStruct.required });
101
+ }
102
+ }
103
+ return layout;
104
+ }
105
+ StructConverter.convertToDigestableLayout = convertToDigestableLayout;
106
+ })(StructConverter || (StructConverter = {}));
107
+ export var Packer;
108
+ (function (Packer) {
109
+ /** Packs data to {type: "f32"|"i32"|"u32", value: number}[] */
110
+ function packToBit32(data, layout) {
111
+ const buffer = new ArrayBuffer(layout.byteLength);
112
+ const view = new DataView(buffer);
113
+ const chunkTypes = new Array(layout.byteLength / 4).fill("u32");
114
+ let byteOffset = 0;
115
+ function writeField(fieldData, field) {
116
+ const isPrimitive = "type" in field;
117
+ if (isPrimitive) {
118
+ const primitiveType = field.type.type;
119
+ const bitLength = field.type.length;
120
+ const numericArray = fieldData;
121
+ for (let i = 0; i < field.length; i++) {
122
+ const value = numericArray[i] ?? 0;
123
+ const chunkIndex = Math.floor(byteOffset / 4);
124
+ if (primitiveType === "float")
125
+ chunkTypes[chunkIndex] = "f32";
126
+ else if (primitiveType === "int")
127
+ chunkTypes[chunkIndex] = "i32";
128
+ if (primitiveType === "uint") {
129
+ if (bitLength === 1)
130
+ view.setUint8(byteOffset, value);
131
+ else if (bitLength === 2)
132
+ view.setUint16(byteOffset, value, true);
133
+ else if (bitLength === 4)
134
+ view.setUint32(byteOffset, value, true);
135
+ }
136
+ else if (primitiveType === "int") {
137
+ if (bitLength === 1)
138
+ view.setInt8(byteOffset, value);
139
+ else if (bitLength === 2)
140
+ view.setInt16(byteOffset, value, true);
141
+ else if (bitLength === 4)
142
+ view.setInt32(byteOffset, value, true);
143
+ }
144
+ else if (primitiveType === "float") {
145
+ if (bitLength === 4)
146
+ view.setFloat32(byteOffset, value, true);
147
+ }
148
+ byteOffset += bitLength;
149
+ }
150
+ }
151
+ else {
152
+ const structArray = fieldData;
153
+ const innerLayout = field.struct;
154
+ for (let i = 0; i < field.length; i++) {
155
+ const innerData = structArray[i] ?? {};
156
+ for (const innerField of innerLayout.items) {
157
+ writeField(innerData[innerField.name], innerField);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ for (const item of layout.items) {
163
+ writeField(data[item.name], item);
164
+ }
165
+ const result = [];
166
+ const total32BitChunks = layout.byteLength / 4;
167
+ for (let i = 0; i < total32BitChunks; i++) {
168
+ const currentByteOffset = i * 4;
169
+ const targetType = chunkTypes[i];
170
+ let value;
171
+ if (targetType === "f32") {
172
+ value = view.getFloat32(currentByteOffset, true);
173
+ }
174
+ else if (targetType === "i32") {
175
+ value = view.getInt32(currentByteOffset, true);
176
+ }
177
+ else {
178
+ value = view.getUint32(currentByteOffset, true);
179
+ }
180
+ result.push({ type: targetType, value });
181
+ }
182
+ return result;
183
+ }
184
+ Packer.packToBit32 = packToBit32;
185
+ })(Packer || (Packer = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmos-js/wgpu-struct",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Helper for cosmos-js to descriptor wgpu structs in js.",
5
5
  "main": "./dist/index.js",
6
6
  "author": {
package/src/index.ts CHANGED
@@ -74,13 +74,12 @@ export interface DATA_TYPE {
74
74
  }
75
75
  export namespace StructValidation {
76
76
  export function validateNames(struct: WGPU_STRUCT) {
77
- let set: Record<string, true> = {};
77
+ const set: Record<string, true> = {};
78
78
  for (const field of struct) {
79
79
  if (set[field.name]) throw new Error("Duplicate field name " + field.name)
80
80
  else if ((field as { name: string } & { innerStruct: WGPU_STRUCT })?.innerStruct) validateNames((field as { name: string } & { innerStruct: WGPU_STRUCT }).innerStruct)
81
81
  set[field.name] = true;
82
82
  }
83
- set = {}
84
83
  }
85
84
  function getByteLength(struct: WGPU_STRUCT) {
86
85
  let bytes = 0;
@@ -205,7 +204,7 @@ export namespace Packer {
205
204
  for (let i = 0; i < total32BitChunks; i++) {
206
205
  const currentByteOffset = i * 4;
207
206
  const targetType = chunkTypes[i];
208
- let value = 0;
207
+ let value;
209
208
 
210
209
  if (targetType === "f32") {
211
210
  value = view.getFloat32(currentByteOffset, true);