-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
136 lines (118 loc) · 3.62 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
const button = document.getElementById('render');
const canvas = document.getElementById('canvas');
const scene = document.getElementById('scene');
const concurrency = document.getElementById('concurrency');
const concurrencyAmt = document.getElementById('concurrency-amt');
const timing = document.getElementById('timing');
const timingVal = document.getElementById('timing-val');
const ctx = canvas.getContext('2d');
button.disabled = true;
concurrency.disabled = true;
// First up, but try to do feature detection to provide better error messages
function loadWasm() {
let msg = 'This demo requires a current version of Firefox (e.g., 79.0)';
if (typeof SharedArrayBuffer !== 'function') {
alert('this browser does not have SharedArrayBuffer support enabled' + '\n\n' + msg);
return
}
// Test for bulk memory operations with passive data segments
// (module (memory 1) (data passive ""))
const buf = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
0x05, 0x03, 0x01, 0x00, 0x01, 0x0b, 0x03, 0x01, 0x01, 0x00]);
if (!WebAssembly.validate(buf)) {
alert('this browser does not support passive wasm memory, demo does not work' + '\n\n' + msg);
return
}
wasm_bindgen('./raytrace_parallel_bg.wasm')
.then(run)
.catch(console.error);
}
loadWasm();
const { Scene, WorkerPool } = wasm_bindgen;
function run() {
// The maximal concurrency of our web worker pool is `hardwareConcurrency`,
// so set that up here and this ideally is the only location we create web
// workers.
pool = new WorkerPool(navigator.hardwareConcurrency);
// Configure various buttons and such.
button.onclick = function() {
button.disabled = true;
console.time('render');
let json;
try {
json = JSON.parse(scene.value);
} catch(e) {
alert(`invalid json: ${e}`);
return
}
canvas.width = json.width;
canvas.height = json.height;
test_groupby(new Scene(json));
render(new Scene(json));
};
button.innerText = 'Render!';
button.disabled = false;
concurrency.oninput = function() {
concurrencyAmt.innerText = 'Concurrency: ' + concurrency.value;
};
concurrency.min = 1;
concurrency.step = 1;
concurrency.max = navigator.hardwareConcurrency;
concurrency.value = concurrency.max;
concurrency.oninput();
concurrency.disabled = false;
}
let rendering = null;
let start = null;
let interval = null;
let pool = null;
class State {
constructor(wasm) {
this.start = performance.now();
this.wasm = wasm;
this.running = true;
this.counter = 1;
this.interval = setInterval(() => this.updateTimer(true), 100);
wasm.promise()
.then(data => {
this.updateTimer(false);
this.updateImage(data);
this.stop();
})
.catch(console.error);
}
updateTimer(updateImage) {
const dur = performance.now() - this.start;
timingVal.innerText = `${dur}ms`;
this.counter += 1;
if (updateImage && this.wasm && this.counter % 3 == 0)
this.updateImage(this.wasm.imageSoFar());
}
updateImage(data) {
ctx.putImageData(data, 0, 0);
}
stop() {
if (!this.running)
return;
console.timeEnd('render');
this.running = false;
this.wasm = null;
clearInterval(this.interval);
button.disabled = false;
}
}
function test_groupby(scene) {
test_data = scene.groupby(parseInt(concurrency.value), pool);
test_data.promise()
.then(data => {
console.log(data);
})
.catch(console.error);
}
function render(scene) {
if (rendering) {
rendering.stop();
rendering = null;
}
rendering = new State(scene.render(parseInt(concurrency.value), pool));
}