@zephyr3d/device 0.2.2 → 0.2.4
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.
- package/README.md +1 -1
- package/dist/base_types.js +72 -5
- package/dist/base_types.js.map +1 -1
- package/dist/builder/ast.js +9 -0
- package/dist/builder/ast.js.map +1 -1
- package/dist/builder/base.js +6 -0
- package/dist/builder/base.js.map +1 -1
- package/dist/builder/builtinfunc.js +43 -18
- package/dist/builder/builtinfunc.js.map +1 -1
- package/dist/builder/programbuilder.js +20 -2
- package/dist/builder/programbuilder.js.map +1 -1
- package/dist/builder/types.js +4 -4
- package/dist/device.js +57 -3
- package/dist/device.js.map +1 -1
- package/dist/gpuobject.js +136 -4
- package/dist/gpuobject.js.map +1 -1
- package/dist/index.d.ts +223 -9
- package/dist/index.js +1 -1
- package/dist/pool.js +352 -0
- package/dist/pool.js.map +1 -0
- package/package.json +4 -7
package/dist/pool.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectPool class is responsible for managing and reusing textures and framebuffers.
|
|
3
|
+
* @public
|
|
4
|
+
*/ class Pool {
|
|
5
|
+
/** @internal */ _memCost;
|
|
6
|
+
/** @internal */ _memCostThreshold;
|
|
7
|
+
/** @internal */ _device;
|
|
8
|
+
/** @internal */ _freeTextures = {};
|
|
9
|
+
/** @internal */ _allocatedTextures = new WeakMap();
|
|
10
|
+
/** @internal */ _autoReleaseTextures = new Set();
|
|
11
|
+
/** @internal */ _freeFramebuffers = {};
|
|
12
|
+
/** @internal */ _allocatedFramebuffers = new WeakMap();
|
|
13
|
+
/** @internal */ _autoReleaseFramebuffers = new Set();
|
|
14
|
+
/**
|
|
15
|
+
* Creates an instance of Pool class
|
|
16
|
+
* @param device - Rendering device
|
|
17
|
+
*/ constructor(device, memCostThreshold = 1024 * 1024 * 1024){
|
|
18
|
+
this._device = device;
|
|
19
|
+
this._memCost = 0;
|
|
20
|
+
this._memCostThreshold = memCostThreshold;
|
|
21
|
+
this._freeTextures = {};
|
|
22
|
+
this._allocatedTextures = new WeakMap();
|
|
23
|
+
this._autoReleaseTextures = new Set();
|
|
24
|
+
this._freeFramebuffers = {};
|
|
25
|
+
this._allocatedFramebuffers = new WeakMap();
|
|
26
|
+
this._autoReleaseFramebuffers = new Set();
|
|
27
|
+
this._memCost = 0;
|
|
28
|
+
}
|
|
29
|
+
autoRelease() {
|
|
30
|
+
// auto release objects
|
|
31
|
+
for (const tex of this._autoReleaseTextures){
|
|
32
|
+
this.releaseTexture(tex);
|
|
33
|
+
}
|
|
34
|
+
this._autoReleaseTextures.clear();
|
|
35
|
+
for (const fb of this._autoReleaseFramebuffers){
|
|
36
|
+
this.releaseFrameBuffer(fb);
|
|
37
|
+
}
|
|
38
|
+
this._autoReleaseFramebuffers.clear();
|
|
39
|
+
// Free up video memory if memory usage is greater than specific value
|
|
40
|
+
if (this._memCost >= this._memCostThreshold) {
|
|
41
|
+
this.purge();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Fetch a temporal 2D texture from the object pool.
|
|
46
|
+
* @param autoRelease - Whether the texture should be automatically released at the next frame.
|
|
47
|
+
* @param format - The format of the texture.
|
|
48
|
+
* @param width - The width of the texture.
|
|
49
|
+
* @param height - The height of the texture.
|
|
50
|
+
* @param mipmapping - Whether this texture support mipmapping
|
|
51
|
+
* @returns The fetched Texture2D object.
|
|
52
|
+
*/ fetchTemporalTexture2D(autoRelease, format, width, height, mipmapping = false) {
|
|
53
|
+
const hash = `2d:${format}:${width}:${height}:${mipmapping ? 1 : 0}`;
|
|
54
|
+
let texture = null;
|
|
55
|
+
const list = this._freeTextures[hash];
|
|
56
|
+
if (!list) {
|
|
57
|
+
texture = this._device.createTexture2D(format, width, height, mipmapping ? {} : {
|
|
58
|
+
samplerOptions: {
|
|
59
|
+
mipFilter: 'none'
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
this._memCost += texture.memCost;
|
|
63
|
+
} else {
|
|
64
|
+
texture = list.pop();
|
|
65
|
+
if (list.length === 0) {
|
|
66
|
+
this._freeTextures[hash] = undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
this._allocatedTextures.set(texture, {
|
|
70
|
+
hash,
|
|
71
|
+
refcount: 1,
|
|
72
|
+
dispose: false
|
|
73
|
+
});
|
|
74
|
+
if (autoRelease) {
|
|
75
|
+
this._autoReleaseTextures.add(texture);
|
|
76
|
+
}
|
|
77
|
+
return texture;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Fetch a temporal 2D array texture from the object pool.
|
|
81
|
+
* @param autoRelease - Whether the texture should be automatically released at the next frame.
|
|
82
|
+
* @param format - Format of the texture.
|
|
83
|
+
* @param width - Width of the texture.
|
|
84
|
+
* @param height - Height of the texture.
|
|
85
|
+
* @param numLayers - Layer count of the texture
|
|
86
|
+
* @param mipmapping - Whether this texture support mipmapping
|
|
87
|
+
* @returns The fetched Texture2DArray object.
|
|
88
|
+
*/ fetchTemporalTexture2DArray(autoRelease, format, width, height, numLayers, mipmapping = false) {
|
|
89
|
+
const hash = `2darray:${format}:${width}:${height}:${numLayers}:${mipmapping ? 1 : 0}`;
|
|
90
|
+
let texture = null;
|
|
91
|
+
const list = this._freeTextures[hash];
|
|
92
|
+
if (!list) {
|
|
93
|
+
texture = this._device.createTexture2DArray(format, width, height, numLayers, mipmapping ? {} : {
|
|
94
|
+
samplerOptions: {
|
|
95
|
+
mipFilter: 'none'
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
this._memCost += texture.memCost;
|
|
99
|
+
} else {
|
|
100
|
+
texture = list.pop();
|
|
101
|
+
if (list.length === 0) {
|
|
102
|
+
this._freeTextures[hash] = undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
this._allocatedTextures.set(texture, {
|
|
106
|
+
hash,
|
|
107
|
+
refcount: 1,
|
|
108
|
+
dispose: false
|
|
109
|
+
});
|
|
110
|
+
if (autoRelease) {
|
|
111
|
+
this._autoReleaseTextures.add(texture);
|
|
112
|
+
}
|
|
113
|
+
return texture;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Fetch a temporal Cube texture from the object pool.
|
|
117
|
+
* @param autoRelease - Whether the texture should be automatically released at the next frame.
|
|
118
|
+
* @param format - Format of the texture.
|
|
119
|
+
* @param size - size of the texture.
|
|
120
|
+
* @param mipmapping - Whether this texture support mipmapping
|
|
121
|
+
* @returns The fetched TextureCube object.
|
|
122
|
+
*/ fetchTemporalTextureCube(autoRelease, format, size, mipmapping = false) {
|
|
123
|
+
const hash = `cube:${format}:${size}:${mipmapping ? 1 : 0}`;
|
|
124
|
+
let texture = null;
|
|
125
|
+
const list = this._freeTextures[hash];
|
|
126
|
+
if (!list) {
|
|
127
|
+
texture = this._device.createCubeTexture(format, size, mipmapping ? {} : {
|
|
128
|
+
samplerOptions: {
|
|
129
|
+
mipFilter: 'none'
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
this._memCost += texture.memCost;
|
|
133
|
+
} else {
|
|
134
|
+
texture = list.pop();
|
|
135
|
+
if (list.length === 0) {
|
|
136
|
+
this._freeTextures[hash] = undefined;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
this._allocatedTextures.set(texture, {
|
|
140
|
+
hash,
|
|
141
|
+
refcount: 1,
|
|
142
|
+
dispose: false
|
|
143
|
+
});
|
|
144
|
+
if (autoRelease) {
|
|
145
|
+
this._autoReleaseTextures.add(texture);
|
|
146
|
+
}
|
|
147
|
+
return texture;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Creates a temporal framebuffer from the object pool.
|
|
151
|
+
* @param autoRelease - Whether the framebuffer should be automatically released at the next frame.
|
|
152
|
+
* @param width - Width of the framebuffer
|
|
153
|
+
* @param height - Height of the framebuffer
|
|
154
|
+
* @param colorAttachments - Array of color attachments or texture format of the framebuffer.
|
|
155
|
+
* @param depthAttachment - Depth attachment or texture format of the framebuffer.
|
|
156
|
+
* @param mipmapping - Whether mipmapping should be enabled when creating color attachment textures, default is false.
|
|
157
|
+
* @param sampleCount - The sample count for the framebuffer, default is 1.
|
|
158
|
+
* @param ignoreDepthStencil - Whether to ignore depth stencil when resolving msaa framebuffer, default is true.
|
|
159
|
+
* @param attachmentMipLevel - The mipmap level to which the color attachment will render, default is 0
|
|
160
|
+
* @param attachmentCubeface - The cubemap face to which the color attachment will render, default is 0
|
|
161
|
+
* @param attachmentLayer - The texture layer to which the color attachment will render, default is 0
|
|
162
|
+
* @returns The fetched FrameBuffer object.
|
|
163
|
+
*/ fetchTemporalFramebuffer(autoRelease, width, height, colorTexOrFormat, depthTexOrFormat = null, mipmapping = false, sampleCount = 1, ignoreDepthStencil = true, attachmentMipLevel = 0, attachmentCubeface = 0, attachmentLayer = 0) {
|
|
164
|
+
const colors = Array.isArray(colorTexOrFormat) ? colorTexOrFormat : colorTexOrFormat ? [
|
|
165
|
+
colorTexOrFormat
|
|
166
|
+
] : [];
|
|
167
|
+
const colorAttachments = colors.map((val)=>{
|
|
168
|
+
return typeof val === 'string' ? this.fetchTemporalTexture2D(false, val, width, height, mipmapping) : val;
|
|
169
|
+
});
|
|
170
|
+
const depthAttachment = typeof depthTexOrFormat === 'string' ? this.fetchTemporalTexture2D(false, depthTexOrFormat, width, height, false) : depthTexOrFormat;
|
|
171
|
+
const fb = this.createTemporalFramebuffer(autoRelease, colorAttachments, depthAttachment, sampleCount, ignoreDepthStencil, attachmentMipLevel, attachmentCubeface, attachmentLayer);
|
|
172
|
+
for(let i = 0; i < colors.length; i++){
|
|
173
|
+
if (typeof colors[i] === 'string') {
|
|
174
|
+
this.releaseTexture(colorAttachments[i]);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (typeof depthTexOrFormat === 'string') {
|
|
178
|
+
this.releaseTexture(depthAttachment);
|
|
179
|
+
}
|
|
180
|
+
return fb;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Creates a temporal framebuffer from the object pool.
|
|
184
|
+
* @param autoRelease - Whether the framebuffer should be automatically released at the next frame.
|
|
185
|
+
* @param colorAttachments - Array of color attachments for the framebuffer.
|
|
186
|
+
* @param depthAttachment - Depth attachment for the framebuffer.
|
|
187
|
+
* @param sampleCount - The sample count for the framebuffer, default is 1.
|
|
188
|
+
* @param ignoreDepthStencil - Whether to ignore depth stencil when resolving msaa framebuffer, default is true.
|
|
189
|
+
* @param attachmentMipLevel - The mipmap level to which the color attachment will render, default is 0.
|
|
190
|
+
* @param attachmentCubeface - The cubemap face to which the color attachment will render, default is 0.
|
|
191
|
+
* @param attachmentLayer - The texture layer to which the color attachment will render, default is 0.
|
|
192
|
+
* @returns The fetched FrameBuffer object.
|
|
193
|
+
*/ createTemporalFramebuffer(autoRelease, colorAttachments, depthAttachment = null, sampleCount = 1, ignoreDepthStencil = true, attachmentMipLevel = 0, attachmentCubeface = 0, attachmentLayer = 0) {
|
|
194
|
+
colorAttachments = colorAttachments ?? [];
|
|
195
|
+
let hash = `${depthAttachment?.uid ?? 0}:${sampleCount ?? 1}:${ignoreDepthStencil ? 1 : 0}`;
|
|
196
|
+
if (colorAttachments.length > 0) {
|
|
197
|
+
hash += `:${attachmentMipLevel}:${attachmentCubeface}:${attachmentLayer}`;
|
|
198
|
+
for (const tex of colorAttachments){
|
|
199
|
+
hash += `:${tex.uid}`;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
let fb = null;
|
|
203
|
+
const list = this._freeFramebuffers[hash];
|
|
204
|
+
if (!list) {
|
|
205
|
+
fb = this._device.createFrameBuffer(colorAttachments, depthAttachment, {
|
|
206
|
+
ignoreDepthStencil,
|
|
207
|
+
sampleCount
|
|
208
|
+
});
|
|
209
|
+
for(let i = 0; i < fb.getColorAttachments().length; i++){
|
|
210
|
+
fb.setColorAttachmentMipLevel(i, attachmentMipLevel);
|
|
211
|
+
fb.setColorAttachmentCubeFace(i, attachmentCubeface);
|
|
212
|
+
fb.setColorAttachmentLayer(i, attachmentLayer);
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
fb = list.pop();
|
|
216
|
+
if (list.length === 0) {
|
|
217
|
+
this._freeFramebuffers[hash] = undefined;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Mark referenced textures
|
|
221
|
+
const info = this._allocatedTextures.get(depthAttachment);
|
|
222
|
+
if (info) {
|
|
223
|
+
info.refcount++;
|
|
224
|
+
}
|
|
225
|
+
for (const tex of colorAttachments){
|
|
226
|
+
const info = this._allocatedTextures.get(tex);
|
|
227
|
+
if (info) {
|
|
228
|
+
info.refcount++;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
this._allocatedFramebuffers.set(fb, hash);
|
|
232
|
+
if (autoRelease) {
|
|
233
|
+
this._autoReleaseFramebuffers.add(fb);
|
|
234
|
+
}
|
|
235
|
+
return fb;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Dispose a texture that is allocated from the object pool.
|
|
239
|
+
* @param texture - The texture to dispose.
|
|
240
|
+
*/ disposeTexture(texture) {
|
|
241
|
+
this.safeReleaseTexture(texture, true);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Release a texture back to the object pool.
|
|
245
|
+
* @param texture - The texture to release.
|
|
246
|
+
*/ releaseTexture(texture) {
|
|
247
|
+
const info = this._allocatedTextures.get(texture);
|
|
248
|
+
if (!info) {
|
|
249
|
+
console.error(`ObjectPool.releaseTexture(): texture is not allocated from pool`);
|
|
250
|
+
} else {
|
|
251
|
+
this.safeReleaseTexture(texture);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Dispose a framebuffer that is allocated from the object pool.
|
|
256
|
+
* @param fb - The framebuffer to dispose.
|
|
257
|
+
*/ disposeFrameBuffer(fb) {
|
|
258
|
+
const hash = this._allocatedFramebuffers.get(fb);
|
|
259
|
+
if (!hash) {
|
|
260
|
+
console.error(`ObjectPool.disposeFrameBuffer(): framebuffer is not allocated from pool`);
|
|
261
|
+
} else {
|
|
262
|
+
this.internalDisposeFrameBuffer(fb);
|
|
263
|
+
fb.dispose();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Release a framebuffer back to the object pool.
|
|
268
|
+
* @param fb - The framebuffer to release.
|
|
269
|
+
*/ releaseFrameBuffer(fb) {
|
|
270
|
+
const hash = this._allocatedFramebuffers.get(fb);
|
|
271
|
+
if (!hash) {
|
|
272
|
+
console.error(`ObjectPool.releaseFrameBuffer(): framebuffer is not allocated from pool`);
|
|
273
|
+
} else {
|
|
274
|
+
this.internalDisposeFrameBuffer(fb);
|
|
275
|
+
const list = this._freeFramebuffers[hash];
|
|
276
|
+
if (list) {
|
|
277
|
+
list.push(fb);
|
|
278
|
+
} else {
|
|
279
|
+
this._freeFramebuffers[hash] = [
|
|
280
|
+
fb
|
|
281
|
+
];
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Purge the object pool by disposing all free framebuffers and textures.
|
|
287
|
+
*/ purge() {
|
|
288
|
+
for(const k in this._freeFramebuffers){
|
|
289
|
+
const list = this._freeFramebuffers[k];
|
|
290
|
+
if (list) {
|
|
291
|
+
for (const fb of this._freeFramebuffers[k]){
|
|
292
|
+
this.internalDisposeFrameBuffer(fb);
|
|
293
|
+
fb.dispose();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
this._freeFramebuffers = {};
|
|
298
|
+
for(const k in this._freeTextures){
|
|
299
|
+
const list = this._freeTextures[k];
|
|
300
|
+
for (const tex of list){
|
|
301
|
+
this._memCost -= tex.memCost;
|
|
302
|
+
tex.dispose();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
this._freeTextures = {};
|
|
306
|
+
}
|
|
307
|
+
/** @internal */ internalDisposeFrameBuffer(fb) {
|
|
308
|
+
if (fb) {
|
|
309
|
+
// Release attachment textures
|
|
310
|
+
const colorAttachments = fb.getColorAttachments();
|
|
311
|
+
if (colorAttachments) {
|
|
312
|
+
for (const tex of colorAttachments){
|
|
313
|
+
this.safeReleaseTexture(tex);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const depthAttachment = fb.getDepthAttachment();
|
|
317
|
+
if (depthAttachment) {
|
|
318
|
+
this.safeReleaseTexture(depthAttachment);
|
|
319
|
+
}
|
|
320
|
+
this._allocatedFramebuffers.delete(fb);
|
|
321
|
+
this._autoReleaseFramebuffers.delete(fb);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/** @internal */ safeReleaseTexture(texture, purge = false) {
|
|
325
|
+
const info = this._allocatedTextures.get(texture);
|
|
326
|
+
if (info) {
|
|
327
|
+
info.refcount--;
|
|
328
|
+
if (info.refcount === 0) {
|
|
329
|
+
this._allocatedTextures.delete(texture);
|
|
330
|
+
this._autoReleaseTextures.delete(texture);
|
|
331
|
+
if (purge || info.dispose) {
|
|
332
|
+
this._memCost -= texture.memCost;
|
|
333
|
+
texture.dispose();
|
|
334
|
+
} else {
|
|
335
|
+
const list = this._freeTextures[info.hash];
|
|
336
|
+
if (list) {
|
|
337
|
+
list.push(texture);
|
|
338
|
+
} else {
|
|
339
|
+
this._freeTextures[info.hash] = [
|
|
340
|
+
texture
|
|
341
|
+
];
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
} else if (purge) {
|
|
345
|
+
info.dispose = true;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export { Pool };
|
|
352
|
+
//# sourceMappingURL=pool.js.map
|
package/dist/pool.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zephyr3d/device",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Device API for zephyr3d",
|
|
5
5
|
"homepage": "https://github.com/gavinyork/zephyr3d#readme",
|
|
6
6
|
"type": "module",
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
"@rollup/plugin-terser": "^0.4.0",
|
|
45
45
|
"@rollup/pluginutils": "^5.0.2",
|
|
46
46
|
"@swc/core": "^1.3.62",
|
|
47
|
-
"@zephyr3d/base": "^0.1.3",
|
|
48
47
|
"cross-env": "^7.0.3",
|
|
49
48
|
"rollup": "^3.15.0",
|
|
50
49
|
"rollup-plugin-copy": "^3.4.0",
|
|
@@ -54,12 +53,10 @@
|
|
|
54
53
|
"shx": "^0.3.4",
|
|
55
54
|
"typescript": "^5.1.3"
|
|
56
55
|
},
|
|
57
|
-
"peerDependencies": {
|
|
58
|
-
"@zephyr3d/base": "^0.1.3"
|
|
59
|
-
},
|
|
60
56
|
"dependencies": {
|
|
61
|
-
"@
|
|
62
|
-
"@webgpu/types": "^0.1.40"
|
|
57
|
+
"@zephyr3d/base": "^0.1.5",
|
|
58
|
+
"@webgpu/types": "^0.1.40",
|
|
59
|
+
"@types/node": "^18.13.0"
|
|
63
60
|
},
|
|
64
61
|
"scripts": {
|
|
65
62
|
"clean": "shx rm -rf ./dist .tsbuildinfo",
|