preliminary web worker support #4

Merged
merged 3 commits into from Nov 20, 2015
Jump to file or symbol
Failed to load files and symbols.
+48 −10
Diff settings

Always

Just for now

Viewing a subset of changes. View all

require sharedarraybuffer support

We use it for sharing low latency buffer metrics.
  • Loading branch information...
taisel committed Nov 20, 2015
commit d6efa2131a95f7f5c707ad83512d88e8fee6a3af
@@ -62,9 +62,13 @@ window.onload = function () {
}
function registerIodineHandler() {
try {
+ if (!window.SharedInt32Array) {
+ //Audio synchronization is much better with shared array memory:
+ throw null;
+ }
//Try starting Iodine in a webworker:
IodineGUI.Iodine = new IodineGBAWorkerShim();
- addEvent("onbeforeunload", window, registerBeforeUnloadHandler);
+ addEvent("beforeunload", window, registerBeforeUnloadHandler);
}
catch (e) {
//Otherwise just run on-thread:
@@ -73,12 +77,12 @@ function registerIodineHandler() {
}
function registerBeforeUnloadHandler(e) {
IodineGUI.Iodine.pause();
- this.style.display = "none";
+ document.getElementById("play").style.display = "none";
document.getElementById("play").style.display = "inline";
if (e.preventDefault) {
e.preventDefault();
}
- removeEvent("onbeforeunload", window, registerBeforeUnloadHandler);
+ removeEvent("beforeunload", window, registerBeforeUnloadHandler);
return "IodineGBA needs to process your save data, leaving now may result in not saving current data.";
}
function registerTimerHandler() {
@@ -11,10 +11,12 @@
function IodineGBAWorkerShim() {
this.gfx = null;
this.audio = null;
+ this.audioInitialized = false;
this.speed = null;
this.saveExport = null;
this.saveImport = null;
this.worker = null;
+ this.shared = null;
this.initialize();
}
var tempvar = document.getElementsByTagName("script");
@@ -25,6 +27,10 @@ IodineGBAWorkerShim.prototype.initialize = function () {
this.worker.onmessage = function (event) {
parentObj.decodeMessage(event.data);
}
+ if (window.SharedInt32Array) {
+ this.shared = new SharedInt32Array(1);
+ this.sendBufferBack(25, this.shared);
+ }
}
IodineGBAWorkerShim.prototype.sendMessageSingle = function (eventCode) {
eventCode = eventCode | 0;
@@ -53,7 +59,14 @@ IodineGBAWorkerShim.prototype.setIntervalRate = function (rate) {
}
IodineGBAWorkerShim.prototype.timerCallback = function (timestamp) {
timestamp = +timestamp;
- this.sendMessageDouble(23, this.audio.remainingBuffer());
+ if (this.audio && this.audioInitialized) {
+ if (this.shared) {
+ this.shared[0] = this.audio.remainingBuffer() | 0;
+ }
+ else {
+ this.sendMessageDouble(23, this.audio.remainingBuffer() | 0);
+ }
+ }
this.sendMessageDouble(4, +timestamp);
}
IodineGBAWorkerShim.prototype.attachGraphicsFrameHandler = function (gfx) {
@@ -154,6 +167,7 @@ IodineGBAWorkerShim.prototype.audioInitialize = function (channels, sampleRate,
//Disable audio in the callback here:
parentObj.disableAudio();
});
+ this.audioInitialized = true;
}
}
IodineGBAWorkerShim.prototype.audioRegister = function () {
@@ -54,8 +54,10 @@ importScripts("../IodineGBA/core/cartridge/EEPROM.js");
var Iodine = new GameBoyAdvanceEmulator();
//Spare audio buffers:
var audioBufferPool = [];
+var audioBufferPassCount = 0;
//Spare graphics buffers:
var graphicsBufferPool = [];
+var graphicsBufferPassCount = 0;
//Save callbacks waiting to be satisfied:
var saveImportPool = [];
//Cached timestamp:
@@ -139,19 +141,29 @@ self.onmessage = function (event) {
break;
case 24:
processSaveImportFail();
+ break;
+ case 25:
+ attachAudioMetricHook(data.payload);
}
}
function graphicsFrameHandler(swizzledFrame) {
- var buffer = getFreeGraphicsBuffer(swizzledFrame.length);
- buffer.set(swizzledFrame);
- postMessage({messageID:4, graphicsBuffer:buffer}, [buffer.buffer]);
+ if ((graphicsBufferPassCount | 0) < 2) {
+ var buffer = getFreeGraphicsBuffer(swizzledFrame.length);
+ buffer.set(swizzledFrame);
+ graphicsBufferPassCount = ((graphicsBufferPassCount | 0) + 1) | 0;
+ postMessage({messageID:4, graphicsBuffer:buffer}, [buffer.buffer]);
+ }
}
//Shim for our audio api:
var audioHandler = {
+ shared:null,
push:function (audioBuffer, amountToSend) {
- var buffer = getFreeAudioBuffer(amountToSend | 0);
- buffer.set(audioBuffer);
- postMessage({messageID:3, audioBuffer:buffer, audioNumSamplesTotal:amountToSend | 0}, [buffer.buffer]);
+ if ((audioBufferPassCount | 0) < 10) {
+ var buffer = getFreeAudioBuffer(amountToSend | 0);
+ buffer.set(audioBuffer);
+ audioBufferPassCount = ((audioBufferPassCount | 0) + 1) | 0;
+ postMessage({messageID:3, audioBuffer:buffer, audioNumSamplesTotal:amountToSend | 0}, [buffer.buffer]);
+ }
},
register:function () {
postMessage({messageID:1});
@@ -166,10 +178,16 @@ var audioHandler = {
postMessage({messageID:0, channels:channels, sampleRate:sampleRate, bufferLimit:bufferLimit});
},
remainingBuffer:function () {
+ if (this.shared) {
+ return this.shared[0];
+ }
return this.remainingBufferCache;
},
remainingBufferCache:0
};
+function attachAudioMetricHook(buffer) {
+ audioHandler.shared = new SharedInt32Array(buffer.buffer);
+}
function speedHandler(speed) {
postMessage({messageID:5, speed:speed});
}
@@ -187,9 +205,11 @@ function processSaveImportFail() {
saveImportPool.shift()[1]();
}
function repoolAudioBuffer(buffer) {
+ audioBufferPassCount = ((audioBufferPassCount | 0) - 1) | 0;
audioBufferPool.push(buffer);
}
function repoolGraphicsBuffer(buffer) {
+ graphicsBufferPassCount = ((graphicsBufferPassCount | 0) - 1) | 0;
graphicsBufferPool.push(buffer);
}
function getFreeGraphicsBuffer(amountToSend) {