为了让新纹理无需锁定即可流入WebGL主UI线程中,我们使用emscripten和asm.js编译了libjpeg和一个实时DXT纹理压缩器到JavaScript,并在单个webworker中运行它们。在Emscripten'd C++程序中处理完数据之后,如何在从Webworker发回数据时如何解决“内存不足”错误
在6年前处理2048x2048 Jpeg源图像的笔记本电脑上,我们在约300ms内解码每个jpeg,然后在230ms左右将它们压缩为DXT1压缩纹理格式。尽管我们确信它可以有所改进,但这对我们的需求来说已经足够了。
但是,我们遇到的问题是,从webworker反序列化返回的数据仍然会导致主UI线程挂起。考虑到每个返回的DTX1文件是2MB,这并不令人意外。为了弥补这一点,我们打算使用webworker可转移对象将数据发送回去,从而允许将产生的ArrayBuffer
简单地转移到主线程而不需要被复制。
但是,每当我们尝试这样做时,我们都会在postMessage
调用中收到InternalError: out of memory
错误。
这是我们呼叫DXT压缩机并发回的方式。 (this.decoded
仅仅是解码JPEG文件的Uint8Array
和可变STB
原始RGBA数据存取我们的DXT压缩机的emscripten'd版)
ImageDecoder.prototype._compressDXT = function(){
console.log('COMPRESS DXT');
var start = Date.now();
var srcSize = this.decoded.length*this.decoded.BYTES_PER_ELEMENT;
var inputPtr = STB._malloc(srcSize);
var outputPtr = STB._malloc(srcSize/8);
var inputHeap = new Uint8Array(STB.HEAPU8.buffer, inputPtr, srcSize);
var outputHeap = new Uint8Array(STB.HEAPU8.buffer, outputPtr, srcSize/8);
//set inputHeap to jpeg decoded RGBA data
inputHeap.set(this.decoded);
//compress data to DXT1
STB.ccall('rygCompress', null, ['number', 'number', 'number', 'number'],
[outputPtr, inputPtr, 2048, 2048]);
var result = new Uint8Array(outputHeap.buffer, outputHeap.byteOffset, outputHeap.length);
STB._free(inputHeap.byteOffset);
STB._free(outputHeap.byteOffset);
console.log('FINAL SIZE: ' + result.length*result.BYTES_PER_ELEMENT);
console.log('compressed in: ' + (Date.now() - start) + 'ms');
//send back to main thread
postMessage({
complete: true,
result: result
}, [result.buffer]);
//perform clean up
this._cleanUp();
}
第二,我们删除transferable
列表并更改postMessage
调用如下:
postMessage({
complete: true,
result: result
});
然后一切都按预期工作。我只能假设这是由于我们对emscripten的经验不足,并且我们在_malloc
,_free
和我们的typedArrays
和ArrayBuffers
中做错了。但是,到目前为止,我们还没有能够弄清楚我们会出错的地方。
任何帮助将不胜感激。
'postMessage'上是否发生错误,而不是'this._cleanUp()'? – zakki
是的,在'''postMessage'''但是我找到了原因,并会回答我自己的问题。 – gordyr