@woosh/meep-engine 2.73.0 → 2.74.0
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/build/bundle-worker-image-decoder.js +1 -1
- package/build/meep.cjs +4 -4
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +4 -4
- package/package.json +1 -1
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.js +2 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +4 -5
- package/src/engine/asset/loaders/image/png/PNGReader.js +23 -19
- package/src/engine/graphics/generate_halton_jitter.js +21 -0
- package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.js +3 -20
- package/src/engine/graphics/texture/virtual/v2/SparseTexture.js +129 -20
- package/src/engine/graphics/texture/virtual/v2/TileLoader.js +24 -7
- package/src/engine/graphics/texture/virtual/v2/UsageMetadata.js +73 -21
- package/src/engine/graphics/texture/virtual/v2/VirtualTextureManager.js +60 -5
- package/src/engine/graphics/texture/virtual/v2/debug/ResidencyDebugView.js +58 -0
- package/src/engine/graphics/texture/virtual/v2/debug/UsageDebugView.js +63 -0
- package/src/engine/graphics/texture/virtual/v2/{UsagePyramidDebugView.js → debug/UsagePyramidDebugView.js} +30 -39
- package/src/engine/graphics/texture/virtual/v2/prototype.js +46 -21
- package/src/engine/graphics/texture/virtual/v2/{TextureTile.js → tile/TextureTile.js} +1 -1
- package/src/engine/graphics/texture/virtual/v2/tile/compose_finger_print.js +23 -0
- package/src/engine/graphics/texture/virtual/v2/tile/compose_tile_address.js +22 -0
- package/src/engine/graphics/texture/virtual/v2/tile/decompose_finger_print.js +12 -0
- package/src/engine/graphics/texture/virtual/v2/tile/finger_print_to_tile_address.js +16 -0
- package/src/engine/graphics/texture/virtual/v2/{tile_index_to_finger_print.js → tile/tile_address_to_finger_print.js} +7 -3
- package/src/view/CSS_ABSOLUTE_POSITIONING.js +5 -0
- package/src/engine/graphics/texture/virtual/v2/UsageDebugView.js +0 -64
- package/src/engine/graphics/texture/virtual/v2/compose_finger_print.js +0 -13
- package/src/engine/graphics/texture/virtual/v2/finger_print_to_tile_index.js +0 -37
package/build/meep.module.js
CHANGED
|
@@ -69586,9 +69586,8 @@ class ThreadedImageDecoder extends Codec {
|
|
|
69586
69586
|
return true;
|
|
69587
69587
|
}
|
|
69588
69588
|
|
|
69589
|
-
|
|
69590
|
-
|
|
69591
|
-
return result;
|
|
69589
|
+
decode(data) {
|
|
69590
|
+
return this.worker.request('decode', [data.buffer]);
|
|
69592
69591
|
}
|
|
69593
69592
|
}
|
|
69594
69593
|
|
|
@@ -69621,7 +69620,8 @@ class NativeImageDecoder extends Codec {
|
|
|
69621
69620
|
const image = new Image();
|
|
69622
69621
|
|
|
69623
69622
|
// convert binary data to image URL that we can load
|
|
69624
|
-
const
|
|
69623
|
+
const blob = new Blob([data]);
|
|
69624
|
+
const url = URL.createObjectURL(blob);
|
|
69625
69625
|
|
|
69626
69626
|
image.src = url;
|
|
69627
69627
|
|
package/package.json
CHANGED
|
@@ -29,7 +29,8 @@ export class NativeImageDecoder extends Codec {
|
|
|
29
29
|
const image = new Image();
|
|
30
30
|
|
|
31
31
|
// convert binary data to image URL that we can load
|
|
32
|
-
const
|
|
32
|
+
const blob = new Blob([data]);
|
|
33
|
+
const url = URL.createObjectURL(blob);
|
|
33
34
|
|
|
34
35
|
image.src = url;
|
|
35
36
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Codec } from "./Codec.js";
|
|
2
|
-
import WorkerBuilder from "../../../../../core/process/worker/WorkerBuilder.js";
|
|
3
1
|
import { OnDemandWorkerManager } from "../../../../../core/process/worker/OnDemandWorkerManager.js";
|
|
2
|
+
import WorkerBuilder from "../../../../../core/process/worker/WorkerBuilder.js";
|
|
4
3
|
import { PNG_HEADER_BYTES } from "../png/PNG_HEADER_BYTES.js";
|
|
4
|
+
import { Codec } from "./Codec.js";
|
|
5
5
|
|
|
6
6
|
export class ThreadedImageDecoder extends Codec {
|
|
7
7
|
constructor() {
|
|
@@ -35,8 +35,7 @@ export class ThreadedImageDecoder extends Codec {
|
|
|
35
35
|
return true;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return result;
|
|
38
|
+
decode(data) {
|
|
39
|
+
return this.worker.request('decode', [data.buffer]);
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
4
|
import zlib from 'pako';
|
|
5
|
-
|
|
6
|
-
import { PNG } from './PNG.js';
|
|
7
5
|
import { BinaryBuffer } from "../../../../../core/binary/BinaryBuffer.js";
|
|
8
6
|
import { isArrayEqualStrict } from "../../../../../core/collection/array/isArrayEqualStrict.js";
|
|
9
|
-
import { PNG_HEADER_BYTES } from "./PNG_HEADER_BYTES.js";
|
|
10
7
|
import { crc } from "./crc.js";
|
|
11
8
|
|
|
9
|
+
import { PNG } from './PNG.js';
|
|
10
|
+
import { PNG_HEADER_BYTES } from "./PNG_HEADER_BYTES.js";
|
|
11
|
+
|
|
12
12
|
/**
|
|
13
13
|
*
|
|
14
14
|
* @param {Uint8Array} buffer
|
|
@@ -217,7 +217,7 @@ PNGReader.prototype.decodeiEXt = function (chunk) {
|
|
|
217
217
|
* Interlace method 1 byte
|
|
218
218
|
*/
|
|
219
219
|
PNGReader.prototype.decodeIHDR = function (chunk) {
|
|
220
|
-
|
|
220
|
+
const png = this.png;
|
|
221
221
|
|
|
222
222
|
png.setWidth(readUInt32(chunk, 0));
|
|
223
223
|
png.setHeight(readUInt32(chunk, 4));
|
|
@@ -263,7 +263,7 @@ PNGReader.prototype.decodeIEND = function () {
|
|
|
263
263
|
* Uncompress IDAT chunks
|
|
264
264
|
*/
|
|
265
265
|
PNGReader.prototype.decodePixels = function () {
|
|
266
|
-
|
|
266
|
+
const png = this.png;
|
|
267
267
|
|
|
268
268
|
const inflator = new zlib.Inflate();
|
|
269
269
|
|
|
@@ -292,21 +292,25 @@ PNGReader.prototype.decodePixels = function () {
|
|
|
292
292
|
|
|
293
293
|
PNGReader.prototype.interlaceNone = function (data) {
|
|
294
294
|
|
|
295
|
-
|
|
295
|
+
const png = this.png;
|
|
296
296
|
|
|
297
|
-
|
|
298
|
-
|
|
297
|
+
const bits_per_pixel = png.bitDepth;
|
|
298
|
+
const bits_per_line = png.colors * bits_per_pixel;
|
|
299
|
+
const bytes_per_pixel = Math.max(1, bits_per_line / 8);
|
|
300
|
+
|
|
301
|
+
const width = png.width;
|
|
302
|
+
const height = png.height;
|
|
299
303
|
|
|
300
304
|
// color bytes per row
|
|
301
|
-
const color_bytes_per_row = bytes_per_pixel *
|
|
305
|
+
const color_bytes_per_row = bytes_per_pixel * width;
|
|
306
|
+
|
|
307
|
+
const pixels = new Uint8Array(bytes_per_pixel * width * height);
|
|
302
308
|
|
|
303
|
-
|
|
304
|
-
// var scanline;
|
|
305
|
-
var offset = 0;
|
|
309
|
+
let offset = 0;
|
|
306
310
|
|
|
307
311
|
const data_length = data.length;
|
|
308
312
|
|
|
309
|
-
for (
|
|
313
|
+
for (let i = 0; i < data_length; i += color_bytes_per_row + 1) {
|
|
310
314
|
|
|
311
315
|
const scanline_address = i + 1;
|
|
312
316
|
|
|
@@ -367,7 +371,7 @@ PNGReader.prototype.unFilterNone = function (scanline, scanline_offset, pixels,
|
|
|
367
371
|
* Sub(x) = Raw(x) + Raw(x - bpp)
|
|
368
372
|
*/
|
|
369
373
|
PNGReader.prototype.unFilterSub = function (scanline, scanline_offset, pixels, bpp, of, length) {
|
|
370
|
-
|
|
374
|
+
let i = 0;
|
|
371
375
|
|
|
372
376
|
for (; i < bpp; i++) {
|
|
373
377
|
pixels[of + i] = scanline[i + scanline_offset];
|
|
@@ -387,7 +391,7 @@ PNGReader.prototype.unFilterSub = function (scanline, scanline_offset, pixels, b
|
|
|
387
391
|
* Up(x) = Raw(x) + Prior(x)
|
|
388
392
|
*/
|
|
389
393
|
PNGReader.prototype.unFilterUp = function (scanline, scanline_offset, pixels, bpp, of, length) {
|
|
390
|
-
|
|
394
|
+
let i = 0, byte, prev;
|
|
391
395
|
// Prior(x) is 0 for all x on the first scanline
|
|
392
396
|
if ((of - length) < 0) for (; i < length; i++) {
|
|
393
397
|
pixels[of + i] = scanline[i + scanline_offset];
|
|
@@ -406,7 +410,7 @@ PNGReader.prototype.unFilterUp = function (scanline, scanline_offset, pixels, bp
|
|
|
406
410
|
* Average(x) = Raw(x) + floor((Raw(x-bpp)+Prior(x))/2)
|
|
407
411
|
*/
|
|
408
412
|
PNGReader.prototype.unFilterAverage = function (scanline, scanline_offset, pixels, bpp, of, length) {
|
|
409
|
-
|
|
413
|
+
let i = 0, byte, prev, prior;
|
|
410
414
|
if ((of - length) < 0) {
|
|
411
415
|
// Prior(x) == 0 && Raw(x - bpp) == 0
|
|
412
416
|
for (; i < bpp; i++) {
|
|
@@ -460,7 +464,7 @@ PNGReader.prototype.unFilterAverage = function (scanline, scanline_offset, pixel
|
|
|
460
464
|
* end
|
|
461
465
|
*/
|
|
462
466
|
PNGReader.prototype.unFilterPaeth = function (scanline, scanline_offset, pixels, bpp, of, length) {
|
|
463
|
-
|
|
467
|
+
let i = 0, raw, a, b, c, p, pa, pb, pc, pr;
|
|
464
468
|
if ((of - length) < 0) {
|
|
465
469
|
// Prior(x) == 0 && Raw(x - bpp) == 0
|
|
466
470
|
for (; i < bpp; i++) {
|
|
@@ -525,7 +529,7 @@ PNGReader.prototype.parse = function () {
|
|
|
525
529
|
this.decodeHeader();
|
|
526
530
|
|
|
527
531
|
while (this.buffer.position < this.buffer.length) {
|
|
528
|
-
|
|
532
|
+
const type = this.decodeChunk();
|
|
529
533
|
// stop after IHDR chunk, or after IEND
|
|
530
534
|
// if (type === 'IHDR' && options.data === false || type === 'IEND') break;
|
|
531
535
|
if (type === 'IEND') {
|
|
@@ -533,7 +537,7 @@ PNGReader.prototype.parse = function () {
|
|
|
533
537
|
}
|
|
534
538
|
}
|
|
535
539
|
|
|
536
|
-
|
|
540
|
+
const png = this.png;
|
|
537
541
|
|
|
538
542
|
this.decodePixels();
|
|
539
543
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { assert } from "../../core/assert.js";
|
|
2
|
+
import { halton_sequence } from "../../core/math/statistics/halton_sequence.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generates a number of 2d jitter offsets in range -1...1
|
|
6
|
+
* @param {number} point_count
|
|
7
|
+
* @return {Float32Array}
|
|
8
|
+
*/
|
|
9
|
+
export function generate_halton_jitter(point_count) {
|
|
10
|
+
assert.isNonNegativeInteger(point_count, 'point_count');
|
|
11
|
+
|
|
12
|
+
const result = new Float32Array(point_count * 2);
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < point_count; i++) {
|
|
15
|
+
const i2 = i * 2;
|
|
16
|
+
result[i2] = halton_sequence(2, i) * 2 - 1;
|
|
17
|
+
result[i2 + 1] = halton_sequence(3, i) * 2 - 1;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return result;
|
|
21
|
+
}
|
package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.js
CHANGED
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
import { EnginePlugin } from "../../../../../plugin/EnginePlugin.js";
|
|
2
|
-
import { halton_sequence } from "../../../../../../core/math/statistics/halton_sequence.js";
|
|
3
1
|
import { array_copy } from "../../../../../../core/collection/array/array_copy.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Generates a number of 2d jitter offsets in range -1...1
|
|
7
|
-
* @param {number} point_count
|
|
8
|
-
* @return {Float32Array}
|
|
9
|
-
*/
|
|
10
|
-
function generate_jitter(point_count) {
|
|
11
|
-
const result = new Float32Array(point_count * 2);
|
|
12
|
-
|
|
13
|
-
for (let i = 0; i < point_count; i++) {
|
|
14
|
-
const i2 = i * 2;
|
|
15
|
-
result[i2] = halton_sequence(2, i) * 2 - 1;
|
|
16
|
-
result[i2 + 1] = halton_sequence(3, i) * 2 - 1;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return result;
|
|
20
|
-
}
|
|
2
|
+
import { EnginePlugin } from "../../../../../plugin/EnginePlugin.js";
|
|
3
|
+
import { generate_halton_jitter } from "../../../../generate_halton_jitter.js";
|
|
21
4
|
|
|
22
5
|
export class TemporalSupersamplingRenderPlugin extends EnginePlugin {
|
|
23
6
|
constructor() {
|
|
@@ -31,7 +14,7 @@ export class TemporalSupersamplingRenderPlugin extends EnginePlugin {
|
|
|
31
14
|
this.__frame_index = 0;
|
|
32
15
|
|
|
33
16
|
this.__sample_count = 16;
|
|
34
|
-
this.__jitter_offset =
|
|
17
|
+
this.__jitter_offset = generate_halton_jitter(this.__sample_count);
|
|
35
18
|
|
|
36
19
|
|
|
37
20
|
this.__projection_modifier = {
|
|
@@ -3,7 +3,9 @@ import { BitSet } from "../../../../../core/binary/BitSet.js";
|
|
|
3
3
|
import { Cache } from "../../../../../core/cache/Cache.js";
|
|
4
4
|
import { array_copy } from "../../../../../core/collection/array/array_copy.js";
|
|
5
5
|
import { passThrough, strictEquals } from "../../../../../core/function/Functions.js";
|
|
6
|
-
import {
|
|
6
|
+
import { max2 } from "../../../../../core/math/max2.js";
|
|
7
|
+
import { min2 } from "../../../../../core/math/min2.js";
|
|
8
|
+
import { tile_address_to_finger_print } from "./tile/tile_address_to_finger_print.js";
|
|
7
9
|
import { TileLoader } from "./TileLoader.js";
|
|
8
10
|
|
|
9
11
|
/**
|
|
@@ -17,18 +19,48 @@ export class SparseTexture {
|
|
|
17
19
|
|
|
18
20
|
#page_texture_size = [1, 1];
|
|
19
21
|
|
|
22
|
+
#version = 0;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Maximum number of new page assignments per single update cycle
|
|
26
|
+
* This helps prevent thrashing and keep performance overhead of updating pages predictable
|
|
27
|
+
* @type {number}
|
|
28
|
+
*/
|
|
29
|
+
#cycle_assignment_limit = 2;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
get page_texture_resolution() {
|
|
33
|
+
return this.#page_texture_size;
|
|
34
|
+
}
|
|
35
|
+
|
|
20
36
|
/**
|
|
21
37
|
*
|
|
22
38
|
* @type {TextureTile[]}
|
|
23
39
|
*/
|
|
24
40
|
#resident_tiles = [];
|
|
25
41
|
|
|
42
|
+
get resident_tiles() {
|
|
43
|
+
return this.#resident_tiles;
|
|
44
|
+
}
|
|
45
|
+
|
|
26
46
|
#page_slot_occupancy = new BitSet();
|
|
27
47
|
|
|
28
48
|
#tile_resolution = 128;
|
|
29
49
|
|
|
50
|
+
get tile_resolution() {
|
|
51
|
+
return this.#tile_resolution;
|
|
52
|
+
}
|
|
53
|
+
|
|
30
54
|
#residency_tile_capacity = 0;
|
|
31
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Must be >=0
|
|
58
|
+
* When 0 - tiles that would not fit onto the page will not be loaded
|
|
59
|
+
* When >0 - same fraction of extra tiles will be fetching and put into cache, resulting in prefetching
|
|
60
|
+
* @type {number}
|
|
61
|
+
*/
|
|
62
|
+
#prefetch_factor = 0.33;
|
|
63
|
+
|
|
32
64
|
#loader = new TileLoader();
|
|
33
65
|
|
|
34
66
|
/**
|
|
@@ -37,6 +69,34 @@ export class SparseTexture {
|
|
|
37
69
|
*/
|
|
38
70
|
#asset_manager = null;
|
|
39
71
|
|
|
72
|
+
constructor() {
|
|
73
|
+
this.#loader.on.loaded.add(this.#handle_tile_loaded, this);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
* @param {TextureTile} tile
|
|
79
|
+
*/
|
|
80
|
+
#handle_tile_loaded(tile) {
|
|
81
|
+
const finderPrint = tile.finder_print;
|
|
82
|
+
|
|
83
|
+
if (this.#tile_cache.has(finderPrint)) {
|
|
84
|
+
// already loaded
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this.#tile_cache.put(finderPrint, tile);
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
*
|
|
94
|
+
* @param {string} v
|
|
95
|
+
*/
|
|
96
|
+
set path(v) {
|
|
97
|
+
this.#loader.path = v;
|
|
98
|
+
}
|
|
99
|
+
|
|
40
100
|
set asset_manager(v) {
|
|
41
101
|
this.#asset_manager = v
|
|
42
102
|
|
|
@@ -51,6 +111,8 @@ export class SparseTexture {
|
|
|
51
111
|
const y = size[1] / tile_resolution;
|
|
52
112
|
|
|
53
113
|
this.#residency_tile_capacity = x * y;
|
|
114
|
+
|
|
115
|
+
this.#loader.queue_limit = max2(16, this.#residency_tile_capacity);
|
|
54
116
|
}
|
|
55
117
|
|
|
56
118
|
|
|
@@ -81,19 +143,19 @@ export class SparseTexture {
|
|
|
81
143
|
const tiles = this.#resident_tiles;
|
|
82
144
|
const count = tiles.length;
|
|
83
145
|
|
|
84
|
-
let
|
|
85
|
-
let
|
|
146
|
+
let min = Infinity;
|
|
147
|
+
let min_index = -1;
|
|
86
148
|
|
|
87
149
|
for (let i = 0; i < count; i++) {
|
|
88
150
|
const tile = tiles[i];
|
|
89
151
|
|
|
90
|
-
if (tile.last_used_time
|
|
91
|
-
|
|
92
|
-
|
|
152
|
+
if (tile.last_used_time < min) {
|
|
153
|
+
min = tile.last_used_time;
|
|
154
|
+
min_index = i;
|
|
93
155
|
}
|
|
94
156
|
}
|
|
95
157
|
|
|
96
|
-
return
|
|
158
|
+
return min_index;
|
|
97
159
|
}
|
|
98
160
|
|
|
99
161
|
#evict_one() {
|
|
@@ -119,12 +181,40 @@ export class SparseTexture {
|
|
|
119
181
|
// mark slot as empty for next tile
|
|
120
182
|
this.#page_slot_occupancy.clear(pageSlot);
|
|
121
183
|
|
|
184
|
+
removed.page_slot = -1;
|
|
185
|
+
|
|
122
186
|
// push into cache
|
|
123
187
|
this.#tile_cache.put(removed.finder_print, removed);
|
|
124
188
|
|
|
125
189
|
return true;
|
|
126
190
|
}
|
|
127
191
|
|
|
192
|
+
/**
|
|
193
|
+
*
|
|
194
|
+
* @param {TextureTile} tile
|
|
195
|
+
*/
|
|
196
|
+
#make_resident(tile) {
|
|
197
|
+
|
|
198
|
+
if (this.#residency_tile_capacity === 0) {
|
|
199
|
+
throw new Error('Capacity is 0');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let slot = this.#page_slot_occupancy.nextClearBit(0);
|
|
203
|
+
|
|
204
|
+
while (slot >= this.#residency_tile_capacity) {
|
|
205
|
+
this.#evict_one();
|
|
206
|
+
|
|
207
|
+
slot = this.#page_slot_occupancy.nextClearBit(0);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
tile.page_slot = slot;
|
|
211
|
+
|
|
212
|
+
this.#page_slot_occupancy.set(slot, true);
|
|
213
|
+
this.#resident_tiles.push(tile);
|
|
214
|
+
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
|
|
128
218
|
/**
|
|
129
219
|
*
|
|
130
220
|
* @param {number[]} v
|
|
@@ -137,7 +227,7 @@ export class SparseTexture {
|
|
|
137
227
|
);
|
|
138
228
|
|
|
139
229
|
this.#page_texture.dispose();
|
|
140
|
-
this.#page_texture.setSize(this.#
|
|
230
|
+
this.#page_texture.setSize(this.#page_texture_size[0], this.#page_texture_size[1]);
|
|
141
231
|
|
|
142
232
|
this.#update_residency_capacity();
|
|
143
233
|
}
|
|
@@ -147,31 +237,50 @@ export class SparseTexture {
|
|
|
147
237
|
* @param {UsageMetadata} usage
|
|
148
238
|
*/
|
|
149
239
|
update_usage(usage) {
|
|
150
|
-
const
|
|
240
|
+
const usage_occupancy = usage.occupancy;
|
|
241
|
+
const usage_occupancy_count = usage.occupancy_count;
|
|
151
242
|
|
|
152
|
-
for (let mip = 0; mip < max_mip; mip++) {
|
|
153
243
|
|
|
154
|
-
|
|
244
|
+
// Usage occupancy is already sorted by priority, so there's no point is trying to fetch more than t
|
|
245
|
+
let fetch_limit = this.#residency_tile_capacity * (1 + this.#prefetch_factor);
|
|
155
246
|
|
|
156
|
-
|
|
157
|
-
|
|
247
|
+
let writes_remaining = min2(
|
|
248
|
+
max2(1, this.#cycle_assignment_limit),
|
|
249
|
+
this.#residency_tile_capacity
|
|
250
|
+
);
|
|
158
251
|
|
|
159
|
-
|
|
252
|
+
let remaining_slots = this.#residency_tile_capacity;
|
|
160
253
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
254
|
+
for (let i = 0; i < usage_occupancy_count && fetch_limit > 0; i++) {
|
|
255
|
+
const tile_address = usage_occupancy[i];
|
|
164
256
|
|
|
165
|
-
|
|
257
|
+
const fingerPrint = tile_address_to_finger_print(tile_address);
|
|
166
258
|
|
|
167
|
-
|
|
259
|
+
const tile = this.#tile_cache.get(fingerPrint);
|
|
260
|
+
if (tile === null) {
|
|
261
|
+
this.#loader.enqueue(fingerPrint);
|
|
262
|
+
} else if (remaining_slots > 0) {
|
|
263
|
+
// found in cache, and we have some slots remaining to write into
|
|
168
264
|
|
|
265
|
+
|
|
266
|
+
// touch to prevent eviction
|
|
267
|
+
tile.last_used_time = this.#version;
|
|
268
|
+
|
|
269
|
+
if (tile.page_slot === -1 && writes_remaining > 0) {
|
|
270
|
+
// tile is not active, and we can write it
|
|
271
|
+
writes_remaining--;
|
|
272
|
+
this.#make_resident(tile);
|
|
169
273
|
}
|
|
170
|
-
}
|
|
171
274
|
|
|
275
|
+
fetch_limit--;
|
|
276
|
+
remaining_slots--;
|
|
277
|
+
}
|
|
172
278
|
}
|
|
173
279
|
|
|
280
|
+
|
|
174
281
|
this.#loader.update_usage(usage);
|
|
282
|
+
|
|
283
|
+
this.#version++;
|
|
175
284
|
}
|
|
176
285
|
|
|
177
286
|
dispose() {
|
|
@@ -3,9 +3,9 @@ import { arrayQuickSort } from "../../../../../core/collection/array/arrayQuickS
|
|
|
3
3
|
import Signal from "../../../../../core/events/signal/Signal.js";
|
|
4
4
|
import { AssetManager } from "../../../../asset/AssetManager.js";
|
|
5
5
|
import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
6
|
-
import { compose_finger_print } from "./compose_finger_print.js";
|
|
7
|
-
import { decompose_finger_print } from "./
|
|
8
|
-
import { TextureTile } from "./TextureTile.js";
|
|
6
|
+
import { compose_finger_print } from "./tile/compose_finger_print.js";
|
|
7
|
+
import { decompose_finger_print } from "./tile/decompose_finger_print.js";
|
|
8
|
+
import { TextureTile } from "./tile/TextureTile.js";
|
|
9
9
|
|
|
10
10
|
export class TileLoader {
|
|
11
11
|
/**
|
|
@@ -14,13 +14,23 @@ export class TileLoader {
|
|
|
14
14
|
*/
|
|
15
15
|
#root_path = "";
|
|
16
16
|
|
|
17
|
+
set path(v) {
|
|
18
|
+
this.#root_path = v;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* When queue gets larger than this, we start discarding elements
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
queue_limit = Infinity;
|
|
26
|
+
|
|
17
27
|
/**
|
|
18
28
|
*
|
|
19
29
|
* @type {AssetManager}
|
|
20
30
|
*/
|
|
21
31
|
#asset_manager = null;
|
|
22
32
|
|
|
23
|
-
set asset_manager(v){
|
|
33
|
+
set asset_manager(v) {
|
|
24
34
|
this.#asset_manager = v;
|
|
25
35
|
}
|
|
26
36
|
|
|
@@ -28,7 +38,7 @@ export class TileLoader {
|
|
|
28
38
|
* How many tiles can be loaded at the same time
|
|
29
39
|
* @type {number}
|
|
30
40
|
*/
|
|
31
|
-
#concurrency =
|
|
41
|
+
#concurrency = 2;
|
|
32
42
|
|
|
33
43
|
/**
|
|
34
44
|
* Tiles that are currently being loaded
|
|
@@ -95,7 +105,6 @@ export class TileLoader {
|
|
|
95
105
|
return false;
|
|
96
106
|
}
|
|
97
107
|
|
|
98
|
-
// TODO limit queue size, if the queue grows too large we may end up with completely irrelevant tiles being loaded minutes after they were actually relevant
|
|
99
108
|
if (this.#queue_add(fingerprint) === false) {
|
|
100
109
|
return false;
|
|
101
110
|
}
|
|
@@ -142,6 +151,12 @@ export class TileLoader {
|
|
|
142
151
|
*/
|
|
143
152
|
update_usage(usage) {
|
|
144
153
|
this.#sort_queue_by_usage(usage);
|
|
154
|
+
|
|
155
|
+
// truncate the queue if necessary
|
|
156
|
+
const queue_overflow = this.#queue.length - this.queue_limit;
|
|
157
|
+
if (queue_overflow > 0) {
|
|
158
|
+
this.#queue.splice(this.queue_limit, queue_overflow);
|
|
159
|
+
}
|
|
145
160
|
}
|
|
146
161
|
|
|
147
162
|
/**
|
|
@@ -165,7 +180,7 @@ export class TileLoader {
|
|
|
165
180
|
*/
|
|
166
181
|
#prod() {
|
|
167
182
|
while (this.#in_flight.length < this.#concurrency && this.#queue.length > 0) {
|
|
168
|
-
const fingerprint = this.#queue
|
|
183
|
+
const fingerprint = this.#queue[0];
|
|
169
184
|
const { mip, x, y } = decompose_finger_print(fingerprint);
|
|
170
185
|
|
|
171
186
|
this.#load(mip, x, y);
|
|
@@ -201,6 +216,8 @@ export class TileLoader {
|
|
|
201
216
|
|
|
202
217
|
|
|
203
218
|
return tile;
|
|
219
|
+
}, (reason) => {
|
|
220
|
+
console.error(`Failed to load tile ${file_name}, reason:${reason}`);
|
|
204
221
|
})
|
|
205
222
|
.finally(() => {
|
|
206
223
|
|